import com.sun.async.test.ChipModel;
import com.sun.async.test.Infrastructure;
import com.sun.async.test.NanosimModel;
+import com.sun.async.test.VerilogModel;
import com.sun.vlsi.chips.marina.test.MarinaUtils.StateWireState;
public class ProperStopper {
- // position of strobes in the control chain
- private static final int BLOCK_STROBE_NDX = 0;
- private static final int FILL_STROBE_NDX = 1;
- private static final int GO_STROBE_NDX = 2;
- private static final int SILENT_STROBE_NDX = 3;
- private static final int CLEAR_STROBE_NDX = 4;
- private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
-
- // position of inputs in report chain
- private static final int PREV_STATE_IN_NDX = 0;
- private static final int FILL_STROBE_IN_NDX = 1;
- private static final int FILL_STATE_IN_NDX = 2;
- private static final int STOPPED_IN_NDX = 3;
-
- private final String name;
- private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
+ // position of strobes in the control chain
+ private static final int BLOCK_STROBE_NDX = 0;
+ private static final int FILL_STROBE_NDX = 1;
+ private static final int GO_STROBE_NDX = 2;
+ private static final int SILENT_STROBE_NDX = 3;
+ private static final int CLEAR_STROBE_NDX = 4;
+ private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
+
+ // position of inputs in report chain
+ private static final int PREV_STATE_IN_NDX = 0;
+ private static final int FILL_STROBE_IN_NDX = 1;
+ private static final int FILL_STATE_IN_NDX = 2;
+ private static final int STOPPED_IN_NDX = 3;
+
+ private final String name;
+ //private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
+ private final String captureClockRelPath = "fillStag@1";
// test library direct write mode doesn't understand per register write
// enables. We get simulation to work by toggling write clock.
private final boolean clockHack;
- private final String captureClockName = "si[4]";
+ private final String captureClockName = "sx[4]";
+ /*
private boolean traceFill = true;
- private boolean traceDrain = true;
-
+ private boolean traceDrain = true;
+ */
+ private boolean traceFill = false;
+ private boolean traceDrain = false;
+
private final String controlChain, controlPath,
- dataChain, dataPath,
- reportChain, reportPath;
+ dataChain, dataPath,
+ reportChain, reportPath;
private final String captureClock;
private final ChainControls cc;
private final ChipModel model;
- private final Indenter indenter;
-
- protected static void fatal(boolean pred, String msg) {
- if (pred) Infrastructure.fatal(msg);
- }
- private void prln(String msg) {indenter.prln(msg);}
- private void adjustIndent(int n) {indenter.adjustIndent(n);}
-
- /** NanosimModel.setNodeState() requires special path names.
- * Each instance name in the path must begin with the character 'x'.
- * Return a path with the added X's. */
- private String prefixInstNamesInPathWithX(String path) {
- StringBuffer sb = new StringBuffer();
- sb.append('x');
- for (int i=0; i<path.length(); i++) {
- char c = path.charAt(i);
- sb.append(c);
- if (c=='.') sb.append('x');
- }
- return sb.toString();
- }
-
- private BitVector getDatTokAdr() {
- // strip the two write enable bits
- return cc.getOutBits(dataPath).get(2, 52);
- }
-
+ private final Indenter indenter;
+
+ protected static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
+ private void prln(String msg) { indenter.prln(msg); }
+ private void adjustIndent(int n) { indenter.adjustIndent(n); }
+
+ /** NanosimModel.setNodeState() requires special path names.
+ * Each instance name in the path must begin with the character 'x'.
+ * Return a path with the added X's. */
+ private String prefixInstNamesInPathWithX(String path) {
+ if (model==null) throw new RuntimeException();
+ if (!(model instanceof NanosimModel)) return path;
+ StringBuffer sb = new StringBuffer();
+ sb.append('x');
+ for (int i=0; i<path.length(); i++) {
+ char c = path.charAt(i);
+ sb.append(c);
+ if (c=='.') sb.append('x');
+ }
+ return sb.toString();
+ }
+
private void shiftControl(boolean readEnable, boolean writeEnable) {
- cc.shift(controlChain, readEnable, writeEnable);
+ //System.out.println("start shiftcontrol");
+ cc.shift(controlChain, readEnable, writeEnable);
+ //System.out.println(" end shiftcontrol");
}
private void shiftData(boolean readEnable, boolean writeEnable) {
- cc.shift(dataChain, readEnable, writeEnable);
- if (writeEnable) {
- System.out.println("shiftData(): clockHack="+(clockHack)+
- ", (model instanceof NanosimModel)="+(model instanceof NanosimModel));
- if (clockHack && model instanceof NanosimModel) {
- NanosimModel nanoModel = (NanosimModel) model;
- nanoModel.setNodeState(captureClock, 1);
- nanoModel.waitNS(1);
- nanoModel.setNodeState(captureClock, 0);
- }
- }
+ //System.out.println("start shiftdata");
+ cc.shift(dataChain, readEnable, writeEnable);
+ if (writeEnable) {
+ if (clockHack && model instanceof NanosimModel) {
+ NanosimModel nanoModel = (NanosimModel) model;
+ nanoModel.setNodeState(captureClock, 1);
+ nanoModel.waitNS(1);
+ nanoModel.setNodeState(captureClock, 0);
+ } else if (clockHack && model instanceof VerilogModel) {
+ VerilogModel nanoModel = (VerilogModel) model;
+ nanoModel.setNodeState(captureClock, 1);
+ nanoModel.waitNS(1);
+ nanoModel.setNodeState(captureClock, 0);
+ }
+ }
+ //System.out.println(" end shiftdata");
}
private void shiftReport(boolean readEnable, boolean writeEnable) {
- cc.shift(reportChain, readEnable, writeEnable);
+ //System.out.println("start shiftreport");
+ cc.shift(reportChain, readEnable, writeEnable);
+ //System.out.println(" end shiftreport");
}
private StateWireState boolToState(boolean b) {
- return b ? StateWireState.FULL : StateWireState.EMPTY;
+ return b ? StateWireState.FULL : StateWireState.EMPTY;
}
// The first 5 bits of the control chain control the fill and drain stages
private void setFillDrainControl(BitVector fdCtl) {
- fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
- BitVector val = cc.getInBits(controlPath);
- for (int i=0; i<fdCtl.getNumBits(); i++) {
- val.set(i, fdCtl.get(i));
- }
- cc.setInBits(controlPath, val);
- shiftControl(false, true);
+ fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
+ BitVector val = cc.getInBits(controlPath);
+ for (int i=0; i<fdCtl.getNumBits(); i++) {
+ val.set(i, fdCtl.get(i));
+ }
+ cc.setInBits(controlPath, val);
+ shiftControl(false, true);
}
// The last bit of the control chain controls the general purpose
// output
public void setGeneralPurposeOutput(Boolean b) {
- BitVector val = cc.getInBits(controlPath);
- val.set(GENERAL_PURPOSE_STROBE_NDX,b);
- shiftControl(false, true);
+ BitVector val = cc.getInBits(controlPath);
+ val.set(GENERAL_PURPOSE_STROBE_NDX,b);
+ shiftControl(false, true);
}
//-------------------------- public methods ----------------------------
-
- /** Allow subclasses to override the formating of the data. For example,
- * the Instruction stopper only uses the 37 bits of data so it only
- * wants to print the 37 instruction bits */
- public String formatDataTokAddr(BitVector dta) {
- return MarinaUtils.formatDataTokAddr(dta);
- }
/** Put stopper in RUN state */
public void run() {
- setFillDrainControl(MarinaUtils.RingIfc.RUN.bits());
+ setFillDrainControl(CommandCodes.RUN.bits());
}
/** Put stopper in IDLE state */
public void idle() {
- setFillDrainControl(MarinaUtils.RingIfc.IDLE.bits());
+ setFillDrainControl(CommandCodes.IDLE.bits());
}
/** Put stopper in FILL state */
public void fill() {
- setFillDrainControl(MarinaUtils.RingIfc.FILL.bits());
+ setFillDrainControl(CommandCodes.FILL.bits());
}
/** Put stopper in BLOCK state */
public void block() {
- setFillDrainControl(MarinaUtils.RingIfc.BLOCK.bits());
+ setFillDrainControl(CommandCodes.BLOCK.bits());
}
/** Put stopper in STOP state */
public void stop() {
- setFillDrainControl(MarinaUtils.RingIfc.STOP.bits());
+ setFillDrainControl(CommandCodes.STOP.bits());
}
/** Put stopper in CLEAR state */
public void clear() {
- setFillDrainControl(MarinaUtils.RingIfc.CLEAR.bits());
+ setFillDrainControl(CommandCodes.CLEAR.bits());
}
/** Put stopper in SOURCE state */
public void source() {
- setFillDrainControl(MarinaUtils.RingIfc.SOURCE.bits());
+ setFillDrainControl(CommandCodes.SOURCE.bits());
}
/** Put stopper in STOPSOURCE state */
public void stopSource() {
- setFillDrainControl(MarinaUtils.RingIfc.STOPSOURCE.bits());
+ setFillDrainControl(CommandCodes.STOPSOURCE.bits());
}
/** Put stopper in SINK state */
public void sink() {
- setFillDrainControl(MarinaUtils.RingIfc.SINK.bits());
+ setFillDrainControl(CommandCodes.SINK.bits());
}
/** Put stopper in STOPSINK state */
public void stopSink() {
- setFillDrainControl(MarinaUtils.RingIfc.STOPSINK.bits());
+ setFillDrainControl(CommandCodes.STOPSINK.bits());
}
+
/** Stop a running stopper in order to add items. Ensure that we don't
* lose the item in the fill stage.
* Exit state: block */
public void stopToFill() {
- stop(); // go = 0
- idle(); // block = 1
- block(); // go = 1
-// idle(); // go = 0
+ stop(); // go = 0
+ idle(); // block = 1
+ block(); // go = 1
+ // idle(); // go = 0
}
+
/** get value of the state wire preceding the fill stage */
public StateWireState getPrevStateWire() {
- shiftReport(true, false);
- BitVector b = cc.getOutBits(reportPath);
- int n = b.getNumBits();
- fatal(n!=4, "Bad number of Stopper report bits: "+n);
- return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
+ shiftReport(true, false);
+ BitVector b = cc.getOutBits(reportPath);
+ int n = b.getNumBits();
+ fatal(n!=4, "Bad number of Stopper report bits: "+n);
+ return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
}
+
/** get the value of drain stage fill wire.
* The fill wire will be interesting if we doubt that the
* scan chain works. */
public boolean getFillStrobe() {
- shiftReport(true, false);
- return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
+ shiftReport(true, false);
+ return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
}
+
/** get value of state wire between the fill and drain stages */
public StateWireState getFillStateWire() {
- shiftReport(true, false);
- return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
+ shiftReport(true, false);
+ return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
}
+
/** get value of drain stage stopped wire */
public boolean getStopped() {
- shiftReport(true, false);
+ shiftReport(true, false);
return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
}
+
public String getReportString() {
- StringBuffer sb = new StringBuffer();
- sb.append("Stopper's prev state: ");
- sb.append(getPrevStateWire()+"\n");
- sb.append("Stopper's fill stage: ");
- sb.append(getFillStateWire()+"\n");
- sb.append("Stopper's stopped: ");
- sb.append(getStopped()+"\n");
- return sb.toString();
+ StringBuffer sb = new StringBuffer();
+ sb.append("Stopper's prev state: ");
+ sb.append(getPrevStateWire()+"\n");
+ sb.append("Stopper's fill stage: ");
+ sb.append(getFillStateWire()+"\n");
+ sb.append("Stopper's stopped: ");
+ sb.append(getStopped()+"\n");
+ return sb.toString();
}
+
/** construct a ProperStopper */
- public ProperStopper(String propInst,
- String controlChain, String dataChain,
- String reportChain,
- ChainControls cc, ChipModel model,
- boolean clockHack,
- Indenter indenter) {
- this.name = propInst;
- this.controlChain = controlChain;
- this.controlPath = controlChain+'.'+propInst;
- this.dataChain = dataChain;
- this.dataPath = dataChain+'.'+propInst;
- this.reportChain = reportChain;
- this.reportPath = reportChain+'.'+propInst;
- this.captureClock =
- prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
- +'.'+captureClockName;
- this.cc = cc;
- this.model = model;
- this.clockHack = clockHack;
- this.indenter = indenter;
+ public ProperStopper(String name,
+ String propInst,
+ String controlChain, String dataChain,
+ String reportChain,
+ ChainControls cc, ChipModel model,
+ boolean clockHack,
+ Indenter indenter) {
+ this.name = name;
+ this.controlChain = controlChain;
+ this.controlPath = controlChain+'.'+propInst;
+ this.dataChain = dataChain;
+ this.dataPath = dataChain+'.'+propInst;
+ this.reportChain = reportChain;
+ this.reportPath = reportChain+'.'+propInst;
+ this.model = model;
+ this.captureClock =
+ prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
+ +'.'+captureClockName;
+ this.cc = cc;
+ this.clockHack = clockHack;
+ this.indenter = indenter;
}
+
/** Reset ProperStopper after the JTAG TRST has been pulsed */
public void resetAfterMasterClear() {
- BitVector we = new BitVector(2, "write enable");
- BitVector data = new BitVector(37, "data");
- BitVector tag = new BitVector(1, "tag");
- BitVector addr = new BitVector(14, "addr");
- we.setFromLong(0);
- data.setFromLong(0);
- tag.setFromLong(0);
- addr.setFromLong(0);
- BitVector wdta = we.cat(data).cat(tag).cat(addr);
-
+ BitVector we = new BitVector(2, "write enable");
+ BitVector packet = new BitVector(MarinaPacket.PACKET_WIDTH, "packet");
+ we.setFromLong(0);
+ packet.setFromLong(0);
+ BitVector wdta = we.cat(packet);
cc.setInBits(dataPath, wdta);
}
* Fill stage must be empty.
* You must stop stopper before calling fill.
* exit state: block */
- public void fill(BitVector dta) {
- if (traceFill) prln("Begin fill. stopper="+name);
- adjustIndent(2);
-
- int n = dta.getNumBits();
- fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
-
- // make sure fill stage is empty
- StateWireState myState = getFillStateWire();
- fatal(myState!=StateWireState.EMPTY,
- "fill: fill stage already full");
-
- if (traceFill) prln("writing data: "+formatDataTokAddr(dta));
-
- idle(); // block = 1, go = 0
-
- BitVector wrEn = new BitVector(2, "write enable");
- wrEn.setFromLong(3);
- BitVector bv1 = wrEn.cat(dta);
- cc.setInBits(dataPath, bv1);
- prln("first shift");
- shiftData(false, true);
-
- BitVector bv0 = new BitVector(bv1.getNumBits(), "");
- for(int i=0; i<bv0.getNumBits(); i++) bv0.set(i, false);
- cc.setInBits(dataPath, bv0);
- prln("second shift");
- shiftData(false, false);
-
- prln("third shift");
- shiftData(true, false);
- BitVector bv2 = cc.getOutBits(dataPath);
- System.out.println("bv1 = " + bv1);
- System.out.println("bv2 = " + bv2);
-
- fill(); // fill = 1
- idle(); // fill = 0
- block(); // go = 1
-// idle();
-
- model.waitNS(5);
-
- // debugging
- if (traceFill) prln(getReportString());
-
- // if data chain is shifted in the future, don't write!
- wrEn.setFromLong(0);
- cc.setInBits(dataPath, wrEn.cat(dta));
-
- adjustIndent(-2);
- if (traceFill) prln("End fill");
+ private void fill_(BitVector dta) {
+ adjustIndent(2);
+
+ int n = dta.getNumBits();
+ fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
+
+ // make sure fill stage is empty
+ StateWireState myState = getFillStateWire();
+ fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
+
+ idle(); // block = 1, go = 0
+
+ BitVector wrEn = new BitVector(2, "write enable");
+ wrEn.setFromLong(3);
+ cc.setInBits(dataPath, wrEn.cat(dta));
+ shiftData(false, true);
+
+ fill(); // fill = 1
+ idle(); // fill = 0
+ block(); // go = 1
+ // idle();
+
+ model.waitNS(5);
+
+ // debugging
+ if (traceFill) prln(getReportString());
+
+ // if data chain is shifted in the future, don't write!
+ wrEn.setFromLong(0);
+ cc.setInBits(dataPath, wrEn.cat(dta));
+
+ adjustIndent(-2);
+ if (traceFill) prln("End fill");
}
+
+ public void fill(BitVector dat) {
+ if (traceFill) prln("Begin fill. stopper="+name);
+ if (traceFill) prln("writing data: "+new MarinaPacket(dat));
+ fill_(dat);
+ }
+
+ public void fill(MarinaPacket mp) {
+ if (traceFill) prln("Begin fill. stopper="+name);
+ if (traceFill) prln("writing data: "+mp);
+ fill_(mp.toSingleBitVector());
+ }
+
/** Insert items from a list, one by one.
* You must stop stopper before calling fillMany()
* exit state: block */
public void fillMany(List<BitVector> data) {
- prln("Begin fillMany. stopper="+name+" numWords="+data.size());
- adjustIndent(2);
- int cnt = 0;
- for (BitVector bv : data) {
- if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
- fill(bv);
- }
- adjustIndent(-2);
- prln("end fillMany");
+ prln("Begin fillMany. stopper="+name+" numWords="+data.size());
+ adjustIndent(2);
+ int cnt = 0;
+ for (BitVector bv : data) {
+ if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
+ fill(bv);
+ }
+ adjustIndent(-2);
+ prln("end fillMany");
}
+
/** Remove one item from fill stage. Return that item.
* An item must be available.
* drain() will stop cleanly.
* exit state: stop */
public BitVector drain() {
- stop(); // all zero, block = 0, go = 0
-
- // make sure an item is available
- StateWireState myState=getFillStateWire();
- fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
+ stop(); // all zero, block = 0, go = 0
+
+ // make sure an item is available
+ StateWireState myState=getFillStateWire();
+ fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
- return drainNoCheck();
+ return drainNoCheck();
}
+
/** Remove one item from fill stage. Return that item.
* Assume that an item is available.
* entry state: stop
* exit state: stop */
private BitVector drainNoCheck() {
- shiftData(true, false);
- BitVector ans = getDatTokAdr();
+ shiftData(true, false);
- idle(); // block = 1
- clear(); // clear = 1
- idle(); // clear = 0
- stop(); // block = 0
+ // strip the two write enable bits
+ BitVector ans = cc.getOutBits(dataPath).get(2, 52);
- if (traceDrain) prln("drain stopper="+name+" data="+formatDataTokAddr(ans));
- return ans;
+ idle(); // block = 1
+ clear(); // clear = 1
+ idle(); // clear = 0
+ stop(); // block = 0
+
+ if (traceDrain) prln("drain stopper="+name+" data="+new MarinaPacket(ans));
+ return ans;
}
+
/** Remove as many items as possible from the fill stage.
* drainStopperMany() will stop cleanly.
* exit state: stop */
public List<BitVector> drainMany() {
- return drainMany(Integer.MAX_VALUE);
+ return drainMany(Integer.MAX_VALUE);
}
/** Remove up to maxNbItems items from the fill stage.
* drainStopperMany() will stop cleanly.
* exit state: stop */
public List<BitVector> drainMany(int maxNbItems) {
- prln("begin drainMany. stopper="+name);
- adjustIndent(2);
-
- stop();
-
- List<BitVector> ans = new ArrayList<BitVector>();
-
- int cnt = 0;
- while (true) {
- StateWireState myState=getFillStateWire();
-
- // debugging
- if (traceDrain) prln(getReportString());
-
- if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
-
- if (traceDrain) prln("drainMany: reading word number: "+cnt++);
-
- BitVector d = drainNoCheck();
-
- ans.add(d);
- }
-
- adjustIndent(-2);
- prln("end drainMany, got "+ans.size()+" items");
-
- return ans;
+ adjustIndent(2);
+
+ stop();
+
+ List<BitVector> ans = new ArrayList<BitVector>();
+
+ int cnt = 0;
+ while (true) {
+ StateWireState myState=getFillStateWire();
+
+ // debugging
+ if (traceDrain) prln(getReportString());
+
+ if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
+
+ cnt++;
+ indenter.pr(" drain"+(maxNbItems==0?"":"Many")+
+ ": reading word"+(maxNbItems==0?":":" number "+cnt+
+ "/"+(maxNbItems==Integer.MAX_VALUE
+ ?"unlimited":("at-most-"+maxNbItems))+": "));
+
+ BitVector d = drainNoCheck();
+ if (maxNbItems>1)
+ prln(" got "+new MarinaPacket(d));
+
+ ans.add(d);
+ }
+
+ prln("end drainMany, got "+ans.size()+" items");
+ adjustIndent(-2);
+
+ return ans;
}
+ /**
+ * (Note by Bill and Adam: Ivan has struck again!)
+ * As of 05 March 2009 the new bits are:
+ * Block Extra Fill Go Clear Silent
+ * => Note: "Extra" gets fed to the mux in the counter
+ * that selects the frequency output that goes off-chip
+ *
+ * Caution: Ivan changes the order of the ProperStopper control bits
+ * from chip to chip. Here is the current order for Marina
+ * as of 14 Aug 2008:
+ * Block, Fill, Go, Silent, Clear
+ *
+ * The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
+ */
+ private static enum CommandCodes {
+ RUN ("000100"),
+ IDLE ("100000"),
+ FILL ("101000"),
+ BLOCK ("100100"),
+ STOP ("000000"),
+ CLEAR ("100010"),
+ SOURCE ("001100"),
+ STOPSOURCE ("001000"),
+ SINK ("000101"),
+ STOPSINK ("000001");
+ private BitVector scanBits;
+ CommandCodes(String bits) {
+ scanBits = new BitVector(bits,"CommandCodes");
+ }
+ public BitVector bits() {return scanBits;}
+ }
}