In my last post I discussed how to use save / restore in the Cadence Incisive Simulator to create checkpoints for designs that contain SystemC. The algorithm for SystemC save / restore is fundamentally different than the algorithm for HDL designs. Although most of the functionality is equivalent between the two styles, there are a few differences.
During restart, all internal variables are restored to their saved values (for example, C variables declared static). While this behavior helps assure that SystemC state information is properly saved and restored, it can also leave variables that reference the process environment (like file descriptor and sockets to other processes) in limbo. To allow control before and after both save and restart, IUS provides the following virtual function definitions:
virtual void start_of_save()
virtual void end_of_save()
virtual void start_of_restore()
virtual void end_of_restore()
These methods are defined for those class definitions that have similar phase callback methods currently defined (for example, start_of_simulation or end_of_simulation).
Here’s a simple example. Class scchild has a thread that writes some data to a log file. If a save operation is performed when the file is open then problems can arise if the program attempts to write to the same file after restore (because the file descriptor associated with the open file will be in a different state after restore). Keep in mind that you could decide to restore this session weeks or months after the original save. The file could be modified or even deleted in that time. Here, in the start_of_restore method, we "fix up" the file by opening it again. Granted, things would be trickier if this was an input file, but you get the idea.
class scchild : public sc_module {
public:
sc_in<sc_logic> in;
SC_CTOR(scchild): in("in") {
SC_THREAD(main);
}
void main() {
int *count = new int;
open_out_log("my_log");
for (*count=0; *count < 10000; (*count)++) {
fprintf(out_log, "*count = %d\n", *count);
wait(10, SC_NS);
}
}
void start_of_save() {
}
void end_of_save() {
}
void start_of_restore() {
}
void end_of_restore() {
}
void open_out_log(const char *name){
out_log = fopen(name);
}
private:
FILE *out_log;
};
In case you’re wondering why we don’t close the file in start_of_restore, the file descriptor associated with out_log before save is gone after the snapshot is restored. The core save / restore code actually does the close.
SystemC save / restore does not work for designs that contain AMS or simulation sessions that are instrumented with IBM PurifyPlus products. However you can use electric fence for debugging memory violations (ncsc_run –efence).
Finally, while using restart with a saved snapshot, ncsim overwrites any SHM databases that were active before restart. With HDL save / restore, a new trn sequence file is generated for each save and restore operation. Thus if you have probes in your design and do a save followed by 2 restarts:
ncsim> probe -create sctop.es.run -database waves -waveform
ncsim> run 20 ns
ncsim>save –over x
ncsim>run 10 ns
ncsim>restart x
ncsim>run 1000 ns
ncsim>restart x
ncsim>run 10 ns
You’ll get an shm directory that contains the following files:
georgef%ls -1 ncsim.shm
ncsim.dsn
ncsim.trn
ncsim.trn-1
ncsim.trn-2
ncsim.trn-3
ncsim.trn contains the probe activity from time 0 to save, ncsim.trn-1 contains the probe activity from after save to the first restart, ncsim.trn-2 contains the probe activity from after the first restart to the second restart, and ncsim.trn-3 contains the probe activity after the second restart.
Because of the SST2 format, we can’t support this kind of data continuity between restarts with the SystemC approach. After the first restore, the entire database (ncsim.shm and ncsim.trn) will be overwritten.
We have an option for restart, however, that allows you to save data between restores in entirely separate databases. Use the –savedb option to keep a complete history of probe activity in a session with multiple restarts:
ncsim> probe -create sctop.es.run -database waves -waveform
ncsim> run 20 ns
ncsim>save –over x
ncsim>run 10 ns
ncsim>restart –savedb x
ncsim>run 1000 ns
ncsim>restart –savedb x
ncsim>run 10 ns
Now instead of a single ncsim.shm directory you will also have ncsim-1.shm and ncsim-2.shm. Each directory contains data written after restart. Note that no separate directory is created after save (as in HDL save / restore).
If you’re using Incisive SystemC, I hope you’ll give save and restore a try. Let us know what you think if you do.