tests 3021 and 3025 pass
[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@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";
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) {
46                 if (pred) Infrastructure.fatal(msg);
47         }
48         private void prln(String msg) {indenter.prln(msg);}
49         private void adjustIndent(int n) {indenter.adjustIndent(n);}
50         
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();
56                 sb.append('x');
57                 for (int i=0; i<path.length(); i++) {
58                         char c = path.charAt(i);
59                         sb.append(c);
60                         if (c=='.')  sb.append('x');
61                 }
62                 return sb.toString();
63         }
64
65     private BitVector getDatTokAdr() {
66         // strip the two write enable bits
67         return cc.getOutBits(dataPath).get(2, 52);
68     }
69     
70     private void shiftControl(boolean readEnable, boolean writeEnable) {
71         cc.shift(controlChain, readEnable, writeEnable);
72     }
73     private void shiftData(boolean readEnable, boolean writeEnable) {
74         cc.shift(dataChain, readEnable, writeEnable);
75         if (writeEnable) {
76                 if (clockHack && model instanceof NanosimModel) {
77                         NanosimModel nanoModel = (NanosimModel) model;
78                         nanoModel.setNodeState(captureClock, 1);
79                         nanoModel.waitNS(1);
80                         nanoModel.setNodeState(captureClock, 0);
81                 }
82         }
83     }
84     private void shiftReport(boolean readEnable, boolean writeEnable) {
85         cc.shift(reportChain, readEnable, writeEnable);
86     }
87
88     private StateWireState boolToState(boolean b) {
89         return b ? StateWireState.FULL : StateWireState.EMPTY;
90     }
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));
97         }
98         cc.setInBits(controlPath, val);
99         shiftControl(false, true);
100     }
101     // The last bit of the control chain controls the general purpose
102     // output
103     public void setGeneralPurposeOutput(Boolean b) {
104         BitVector val = cc.getInBits(controlPath);
105         val.set(GENERAL_PURPOSE_STROBE_NDX,b);
106         shiftControl(false, true);
107     }
108     
109     //-------------------------- public methods ----------------------------
110     
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);
116     }
117
118     /** Put stopper in RUN state */
119     public void run() {
120         setFillDrainControl(MarinaUtils.RingIfc.RUN.bits());
121     }
122     /** Put stopper in IDLE state */
123     public void idle() {
124         setFillDrainControl(MarinaUtils.RingIfc.IDLE.bits());
125     }
126     /** Put stopper in FILL state */
127     public void fill() {
128         setFillDrainControl(MarinaUtils.RingIfc.FILL.bits());
129     }
130     /** Put stopper in BLOCK state */
131     public void block() {
132         setFillDrainControl(MarinaUtils.RingIfc.BLOCK.bits());
133     }
134     /** Put stopper in STOP state */
135     public void stop() {
136         setFillDrainControl(MarinaUtils.RingIfc.STOP.bits());
137     }
138     /** Put stopper in CLEAR state */
139     public void clear() {
140         setFillDrainControl(MarinaUtils.RingIfc.CLEAR.bits());
141     }
142     /** Put stopper in SOURCE state */
143     public void source() {
144         setFillDrainControl(MarinaUtils.RingIfc.SOURCE.bits());
145     }
146     /** Put stopper in STOPSOURCE state */
147     public void stopSource() {
148         setFillDrainControl(MarinaUtils.RingIfc.STOPSOURCE.bits());
149     }
150     /** Put stopper in SINK state */
151     public void sink() {
152         setFillDrainControl(MarinaUtils.RingIfc.SINK.bits());
153     }
154     /** Put stopper in STOPSINK state */
155     public void stopSink() {
156         setFillDrainControl(MarinaUtils.RingIfc.STOPSINK.bits());
157     }
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() {
162         stop();                                 // go = 0
163         idle();                                 // block = 1
164         block();                                // go = 1
165 //      idle();                                 // go = 0
166     }
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));
174     }
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);
181     }
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));
186     }
187     /** get value of drain stage stopped wire */
188     public boolean getStopped() {
189         return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
190     }
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();
200     }
201     /** construct a ProperStopper */
202     public ProperStopper(String propInst,
203                                          String controlChain, String dataChain, 
204                              String reportChain,
205                              ChainControls cc, ChipModel model,
206                              boolean clockHack,
207                              Indenter indenter) {
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;
215         this.captureClock = 
216                 prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
217                 +'.'+captureClockName;
218         this.cc = cc;
219         this.model = model;
220         this.clockHack = clockHack;
221         this.indenter = indenter;
222     }
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");
229         we.setFromLong(0);
230         data.setFromLong(0);
231         tag.setFromLong(0);
232         addr.setFromLong(0);
233         BitVector wdta = we.cat(data).cat(tag).cat(addr);
234         
235         cc.setInBits(dataPath, wdta);
236     }
237     
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);
244         adjustIndent(2);
245         
246         int n = dta.getNumBits();
247         fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
248         
249         // make sure fill stage is empty
250         StateWireState myState = getFillStateWire();
251         fatal(myState!=StateWireState.EMPTY, 
252                   "fill: fill stage already full");
253         
254         if (traceFill) prln("writing data: "+formatDataTokAddr(dta));
255         
256         idle();                                 // block = 1, go = 0
257
258         BitVector wrEn = new BitVector(2, "write enable");
259         wrEn.setFromLong(3);
260         cc.setInBits(dataPath, wrEn.cat(dta));
261         shiftData(false, true);
262         
263         fill();                                 // fill = 1
264         idle();                                 // fill = 0
265         block();                                // go = 1
266 //      idle();
267         
268         model.waitNS(5);
269
270         // debugging
271         if (traceFill) prln(getReportString());
272         
273         // if data chain is shifted in the future, don't write!
274         wrEn.setFromLong(0);
275         cc.setInBits(dataPath, wrEn.cat(dta));
276         
277         adjustIndent(-2);
278         if (traceFill) prln("End fill");
279     }
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());
285         adjustIndent(2);
286         int cnt = 0;
287         for (BitVector bv : data) {
288                 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
289                 fill(bv);
290         }
291         adjustIndent(-2);
292         prln("end fillMany");
293     }
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
300         
301         // make sure an item is available
302         StateWireState myState=getFillStateWire();
303         fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
304
305         return drainNoCheck();
306     }
307     /** Remove one item from fill stage. Return that item.
308      * Assume that an item is available. 
309      * entry state: stop
310      * exit state: stop */
311     private BitVector drainNoCheck() {
312         shiftData(true, false);
313         BitVector ans = getDatTokAdr();
314
315         idle();                                 // block = 1
316         clear();                                // clear = 1
317         idle();                                 // clear = 0
318         stop();                                 // block = 0
319
320         if (traceDrain) prln("drain stopper="+name+" data="+formatDataTokAddr(ans));
321         return ans;
322     }
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);
328     }
329
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);
335         adjustIndent(2);
336         
337         stop();
338         
339         List<BitVector> ans = new ArrayList<BitVector>();
340         
341         int cnt = 0;
342         while (true) {
343                 StateWireState myState=getFillStateWire();
344
345                 // debugging
346                 if (traceDrain) prln(getReportString());
347
348                 if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
349                 
350                 if (traceDrain) prln("drainMany: reading word number: "+cnt++);
351                 
352                 BitVector d = drainNoCheck();
353
354                 ans.add(d);
355         }
356         
357         adjustIndent(-2);
358         prln("end drainMany, got "+ans.size()+" items");
359         
360         return ans;
361     }
362
363
364
365 }