+++ /dev/null
-package com.sun.vlsi.chips.marina.test;
-import com.sun.electric.tool.simulation.test.*;
-import java.util.ArrayList;
-import java.util.List;
-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";
- 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 = "sx[4]";
-
- /*
- private boolean traceFill = true;
- private boolean traceDrain = true;
- */
- private boolean traceFill = false;
- private boolean traceDrain = false;
-
- private final String
- controlChain = Marina.CONTROL_CHAIN,
- controlPath,
- dataChain = Marina.DATA_CHAIN,
- dataPath,
- reportChain = Marina.REPORT_CHAIN,
- reportPath;
- private final String captureClock;
- private final ChainControls cc;
- private final ChipModel model;
- private final Indenter indenter;
-
- private final String pathToCounter;
-
- 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) {
- //System.out.println("start shiftcontrol");
- cc.shift(controlChain, readEnable, writeEnable);
- //System.out.println(" end shiftcontrol");
- }
- private void shiftData(boolean readEnable, boolean writeEnable) {
- //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) {
- //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;
- }
-
- private CommandCodes fdcstate = null;
-
- public void setCounterEnable(boolean enable) {
- this.extra = enable;
- setFillDrainControl(fdcstate);
- }
-
- public void setCounterValue(int val) {
- SubchainNode chainNode = (SubchainNode) cc.getChainControlFromPath(dataChain).findNode(pathToCounter);
- int bitIndex = chainNode.getBitIndex();
- ChainNode root = chainNode.getParentChain();
- for(int i=0; i<31; i++)
- root.getInBits().set(bitIndex+i, ((1<<i) & val)!=0);
- shiftData(false, true);
- }
-
- // DOES NOT SHIFT THE CHAIN!!!!
- public int getCounterValue() {
- SubchainNode chainNode = (SubchainNode) cc.getChainControlFromPath(dataChain).findNode(pathToCounter);
- int bitIndex = chainNode.getBitIndex();
- ChainNode root = chainNode.getParentChain();
- return (int)root.getOutBits().get(bitIndex, 30).bitReverse().toLong();
- }
-
- // The first 5 bits of the control chain control the fill and drain stages
- private void setFillDrainControl(CommandCodes ccc) {
- BitVector fdCtl = ccc.bits(extra);
- fdcstate = ccc;
- 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);
- }
-
- //-------------------------- public methods ----------------------------
-
- /** Put stopper in RUN state */
- public void run() {
- setFillDrainControl(CommandCodes.RUN);
- }
- /** Put stopper in IDLE state */
- public void idle() {
- setFillDrainControl(CommandCodes.IDLE);
- }
- /** Put stopper in FILL state */
- public void fill() {
- setFillDrainControl(CommandCodes.FILL);
- }
- /** Put stopper in BLOCK state */
- public void block() {
- setFillDrainControl(CommandCodes.BLOCK);
- }
- /** Put stopper in STOP state */
- public void stop() {
- setFillDrainControl(CommandCodes.STOP);
- }
- /** Put stopper in CLEAR state */
- public void clear() {
- setFillDrainControl(CommandCodes.CLEAR);
- }
- /** Put stopper in SOURCE state */
- public void source() {
- setFillDrainControl(CommandCodes.SOURCE);
- }
- /** Put stopper in STOPSOURCE state */
- public void stopSource() {
- setFillDrainControl(CommandCodes.STOPSOURCE);
- }
- /** Put stopper in SINK state */
- public void sink() {
- setFillDrainControl(CommandCodes.SINK);
- }
- /** Put stopper in STOPSINK state */
- public void stopSink() {
- setFillDrainControl(CommandCodes.STOPSINK);
- }
-
- public boolean extra = false;
-
- /** 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
- }
-
- /** 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));
- }
-
- /** 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);
- }
-
- /** 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));
- }
-
- /** get value of drain stage stopped wire */
- public boolean getStopped() {
- 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();
- }
-
- /** construct a ProperStopper */
- public ProperStopper(String name,
- String propInst,
- ChainControls cc, ChipModel model,
- boolean clockHack,
- Indenter indenter,
- String pathToCounter) {
- this.name = name;
- this.controlPath = controlChain+'.'+propInst;
- this.dataPath = dataChain+'.'+propInst;
- this.reportPath = reportChain+'.'+propInst;
- this.model = model;
- this.captureClock =
- prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
- +'.'+captureClockName;
- this.cc = cc;
- this.clockHack = clockHack;
- this.indenter = indenter;
- this.pathToCounter = dataChain+'.'+pathToCounter;
- }
-
- /** Reset ProperStopper after the JTAG TRST has been pulsed */
- public void resetAfterMasterClear() {
- 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);
- }
-
- /** Insert one item into the fill stage.
- * Fill stage must be empty.
- * You must stop stopper before calling fill.
- * exit state: block */
- 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");
- }
-
- /** 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");
-
- 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);
-
- // strip the two write enable bits
- BitVector ans = cc.getOutBits(dataPath).get(2, 52);
-
- 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);
- }
-
- /** Remove up to maxNbItems items from the fill stage.
- * drainStopperMany() will stop cleanly.
- * exit state: stop */
- public List<BitVector> drainMany(int maxNbItems) {
- 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;
- }
-
- // proper stopper ring occupancy bits
- //southFif@1.upDown8w@1.weakStag@18.scanEx1@0 REPORT chain
- //18, 22, 19, 23, 20, 24, 21, 25
- //northFif@1.upDown8w@2...
- // south fifo tap stage:
- // southFif@1.tapPropS@1.tapStage@2.scanEx1@0 (also REPORT chain)
-
- /**
- * (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","010100"),
- IDLE ("100000","110000"),
- FILL ("101000","111000"),
- BLOCK ("100100","110100"),
- STOP ("000000","010000"),
- CLEAR ("100010","110010"),
- SOURCE ("001100","011100"),
- STOPSOURCE ("001000","011000"),
- SINK ("000101","010101"),
- STOPSINK ("000001","010001");
- private BitVector scanBits0;
- private BitVector scanBits1;
- CommandCodes(String bits0,String bits1) {
- scanBits0 = new BitVector(bits0,"CommandCodes");
- scanBits1 = new BitVector(bits1,"CommandCodes");
- }
- public BitVector bits(boolean extra) {
- return extra ? scanBits1 : scanBits0;
- }
- }
-
-}