import byucc.jhdl.base.CellInterface;
import byucc.jhdl.base.Node;
import byucc.jhdl.base.Wire;
import byucc.jhdl.base.SimulatorCallback;
import byucc.jhdl.Logic.Logic;

/** Class to demonstrate the SimulatorCallback interface. */
public class TestSimCallback extends Logic implements SimulatorCallback {

  /** The interface for this Cell, including the output interface, and
   * the width of that interface */
  public static CellInterface[] cell_interface = {
    out ( "q", "WID" ),
    param ("WID", INTEGER),
  };

  /** The output wire of the Cell */
  Wire q;

  /** Constructor for our Cell
   * @param parent the parent node for this Cell (will be a TestBench)
   * @param q the output wire for this Cell
   * @param instanceName the name of this Cell */
  public TestSimCallback(
			 Node parent,
			 Wire q,
			 String instanceName
			 ) {
    super(parent, instanceName);
    bind("WID", q.getWidth());
    this.q = connect("q", q);

    // Build a simple counter...
    Wire s = wire(q.getWidth(), "sum");
    add_o(q, constant(q.getWidth(), 1), s, "addn");
    reg_o( s, q, "cntOut");
  }

  // The SimulatorCallback interface stuff follows
  TestFrame tf;        // Frame to hold cycle count in GUI

  /** Called when the simulator is reset (including before the first
   * cycle) */
  public void simulatorReset() {
    // Create a testFrame if one doesn't exist yet
    if (tf != null)
      tf.dispose();
    tf = new TestFrame();
  }

  /** Called after each simulator run. This will update the TestFrame
   * object to display the current output. */
  public void simulatorRefresh(int cycle, int phase) {
    tf.updateValues(q.get(this));
  }

  /** This is a finer granularity method that we don't need now. */
  public void simulatorUpdate(int cycle, int phase) {
    // Print results to screen as well
    System.out.println("Cycle = " + cycle +
                       ", Phase = " + phase +
                       ": " + q.get(this));
  }
}

