formatting changes
[fleet.git] / testCode / com / sun / vlsi / chips / marina / test / ProperStopper.java
1 package com.sun.vlsi.chips.marina.test;
2 import java.util.ArrayList;
3 import java.util.List;
4
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;
11
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;
20         
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;
26         
27     private final String name;
28     private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
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 = "si[4]";
33
34     private boolean traceFill = true;
35     private boolean traceDrain = true;
36         
37     private final String controlChain, controlPath, 
38         dataChain, dataPath, 
39         reportChain, reportPath;
40     private final String captureClock;
41     private final ChainControls cc;
42     private final ChipModel model;
43     private final Indenter indenter;
44
45     protected static void fatal(boolean pred, String msg) { if (pred) Infrastructure.fatal(msg); }
46     private void prln(String msg) { indenter.prln(msg); }
47     private void adjustIndent(int n) { indenter.adjustIndent(n); }
48         
49     /** NanosimModel.setNodeState() requires special path names.  
50      * Each instance name in the path must begin with the character 'x'.
51      * Return a path with the added X's. */
52     private String prefixInstNamesInPathWithX(String path) {
53         StringBuffer sb = new StringBuffer();
54         sb.append('x');
55         for (int i=0; i<path.length(); i++) {
56             char c = path.charAt(i);
57             sb.append(c);
58             if (c=='.')  sb.append('x');
59         }
60         return sb.toString();
61     }
62   
63     private void shiftControl(boolean readEnable, boolean writeEnable) {
64         cc.shift(controlChain, readEnable, writeEnable);
65     }
66     private void shiftData(boolean readEnable, boolean writeEnable) {
67         cc.shift(dataChain, readEnable, writeEnable);
68         if (writeEnable) {
69             if (clockHack && model instanceof NanosimModel) {
70                 NanosimModel nanoModel = (NanosimModel) model;
71                 nanoModel.setNodeState(captureClock, 1);
72                 nanoModel.waitNS(1);
73                 nanoModel.setNodeState(captureClock, 0);
74             }
75         }
76     }
77     private void shiftReport(boolean readEnable, boolean writeEnable) {
78         cc.shift(reportChain, readEnable, writeEnable);
79     }
80
81     private StateWireState boolToState(boolean b) {
82         return b ? StateWireState.FULL : StateWireState.EMPTY;
83     }
84     // The first 5 bits of the control chain control the fill and drain stages
85     private void setFillDrainControl(BitVector fdCtl) {
86         fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
87         BitVector val = cc.getInBits(controlPath);
88         for (int i=0; i<fdCtl.getNumBits(); i++) {
89             val.set(i, fdCtl.get(i));
90         }
91         cc.setInBits(controlPath, val);
92         shiftControl(false, true);
93     }
94     // The last bit of the control chain controls the general purpose
95     // output
96     public void setGeneralPurposeOutput(Boolean b) {
97         BitVector val = cc.getInBits(controlPath);
98         val.set(GENERAL_PURPOSE_STROBE_NDX,b);
99         shiftControl(false, true);
100     }
101     
102     //-------------------------- public methods ----------------------------
103
104     /** Put stopper in RUN state */
105     public void run() {
106         setFillDrainControl(CommandCodes.RUN.bits());
107     }
108     /** Put stopper in IDLE state */
109     public void idle() {
110         setFillDrainControl(CommandCodes.IDLE.bits());
111     }
112     /** Put stopper in FILL state */
113     public void fill() {
114         setFillDrainControl(CommandCodes.FILL.bits());
115     }
116     /** Put stopper in BLOCK state */
117     public void block() {
118         setFillDrainControl(CommandCodes.BLOCK.bits());
119     }
120     /** Put stopper in STOP state */
121     public void stop() {
122         setFillDrainControl(CommandCodes.STOP.bits());
123     }
124     /** Put stopper in CLEAR state */
125     public void clear() {
126         setFillDrainControl(CommandCodes.CLEAR.bits());
127     }
128     /** Put stopper in SOURCE state */
129     public void source() {
130         setFillDrainControl(CommandCodes.SOURCE.bits());
131     }
132     /** Put stopper in STOPSOURCE state */
133     public void stopSource() {
134         setFillDrainControl(CommandCodes.STOPSOURCE.bits());
135     }
136     /** Put stopper in SINK state */
137     public void sink() {
138         setFillDrainControl(CommandCodes.SINK.bits());
139     }
140     /** Put stopper in STOPSINK state */
141     public void stopSink() {
142         setFillDrainControl(CommandCodes.STOPSINK.bits());
143     }
144
145     /** Stop a running stopper in order to add items.  Ensure that we don't
146      * lose the item in the fill stage.  
147      * Exit state: block */
148     public void stopToFill() {
149         stop();                                 // go = 0
150         idle();                                 // block = 1
151         block();                                // go = 1
152         //      idle();                                 // go = 0
153     }
154
155     /** get value of the state wire preceding the fill stage */
156     public StateWireState getPrevStateWire() {
157         shiftReport(true, false);
158         BitVector b = cc.getOutBits(reportPath);
159         int n = b.getNumBits(); 
160         fatal(n!=4, "Bad number of Stopper report bits: "+n);
161         return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
162     }
163
164     /** get the value of drain stage fill wire.
165      * The fill wire will be interesting if we doubt that the
166      * scan chain works. */
167     public boolean getFillStrobe() {
168         shiftReport(true, false);
169         return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
170     }
171
172     /** get value of state wire between the fill and drain stages */
173     public StateWireState getFillStateWire() {
174         shiftReport(true, false);
175         return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
176     }
177
178     /** get value of drain stage stopped wire */
179     public boolean getStopped() {
180         shiftReport(true, false);
181         return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
182     }
183
184     public String getReportString() {
185         StringBuffer sb = new StringBuffer();
186         sb.append("Stopper's prev state: ");
187         sb.append(getPrevStateWire()+"\n");
188         sb.append("Stopper's fill stage: ");
189         sb.append(getFillStateWire()+"\n");
190         sb.append("Stopper's stopped: ");
191         sb.append(getStopped()+"\n");
192         return sb.toString();
193     }
194
195     /** construct a ProperStopper */
196     public ProperStopper(String propInst,
197                          String controlChain, String dataChain, 
198                          String reportChain,
199                          ChainControls cc, ChipModel model,
200                          boolean clockHack,
201                          Indenter indenter) {
202         this.name = propInst;
203         this.controlChain = controlChain;
204         this.controlPath = controlChain+'.'+propInst;
205         this.dataChain = dataChain;
206         this.dataPath = dataChain+'.'+propInst;
207         this.reportChain = reportChain;
208         this.reportPath = reportChain+'.'+propInst;
209         this.captureClock = 
210             prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
211             +'.'+captureClockName;
212         this.cc = cc;
213         this.model = model;
214         this.clockHack = clockHack;
215         this.indenter = indenter;
216     }
217
218     /** Reset ProperStopper after the JTAG TRST has been pulsed */
219     public void resetAfterMasterClear() {
220         BitVector we = new BitVector(2, "write enable");
221         BitVector packet = new BitVector(MarinaPacket.PACKET_WIDTH, "packet");
222         we.setFromLong(0);
223         packet.setFromLong(0);
224         BitVector wdta = we.cat(packet);
225         cc.setInBits(dataPath, wdta);
226     }
227     
228     /** Insert one item into the fill stage.
229      * Fill stage must be empty. 
230      * You must stop stopper before calling fill.
231      * exit state: block */
232     public void fill(BitVector dta) {
233         if (traceFill) prln("Begin fill. stopper="+name);
234         adjustIndent(2);
235         
236         int n = dta.getNumBits();
237         fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
238         
239         // make sure fill stage is empty
240         StateWireState myState = getFillStateWire();
241         fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
242         
243         if (traceFill) prln("writing data: "+new MarinaPacket(dta));
244         
245         idle();                                 // block = 1, go = 0
246
247         BitVector wrEn = new BitVector(2, "write enable");
248         wrEn.setFromLong(3);
249         cc.setInBits(dataPath, wrEn.cat(dta));
250         shiftData(false, true);
251         
252         fill();                                 // fill = 1
253         idle();                                 // fill = 0
254         block();                                // go = 1
255         //      idle();
256         
257         model.waitNS(5);
258
259         // debugging
260         if (traceFill) prln(getReportString());
261         
262         // if data chain is shifted in the future, don't write!
263         wrEn.setFromLong(0);
264         cc.setInBits(dataPath, wrEn.cat(dta));
265         
266         adjustIndent(-2);
267         if (traceFill) prln("End fill");
268     }
269
270     public void fill(MarinaPacket mp) {
271         fill(mp.toSingleBitVector());
272     }
273
274     /** Insert items from a list, one by one. 
275      * You must stop stopper before calling fillMany()
276      * exit state: block */
277     public void fillMany(List<BitVector> data) {
278         prln("Begin fillMany. stopper="+name+" numWords="+data.size());
279         adjustIndent(2);
280         int cnt = 0;
281         for (BitVector bv : data) {
282             if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
283             fill(bv);
284         }
285         adjustIndent(-2);
286         prln("end fillMany");
287     }
288
289     /** Remove one item from fill stage. Return that item.
290      * An item must be available.
291      * drain() will stop cleanly.
292      * exit state: stop */
293     public BitVector drain() {
294         stop();                                 // all zero, block = 0, go = 0
295         
296         // make sure an item is available
297         StateWireState myState=getFillStateWire();
298         fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
299
300         return drainNoCheck();
301     }
302
303     /** Remove one item from fill stage. Return that item.
304      * Assume that an item is available. 
305      * entry state: stop
306      * exit state: stop */
307     protected BitVector drainNoCheck() {
308         shiftData(true, false);
309
310         // strip the two write enable bits
311         BitVector ans = cc.getOutBits(dataPath).get(2, 52);
312
313         idle();                                 // block = 1
314         clear();                                // clear = 1
315         idle();                                 // clear = 0
316         stop();                                 // block = 0
317
318         if (traceDrain) prln("drain stopper="+name+" data="+new MarinaPacket(ans));
319         return ans;
320     }
321
322     /** Remove as many items as possible from the fill stage.
323      * drainStopperMany() will stop cleanly.
324      * exit state: stop */
325     public List<BitVector> drainMany() {
326         return drainMany(Integer.MAX_VALUE);
327     }
328
329     /** Remove up to maxNbItems items from the fill stage.
330      * drainStopperMany() will stop cleanly.
331      * exit state: stop */
332     public List<BitVector> drainMany(int maxNbItems) {
333         prln("begin drainMany. stopper="+name);
334         adjustIndent(2);
335         
336         stop();
337         
338         List<BitVector> ans = new ArrayList<BitVector>();
339         
340         int cnt = 0;
341         while (true) {
342             StateWireState myState=getFillStateWire();
343
344             // debugging
345             if (traceDrain) prln(getReportString());
346
347             if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
348                 
349             if (traceDrain) prln("drainMany: reading word number: "+cnt++);
350                 
351             BitVector d = drainNoCheck();
352
353             ans.add(d);
354         }
355         
356         adjustIndent(-2);
357         prln("end drainMany, got "+ans.size()+" items");
358         
359         return ans;
360     }
361
362
363     /**
364      * (Note by Bill and Adam: Ivan has struck again!)
365      * As of 05 March 2009 the new bits are:
366      *    Block Extra Fill Go Clear Silent
367      *      => Note: "Extra" gets fed to the mux in the counter
368      *         that selects the frequency output that goes off-chip
369      *
370      * Caution: Ivan changes the order of the ProperStopper control bits 
371      * from chip to chip.  Here is the current order for Marina
372      * as of 14 Aug 2008: 
373      *  Block, Fill, Go, Silent, Clear
374      *
375      *  The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
376      */
377     private static enum CommandCodes {
378         RUN        ("000100"),
379             IDLE       ("100000"),
380             FILL       ("101000"),
381             BLOCK      ("100100"),
382             STOP       ("000000"),
383             CLEAR      ("100010"),
384             SOURCE     ("001100"),
385             STOPSOURCE ("001000"),
386             SINK       ("000101"),
387             STOPSINK   ("000001");
388         private BitVector scanBits;
389         CommandCodes(String bits) {
390             scanBits = new BitVector(bits,"CommandCodes");
391         }
392         public BitVector bits() {return scanBits;}
393     }
394
395 }