1 package com.sun.vlsi.chips.marina.test;
2 import java.util.ArrayList;
5 import com.sun.async.test.BitVector;
6 import com.sun.async.test.ChainControl;
7 import com.sun.async.test.ChipModel;
8 import com.sun.async.test.Infrastructure;
9 import com.sun.async.test.NanosimModel;
10 import com.sun.async.test.VerilogModel;
11 import com.sun.vlsi.chips.marina.test.MarinaUtils.StateWireState;
13 public class ProperStopper {
14 // position of strobes in the control chain
15 private static final int BLOCK_STROBE_NDX = 0;
16 private static final int FILL_STROBE_NDX = 1;
17 private static final int GO_STROBE_NDX = 2;
18 private static final int SILENT_STROBE_NDX = 3;
19 private static final int CLEAR_STROBE_NDX = 4;
20 private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
22 // position of inputs in report chain
23 private static final int PREV_STATE_IN_NDX = 0;
24 private static final int FILL_STROBE_IN_NDX = 1;
25 private static final int FILL_STATE_IN_NDX = 2;
26 private static final int STOPPED_IN_NDX = 3;
28 private final String name;
29 //private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
30 private final String captureClockRelPath = "fillStag@1";
31 // test library direct write mode doesn't understand per register write
32 // enables. We get simulation to work by toggling write clock.
33 private final boolean clockHack;
34 private final String captureClockName = "sx[4]";
37 private boolean traceFill = true;
38 private boolean traceDrain = true;
40 private boolean traceFill = false;
41 private boolean traceDrain = false;
43 private final String controlChain, controlPath,
45 reportChain, reportPath;
46 private final String captureClock;
47 private final ChainControls cc;
48 private final ChipModel model;
49 private final Indenter indenter;
51 protected static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
52 private void prln(String msg) { indenter.prln(msg); }
53 private void adjustIndent(int n) { indenter.adjustIndent(n); }
55 /** NanosimModel.setNodeState() requires special path names.
56 * Each instance name in the path must begin with the character 'x'.
57 * Return a path with the added X's. */
58 private String prefixInstNamesInPathWithX(String path) {
59 if (model==null) throw new RuntimeException();
60 if (!(model instanceof NanosimModel)) return path;
61 StringBuffer sb = new StringBuffer();
63 for (int i=0; i<path.length(); i++) {
64 char c = path.charAt(i);
66 if (c=='.') sb.append('x');
71 private void shiftControl(boolean readEnable, boolean writeEnable) {
72 //System.out.println("start shiftcontrol");
73 cc.shift(controlChain, readEnable, writeEnable);
74 //System.out.println(" end shiftcontrol");
76 private void shiftData(boolean readEnable, boolean writeEnable) {
77 //System.out.println("start shiftdata");
78 cc.shift(dataChain, readEnable, writeEnable);
80 if (clockHack && model instanceof NanosimModel) {
81 NanosimModel nanoModel = (NanosimModel) model;
82 nanoModel.setNodeState(captureClock, 1);
84 nanoModel.setNodeState(captureClock, 0);
85 } else if (clockHack && model instanceof VerilogModel) {
86 VerilogModel nanoModel = (VerilogModel) model;
87 nanoModel.setNodeState(captureClock, 1);
89 nanoModel.setNodeState(captureClock, 0);
92 //System.out.println(" end shiftdata");
94 private void shiftReport(boolean readEnable, boolean writeEnable) {
95 //System.out.println("start shiftreport");
96 cc.shift(reportChain, readEnable, writeEnable);
97 //System.out.println(" end shiftreport");
100 private StateWireState boolToState(boolean b) {
101 return b ? StateWireState.FULL : StateWireState.EMPTY;
103 // The first 5 bits of the control chain control the fill and drain stages
104 private void setFillDrainControl(BitVector fdCtl) {
105 fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
106 BitVector val = cc.getInBits(controlPath);
107 for (int i=0; i<fdCtl.getNumBits(); i++) {
108 val.set(i, fdCtl.get(i));
110 cc.setInBits(controlPath, val);
111 shiftControl(false, true);
113 // The last bit of the control chain controls the general purpose
115 public void setGeneralPurposeOutput(Boolean b) {
116 BitVector val = cc.getInBits(controlPath);
117 val.set(GENERAL_PURPOSE_STROBE_NDX,b);
118 shiftControl(false, true);
121 //-------------------------- public methods ----------------------------
123 /** Put stopper in RUN state */
125 setFillDrainControl(CommandCodes.RUN.bits());
127 /** Put stopper in IDLE state */
129 setFillDrainControl(CommandCodes.IDLE.bits());
131 /** Put stopper in FILL state */
133 setFillDrainControl(CommandCodes.FILL.bits());
135 /** Put stopper in BLOCK state */
136 public void block() {
137 setFillDrainControl(CommandCodes.BLOCK.bits());
139 /** Put stopper in STOP state */
141 setFillDrainControl(CommandCodes.STOP.bits());
143 /** Put stopper in CLEAR state */
144 public void clear() {
145 setFillDrainControl(CommandCodes.CLEAR.bits());
147 /** Put stopper in SOURCE state */
148 public void source() {
149 setFillDrainControl(CommandCodes.SOURCE.bits());
151 /** Put stopper in STOPSOURCE state */
152 public void stopSource() {
153 setFillDrainControl(CommandCodes.STOPSOURCE.bits());
155 /** Put stopper in SINK state */
157 setFillDrainControl(CommandCodes.SINK.bits());
159 /** Put stopper in STOPSINK state */
160 public void stopSink() {
161 setFillDrainControl(CommandCodes.STOPSINK.bits());
164 /** Stop a running stopper in order to add items. Ensure that we don't
165 * lose the item in the fill stage.
166 * Exit state: block */
167 public void stopToFill() {
174 /** get value of the state wire preceding the fill stage */
175 public StateWireState getPrevStateWire() {
176 shiftReport(true, false);
177 BitVector b = cc.getOutBits(reportPath);
178 int n = b.getNumBits();
179 fatal(n!=4, "Bad number of Stopper report bits: "+n);
180 return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
183 /** get the value of drain stage fill wire.
184 * The fill wire will be interesting if we doubt that the
185 * scan chain works. */
186 public boolean getFillStrobe() {
187 shiftReport(true, false);
188 return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
191 /** get value of state wire between the fill and drain stages */
192 public StateWireState getFillStateWire() {
193 shiftReport(true, false);
194 return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
197 /** get value of drain stage stopped wire */
198 public boolean getStopped() {
199 shiftReport(true, false);
200 return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
203 public String getReportString() {
204 StringBuffer sb = new StringBuffer();
205 sb.append("Stopper's prev state: ");
206 sb.append(getPrevStateWire()+"\n");
207 sb.append("Stopper's fill stage: ");
208 sb.append(getFillStateWire()+"\n");
209 sb.append("Stopper's stopped: ");
210 sb.append(getStopped()+"\n");
211 return sb.toString();
214 /** construct a ProperStopper */
215 public ProperStopper(String name,
217 String controlChain, String dataChain,
219 ChainControls cc, ChipModel model,
223 this.controlChain = controlChain;
224 this.controlPath = controlChain+'.'+propInst;
225 this.dataChain = dataChain;
226 this.dataPath = dataChain+'.'+propInst;
227 this.reportChain = reportChain;
228 this.reportPath = reportChain+'.'+propInst;
231 prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
232 +'.'+captureClockName;
234 this.clockHack = clockHack;
235 this.indenter = indenter;
238 /** Reset ProperStopper after the JTAG TRST has been pulsed */
239 public void resetAfterMasterClear() {
240 BitVector we = new BitVector(2, "write enable");
241 BitVector packet = new BitVector(MarinaPacket.PACKET_WIDTH, "packet");
243 packet.setFromLong(0);
244 BitVector wdta = we.cat(packet);
245 cc.setInBits(dataPath, wdta);
248 /** Insert one item into the fill stage.
249 * Fill stage must be empty.
250 * You must stop stopper before calling fill.
251 * exit state: block */
252 private void fill_(BitVector dta) {
255 int n = dta.getNumBits();
256 fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
258 // make sure fill stage is empty
259 StateWireState myState = getFillStateWire();
260 fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
262 idle(); // block = 1, go = 0
264 BitVector wrEn = new BitVector(2, "write enable");
266 cc.setInBits(dataPath, wrEn.cat(dta));
267 shiftData(false, true);
277 if (traceFill) prln(getReportString());
279 // if data chain is shifted in the future, don't write!
281 cc.setInBits(dataPath, wrEn.cat(dta));
284 if (traceFill) prln("End fill");
287 public void fill(BitVector dat) {
288 if (traceFill) prln("Begin fill. stopper="+name);
289 if (traceFill) prln("writing data: "+new MarinaPacket(dat));
293 public void fill(MarinaPacket mp) {
294 if (traceFill) prln("Begin fill. stopper="+name);
295 if (traceFill) prln("writing data: "+mp);
296 fill_(mp.toSingleBitVector());
299 /** Insert items from a list, one by one.
300 * You must stop stopper before calling fillMany()
301 * exit state: block */
302 public void fillMany(List<BitVector> data) {
303 prln("Begin fillMany. stopper="+name+" numWords="+data.size());
306 for (BitVector bv : data) {
307 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
311 prln("end fillMany");
314 /** Remove one item from fill stage. Return that item.
315 * An item must be available.
316 * drain() will stop cleanly.
317 * exit state: stop */
318 public BitVector drain() {
319 stop(); // all zero, block = 0, go = 0
321 // make sure an item is available
322 StateWireState myState=getFillStateWire();
323 fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
325 return drainNoCheck();
328 /** Remove one item from fill stage. Return that item.
329 * Assume that an item is available.
331 * exit state: stop */
332 private BitVector drainNoCheck() {
333 shiftData(true, false);
335 // strip the two write enable bits
336 BitVector ans = cc.getOutBits(dataPath).get(2, 52);
339 clear(); // clear = 1
343 if (traceDrain) prln("drain stopper="+name+" data="+new MarinaPacket(ans));
347 /** Remove as many items as possible from the fill stage.
348 * drainStopperMany() will stop cleanly.
349 * exit state: stop */
350 public List<BitVector> drainMany() {
351 return drainMany(Integer.MAX_VALUE);
354 /** Remove up to maxNbItems items from the fill stage.
355 * drainStopperMany() will stop cleanly.
356 * exit state: stop */
357 public List<BitVector> drainMany(int maxNbItems) {
362 List<BitVector> ans = new ArrayList<BitVector>();
366 StateWireState myState=getFillStateWire();
369 if (traceDrain) prln(getReportString());
371 if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
374 indenter.pr(" drain"+(maxNbItems==0?"":"Many")+
375 ": reading word"+(maxNbItems==0?":":" number "+cnt+
376 "/"+(maxNbItems==Integer.MAX_VALUE
377 ?"unlimited":("at-most-"+maxNbItems))+": "));
379 BitVector d = drainNoCheck();
381 prln(" got "+new MarinaPacket(d));
386 prln("end drainMany, got "+ans.size()+" items");
394 * (Note by Bill and Adam: Ivan has struck again!)
395 * As of 05 March 2009 the new bits are:
396 * Block Extra Fill Go Clear Silent
397 * => Note: "Extra" gets fed to the mux in the counter
398 * that selects the frequency output that goes off-chip
400 * Caution: Ivan changes the order of the ProperStopper control bits
401 * from chip to chip. Here is the current order for Marina
403 * Block, Fill, Go, Silent, Clear
405 * The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
407 private static enum CommandCodes {
415 STOPSOURCE ("001000"),
418 private BitVector scanBits;
419 CommandCodes(String bits) {
420 scanBits = new BitVector(bits,"CommandCodes");
422 public BitVector bits() {return scanBits;}