1 package com.sun.vlsi.chips.marina.test;
2 import java.util.ArrayList;
5 import com.sun.async.test.*;
6 import com.sun.vlsi.chips.marina.test.MarinaUtils.StateWireState;
8 public class ProperStopper {
9 // position of strobes in the control chain
10 private static final int BLOCK_STROBE_NDX = 0;
11 private static final int FILL_STROBE_NDX = 1;
12 private static final int GO_STROBE_NDX = 2;
13 private static final int SILENT_STROBE_NDX = 3;
14 private static final int CLEAR_STROBE_NDX = 4;
15 private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
17 // position of inputs in report chain
18 private static final int PREV_STATE_IN_NDX = 0;
19 private static final int FILL_STROBE_IN_NDX = 1;
20 private static final int FILL_STATE_IN_NDX = 2;
21 private static final int STOPPED_IN_NDX = 3;
23 private final String name;
24 //private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
25 private final String captureClockRelPath = "fillStag@1";
26 // test library direct write mode doesn't understand per register write
27 // enables. We get simulation to work by toggling write clock.
28 private final boolean clockHack;
29 private final String captureClockName = "sx[4]";
32 private boolean traceFill = true;
33 private boolean traceDrain = true;
35 private boolean traceFill = false;
36 private boolean traceDrain = false;
38 private final String controlChain, controlPath,
40 reportChain, reportPath;
41 private final String captureClock;
42 private final ChainControls cc;
43 private final ChipModel model;
44 private final Indenter indenter;
46 private final String pathToCounter;
48 protected static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
49 private void prln(String msg) { indenter.prln(msg); }
50 private void adjustIndent(int n) { indenter.adjustIndent(n); }
52 /** NanosimModel.setNodeState() requires special path names.
53 * Each instance name in the path must begin with the character 'x'.
54 * Return a path with the added X's. */
55 private String prefixInstNamesInPathWithX(String path) {
56 if (model==null) throw new RuntimeException();
57 if (!(model instanceof NanosimModel)) return path;
58 StringBuffer sb = new StringBuffer();
60 for (int i=0; i<path.length(); i++) {
61 char c = path.charAt(i);
63 if (c=='.') sb.append('x');
68 private void shiftControl(boolean readEnable, boolean writeEnable) {
69 //System.out.println("start shiftcontrol");
70 cc.shift(controlChain, readEnable, writeEnable);
71 //System.out.println(" end shiftcontrol");
73 private void shiftData(boolean readEnable, boolean writeEnable) {
74 //System.out.println("start shiftdata");
75 cc.shift(dataChain, readEnable, writeEnable);
77 if (clockHack && model instanceof NanosimModel) {
78 NanosimModel nanoModel = (NanosimModel) model;
79 nanoModel.setNodeState(captureClock, 1);
81 nanoModel.setNodeState(captureClock, 0);
82 } else if (clockHack && model instanceof VerilogModel) {
83 VerilogModel nanoModel = (VerilogModel) model;
84 nanoModel.setNodeState(captureClock, 1);
86 nanoModel.setNodeState(captureClock, 0);
89 //System.out.println(" end shiftdata");
91 private void shiftReport(boolean readEnable, boolean writeEnable) {
92 //System.out.println("start shiftreport");
93 cc.shift(reportChain, readEnable, writeEnable);
94 //System.out.println(" end shiftreport");
97 private StateWireState boolToState(boolean b) {
98 return b ? StateWireState.FULL : StateWireState.EMPTY;
101 private CommandCodes fdcstate = null;
103 public void setCounterEnable(boolean enable) {
105 setFillDrainControl(fdcstate);
108 public void setCounterValue(int val) {
109 SubchainNode chainNode = (SubchainNode) cc.getChainControlFromPath(dataChain).findNode(pathToCounter);
110 int bitIndex = chainNode.getBitIndex();
111 ChainNode root = chainNode.getParentChain();
112 for(int i=0; i<31; i++)
113 root.getInBits().set(bitIndex+i, ((1<<i) & val)!=0);
114 shiftData(false, true);
117 // DOES NOT SHIFT THE CHAIN!!!!
118 public int getCounterValue() {
119 SubchainNode chainNode = (SubchainNode) cc.getChainControlFromPath(dataChain).findNode(pathToCounter);
120 int bitIndex = chainNode.getBitIndex();
121 ChainNode root = chainNode.getParentChain();
122 return (int)root.getOutBits().get(bitIndex, 30).bitReverse().toLong();
125 // The first 5 bits of the control chain control the fill and drain stages
126 private void setFillDrainControl(CommandCodes ccc) {
127 BitVector fdCtl = ccc.bits(extra);
129 fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
130 BitVector val = cc.getInBits(controlPath);
131 for (int i=0; i<fdCtl.getNumBits(); i++) {
132 val.set(i, fdCtl.get(i));
134 cc.setInBits(controlPath, val);
135 shiftControl(false, true);
137 // The last bit of the control chain controls the general purpose
139 public void setGeneralPurposeOutput(Boolean b) {
140 BitVector val = cc.getInBits(controlPath);
141 val.set(GENERAL_PURPOSE_STROBE_NDX,b);
142 shiftControl(false, true);
145 //-------------------------- public methods ----------------------------
147 /** Put stopper in RUN state */
149 setFillDrainControl(CommandCodes.RUN);
151 /** Put stopper in IDLE state */
153 setFillDrainControl(CommandCodes.IDLE);
155 /** Put stopper in FILL state */
157 setFillDrainControl(CommandCodes.FILL);
159 /** Put stopper in BLOCK state */
160 public void block() {
161 setFillDrainControl(CommandCodes.BLOCK);
163 /** Put stopper in STOP state */
165 setFillDrainControl(CommandCodes.STOP);
167 /** Put stopper in CLEAR state */
168 public void clear() {
169 setFillDrainControl(CommandCodes.CLEAR);
171 /** Put stopper in SOURCE state */
172 public void source() {
173 setFillDrainControl(CommandCodes.SOURCE);
175 /** Put stopper in STOPSOURCE state */
176 public void stopSource() {
177 setFillDrainControl(CommandCodes.STOPSOURCE);
179 /** Put stopper in SINK state */
181 setFillDrainControl(CommandCodes.SINK);
183 /** Put stopper in STOPSINK state */
184 public void stopSink() {
185 setFillDrainControl(CommandCodes.STOPSINK);
188 public boolean extra = false;
190 /** Stop a running stopper in order to add items. Ensure that we don't
191 * lose the item in the fill stage.
192 * Exit state: block */
193 public void stopToFill() {
200 /** get value of the state wire preceding the fill stage */
201 public StateWireState getPrevStateWire() {
202 shiftReport(true, false);
203 BitVector b = cc.getOutBits(reportPath);
204 int n = b.getNumBits();
205 fatal(n!=4, "Bad number of Stopper report bits: "+n);
206 return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
209 /** get the value of drain stage fill wire.
210 * The fill wire will be interesting if we doubt that the
211 * scan chain works. */
212 public boolean getFillStrobe() {
213 shiftReport(true, false);
214 return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
217 /** get value of state wire between the fill and drain stages */
218 public StateWireState getFillStateWire() {
219 shiftReport(true, false);
220 return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
223 /** get value of drain stage stopped wire */
224 public boolean getStopped() {
225 shiftReport(true, false);
226 return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
229 public String getReportString() {
230 StringBuffer sb = new StringBuffer();
231 sb.append("Stopper's prev state: ");
232 sb.append(getPrevStateWire()+"\n");
233 sb.append("Stopper's fill stage: ");
234 sb.append(getFillStateWire()+"\n");
235 sb.append("Stopper's stopped: ");
236 sb.append(getStopped()+"\n");
237 return sb.toString();
240 /** construct a ProperStopper */
241 public ProperStopper(String name,
243 String controlChain, String dataChain,
245 ChainControls cc, ChipModel model,
248 String pathToCounter) {
250 this.controlChain = controlChain;
251 this.controlPath = controlChain+'.'+propInst;
252 this.dataChain = dataChain;
253 this.dataPath = dataChain+'.'+propInst;
254 this.reportChain = reportChain;
255 this.reportPath = reportChain+'.'+propInst;
258 prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
259 +'.'+captureClockName;
261 this.clockHack = clockHack;
262 this.indenter = indenter;
263 this.pathToCounter = dataChain+'.'+pathToCounter;
266 /** Reset ProperStopper after the JTAG TRST has been pulsed */
267 public void resetAfterMasterClear() {
268 BitVector we = new BitVector(2, "write enable");
269 BitVector packet = new BitVector(MarinaPacket.PACKET_WIDTH, "packet");
271 packet.setFromLong(0);
272 BitVector wdta = we.cat(packet);
273 cc.setInBits(dataPath, wdta);
276 /** Insert one item into the fill stage.
277 * Fill stage must be empty.
278 * You must stop stopper before calling fill.
279 * exit state: block */
280 private void fill_(BitVector dta) {
283 int n = dta.getNumBits();
284 fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
286 // make sure fill stage is empty
287 StateWireState myState = getFillStateWire();
288 fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
290 idle(); // block = 1, go = 0
292 BitVector wrEn = new BitVector(2, "write enable");
294 cc.setInBits(dataPath, wrEn.cat(dta));
295 shiftData(false, true);
305 if (traceFill) prln(getReportString());
307 // if data chain is shifted in the future, don't write!
309 cc.setInBits(dataPath, wrEn.cat(dta));
312 if (traceFill) prln("End fill");
315 public void fill(BitVector dat) {
316 if (traceFill) prln("Begin fill. stopper="+name);
317 if (traceFill) prln("writing data: "+new MarinaPacket(dat));
321 public void fill(MarinaPacket mp) {
322 if (traceFill) prln("Begin fill. stopper="+name);
323 if (traceFill) prln("writing data: "+mp);
324 fill_(mp.toSingleBitVector());
327 /** Insert items from a list, one by one.
328 * You must stop stopper before calling fillMany()
329 * exit state: block */
330 public void fillMany(List<BitVector> data) {
331 prln("Begin fillMany. stopper="+name+" numWords="+data.size());
334 for (BitVector bv : data) {
335 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
339 prln("end fillMany");
342 /** Remove one item from fill stage. Return that item.
343 * An item must be available.
344 * drain() will stop cleanly.
345 * exit state: stop */
346 public BitVector drain() {
347 stop(); // all zero, block = 0, go = 0
349 // make sure an item is available
350 StateWireState myState=getFillStateWire();
351 fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
353 return drainNoCheck();
356 /** Remove one item from fill stage. Return that item.
357 * Assume that an item is available.
359 * exit state: stop */
360 private BitVector drainNoCheck() {
361 shiftData(true, false);
363 // strip the two write enable bits
364 BitVector ans = cc.getOutBits(dataPath).get(2, 52);
367 clear(); // clear = 1
371 if (traceDrain) prln("drain stopper="+name+" data="+new MarinaPacket(ans));
375 /** Remove as many items as possible from the fill stage.
376 * drainStopperMany() will stop cleanly.
377 * exit state: stop */
378 public List<BitVector> drainMany() {
379 return drainMany(Integer.MAX_VALUE);
382 /** Remove up to maxNbItems items from the fill stage.
383 * drainStopperMany() will stop cleanly.
384 * exit state: stop */
385 public List<BitVector> drainMany(int maxNbItems) {
390 List<BitVector> ans = new ArrayList<BitVector>();
394 StateWireState myState=getFillStateWire();
397 if (traceDrain) prln(getReportString());
399 if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
402 indenter.pr(" drain"+(maxNbItems==0?"":"Many")+
403 ": reading word"+(maxNbItems==0?":":" number "+cnt+
404 "/"+(maxNbItems==Integer.MAX_VALUE
405 ?"unlimited":("at-most-"+maxNbItems))+": "));
407 BitVector d = drainNoCheck();
409 prln(" got "+new MarinaPacket(d));
414 prln("end drainMany, got "+ans.size()+" items");
420 // proper stopper ring occupancy bits
421 //southFif@1.upDown8w@1.weakStag@18.scanEx1@0 REPORT chain
422 //18, 22, 19, 23, 20, 24, 21, 25
423 //northFif@1.upDown8w@2...
424 // south fifo tap stage:
425 // southFif@1.tapPropS@1.tapStage@2.scanEx1@0 (also REPORT chain)
428 * (Note by Bill and Adam: Ivan has struck again!)
429 * As of 05 March 2009 the new bits are:
430 * Block Extra Fill Go Clear Silent
431 * => Note: "Extra" gets fed to the mux in the counter
432 * that selects the frequency output that goes off-chip
434 * Caution: Ivan changes the order of the ProperStopper control bits
435 * from chip to chip. Here is the current order for Marina
437 * Block, Fill, Go, Silent, Clear
439 * The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
441 private static enum CommandCodes {
442 RUN ("000100","010100"),
443 IDLE ("100000","110000"),
444 FILL ("101000","111000"),
445 BLOCK ("100100","110100"),
446 STOP ("000000","010000"),
447 CLEAR ("100010","110010"),
448 SOURCE ("001100","011100"),
449 STOPSOURCE ("001000","011000"),
450 SINK ("000101","010101"),
451 STOPSINK ("000001","010001");
452 private BitVector scanBits0;
453 private BitVector scanBits1;
454 CommandCodes(String bits0,String bits1) {
455 scanBits0 = new BitVector(bits0,"CommandCodes");
456 scanBits1 = new BitVector(bits1,"CommandCodes");
458 public BitVector bits(boolean extra) {
459 return extra ? scanBits1 : scanBits0;