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.vlsi.chips.marina.test.MarinaUtils.StateWireState;
12 public class ProperStopper {
13 // position of strobes in the control chain
14 private static final int BLOCK_STROBE_NDX = 0;
15 private static final int FILL_STROBE_NDX = 1;
16 private static final int GO_STROBE_NDX = 2;
17 private static final int SILENT_STROBE_NDX = 3;
18 private static final int CLEAR_STROBE_NDX = 4;
19 private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
21 // position of inputs in report chain
22 private static final int PREV_STATE_IN_NDX = 0;
23 private static final int FILL_STROBE_IN_NDX = 1;
24 private static final int FILL_STATE_IN_NDX = 2;
25 private static final int STOPPED_IN_NDX = 3;
27 private final String name;
28 private final String captureClockRelPath = "fillStag@0.all1in52@1.data1in3@0";
29 // test library direct write mode doesn't understand per register write
30 // enables. We get simulation to work by toggling write clock.
31 private final boolean clockHack;
32 private final String captureClockName = "wrr";
34 private boolean traceFill = true;
35 private boolean traceDrain = true;
37 private final String controlChain, controlPath,
39 reportChain, reportPath;
40 private final String captureClock;
41 private final ChainControls cc;
42 private final ChipModel model;
43 private final Indenter indenter;
45 protected static void fatal(boolean pred, String msg) {
46 if (pred) Infrastructure.fatal(msg);
48 private void prln(String msg) {indenter.prln(msg);}
49 private void adjustIndent(int n) {indenter.adjustIndent(n);}
51 /** NanosimModel.setNodeState() requires special path names.
52 * Each instance name in the path must begin with the character 'x'.
53 * Return a path with the added X's. */
54 private String prefixInstNamesInPathWithX(String path) {
55 StringBuffer sb = new StringBuffer();
57 for (int i=0; i<path.length(); i++) {
58 char c = path.charAt(i);
60 if (c=='.') sb.append('x');
65 private BitVector getDatTokAdr() {
66 // strip the two write enable bits
67 return cc.getOutBits(dataPath).get(2, 52);
70 private void shiftControl(boolean readEnable, boolean writeEnable) {
71 cc.shift(controlChain, readEnable, writeEnable);
73 private void shiftData(boolean readEnable, boolean writeEnable) {
74 cc.shift(dataChain, readEnable, writeEnable);
76 if (clockHack && model instanceof NanosimModel) {
77 NanosimModel nanoModel = (NanosimModel) model;
78 nanoModel.setNodeState(captureClock, 1);
80 nanoModel.setNodeState(captureClock, 0);
84 private void shiftReport(boolean readEnable, boolean writeEnable) {
85 cc.shift(reportChain, readEnable, writeEnable);
88 private StateWireState boolToState(boolean b) {
89 return b ? StateWireState.FULL : StateWireState.EMPTY;
91 // The first 5 bits of the control chain control the fill and drain stages
92 private void setFillDrainControl(BitVector fdCtl) {
93 fatal(fdCtl.getNumBits()!=5, "expect 5 proper stopper control bits");
94 BitVector val = cc.getInBits(controlPath);
95 for (int i=0; i<fdCtl.getNumBits(); i++) {
96 val.set(i, fdCtl.get(i));
98 cc.setInBits(controlPath, val);
99 shiftControl(false, true);
101 // The last bit of the control chain controls the general purpose
103 public void setGeneralPurposeOutput(Boolean b) {
104 BitVector val = cc.getInBits(controlPath);
105 val.set(GENERAL_PURPOSE_STROBE_NDX,b);
106 shiftControl(false, true);
109 //-------------------------- public methods ----------------------------
111 /** Allow subclasses to override the formating of the data. For example,
112 * the Instruction stopper only uses the 37 bits of data so it only
113 * wants to print the 37 instruction bits */
114 public String formatDataTokAddr(BitVector dta) {
115 return MarinaUtils.formatDataTokAddr(dta);
118 /** Put stopper in RUN state */
120 setFillDrainControl(MarinaUtils.RingIfc.RUN.bits());
122 /** Put stopper in IDLE state */
124 setFillDrainControl(MarinaUtils.RingIfc.IDLE.bits());
126 /** Put stopper in FILL state */
128 setFillDrainControl(MarinaUtils.RingIfc.FILL.bits());
130 /** Put stopper in BLOCK state */
131 public void block() {
132 setFillDrainControl(MarinaUtils.RingIfc.BLOCK.bits());
134 /** Put stopper in STOP state */
136 setFillDrainControl(MarinaUtils.RingIfc.STOP.bits());
138 /** Put stopper in CLEAR state */
139 public void clear() {
140 setFillDrainControl(MarinaUtils.RingIfc.CLEAR.bits());
142 /** Put stopper in SOURCE state */
143 public void source() {
144 setFillDrainControl(MarinaUtils.RingIfc.SOURCE.bits());
146 /** Put stopper in STOPSOURCE state */
147 public void stopSource() {
148 setFillDrainControl(MarinaUtils.RingIfc.STOPSOURCE.bits());
150 /** Put stopper in SINK state */
152 setFillDrainControl(MarinaUtils.RingIfc.SINK.bits());
154 /** Put stopper in STOPSINK state */
155 public void stopSink() {
156 setFillDrainControl(MarinaUtils.RingIfc.STOPSINK.bits());
158 /** Stop a running stopper in order to add items. Ensure that we don't
159 * lose the item in the fill stage.
160 * Exit state: block */
161 public void stopToFill() {
167 /** get value of the state wire preceding the fill stage */
168 public StateWireState getPrevStateWire() {
169 shiftReport(true, false);
170 BitVector b = cc.getOutBits(reportPath);
171 int n = b.getNumBits();
172 fatal(n!=4, "Bad number of Stopper report bits: "+n);
173 return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
175 /** get the value of drain stage fill wire.
176 * The fill wire will be interesting if we doubt that the
177 * scan chain works. */
178 public boolean getFillStrobe() {
179 shiftReport(true, false);
180 return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
182 /** get value of state wire between the fill and drain stages */
183 public StateWireState getFillStateWire() {
184 shiftReport(true, false);
185 return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
187 /** get value of drain stage stopped wire */
188 public boolean getStopped() {
189 return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
191 public String getReportString() {
192 StringBuffer sb = new StringBuffer();
193 sb.append("Stopper's prev state: ");
194 sb.append(getPrevStateWire()+"\n");
195 sb.append("Stopper's fill stage: ");
196 sb.append(getFillStateWire()+"\n");
197 sb.append("Stopper's stopped: ");
198 sb.append(getStopped()+"\n");
199 return sb.toString();
201 /** construct a ProperStopper */
202 public ProperStopper(String propInst,
203 String controlChain, String dataChain,
205 ChainControls cc, ChipModel model,
208 this.name = propInst;
209 this.controlChain = controlChain;
210 this.controlPath = controlChain+'.'+propInst;
211 this.dataChain = dataChain;
212 this.dataPath = dataChain+'.'+propInst;
213 this.reportChain = reportChain;
214 this.reportPath = reportChain+'.'+propInst;
216 prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
217 +'.'+captureClockName;
220 this.clockHack = clockHack;
221 this.indenter = indenter;
223 /** Reset ProperStopper after the JTAG TRST has been pulsed */
224 public void resetAfterMasterClear() {
225 BitVector we = new BitVector(2, "write enable");
226 BitVector data = new BitVector(37, "data");
227 BitVector tag = new BitVector(1, "tag");
228 BitVector addr = new BitVector(14, "addr");
233 BitVector wdta = we.cat(data).cat(tag).cat(addr);
235 cc.setInBits(dataPath, wdta);
238 /** Insert one item into the fill stage.
239 * Fill stage must be empty.
240 * You must stop stopper before calling fill.
241 * exit state: block */
242 public void fill(BitVector dta) {
243 if (traceFill) prln("Begin fill. stopper="+name);
246 int n = dta.getNumBits();
247 fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
249 // make sure fill stage is empty
250 StateWireState myState = getFillStateWire();
251 fatal(myState!=StateWireState.EMPTY,
252 "fill: fill stage already full");
254 if (traceFill) prln("writing data: "+formatDataTokAddr(dta));
256 idle(); // block = 1, go = 0
258 BitVector wrEn = new BitVector(2, "write enable");
260 cc.setInBits(dataPath, wrEn.cat(dta));
261 shiftData(false, true);
271 if (traceFill) prln(getReportString());
273 // if data chain is shifted in the future, don't write!
275 cc.setInBits(dataPath, wrEn.cat(dta));
278 if (traceFill) prln("End fill");
280 /** Insert items from a list, one by one.
281 * You must stop stopper before calling fillMany()
282 * exit state: block */
283 public void fillMany(List<BitVector> data) {
284 prln("Begin fillMany. stopper="+name+" numWords="+data.size());
287 for (BitVector bv : data) {
288 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
292 prln("end fillMany");
294 /** Remove one item from fill stage. Return that item.
295 * An item must be available.
296 * drain() will stop cleanly.
297 * exit state: stop */
298 public BitVector drain() {
299 stop(); // all zero, block = 0, go = 0
301 // make sure an item is available
302 StateWireState myState=getFillStateWire();
303 fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
305 return drainNoCheck();
307 /** Remove one item from fill stage. Return that item.
308 * Assume that an item is available.
310 * exit state: stop */
311 private BitVector drainNoCheck() {
312 shiftData(true, false);
313 BitVector ans = getDatTokAdr();
316 clear(); // clear = 1
320 if (traceDrain) prln("drain stopper="+name+" data="+formatDataTokAddr(ans));
323 /** Remove as many items as possible from the fill stage.
324 * drainStopperMany() will stop cleanly.
325 * exit state: stop */
326 public List<BitVector> drainMany() {
327 return drainMany(Integer.MAX_VALUE);
330 /** Remove up to maxNbItems items from the fill stage.
331 * drainStopperMany() will stop cleanly.
332 * exit state: stop */
333 public List<BitVector> drainMany(int maxNbItems) {
334 prln("begin drainMany. stopper="+name);
339 List<BitVector> ans = new ArrayList<BitVector>();
343 StateWireState myState=getFillStateWire();
346 if (traceDrain) prln(getReportString());
348 if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
350 if (traceDrain) prln("drainMany: reading word number: "+cnt++);
352 BitVector d = drainNoCheck();
358 prln("end drainMany, got "+ans.size()+" items");