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.vlsi.chips.marina.test.MarinaUtils.StateWireState;
11 public class ProperStopper {
12 private boolean traceFill = true;
13 private boolean traceDrain = true;
15 private final String controlChain, controlPath,
17 reportChain, reportPath;
18 private final ChainControl cc;
19 private final ChipModel model;
20 private final Indenter indenter;
22 private static void fatal(boolean pred, String msg) {
23 if (pred) Infrastructure.fatal(msg);
25 private void prln(String msg) {indenter.prln(msg);}
26 private void adjustIndent(int n) {indenter.adjustIndent(n);}
28 private BitVector getDatTokAdr() {
29 // strip the two write enable bits
30 return cc.getOutBits(dataPath).get(2, 52);
33 private void shiftControl(boolean readEnable, boolean writeEnable) {
34 cc.shift(controlChain, readEnable, writeEnable);
36 private void shiftData(boolean readEnable, boolean writeEnable) {
37 cc.shift(dataChain, readEnable, writeEnable);
39 private void shiftReport(boolean readEnable, boolean writeEnable) {
40 cc.shift(reportChain, readEnable, writeEnable);
43 private StateWireState boolToState(boolean b) {
44 return b ? StateWireState.FULL : StateWireState.EMPTY;
47 //-------------------------- public methods ----------------------------
49 /** Put stopper in RUN state */
51 cc.setInBits(controlPath, MarinaUtils.RingIfc.RUN.bits());
53 /** Put stopper in IDLE state */
55 cc.setInBits(controlPath, MarinaUtils.RingIfc.IDLE.bits());
57 /** Put stopper in FILL state */
59 cc.setInBits(controlPath, MarinaUtils.RingIfc.FILL.bits());
61 /** Put stopper in BLOCK state */
63 cc.setInBits(controlPath, MarinaUtils.RingIfc.BLOCK.bits());
65 /** Put stopper in STOP state */
67 cc.setInBits(controlPath, MarinaUtils.RingIfc.STOP.bits());
69 /** Put stopper in CLEAR state */
71 cc.setInBits(controlPath, MarinaUtils.RingIfc.CLEAR.bits());
73 /** Put stopper in SOURCE state */
74 public void source() {
75 cc.setInBits(controlPath, MarinaUtils.RingIfc.SOURCE.bits());
77 /** Put stopper in STOPSOURCE state */
78 public void stopSource() {
79 cc.setInBits(controlPath, MarinaUtils.RingIfc.STOPSOURCE.bits());
81 /** Put stopper in SINK state */
83 cc.setInBits(controlPath, MarinaUtils.RingIfc.SINK.bits());
85 /** Put stopper in STOPSINK state */
86 public void stopSink() {
87 cc.setInBits(controlPath, MarinaUtils.RingIfc.STOPSINK.bits());
89 /** Stop a running stopper in order to add items. Ensure that we don't
90 * lose the item in the fill stage. Wait long enough for ring to quiesce.
92 public void stopToFill() {
94 shiftControl(false, true);
97 shiftControl(false, true);
100 shiftControl(false, true);
103 shiftControl(false, true);
105 /** get value of the state wire preceeding the fill stage */
106 public StateWireState getPrevStateWire() {
107 BitVector b = cc.getOutBits(reportPath);
108 int n = b.getNumBits();
109 fatal(n!=4, "Bad number of Stopper report bits: "+n);
110 return boolToState(cc.getOutBits(reportPath).get(0));
112 /** get the value of drain stage fill wire.
113 * The fill wire will be interesting if we doubt that the
114 * scan chain works. */
115 public boolean getFillWire() {
116 return cc.getOutBits(reportPath).get(1);
118 /** get value of state wire between the fill and drain stages */
119 public StateWireState getMyStateWire() {
120 return boolToState(cc.getOutBits(reportPath).get(2));
122 /** get value of drain stage stopped wire */
123 public boolean getStopped() {
124 return cc.getOutBits(reportPath).get(3);
126 public String getReportString() {
127 StringBuffer sb = new StringBuffer();
128 sb.append("Stopper's prev state: ");
129 sb.append(getPrevStateWire()+"\n");
130 sb.append("Stopper's state: ");
131 sb.append(getMyStateWire()+"\n");
132 sb.append("Stopper's stopped: ");
133 sb.append(getStopped()+"\n");
134 return sb.toString();
136 /** construct a ProperStopper */
137 public ProperStopper(String controlChain, String controlInst,
138 String dataChain, String dataInst,
139 String reportChain, String reportInst,
140 ChainControl cc, ChipModel model,
142 this.controlChain = controlChain;
143 this.controlPath = controlChain+controlInst;
144 this.dataChain = dataChain;
145 this.dataPath = dataChain+dataInst;
146 this.reportChain = reportChain;
147 this.reportPath = reportChain+reportInst;
150 this.indenter = indenter;
152 /** Reset ProperStopper after the JTAG TRST has been pulsed */
153 public void resetAfterMasterClear() {
154 BitVector we = new BitVector(2, "write enable");
155 BitVector data = new BitVector(37, "data");
156 BitVector tag = new BitVector(1, "tag");
157 BitVector addr = new BitVector(14, "addr");
162 BitVector wdta = we.cat(data).cat(tag).cat(addr);
164 cc.setInBits(dataPath, wdta);
167 /** Insert one item into the fill stage.
168 * Fill stage must be empty.
169 * You must stop stopper before calling fill.
170 * exit state: idle */
171 public void fill(BitVector dta) {
172 if (traceFill) prln("Begin fillStopper");
175 int n = dta.getNumBits();
176 fatal(n!=(37+1+14), "fillStopper: wrong num bits: "+n);
178 // make sure fill stage is empty
179 shiftReport(true, false);
180 StateWireState myState = getMyStateWire();
181 fatal(myState!=StateWireState.EMPTY,
182 "fillStopper: fill stage already full");
184 if (traceFill) prln("writing data: "+MarinaUtils.formatDataTokAddr(dta));
186 idle(); // block = 1, go = 0
187 shiftControl(false, true);
189 BitVector wrEn = new BitVector(2, "write enable");
191 cc.setInBits(dataPath, wrEn.cat(dta));
192 shiftData(false, true);
195 shiftControl(false, true);
197 shiftControl(false, true);
199 shiftControl(false, true);
201 shiftControl(false, true);
206 if (traceFill) prln(getReportString());
208 // if data chain is shifted in the future, don't write!
210 cc.setInBits(dataPath, wrEn.cat(dta));
213 if (traceFill) prln("End fillStopper");
215 /** Insert items from a list, one by one.
216 * You must stop stopper before calling fillMany()
217 * exit state: idle */
218 public void fillMany(List<BitVector> data) {
219 prln("begin fillMany "+data.size()+" words");
222 for (BitVector bv : data) {
223 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
227 prln("end fillMany");
229 /** Remove one item from fill stage. Return that item.
230 * An item must be available.
231 * drain() will stop cleanly.
232 * exit state: stop */
233 public BitVector drain() {
234 stop(); // all zero, block = 0, go = 0
235 shiftControl(false, true);
237 // make sure an item is available
238 shiftReport(true, false);
239 StateWireState myState=getMyStateWire();
240 fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
242 shiftData(true, false);
243 BitVector ans = getDatTokAdr();
246 shiftControl(false, true);
247 clear(); // clear = 1
248 shiftControl(false, true);
250 shiftControl(false, true);
252 shiftControl(false, true);
254 if (traceDrain) prln("drainStopper data: "+MarinaUtils.formatDataTokAddr(ans));
257 /** Remove as many items as possible from the fill stage.
258 * drainStopperMany() will stop cleanly.
259 * exit state: stop */
260 public List<BitVector> drainMany() {
261 return drainMany(Integer.MAX_VALUE);
264 /** Remove up to maxNbItems items from the fill stage.
265 * drainStopperMany() will stop cleanly.
266 * exit state: stop */
267 public List<BitVector> drainMany(int maxNbItems) {
268 prln("begin drainStopperMany");
271 List<BitVector> ans = new ArrayList<BitVector>();
275 shiftReport(true, false);
276 StateWireState myState=getMyStateWire();
279 if (traceDrain) prln(getReportString());
281 if (myState==StateWireState.EMPTY || cnt>maxNbItems) break;
283 if (traceDrain) prln("drainStopperMany: reading word number: "+cnt++);
285 BitVector d = drain();
291 prln("end drainStopperMany, got "+ans.size()+" entries");