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