Checkpointing Simulation of a Circuit in JHDL


Forward

This document is a fairly thorough HOW-TO on circuit checkpointing in JHDL. Since the setup of checkpointing is fairly straightforward, the examples shown are fairly simple examples, but can be easily extended to any general case.


Checkpointing and Readback

In order to avoid any confusion, we will use the following definitions in reference to JHDL:

Checkpointing and readback can be used together (i.e. read the state of a circuit from a board, then checkpoint it to a file or other stream) but currently this is unidirectional, since writeback is not yet fully supported.


TBone Checkpointing

The first (and easiest) way to use checkpointing is to use it directly from TBone. All you really need to know to use this feature is the following TBone commands: (if you forget them, type "help" in TBone)

TBone also will save the put values that you had on your wires when you did your checkpoint. (Althought you may do a TBone put on any inputs before you cycle the simulator to change their value, as usual.)

That's all there is to it!


Checkpointable TestBecnhes & Behavioral Models

The next way to use Checkpointing is to make a Checkpointable TestBench or a Checkpointable Behavioral model. Essentially, a testbench is just a behavioral model, and so all of the same principles apply to both. Basically, there are two kinds of state that you must save (if you want your circuit to checkpoint correctly!) and one other kind of state that is optional.

Doing this is fairly simple if it's encapsulated well. The following is a checkpointable TestBench that does nothing but checkpoint and restore a circuit (just for this example). In practice, you would (probably) want to actually do something useful. ;)

import byucc.jhdl.base.*; // base is where Checkpointable lives
import byucc.jhdl.Logic.*;
import byucc.jhdl.Xilinx.Virtex.*;
import java.io.*; // included for Serializable

// notice we implement Checkpointable
public class tb_arraytest extends Logic implements TestBench, Checkpointable {
  public static void main(String argv[]) {
    HWSystem hw = new HWSystem();
    tb_arraytest tb = new tb_arraytest(hw);
    hw.cycle(4);
    // this is the command to do a checkpoint
    hw.writeSystemState();
    hw.cycle(20);
    // since we did a cycle(4), and cycles start at 0, we restore cycle #3
    hw.readSystemState(3);
    hw.cycle(20);
  }

  // all state that should be saved must go in a serializable state object
  private State myState = new State();

  public void reset() {
    myState.count = 0;
    myState.a = 0;
    myState.b = 0;

    doPuts();
  }

  public void clock() {

    /* println... */
    System.out.print("Cycle " + myState.count + ": ");
    System.out.println("  o: " + o.get(this));

    /* Outputs (*to* circuit) */
    // here we save the outputs of our testbench, needed for checkpointing
    myState.a = myState.count*456;
    myState.b = myState.count*343;

    myState.count++;

    doPuts();

  }

  // this function is just a helper. We have to do the same put from the
  // state object in reset, clock, and setData, so we can just put it all
  // in this function and call it when needed. This is just for convenience.
  public void doPuts() {
    a.put(this,myState.a);
    b.put(this,myState.b);
  }
 
  Wire a, b, o;

  final int gw = 4;

  public tb_arraytest(Node parent) {
    super(parent);
    TechMapper tm = new VirtexTechMapper( true );
    Logic.setDefaultTechMapper(tm);
    a = wire(gw,"a");
    b = wire(gw,"b");
    o = wire(gw*2,"o");
    arraytest my_arraytest = new arraytest(this,a,b,o);
    my_arraytest.disableAllBehavioralModels();
  }

  // these two functions implement Checkpointable

  public Serializable getData() {
    // here, we simply return our checkpointable state object
    return myState;
  }

  // 
  public void setData( Serializable data ) {
    // first we restore our state
    myState = (State)data;

    // then we MUST do puts on all of our outputs, and they *must* match
    // what our outputs were when we checkpointed. Hense the importance of
    // storing these in the state object. If these are stored or put
    // incorrectly, simulation will break after a restored checkpoint.

    // DO NOT do puts by calling clock(), or by doing any
    // calculation. Do the puts as they were stored.

    // clock(); <<--- NO NO NO NO NO! Don't call any function that
    // will recalculate outputs. The original output values restored
    // from the state object must be the ones that are put during the
    // setData cycle. Instead, we'll call this--which just puts from the
    // state object.
    doPuts();
  }

  
};

// this MUST be a package scope outerclass (inner classes are not supported
// correctly for serialization in java 1.1 for some bizarre reason.)
// this is probably supported in java 1.2 and 1.3, but we're not using those...

// the class must be package scope and implement Serializable
class State implements Serializable {

  // data members can be anything Serializable, which is almost every
  // internal java type. The can be package scope, or public, or can even
  // be private and have constructors and accessors, whatever. The only
  // limitiation is whatever Serializable imposes.

  // because count is used to determine the outputs, it must be saved
  int count = 0;
  
  // outputs (*to* circuit) - here we must save all values that are PUT
  int a = 0;
  int b = 0;

};

With this info, you can make checkpointable testbenches, checkpointable behavioral models, checkpointable anything you want!


The Checkpointable Interface

The example above should show you all that you need to get started using the Checkpointable Interface. However, here are a few more details about the functions in Checkpointable for anyone so interested:


Checkpoint calls in HWSystem

The following checkpointing calls are supported HWSystem:


Finally...

That's it for now! This document will be updated and posted on the JHDL web page after a few more things are added and once it is polished up a little bit. But for now, you can checkpoint all you want!


wjl@ee.byu.edu