5aa6daeead9828a2c7eca847a27fcb4c8fcf44f9
[fleet.git] / src / com / sun / vlsi / chips / marina / test / Marina.java
1 package com.sun.vlsi.chips.marina.test;
2 /* -*- tab-width: 4 -*- */
3 import com.sun.async.test.BitVector;
4 import com.sun.async.test.ChainControl;
5 import com.sun.async.test.ChipModel;
6 import com.sun.async.test.JtagTester;
7 import com.sun.async.test.NanosimModel;
8 import com.sun.async.test.VerilogModel;
9 import com.sun.async.test.*;
10
11 import edu.berkeley.fleet.api.Instruction;
12 import edu.berkeley.fleet.marina.MarinaPath;
13
14 /** The Marina object will eventually represent the Marina test chip.  
15  * Right now, it doesn't do much of anything. It just helps me exercise
16  * my test infrastructure. */
17 public class Marina {
18
19     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE  = 5;
20     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO = MarinaPath.SIGNAL_BIT_INDEX;
21
22        
23     public static int TOKEN_FIFO_CAPACITY = 3;
24     
25     //public static boolean kesselsCounter = true;
26     public static boolean kesselsCounter = false;
27     public static boolean omegaCounter = false;
28
29     public static final String DATA_CHAIN =    kesselsCounter ? "marina.marina_data" : "marina.ivan_data";      
30     public static final String CONTROL_CHAIN = kesselsCounter ? "marina.marina_control" : "marina.ivan_control";
31     public static final String REPORT_CHAIN =  kesselsCounter ? "marina.marina_report" : "marina.ivan_report";
32
33     public static String prefix = "marinaGu@0.outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@"+(kesselsCounter?"1":"0")+".";
34     public static String MASTER_CLEAR = "mc";
35
36
37     /*
38     private static String prefix = "outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@1.";
39     private static String MASTER_CLEAR = "EXTmasterClear";
40     */
41
42     private static final String OLC_PATH_EVEN = 
43         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@1"; // bits 2,4,6
44     private static final String OLC_PATH_ODD = 
45         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@2"; // bits 1,3,5
46     public static final String OLC_PATH_KESSEL = 
47         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.counte@0.adamScan@1.scanEx6h@";
48     private static final String ILC_PATH_ODD = 
49         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
50     private static final String ILC_PATH_EVEN = 
51         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
52     private static final String FLAGS_PATH = 
53         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.scanEx3h@0";
54
55     private static final String INSTR_RING_CONTROL_PATH = 
56         prefix+"southFif@1.tapPropS@1.tapStage@2";
57     private static final String TOK_FIFO_PATH =
58         prefix+"tokenFIF@1";
59     private static final String INSTRUCTION_COUNTER_PATH =
60         prefix+"southFif@1.tapPropS@1.instruct@0";
61     private static final String DATA_COUNTER_PATH =
62         prefix+"northFif@1.fillDrai@1.instruct@0";
63     private static final String TOK_PRED_PATH =
64         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx2h@0.scanCell@10";
65
66     private static final int COUNTER_LENGTH = 34;
67     private static final int INSTRUCTION_SEND_NDX = 1;
68     private static final int INSTRUCTION_RECIRCULATE_NDX = 0;
69
70     public static final int INSTRUCTION_LENGTH = 36;
71         
72     private static final int A_FLAG_NDX = 0;
73     private static final int B_FLAG_NDX = 1;
74         
75     public static final int SOUTH_RING_CAPACITY = 11;
76         
77     // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
78     public class Ilc {
79         // value is bit reversed and complemented
80         private int value;
81         private Ilc() {
82             shiftReport(true, false);
83             BitVector odd  = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
84             BitVector even = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
85             BitVector ret  = new BitVector(8, "olc");
86             for(int i=0; i<4; i++) {
87                 ret.set(i*2+1, odd.get(i));
88                 ret.set(i*2,   even.get(i));
89             }
90             value = (int)ret.toLong();
91         }
92         /** Get the inner loop counter done bit. */
93         public boolean getDone() {
94             return (value & 0x40) != 0;
95         }
96         /** Get the inner loop counter infinity bit */
97         public boolean getInfinity() {
98             return (value & 0x80) != 0;
99         }
100         /** Get the 6 bits of count of the inner loop counter */
101         public int getCount() {
102             return value & 0x3f;
103         }
104         public String toString() {
105             return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
106         }
107     }
108         
109     private final Indenter indenter;
110
111     // The name of the scan chain
112     // The instance path, from the top cell of the netlist, of the instance of infinityWithCover 
113     public final ChainControls cc;           // specifies the scan chain
114     private final ChipModel model;
115     public final ProperStopper data;
116     public final InstructionStopper instrIn;
117     
118     private void prln(String msg) {indenter.prln(msg);}
119     private void pr(String msg) {indenter.pr(msg);}
120     
121     /** Shift the report scan chain */
122     public void shiftReport(boolean readEnable, boolean writeEnable) {
123         cc.shift(REPORT_CHAIN, readEnable, writeEnable);
124     }
125     
126     /** Shift the report scan chain */
127     private void shiftControl(boolean readEnable, boolean writeEnable) {
128         cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
129     }
130         
131     /** Shift the data scan chain */
132     private void shiftData(boolean readEnable, boolean writeEnable) {
133         cc.shift(DATA_CHAIN, readEnable, writeEnable);
134     }
135
136     public Marina(ChainControls cc, ChipModel model, boolean clockHack, Indenter indenter) {
137         this.cc = cc;
138         this.model = model;
139         this.indenter = indenter;
140         data = new ProperStopper("north fifo",
141                                  prefix+"northFif@1.fillDrai@1.properSt@1",
142                                  CONTROL_CHAIN, 
143                                  DATA_CHAIN,  
144                                  REPORT_CHAIN,
145                                  cc, model, clockHack, indenter,
146                                  prefix+"northFif@1.fillDrai@1.instruct@0.cntScnTh@1.cntScnOn@1");
147         instrIn = new InstructionStopper("south fifo",
148                                          prefix+"southFif@1.tapPropS@1.properSt@1", 
149                                          CONTROL_CHAIN,
150                                          DATA_CHAIN,
151                                          REPORT_CHAIN,
152                                          cc, model, clockHack, indenter,
153                                          prefix+"southFif@1.tapPropS@1.instruct@0.cntScnTh@1.cntScnOn@1");
154     }
155
156     int northCount = 0;
157     int southCount = 0;
158
159     public void stopAndResetCounters() {
160         instrIn.setCounterEnable(false);
161         data.setCounterEnable(false);
162         cc.shift(DATA_CHAIN, true, false);        
163         northCount = data.getCounterValue();
164         southCount = instrIn.getCounterValue();
165         data.setCounterValue(0);
166         instrIn.setCounterValue(0);
167     }
168     public void startCounters() {
169         instrIn.setCounterEnable(true);
170         data.setCounterEnable(true);
171     }
172     public int getNorthCount() { return northCount; }
173     public int getSouthCount() { return southCount; }
174
175
176     public void masterClear() {
177         final double WIDTH = 10; // ns
178         // Put a high going pulse on the internal chip master clear signal
179         if (model instanceof VerilogModel) {
180
181             data.clear();
182             instrIn.clear();
183
184             VerilogModel vm = (VerilogModel)model;
185             //
186             // In real life the flags come up with some undefined
187             // value.  In verilog we need to prevent the X'es from
188             // propagating, so we force the flags to a known value
189             //
190             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_", 0);
191             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_", 1);
192             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_", 0);
193             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_", 1);
194
195             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_", 1);
196             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_", 0);
197
198             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50", 0);       // A
199             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50", 0);       // B
200             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
201
202             // possible C-flag inputs
203             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
204             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
205
206             // force the OLC to zero
207             if (!kesselsCounter)
208                 for(int i=1; i<=6; i++)
209                     vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
210
211             // set the ILC input to 1
212             for(int i=1; i<=8; i++) {
213                 if (i!=7)
214                     vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
215             }
216
217             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
218             model.waitNS(1000);
219             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
220             model.waitNS(1000);
221
222             vm.setNodeState(MASTER_CLEAR, 1);
223             model.waitNS(1000);
224             vm.setNodeState(MASTER_CLEAR, 0);
225             model.waitNS(1000);
226
227             // pulse ilc[load] and olc[load]
228             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_", 1);
229             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_", 1);
230             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
231             if (!kesselsCounter)
232                 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_", 1);
233             model.waitNS(100);
234             model.waitNS(1);
235             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_");
236             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_");
237             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_");
238             if (!kesselsCounter)
239                 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_");
240
241             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_");
242             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_");
243             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_");
244             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_");
245
246             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_");
247             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_");
248
249             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50");
250             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50");
251
252             // Every move instruction, even those with Ti=0,Di=0,
253             // loads the C-flag.  It will get loaded with an "X",
254             // which will then leak into the flags and from there the
255             // predicate.
256             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
257             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
258             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
259             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
260
261             for(int i=1; i<=8; i++) {
262                 if (i!=7)
263                     vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
264             }
265             model.waitNS(1000);
266
267             if (!kesselsCounter)
268                 for(int i=1; i<=6; i++)
269                     vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]");
270
271             // the proper stopper states come up in an undefined ("X")
272             // state, so under Verilog we need to force them to a
273             // known state
274
275             data.idle();
276             instrIn.idle();
277
278         } else if (model instanceof NanosimModel) {
279             NanosimModel nModel = (NanosimModel) model;
280             /*
281             nModel.setNodeVoltage(prefix+"sid[9]",1.0);
282             nModel.setNodeVoltage(prefix+"sic[9]",1.0);
283             nModel.setNodeVoltage(prefix+"sir[9]",1.0);
284             nModel.waitNS(WIDTH);
285             nModel.setNodeVoltage(prefix+"sid[9]",0.0);
286             nModel.setNodeVoltage(prefix+"sic[9]",0.0);
287             nModel.setNodeVoltage(prefix+"sir[9]",0.0);
288             nModel.waitNS(1);
289             */
290             nModel.setNodeVoltage(MASTER_CLEAR,1.0);
291             nModel.waitNS(WIDTH);
292             nModel.setNodeVoltage(MASTER_CLEAR,0.0);
293             nModel.waitNS(1);
294         } else {
295
296             mc0.setLogicState(true);
297             mc1.setLogicState(true);
298             model.waitNS(1000);
299             mc0.setLogicState(false);
300             mc1.setLogicState(false);
301             model.waitNS(1000);
302
303         }
304         resetAfterMasterClear();
305     }
306
307     JtagLogicLevel mc0;
308     JtagLogicLevel mc1;
309
310     private void resetAfterMasterClear() {
311         // The following call to ChainControl.resetInBits() is vital!
312         // If you forget, then the inBits member initializes 
313         // with random data. Then when you do your first write,
314         // some bits are written randomly.
315         cc.resetInBits();
316
317         // For reset, I want to clear all the stoppers simultaneously
318         data.clear();
319         //tokOut.clear();
320         instrIn.clear();
321         
322         data.stop();
323         //tokOut.stop();
324         instrIn.stop();
325         
326         data.resetAfterMasterClear();
327         //tokOut.resetAfterMasterClear();
328         instrIn.resetAfterMasterClear();
329     }
330
331
332     /** Get the 6 bit outer loop counter. */
333     public int getOLC() {
334         shiftReport(true, false);
335         if (omegaCounter) {
336             BitVector bits = null;
337             for(int i=0; i<4; i++) {
338                 BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
339                 //System.out.println("bits are: " + x);
340                 bits = bits==null ? x : bits.cat(x);
341             }
342             System.out.print("  kesselsCounter = ");
343             int ret = 0;
344             boolean done = true;
345             boolean bad = false;
346             for(int bit=5; bit>=0; bit--) {
347                 boolean zeroOrTwo  = bits.get(4+bit*3);
348                 boolean zeroOrDone = bits.get(4+bit*3+1);
349                 if      ( zeroOrTwo && !zeroOrDone) {
350                     ret += (2<<bit);
351                     System.out.print("2");
352                     done = false;
353                 } else if (!zeroOrTwo && !zeroOrDone) {
354                     ret += (1<<bit);
355                     System.out.print("1");
356                     done = false;
357                 } else if ( zeroOrTwo &&  zeroOrDone) {
358                     System.out.print("0");
359                     bad = true;
360                     done = false;
361                 } else if (!zeroOrTwo &&  zeroOrDone) {
362                     System.out.print("_");
363                     if (!done) bad = true;
364                 }
365                 // FIXME: check for unreduced counter and warn about it
366             }
367             if (bad) System.out.print("  WARNING: UNREDUCED COUNTER VALUE!!!!!!");
368             System.out.println();
369             return ret;
370         } else if (kesselsCounter) {
371             BitVector bits = null;
372             for(int i=0; i<4; i++) {
373                 BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
374                 //System.out.println("bits are: " + x);
375                 bits = bits==null ? x : bits.cat(x);
376             }
377             //System.out.println("kesselsCounter = " + bits);
378             int first = 0;
379             int second = 0;
380             String hi="";
381             String lo="";
382             String latched="";
383             String res="";
384             for(int i=0; i<6; i++) {
385                 first  |= bits.get(4+i*3)   ? (1<<i) : 0;
386                 second |= bits.get(4+i*3+2) ? (1<<i) : 0;
387                 hi = (bits.get(4+i*3)   ? "1" : "0") + hi;
388                 lo = (bits.get(4+i*3+2)   ? "1" : "0") + lo;
389                 res =
390                     (   bits.get(4+i*3) && !bits.get(4+i*3+2) ? "X"
391                      : !bits.get(4+i*3) && !bits.get(4+i*3+2) ? "0"
392                      : !bits.get(4+i*3) &&  bits.get(4+i*3+2) ? "1"
393                      : "2")
394                     +res;
395                 latched = (bits.get(4+i*3+1)   ? "0" : "1") + latched;
396             }
397             System.out.println("kesselsCounter: "+
398                                "s[1]="+hi+
399                                " s[3]="+lo+
400                                " latched="+latched +
401                                " res="+res+
402                                " do[ins]="+(bits.get(0) ? "1" : "0")+
403                                " dec="+(bits.get(1) ? "1" : "0")+
404                                " flag[D][set]="+(bits.get(2) ? "1" : "0")+
405                                " resetting="+(bits.get(3) ? "1" : "0")+
406                                ""
407                                );
408             return (first+second);
409         } else {
410             BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
411             BitVector even = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
412             odd = odd.not();
413             even = even.not();
414             BitVector bv = new BitVector(6, "olc");
415             for(int i=0; i<3; i++) {
416                 bv.set(i*2,   odd.get(i));
417                 bv.set(i*2+1, even.get(i));
418             }
419             return (int)bv.toLong();
420         }
421     }
422     /** Get the 7 bit inner loop counter. The MSB is the zero bit.
423      * The low order 6 bits are the count */
424     public Ilc getILC() {
425         return new Ilc();
426     }
427     /** Get the A flag */
428     public boolean getFlagA() {
429         shiftReport(true, false);
430         return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(A_FLAG_NDX);
431     }
432     /** Get the B flag */
433     public boolean getFlagB() {
434         shiftReport(true, false);
435         return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(B_FLAG_NDX);
436     }
437     /** return value of instruction counter. Instruction counter counts 
438      * the instructions flowing through 1/2 of alternating FIFO.
439      * Caution: instruction counter is written by all scans, 
440      * regardless of readEnable or writeEnable! */
441     public long getInstructionCounter() {
442         shiftData(true, false);
443         BitVector count = cc.getOutBits(DATA_CHAIN+"."+INSTRUCTION_COUNTER_PATH);
444         int sz = count.getNumBits(); 
445         MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
446                          " expected: "+COUNTER_LENGTH);
447         return count.bitReverse().toLong();
448     }
449     /** return value of data counter. Data counter counts items flowing
450      * through drain stage of data proper stopper. 
451      * Caution: data counter is written by all scans, 
452      * regardless of readEnable or writeEnable! */
453     public long getDataCounter() {
454         shiftData(true, false);
455         BitVector count = cc.getOutBits(DATA_CHAIN+"."+DATA_COUNTER_PATH);
456         int sz = count.getNumBits(); 
457         MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
458                          " expected: "+COUNTER_LENGTH);
459         return count.bitReverse().toLong();
460     }
461     /** Fill the "North" Fifo ring */
462     public void fillNorthProperStopper() {
463         BitVector data = new BitVector(37, "empty");
464         BitVector addr = new BitVector(14, "empty");
465         for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
466         for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
467         fillNorthProperStopper(new MarinaPacket(data, false, addr));
468     }
469     /** Fill the "North" Fifo ring */
470     public void fillNorthProperStopper(MarinaPacket mp) {
471         prln("inserting into north: " + mp);
472         this.data.fill(mp.toSingleBitVector());
473     }
474     /** Enable the transmission of instructions from the instruction
475      * ring test structure to the EPI FIFO. */
476     public void enableInstructionSend(boolean b) {
477         BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
478         bv.set(INSTRUCTION_SEND_NDX, b);
479         cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
480         shiftControl(false, true);
481     } 
482     /** Enable the recirculation of instructions within the South FIFO */
483     public void enableInstructionRecirculate(boolean b) {
484         BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
485         bv.set(INSTRUCTION_RECIRCULATE_NDX, b);
486         cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
487         shiftControl(false, true);
488     }
489     /** get the number of tokens in the token FIFO.
490      * This includes the Token successor wire, the token FIFO wires,
491      * and Token predecessor wire.
492      * Master clear clears the token FIFO. */
493     public int getNumTokens() {
494         shiftReport(true, false);
495         // get the token successor and token FIFO wires
496         BitVector bv = cc.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
497         int sz = bv.getNumBits();
498         MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
499         
500         // get the token predecessor wire
501         BitVector pred = cc.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
502         sz = pred.getNumBits();
503         MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
504
505         // concatenate them
506         bv = bv.cat(pred);
507         sz = bv.getNumBits();
508         prln("Token state wires: "+bv.getState());
509         
510         int nbTok = 0;
511         for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
512         return nbTok;
513     }
514     /** Configure the test probe so it measures the throughput of
515      * the north data FIFO. The test probe frequency is 8192 
516      * times slower than the FIFO throughput. This control has
517      * highest priority. */
518     public void probeDataCounter(Boolean b) {
519         data.setGeneralPurposeOutput(b);
520     }
521     /** Configure the test probe so it measures the throughput of
522      * the alternating instruction FIFO. The test probe frequency is
523      * 1/16384 of the FIFO throughput. This control has second
524      * highest priority. Thus the following two calls probe the
525      * instruction counter: 
526      *      probeDataCounter(false);
527      *      probeInstructionCounter(true)
528      */
529     public void enableInstructionCounter(Boolean b) {
530         instrIn.setGeneralPurposeOutput(b);
531     }
532
533     public void fillSouthProperStopper(Instruction i) {
534         instrIn.fill(i);
535     }
536     public void fillSouthProperStopper(Instruction[] instructions) { fillSouthProperStopper(instructions, false); }
537     public void fillSouthProperStopper(Instruction[] instructions, boolean repeat) { fillSouthProperStopper(instructions, repeat, false); }
538     public void fillSouthProperStopper(Instruction[] instructions, boolean repeat, boolean leaveStopped) {
539         enableInstructionSend(false);
540         enableInstructionRecirculate(true);
541         for(Instruction i : instructions)
542             if (i!=null) {
543                 instrIn.fill(i);
544             } else {
545                 instrIn.fillTorpedo();
546             }
547         enableInstructionRecirculate(repeat);
548         enableInstructionSend(true);
549         if (!leaveStopped) instrIn.run();
550     }
551
552     
553 }