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