remove unused code in Marina tests
[fleet.git] / src / edu / berkeley / fleet / marina / MarinaTest.java
1 package edu.berkeley.fleet.marina;
2 /* -*- tab-width: 4 -*- */
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import com.sun.electric.tool.simulation.test.*;
7 import edu.berkeley.fleet.marina.Marina.Ilc;
8 import edu.berkeley.fleet.marina.CmdArgs;
9 import edu.berkeley.fleet.marina.CmdArgs.Mode;
10
11 import edu.berkeley.fleet.api.Dock;
12 import edu.berkeley.fleet.api.Instruction;
13 import edu.berkeley.fleet.api.Predicate;
14 import edu.berkeley.fleet.api.Instruction.Set.SetDest;
15 import edu.berkeley.fleet.api.Instruction.Set.SetSource;
16 import edu.berkeley.fleet.marina.MarinaFleet;
17 import edu.berkeley.fleet.marina.MarinaPath;
18
19 import java.io.*;
20
21 /**
22  * Tests for Marina
23  */
24 public class MarinaTest {
25     public static final MarinaFleet marinaFleet = new MarinaFleet();
26     public static final Dock dock = marinaFleet.getOnlyInputDock();
27
28     public static float vdd = 1.0f;
29
30     //--------------------------  constants -----------------------------------
31     private static final String SCAN_CHAIN_XML = "marina.xml";
32     private static final String NET_LIST = "marina.spi";
33
34     public static final int INSTR_SZ = 36;
35
36        
37     public static final Instruction.Set.FlagFunction CLEAR_FLAG 
38         = Instruction.Set.FlagFunction.ZERO;
39     public static final Instruction.Set.FlagFunction SET_FLAG 
40         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA)
41         .add(Predicate.NotFlagA);
42     public static final Instruction.Set.FlagFunction A_FLAG 
43         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA);
44
45     public static final Instruction.Set.FlagFunction B_FLAG 
46         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagB);
47     
48     // COLUMN_LATENCY is a delay that is larger than the latency through an Infinity column
49     private static final int COLUMN_LATENCY = 10; // nanoseconds
50
51
52     // Officially, this should be the number of requeueing no-ops that
53     // can be inserted into an idle dock whose OLC is nonzero.
54     //
55     // Less formally, this is roughly the number of stages of
56     // buffering between the instruction insertion point and the
57     // instruction ring, plus the capacity of the instruction ring.
58     private static final int INSTRUCTION_IN_SATURATION_AMOUNT = 19;
59
60     // This is some number which is significantly greater than
61     // INSTRUCTION_IN_SATURATION_AMOUNT.  Increasing it may slow the tests down, but
62     // will never cause them to operate incorrectly.
63     private static final int MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT = 25;
64         
65     // This is the number of items which can be in the instruction
66     // fifo ring WITHOUT causing it to stop circulating.
67     private static final int INSTRUCTION_RING_CAPACITY = 13;
68         
69     // Officially, this should be the number of data items which can
70     // be sent from the dock while the "data" proper stopper is in
71     // the "stopped" state
72     //
73     // Less formally, this is roughly the number of stages of
74     // buffering between the dock's data successor and the "data"
75     // proper stopper
76     /*
77       FIXME: what is the correct value here?
78       private static final int DATA_OUT_SATURATION_AMOUNT = XXX;
79     */
80
81     // This is some number which is greater than
82     // DATA_OUT_SATURATION_AMOUNT, but less than the capacity of the
83     // instruction fifo.
84     private static final int MORE_THAN_DATA_OUT_SATURATION_AMOUNT = 10;
85         
86     // Nominal cycle time assuming 4 GHz throughput
87     public static double CYCLE_TIME_NS;
88
89     //--------------------------------  types ---------------------------------
90
91     //--------------------------  private data --------------------------------
92     private static long startTime;
93
94     public static Indenter indenter = new Indenter();
95     private Marina marina;
96     private ChipModel model;
97     //private ChainControl cc;
98     //private JtagTester tester;
99     private CmdArgs cmdArgs;
100     private PowerChannel corePowerSupply, padsPowerSupply;
101     private VoltageReadable coreVoltmeter, voltmeterForCurrent;
102
103
104
105     private ChainTest ctD, ctR, ctC, ct;
106     private ChainControl ccD, ccR, ccC, cc;
107         
108     //--------------------------  private methods -----------------------------
109     /** @return true if simulation. Return false if we're testing silicon. */
110     private boolean sim() {return model instanceof SimulationModel;}
111         
112     private void prln(String msg) {indenter.prln(msg);}
113     private void pr(String msg) {indenter.pr(msg);}
114     private void adjustIndent(int n) {indenter.adjustIndent(n);}
115         
116     public static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
117
118     public static void fatalIfBitVectorsDoNotMatch(BitVector bv1, BitVector bv2) {
119         // FIXME: better error reporting needed here
120
121         fatal(bv1.getNumBits()!=bv2.getNumBits(), "lengths do not match");
122
123         boolean mismatch = false;
124         String err = "";
125         for(int i=0; i<bv1.getNumBits(); i++) {
126             if (bv1.get(i) != bv2.get(i)) {
127                 mismatch = true;
128                 err += ""+i+", ";
129             }
130         }
131         fatal(mismatch, "bit vectors do not match on bits " + err + "\n  "+bv1+"\n  "+bv2);
132     }
133
134     private static void printTestTime() {
135         long endTime = System.currentTimeMillis();
136         System.out.println("Test took: "+(endTime-startTime)/1000.0+"  sec");
137     }
138     
139     // Tell user what we're about to do
140     private static void reportTask(CmdArgs args) {
141         System.out.println("Begin testing Marina");
142         switch (args.mode) {
143             case WHOLE_CHIP_SCHEMATIC_PARASITICS:
144                 System.out.println("  Simulate whole chip, schematic parasitics");
145                 break;
146             case WHOLE_CHIP_LAYOUT_PARASITICS:
147                 System.out.println("  Simulate whole chip, layout parasitics");
148                 break;
149             case TEST_SILICON:
150                 System.out.println("  Test silicon");
151                 break;
152             default:
153                 fatal(true, "unrecognized CmdArgs.Mode");
154                 return;
155         }
156     }
157
158     private MarinaTest(String[] args) throws Exception {
159         cmdArgs = new CmdArgs(args);
160         reportTask(cmdArgs);
161         doSim();
162     }
163         
164     static PowerChannel vdd18;
165     static PowerChannel vdd10;
166     static PowerChannel vdds;
167
168     private void setVdd10(float v) {
169         if (vdd10==null) return;
170         vdd10.setVoltageWait(v);
171     }
172
173     private void doSim() throws Exception {
174         String netListName;
175         switch (cmdArgs.mode) {
176             case WHOLE_CHIP_SCHEMATIC_PARASITICS:
177                 netListName = NET_LIST; 
178                 break;
179             case WHOLE_CHIP_LAYOUT_PARASITICS:
180                 netListName = "marina_pads_guts.spi"; 
181                 break;
182             default:
183                 fatal(true, "unrecognized CmdArgs.Mode");
184                 return;
185         }
186
187
188         Infrastructure.gpibControllers = new int[]{1};
189         vdd18 = new Pst3202Channel("ch1", "tiPST3202", 1);
190         vdd18 = new Pst3202Channel("ch3", "tiPST3202", 3);
191         vdd10 = new PowerChannelResistorVoltageReadable(new Pst3202Channel("ch2", "tiPST3202", 2),
192                                                         1000, 
193                                                         new HP34401A("HP34970"),
194                                                         true);
195         
196         if (vdd10!=null) setVdd10(vdd);
197         if (vdd18!=null) vdd18.setVoltageNoWait(1.8f);
198
199         model = cmdArgs.useVerilog
200             ? new VerilogModel()
201             : cmdArgs.useHsim
202             ? new HsimModel()
203             : cmdArgs.silicon
204             ? new SiliconChip()
205             : new NanosimModel();
206             
207         if (model instanceof SimulationModel)
208             ((SimulationModel)model).setOptimizedDirectReadsWrites(true);
209
210         CYCLE_TIME_NS = cmdArgs.useVerilog ? (100*20) : 0.250;
211         int khz   =
212             model instanceof VerilogModel
213             ? 100000
214             : cmdArgs.jtagShift
215             ? 20000
216             : model instanceof ChipModel
217             ? 1000
218             : 1000000;
219
220         System.err.println("constructing jtag controller");
221         JtagTester tester =
222             model instanceof SimulationModel
223             ? ((SimulationModel)model).createJtagTester("TCK", "TMS", "TRSTb", "TDI", "TDO")
224             : new Netscan("jtag2");
225         //: new Netscan("10.0.0.200");
226         //: new Signalyzer();
227         //: new Netscan("jtag2");
228         JtagLogicLevel mc0=null;
229         JtagLogicLevel mc1=null;
230         if (tester instanceof NetscanGeneric) {
231             ((NetscanGeneric)tester).reset();
232             // master clear
233             // not sure if "GPIO1" means "index 0" or not
234             mc0 = new JtagLogicLevel(tester, 0);
235             mc1 = new JtagLogicLevel(tester, 1);
236             mc1 = mc0;
237             mc0.setLogicState(true);
238             mc1.setLogicState(true);
239         }
240         /*
241           Logger.setLogInits(true);
242           tester.setLogSets(true);
243           tester.setLogOthers(true);
244           tester.setAllLogging(true);
245           tester.printInfo = true;
246         */
247         tester.printInfo = false;
248
249         ChainControls ccs = new ChainControls();
250         PowerChannel pc = new ManualPowerChannel("pc", false);
251         /*
252           JtagTester testerD, testerR, testerC;
253           testerD = ((SimulationModel)model).createJtagSubchainTester("sid[1:9]", null); 
254           testerR = ((SimulationModel)model).createJtagSubchainTester("sir[1:9]", null); 
255           testerC = ((SimulationModel)model).createJtagSubchainTester("sic[1:9]", null); 
256           testerD.printInfo = testerR.printInfo = testerC.printInfo = false;
257
258           ccD = new ChainControl(SCAN_CHAIN_XML, testerD, 1.8f, khz);
259           ccR = new ChainControl(SCAN_CHAIN_XML, testerR, 1.8f, khz);
260           ccC = new ChainControl(SCAN_CHAIN_XML, testerC, 1.8f, khz);
261           ccD.noTestSeverity = ccR.noTestSeverity = ccC.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
262
263         
264           ctD = new ChainTest(ccD, pc);
265           ctR = new ChainTest(ccR, pc);
266           ctC = new ChainTest(ccC, pc);
267         */        
268         /*
269           ccs.addChain(Marina.DATA_CHAIN, ccD);
270           ccs.addChain(Marina.REPORT_CHAIN, ccR);
271           ccs.addChain(Marina.CONTROL_CHAIN, ccC);
272         */
273         /*
274           PowerChannel ch2 = new Pst3202Channel("ch2", "tiPST3202", 2);
275           PowerChannel ch3 = new Pst3202Channel("ch3", "tiPST3202", 3);
276           Infrastructure.gpibControllers = new int[]{1};
277           ch2.setVoltageNoWait(1f);
278           ch3.setVoltageNoWait(1.8f);
279         */
280
281
282         cc = new ChainControl(SCAN_CHAIN_XML, tester, 1.8f, khz);
283         cc.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
284         ct = new ChainTest(cc, pc);
285         ccs.addChain(Marina.DATA_CHAIN, cc);
286         ccs.addChain(Marina.REPORT_CHAIN, cc);
287         ccs.addChain(Marina.CONTROL_CHAIN, cc);
288         ccs.addChain(Marina.DUKE_CHAIN, cc);
289
290         marina = new Marina(ccs, model, !cmdArgs.jtagShift, indenter);
291         marina.mc0=mc0;
292         marina.mc1=mc1;
293
294         if (model instanceof NanosimModel) {
295             NanosimLogicSettable mc = (NanosimLogicSettable)
296                 ((SimulationModel)model).createLogicSettable(Marina.MASTER_CLEAR);
297             mc.setInitState(true);
298         }
299
300         prln("starting model");
301         if (model instanceof VerilogModel)
302             ((SimulationModel)model).start("verilog", "marina.v", VerilogModel.DUMPVARS, !cmdArgs.jtagShift);
303         else if (model instanceof HsimModel)
304             ((SimulationModel)model).start("hsim64", netListName, 0, !cmdArgs.jtagShift);
305         else if (model instanceof NanosimModel)
306             ((SimulationModel)model).start("nanosim -c cfg", netListName, 0, !cmdArgs.jtagShift);
307         else
308             {}
309         prln("model started");
310
311         model.waitNS(1000);
312         prln("deasserting master clear");
313         if (model instanceof SimulationModel)
314             ((SimulationModel)model).setNodeState(Marina.MASTER_CLEAR, 0);
315         else
316             marina.masterClear();
317         model.waitNS(1000);
318
319         if (cmdArgs.testNum!=0 && cmdArgs.testNum!=1) {
320             cc.resetInBits();
321             cc.shift(Marina.CONTROL_CHAIN, false, true);
322         }
323         
324         doOneTest(cmdArgs.testNum);
325
326         if (model instanceof SimulationModel)
327             ((SimulationModel)model).finish();
328     }
329
330     /** In the absence of looping, the longest path through Infinity is 4 column delays */
331     private void waitUntilQuiescent() {
332         model.waitNS(4*COLUMN_LATENCY);
333     }
334     
335    
336     /** Generate List of BitVectors where Token=true, high 25 data bits  
337      * are alternating ones and zeros, low 12 data bits increment from 
338      * zero, and address is given by addr. */
339     private List<BitVector> makeIncrDataConstAdr(int num, int addr) {
340         List<BitVector> ans = new ArrayList<BitVector>();
341         BitVector dHi = new BitVector(25, "dataHi");
342         BitVector dLo = new BitVector(12, "dataLo");
343         BitVector t = new BitVector("1", "token");
344         BitVector a = new BitVector(14, "addr");
345         dHi.setFromLong(0x00aaaaa);
346         a.setFromLong(addr);
347         for (int i=0; i<num; i++) {
348             dLo.setFromLong(i);
349             ans.add(dHi.cat(dLo).cat(t).cat(a));
350             dHi = dHi.not();
351         }
352         return ans;
353     }
354     private void stopToStop(ProperStopper s1, ProperStopper s2, 
355                             Counter ctr,
356                             List<BitVector> din) {
357         prln("Begin stopToStop");
358         adjustIndent(2);
359         
360         s1.stop();
361         
362         long ctrStart = ctr==null ? 0 : ctr.getCount();
363         
364         s1.fillMany(din);
365         waitUntilQuiescent();
366         
367         List<BitVector> dout = s2.drainMany();
368         
369         MarinaUtils.compareItemsOrdered(din, dout);
370         
371         if (ctr!=null) {
372             long ctrEnd = ctr.getCount();
373             long delta = ctrEnd - ctrStart;
374             long expect = din.size();
375             fatal(delta!=expect, 
376                   "counter delta wrong: expected delta: "+expect+
377                   " counter before:"+ctrStart+" counter after:"+ctrEnd);
378         }
379         
380         adjustIndent(-2);
381         prln("End stopToStop");
382     }
383     /** Burst data from src to dst. gate is stopped while loading src. gate
384      * is then run to allow the burst to flow. */
385     private void stopToStopBurst(ProperStopper src, ProperStopper gate, 
386                                  ProperStopper dst,
387                                  Counter ctr,
388                                  List<BitVector> din) {
389         prln("Begin stopToStopBurst test");
390         adjustIndent(2);
391                 
392         src.stop();
393         gate.stop();
394                 
395         long ctrStart = ctr==null ? 0 : ctr.getCount();
396                 
397         src.fillMany(din);
398         waitUntilQuiescent();
399
400         // open the gate to start the burst
401         gate.run();
402         waitUntilQuiescent();
403                 
404         List<BitVector> dout = dst.drainMany();
405                 
406         MarinaUtils.compareItemsOrdered(din, dout);
407                 
408         if (ctr!=null) {
409             long ctrEnd = ctr.getCount();
410             long delta = ctrEnd - ctrStart;
411                 
412             long expectA = din.size();
413             fatal(delta!=expectA, 
414                   "counter delta wrong: expected delta: "+expectA+
415                   " counter before:"+ctrStart+" counter after:"+ctrEnd);
416         }
417                 
418         adjustIndent(-2);
419         prln("End stopToStopBurst test");
420     }
421
422     private void stopToStopOne(ProperStopper s1, ProperStopper s2, 
423                                Counter ctr, int adr) {
424         prln("Begin stopToStopOne");
425         adjustIndent(2);
426         
427         List<BitVector> din = makeIncrDataConstAdr(1, adr);
428         stopToStop(s1, s2, ctr, din);
429
430         adjustIndent(-2);
431         prln("End stopToStopOne");
432     }
433     
434     private void stopToStopThree(ProperStopper s1, ProperStopper s2, 
435                                  Counter ctr, int adr) {
436         prln("Begin stopToStopOne");
437         adjustIndent(2);
438         
439         List<BitVector> din = makeIncrDataConstAdr(3, adr);
440         stopToStop(s1, s2, ctr, din);
441
442         adjustIndent(-2);
443         prln("End stopToStopOne");
444     }
445
446     private int indexOf(BitVector o, List<BitVector> dIn) {
447         for (int i=0; i<dIn.size(); i++) {
448             if (o.equals(dIn.get(i)))  return i;
449         }
450         return -1;
451     }
452     private String ringDump(List<BitVector> dIn, List<BitVector> dOut) {
453         StringBuffer sb = new StringBuffer();
454         sb.append("  ring dump: ");
455         for (BitVector o : dOut) {
456             sb.append(indexOf(o, dIn)+" ");
457         }
458         return sb.toString();
459     }
460
461     private int[][] makeIntArray2D(int a, int b) {
462         int[][] ans = new int[a][];
463         for (int i=0; i<a; i++) ans[i] = new int[b];
464         return ans;
465     }
466
467     //=========================================================================
468     // Put top level tests here
469
470     private void testChains(Marina marina) {
471         if (ctC!=null) {
472             prln("Testing control chain...");
473             ctC.testOneChain(Marina.CONTROL_CHAIN, Infrastructure.SEVERITY_WARNING);
474             ccC.resetInBits();
475             ccC.shift(Marina.CONTROL_CHAIN, false, true);
476         }
477         
478         if (ctD!=null) {
479             prln("Testing data chain...");
480             ctD.testOneChain(Marina.DATA_CHAIN, Infrastructure.SEVERITY_WARNING);
481             //ccD.resetInBits();
482             //ccD.shift(Marina.DATA_CHAIN, false, true);
483         }
484         
485         if (ctR!=null) {
486             prln("Testing report chain...");            
487             ctR.testOneChain(Marina.REPORT_CHAIN, Infrastructure.SEVERITY_WARNING);
488             //ccR.resetInBits();
489             //ccR.shift(Marina.REPORT_CHAIN, false, true);
490         }
491
492         if (ct!=null) {
493             prln("Testing control chain...");
494             ct.testOneChain(Marina.CONTROL_CHAIN, Infrastructure.SEVERITY_WARNING);
495             cc.resetInBits();
496             cc.shift(Marina.CONTROL_CHAIN, false, true);
497             prln("Testing data chain...");
498             ct.testOneChain(Marina.DATA_CHAIN, Infrastructure.SEVERITY_WARNING);
499             prln("Testing report chain...");            
500             ct.testOneChain(Marina.REPORT_CHAIN, Infrastructure.SEVERITY_WARNING);
501         }
502     }
503
504     private void testProperStoppers(Marina marina) {
505         prln("Begin testProperStoppers");
506         adjustIndent(2);
507
508         for(ProperStopper ps : new ProperStopper[] { marina.data, marina.instrIn }) {
509
510             prln("testing " + (ps == marina.data ? "data" : "instruction") + " stopper");
511             adjustIndent(2);
512
513             prln("un-stopping stopper");
514             ps.run();
515             fatal( ps.getStopped(), "stopper should not have been stopped, but was");
516
517             prln("stopping stopper");
518             ps.stop();
519             fatal( !ps.getStopped(), "stopper should have been stopped, but was not");
520
521             adjustIndent(-2);
522         }
523
524         adjustIndent(-2);
525     }
526
527     private void sendInstructions(Marina marina) {
528         prln("Begin sendInstructions");
529         adjustIndent(2);
530         
531         List<BitVector> din = new ArrayList<BitVector>();
532
533         BitVector count = new BitVector(MarinaPacket.WORD_WIDTH,"count");
534         BitVector one = new BitVector(MarinaPacket.WORD_WIDTH, "one");
535         count.setFromLong(0);
536         one.setFromLong(1);
537         for (int i=0; i<3; i++) {
538             din.add(count);
539             count = count.add(one);
540         }
541
542         for(BitVector d : din)
543             marina.instrIn.fill(new MarinaPacket(d, false, MarinaPacket.null_path));
544
545         adjustIndent(-2);
546         prln("End sendInstructions");
547     }
548
549     private void sendToken(Marina marina) {
550         prln("Begin sendToken");
551         adjustIndent(2);
552         
553         //getCtrsFlags(marina);
554         
555         int nbToks = marina.getNumTokens();
556         fatal(nbToks!=0, "Expected no tokens on initialization but got: "+nbToks+" tokens");
557
558         marina.instrIn.fill(setIlc(1));
559         marina.instrIn.fill(SEND_TOKEN);
560         nbToks = marina.getNumTokens();
561         fatal(nbToks!=1, "Expected one token to emerge but got: "+nbToks+" tokens");
562         
563         adjustIndent(-2);
564         prln("End sendToken");
565     }
566
567     private void sendData(Marina marina) {
568         prln("Begin sendData");
569         adjustIndent(2);
570         
571         edu.berkeley.fleet.api.BitVector bv = new edu.berkeley.fleet.api.BitVector(13);
572         for(int i=0; i<bv.length(); i+=2) bv.set(i, false);
573         MarinaPath path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(), bv);
574
575         marina.instrIn.fill(setIlc(1));
576         marina.instrIn.fill(SEND_DATA);
577         
578         List<BitVector> dataItems = marina.data.drainMany();
579         fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
580
581         MarinaPacket mp = new MarinaPacket(dataItems.get(0));
582         fatal(mp.tokenhood, "Expected tokenhood=data, but got tokenhood=token");
583
584         adjustIndent(-2);
585         prln("End sendData");
586     }
587
588     private void sendDataIlcInfinite(Marina marina) {
589         prln("Begin sendDataIlcInfinite");
590         adjustIndent(2);
591         
592         marina.fillSouthProperStopper(new Instruction[] {
593                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.Infinity),
594                 SEND_DATA,
595             });
596         
597         // more than MAX_ILC
598         int howmany = 70;
599         List<BitVector> dataItems = marina.data.drainMany(howmany);
600         fatal(dataItems.size()!=howmany,
601               "Expected an unending supply of data items to emerge but only got got: "+dataItems.size());
602
603         adjustIndent(-2);
604         prln("End sendDataIlcInfinite");
605     }
606
607     private Instruction setOlc(int olc) {
608         return new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, olc);
609     }
610     private Instruction setOlcIfZero(int olc) {
611         return new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter, olc);
612     }
613     private Instruction setIlc(int ilc) {
614         return new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, ilc);
615     }
616
617     private void testFlagD(Marina marina) {
618         prln("Begin testFlagD");
619         adjustIndent(2);
620         
621         List<BitVector> toks;
622
623         Predicate only_if_olc_zero    = Predicate.FlagD;
624         Predicate only_if_olc_nonzero = Predicate.Default;
625
626         marina.instrIn.fill(setIlc(1));
627
628         for(int olc : new int[] { 1, 0 }) {
629             for(boolean predicate_olc_nonzero : new boolean[] { true, false }) {
630                 prln("Attempting send data item with "+
631                      "olc=="+olc+" and "+
632                      "predicate olc"+(predicate_olc_nonzero?"!=0":"==0"));
633                 adjustIndent(2);
634
635                 marina.fillSouthProperStopper(new Instruction[] {
636                         setOlc(olc),
637                         new Instruction.Move(dock,
638                                              predicate_olc_nonzero  // predicate   
639                                              ? only_if_olc_nonzero
640                                              : only_if_olc_zero
641                                              ,
642                                              false,                 // torpedoable 
643                                              null,                  // path        
644                                              false,                 // tokenIn     
645                                              false,                 // dataIn      
646                                              false,                 // latchData   
647                                              false,                 // latchPath   
648                                              true,                  // dataOut     
649                                              false                  // tokenOut    
650                                              ),
651                     });
652                 expectNorthFifoExactly((predicate_olc_nonzero == (olc!=0)) ? 1 : 0);
653
654                 for(int i=0; i<olc; i++)
655                     marina.instrIn.fill(DEC);
656
657                 adjustIndent(-2);
658             }
659         }
660         adjustIndent(-2);
661         prln("End testFlagD");
662     }
663
664     private void testPredicationOnAB(Marina marina) {
665         prln("Begin testPredicationOnAB");
666         adjustIndent(2);
667         
668         List<BitVector> dItems;
669
670         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 1));
671         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 1));
672
673         for(boolean flag_a : new boolean[] { false, true }) {
674             for(boolean flag_b : new boolean[] { false, true }) {
675                 prln("Setting flags, a="+flag_a+" b="+flag_b);
676                 marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,
677                                                         flag_a
678                                                         ? Instruction.Set.FlagFunction.ONE
679                                                         : Instruction.Set.FlagFunction.ZERO,
680                                                         flag_b
681                                                         ? Instruction.Set.FlagFunction.ONE
682                                                         : Instruction.Set.FlagFunction.ZERO
683                                                         ));
684                 getCtrsFlags(marina);
685
686                 adjustIndent(2);
687                 for(Predicate predicate : new Predicate[] {
688                         Predicate.Default,
689                         Predicate.FlagA,
690                         Predicate.FlagB,
691                         Predicate.NotFlagA,
692                         Predicate.NotFlagB,
693                     }) {
694
695                     prln("Attempting send data with a="+flag_a+", b="+flag_b+", predicate="+predicate);
696                     adjustIndent(2);
697                     marina.instrIn.fill(new Instruction.Move(dock,
698                                                              predicate,  // predicate   
699                                                              false,      // torpedoable 
700                                                              null,       // path        
701                                                              false,      // tokenIn     
702                                                              false,      // dataIn      
703                                                              false,      // latchData   
704                                                              false,      // latchPath   
705                                                              true,       // dataOut     
706                                                              false       // tokenOut    
707                                                              ));
708                     adjustIndent(-2);
709                     dItems = marina.data.drainMany();
710                     int expected = predicate.evaluate(flag_a, flag_b, false, false) ? 1 : 0;
711                     fatal(dItems.size()!=expected, "Expected "+expected+" data items to emerge but got: "+
712                           dItems.size()+" items(s)");
713                 }
714                 adjustIndent(-2);
715             }
716         }
717         adjustIndent(-2);
718         prln("End testPredicationOnAB");
719     }
720
721
722     private void showOlc() {
723         prln("OLC=="+marina.getOLC());
724     }
725     private void expectOlc(int x) {
726         int olc = marina.getOLC();
727         fatal(x!=olc, "expected OLC=="+x+", but scanned out OLC=="+olc);
728     }
729
730     private void getCtrsFlags(Marina marina) {
731         prln("begin getCtrsFlags");
732         adjustIndent(2);
733         
734         showOlc();
735         Ilc ilc = marina.getILC();
736         prln("ILC.done=="+ilc.getDone()+
737              " ILC.infinity=="+ilc.getInfinity()+
738              " ILC.count=="+ilc.getCount());
739         prln("flagA=="+marina.getFlagA());
740         prln("flagB=="+marina.getFlagB());
741         adjustIndent(-2);
742         prln("end getCtrsFlags");
743     }
744
745     private void walkOneOLC(Marina marina) {
746         prln("Begin walkOneOLC");
747         adjustIndent(2);
748         /*
749         //for (int i=-1; i<6; i++) {
750         marina.fillSouthProperStopper(new Instruction[] {
751
752         new Instruction.Head(dock),
753
754         //                new Instruction.Set(dock,Predicate.IgnoreFlagD, SetDest.OuterLoopCounter, 1),
755         FLAG_NOP,
756         FLAG_NOP,
757         FLAG_NOP,
758         TORPEDOABLE_RECV_DATA,
759         FLAG_NOP,
760         FLAG_NOP,
761         FLAG_NOP,
762
763
764         //new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, SetSource.Decrement),
765                 
766         new Instruction.Tail(dock),
767         });
768         marina.fillSouthProperStopper(new Instruction[] {
769         null,
770         },
771         true);
772         while(true) {
773         BitVector bits = null;
774         marina.shiftReport(true, false);
775         for(int i=0; i<4; i++) {
776         BitVector x = marina.cc.getOutBits(marina.REPORT_CHAIN+"."+marina.OLC_PATH_KESSEL+i);
777         //System.out.println("bits are: " + x);
778         bits = bits==null ? x : bits.cat(x);
779         }
780         System.out.println("dec="+bits.get(0));
781         if (bits.get(1)) throw new RuntimeException();
782         }
783         */
784         /*        for (int i=0; i<64; i++) {
785
786                   if (marina.kesselsCounter) {
787                   System.out.println("master-clearing...");
788                   // master clear on each iteration; otherwise we'd need to "run down" the olc
789                   marina.masterClear();
790                   marina.enableInstructionSend(true);
791                   }
792
793                   expectTokensExactly(0);
794                   marina.getOLC();
795
796                   int inOlc = i==-1 ? 0 : (1<<i);
797                   inOlc = i;
798                   marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, inOlc));
799                   marina.instrIn.fill(SEND_DATA_IF_D_SET);
800                   marina.instrIn.fill(SEND_DATA_IF_D_NOT_SET);
801                   marina.instrIn.fill(SEND_DATA);
802
803                   model.waitNS(128 * CYCLE_TIME_NS);
804
805                   expectOlc(inOlc);
806                   prln("walkOneOLC: "+inOlc+" checks out");
807                   expectNorthFifoExactly(0);
808                   }
809                   adjustIndent(-2);
810                   prln("End walkOneOLC");
811         */
812     }
813     private void walkOneILC(Marina marina) {
814         prln("Begin walkOneILC");
815         adjustIndent(2);
816         for (int i=0; i<6; i++) {
817             // Mask off the "zero" bit position
818             int inIlc = 1 << i;
819             prln("inIlc="+inIlc);
820             marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, inIlc));
821             Ilc ilc = marina.getILC();
822             int outIlc = ilc.getCount();
823             fatal(outIlc!=inIlc, "bad ILC count: "+outIlc+" expected: "+inIlc);
824             fatal(ilc.getInfinity(), "bad Infinity bit: true");
825         }
826         prln("Now test the infinity bit");
827         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, SetSource.Infinity));
828         Ilc ilc = marina.getILC();
829         fatal(!ilc.getInfinity(), "bad Infinity bit: false");
830         adjustIndent(-2);
831         prln("End walkOneILC");
832     }
833     private void countIlc(Marina marina) {
834         final int maxIlc = 63;
835         prln("Begin countIlc");
836         adjustIndent(2);
837         
838         marina.instrIn.fill(new 
839                             Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, maxIlc));
840
841         int ilc = marina.getILC().getCount();
842         fatal(ilc!=maxIlc, "bad ILC count: "+ilc+" expected: "+maxIlc);
843                 
844         prln("execute a move instruction that does nothing except decrement the ILC to zero");
845         marina.instrIn.fill(
846                             new Instruction.Move(dock,
847                                                  Predicate.IgnoreFlagD, // predicate   
848                                                  false,                 // torpedoable 
849                                                  null,                  // path        
850                                                  false,                 // tokenIn     
851                                                  false,                 // dataIn      
852                                                  false,                 // latchData   
853                                                  false,                 // latchPath   
854                                                  false,                 // dataOut     
855                                                  false                  // tokenOut    
856                                                  ));
857         
858         // wait for ILC to count from 63 to 0
859         model.waitNS(128 * CYCLE_TIME_NS);
860         //model.waitNS(10000);
861
862         prln("Check that ILC==0");
863         ilc = marina.getILC().getCount();
864         fatal(ilc!=0, "bad ILC count: "+ilc+" expected: "+0);
865         
866         adjustIndent(-2);
867         prln("End countIlc");
868     }
869     // Note: countOlc takes 44 minutes to run on nanosim
870     private void countOlc(Marina marina) {
871         int maxOlc = 63;
872         prln("Begin countOlc");
873         adjustIndent(2);
874
875         marina.instrIn.fill(setOlc(maxOlc));
876
877         for (int i=maxOlc; i>=0; i--) {
878             model.waitNS(128 * CYCLE_TIME_NS);
879             prln("OLC should be: "+i);
880             expectOlc(i);
881             marina.instrIn.fill(new 
882                                 Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, SetSource.Decrement));
883         }
884
885         adjustIndent(-2);
886         prln("End countOlc");
887     }
888     private void loadEveryValueOLC(Marina marina) {
889         adjustIndent(2);
890         //while(true)
891         for (int i=0; i<(1<<6); i++) {
892
893             if (marina.kesselsCounter) {
894                 System.out.println("master-clearing...");
895                 // master clear on each iteration; otherwise we'd need to "run down" the olc
896                 marina.masterClear();
897                 marina.enableInstructionSend(true);
898             }
899
900             int inOlc = i;
901             marina.fillSouthProperStopper(new Instruction[] {
902
903                     setIlc(1),
904
905                     // to ensure that instruction is bubble-limited
906                     RECV_DATA,
907
908                     // the Set-OLC instruction
909                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, inOlc),
910
911                     // put a Set-ILC instruction right behind it with inverted bits to be sure we're
912                     // not capturing the instruction-latch value too late in the cycle
913                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, (inOlc ^ (~(-1<<6)))),
914                     
915                 });
916
917             model.waitNS(128 * CYCLE_TIME_NS);
918             marina.fillNorthProperStopper();
919             model.waitNS(128 * CYCLE_TIME_NS);
920
921             expectOlc(inOlc);
922             prln("loadEveryValueOLC: "+inOlc+" checks out");
923         }
924         adjustIndent(-2);
925     }
926
927     private void saturateInstructionFifo(Marina marina, Instruction instruction, int quantity, boolean expect_it_to_jam_up) {
928         prln("Inserting "+quantity+" copies of \"" + instruction + "\"");
929         adjustIndent(2);
930         int i=0;
931         for(i=0; i<quantity; i++) {
932             prln("Inserting instruction " + (i+1) +"/"+ quantity);
933             marina.instrIn.fill(instruction);
934             boolean jammed = (marina.instrIn.getFillStateWire()==MarinaUtils.StateWireState.FULL);
935             if (jammed && expect_it_to_jam_up) {
936                 prln("Stopper remained full after inserting instruction; this was expected; we are happy.");
937                 adjustIndent(-2);
938                 return;
939             }
940             fatal(jammed, "Instruction stopper did not drain after inserting " + (i+1) + " instructions; not good!");
941         }
942         fatal(expect_it_to_jam_up, "Expected instruction stopper to jam up, but it did not");
943         adjustIndent(-2);
944         prln("Successfully inserted " + i + " instructions");
945     }
946
947     private static MarinaPath null_path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(),
948                                                          MarinaUtils.sunToBerk(MarinaPacket.null_path));
949
950     private static final Instruction DEC = 
951         new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter, SetSource.Decrement);
952
953     private static final Instruction FLAG_NOP =
954         new Instruction.Set(dock, Predicate.IgnoreFlagD,
955                             CLEAR_FLAG.add(Predicate.FlagA),
956                             CLEAR_FLAG.add(Predicate.FlagB));
957
958     private static final Instruction FLAG_NOP_IF_FLAG_A =
959         new Instruction.Set(dock, Predicate.FlagA,
960                             CLEAR_FLAG.add(Predicate.FlagA),
961                             CLEAR_FLAG.add(Predicate.FlagB));
962
963     private static final Instruction NOP =
964         new Instruction.Move(dock,
965                              Predicate.IgnoreFlagD, /* predicate   */
966                              false,                 /* torpedoable */
967                              null,                  /* path        */
968                              false,                 /* tokenIn     */
969                              false,                 /* dataIn      */
970                              false,                 /* latchData   */
971                              false,                 /* latchPath   */
972                              false,                 /* dataOut     */
973                              false                  /* tokenOut    */
974                              );
975
976     private static final Instruction SEND_DATA =
977         new Instruction.Move(dock,
978                              Predicate.IgnoreFlagD,   /* predicate   */
979                              false,                 /* torpedoable */
980                              null_path,                  /* path        */
981                              false,                 /* tokenIn     */
982                              false,                 /* dataIn      */
983                              false,                 /* latchData   */
984                              false,                 /* latchPath   */
985                              true,                  /* dataOut     */
986                              false                  /* tokenOut    */
987                              );
988
989     private static final Instruction SEND_DATA_IF_D_NOT_SET =
990         new Instruction.Move(dock,
991                              Predicate.Default,     /* predicate   */
992                              false,                 /* torpedoable */
993                              null_path,             /* path        */
994                              false,                 /* tokenIn     */
995                              false,                 /* dataIn      */
996                              false,                 /* latchData   */
997                              false,                 /* latchPath   */
998                              true,                  /* dataOut     */
999                              false                  /* tokenOut    */
1000                              );
1001
1002     private static final Instruction SEND_DATA_IF_A_SET_AND_D_NOT_SET =
1003         new Instruction.Move(dock,
1004                              Predicate.FlagA,       /* predicate   */
1005                              false,                 /* torpedoable */
1006                              null_path,             /* path        */
1007                              false,                 /* tokenIn     */
1008                              false,                 /* dataIn      */
1009                              false,                 /* latchData   */
1010                              false,                 /* latchPath   */
1011                              true,                  /* dataOut     */
1012                              false                  /* tokenOut    */
1013                              );
1014
1015     private static final Instruction SEND_DATA_IF_D_SET =
1016         new Instruction.Move(dock,
1017                              Predicate.FlagD,       /* predicate   */
1018                              false,                 /* torpedoable */
1019                              null_path,             /* path        */
1020                              false,                 /* tokenIn     */
1021                              false,                 /* dataIn      */
1022                              false,                 /* latchData   */
1023                              false,                 /* latchPath   */
1024                              true,                  /* dataOut     */
1025                              false                  /* tokenOut    */
1026                              );
1027
1028     private static final Instruction SEND_TOKEN_IF_D_SET =
1029         new Instruction.Move(dock,
1030                              Predicate.FlagD,       /* predicate   */
1031                              false,                 /* torpedoable */
1032                              null_path,             /* path        */
1033                              false,                 /* tokenIn     */
1034                              false,                 /* dataIn      */
1035                              false,                 /* latchData   */
1036                              false,                 /* latchPath   */
1037                              false,                 /* dataOut     */
1038                              true                   /* tokenOut    */
1039                              );
1040
1041     private static final Instruction SEND_TOKEN_IF_D_NOT_SET =
1042         new Instruction.Move(dock,
1043                              Predicate.Default,     /* predicate   */
1044                              false,                 /* torpedoable */
1045                              null_path,             /* path        */
1046                              false,                 /* tokenIn     */
1047                              false,                 /* dataIn      */
1048                              false,                 /* latchData   */
1049                              false,                 /* latchPath   */
1050                              false,                 /* dataOut     */
1051                              true                   /* tokenOut    */
1052                              );
1053
1054     private static final Instruction TORPEDOABLE_RECV_DATA =
1055         new Instruction.Move(dock,
1056                              Predicate.IgnoreFlagD, /* predicate   */
1057                              true,                  /* torpedoable */
1058                              null,                  /* path        */
1059                              false,                 /* tokenIn     */
1060                              true,                  /* dataIn      */
1061                              true,                  /* latchData   */
1062                              false,                 /* latchPath   */
1063                              false,                 /* dataOut     */
1064                              false                  /* tokenOut    */
1065                              );
1066
1067     private static final Instruction RECV_DATA =
1068         new Instruction.Move(dock,
1069                              Predicate.IgnoreFlagD,   /* predicate   */
1070                              false,                 /* torpedoable */
1071                              null,                  /* path        */
1072                              false,                 /* tokenIn     */
1073                              true,                  /* dataIn      */
1074                              true,                  /* latchData   */
1075                              false,                 /* latchPath   */
1076                              false,                 /* dataOut     */
1077                              false                  /* tokenOut    */
1078                              );
1079
1080     private static final Instruction SEND_TOKEN =
1081         new Instruction.Move(dock,
1082                              Predicate.IgnoreFlagD,   /* predicate   */
1083                              false,                 /* torpedoable */
1084                              null_path,                  /* path        */
1085                              false,                 /* tokenIn     */
1086                              false,                 /* dataIn      */
1087                              false,                 /* latchData   */
1088                              false,                 /* latchPath   */
1089                              false,                 /* dataOut     */
1090                              true                   /* tokenOut    */
1091                              );
1092
1093     private static final Instruction RECV_TOKEN =
1094         new Instruction.Move(dock,
1095                              Predicate.IgnoreFlagD,   /* predicate   */
1096                              false,                 /* torpedoable */
1097                              null,                  /* path        */
1098                              true,                  /* tokenIn     */
1099                              false,                 /* dataIn      */
1100                              false,                 /* latchData   */
1101                              false,                 /* latchPath   */
1102                              false,                 /* dataOut     */
1103                              false                  /* tokenOut    */
1104                              );
1105
1106
1107     private void expectNorthFifoNoMoreThan(int num) {
1108         model.waitNS(128 * CYCLE_TIME_NS);
1109         List<BitVector> dataItems = marina.data.drainMany(num+1);
1110         fatal(dataItems.size()>num,
1111               "Expected no more than "+num+
1112               " data items to emerge but got at least: "+dataItems.size());
1113     }
1114     private void expectNorthFifoExactly(int num) {
1115         model.waitNS(128 * CYCLE_TIME_NS);
1116         List<BitVector> dataItems = marina.data.drainMany(num+1);
1117         fatal(dataItems.size()!=num,
1118               "Expected exactly "+num+
1119               " data items to emerge but got at least: "+dataItems.size());
1120     }
1121     private void expectNorthFifoAtLeast(int num) {
1122         model.waitNS(128 * CYCLE_TIME_NS);
1123         List<BitVector> dataItems = marina.data.drainMany(num);
1124         fatal(dataItems.size()<num,
1125               "Expected at least "+num+
1126               " data items to emerge but got only: "+dataItems.size());
1127     }
1128     private void expectTokensNoMoreThan(int num) {
1129         int x = marina.getNumTokens();
1130         List<BitVector> dataItems = marina.data.drainMany(num+1);
1131         fatal(x>num,
1132               "Expected no more than "+num+
1133               " tokens to emerge but got at least: "+x);
1134     }
1135     private void expectTokensExactly(int num) {
1136         int x = marina.getNumTokens();
1137         fatal(x!=num,
1138               "Expected exactly "+num+
1139               " tokens but got at least: "+x);
1140     }
1141
1142     private void testFlagDRecomputationTime(Marina marina) {
1143         marina.instrIn.fill(setIlc(1));
1144         marina.fillSouthProperStopper(new Instruction[] {
1145                 RECV_DATA,
1146                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,0),
1147                 SEND_DATA_IF_D_NOT_SET
1148             });
1149         marina.fillNorthProperStopper();
1150         expectNorthFifoNoMoreThan(0);
1151
1152         marina.fillSouthProperStopper(new Instruction[] {
1153                 RECV_DATA,
1154                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,1),
1155                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.Decrement),
1156                 SEND_DATA_IF_D_NOT_SET
1157             });
1158         marina.fillNorthProperStopper();
1159         expectNorthFifoNoMoreThan(0);
1160
1161         marina.fillSouthProperStopper(new Instruction[] {
1162                 RECV_DATA,
1163                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,2),
1164                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.Decrement),
1165                 SEND_DATA_IF_D_NOT_SET
1166             });
1167         marina.fillNorthProperStopper();
1168         expectNorthFifoExactly(1);
1169         marina.instrIn.fill(DEC);
1170
1171         marina.fillSouthProperStopper(new Instruction[] {
1172                 RECV_DATA,
1173                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,0),
1174                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,1),
1175                 SEND_DATA_IF_D_NOT_SET
1176             });
1177         marina.fillNorthProperStopper();
1178         expectNorthFifoExactly(1);
1179     }
1180
1181     private void testTailWaitsForHead(Marina marina) {
1182         marina.instrIn.fill(setIlc(1));
1183         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63));
1184         
1185         marina.enableInstructionSend(false);
1186         marina.enableInstructionRecirculate(true);
1187         
1188         marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
1189         marina.instrIn.fill(new Instruction.Head(dock));
1190         marina.instrIn.fill(SEND_DATA);
1191         marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
1192         marina.instrIn.fill(SEND_TOKEN);
1193         marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
1194         marina.instrIn.fill(new Instruction.Tail(dock));
1195         marina.instrIn.fillTorpedo();
1196         
1197         marina.enableInstructionRecirculate(false);
1198         marina.enableInstructionSend(true);
1199         marina.instrIn.run();
1200         
1201         expectNorthFifoNoMoreThan(0);
1202         prln("inserting into north proper stopper");
1203         marina.fillNorthProperStopper();
1204         expectNorthFifoExactly(1);
1205         int nbToks = marina.getNumTokens();
1206         fatal(nbToks!=1, "Expected one token to emerge but got: "+nbToks+" tokens");
1207     }
1208
1209     /*
1210       marina.instrIn.fill(setIlc(1));
1211       marina.instrIn.fill(setOlc(1));
1212
1213       // this makes the head wait for the torpedo
1214       marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
1215
1216       // the head should wait for the tail
1217       marina.instrIn.fill(new Instruction.Head(dock));
1218       marina.instrIn.fill(NOP);
1219       marina.instrIn.fill(SEND_DATA);
1220       marina.instrIn.fill(RECV_DATA);
1221
1222       expectNorthFifoNoMoreThan(0);
1223
1224       marina.instrIn.fillTorpedo();
1225       expectNorthFifoNoMoreThan(0);
1226
1227       marina.instrIn.fill(new Instruction.Tail(dock));
1228       expectNorthFifoExactly(1);
1229     */
1230
1231     private void testTailWithoutHead(Marina marina) {
1232         marina.instrIn.fill(setIlc(1));
1233         marina.fillSouthProperStopper(new Instruction[] {
1234                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63),
1235                 new Instruction.Tail(dock),
1236                 SEND_DATA,
1237             });
1238         List<BitVector> dataItems = marina.data.drainMany(1);
1239         fatal(dataItems.size()!=0, "Expected exactly no data items to emerge but got at least: "+dataItems.size());
1240     }
1241
1242     private void testHeadWaitsForTail(Marina marina) {
1243         List<BitVector> dataItems;
1244
1245         prln("Begin testHeadWaitsForTail");
1246         adjustIndent(2);
1247
1248         marina.instrIn.fill(setIlc(1));
1249         marina.fillSouthProperStopper(new Instruction[] {
1250                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63),
1251                 new Instruction.Head(dock),
1252                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
1253                 SEND_DATA,
1254             });
1255
1256         expectNorthFifoExactly(0);
1257         marina.instrIn.fill(new Instruction.Tail(dock));
1258         expectNorthFifoAtLeast(1);
1259
1260         adjustIndent(-2);
1261         prln("End testHeadWaitsForTail");
1262     }
1263
1264     private void testNonTorpedoableMoveDoesNotResetDFlag(Marina marina) {
1265         marina.instrIn.fill(setIlc(1));
1266         marina.fillSouthProperStopper(new Instruction[] {
1267                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,63),
1268                 new Instruction.Move(dock,
1269                                      Predicate.IgnoreFlagD, // predicate   
1270                                      true,                  // torpedoable 
1271                                      null,                  // path        
1272                                      true,                  // tokenIn     
1273                                      false,                 // dataIn      
1274                                      false,                 // latchData   
1275                                      false,                 // latchPath   
1276                                      false,                 // dataOut     
1277                                      false                  // tokenOut    
1278                                      ),
1279                 new Instruction.Move(dock,
1280                                      Predicate.FlagD,       // predicate   
1281                                      false,                 // torpedoable 
1282                                      null,                  // path        
1283                                      false,                 // tokenIn     
1284                                      false,                 // dataIn      
1285                                      false,                 // latchData   
1286                                      false,                 // latchPath   
1287                                      true,                  // dataOut     
1288                                      false                  // tokenOut    
1289                                      ),
1290             });
1291         marina.instrIn.fillTorpedo();
1292         expectNorthFifoExactly(1);
1293         marina.fillSouthProperStopper(new Instruction[] {
1294                 new Instruction.Move(dock,
1295                                      Predicate.Default,     // predicate   
1296                                      false,                 // torpedoable 
1297                                      null,                  // path        
1298                                      false,                 // tokenIn     
1299                                      false,                 // dataIn      
1300                                      false,                 // latchData   
1301                                      false,                 // latchPath   
1302                                      true,                  // dataOut     
1303                                      false                  // tokenOut    
1304                                      ),
1305             });
1306         expectNorthFifoNoMoreThan(0);
1307     }
1308
1309     private void testAbort(Marina marina) {
1310         
1311         marina.instrIn.fill(setIlc(1));
1312         marina.fillSouthProperStopper(new Instruction[] {
1313                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.DataLatch,1),
1314                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,2),
1315                 SEND_DATA_IF_D_NOT_SET,
1316                 new Instruction.Head(dock),
1317                 SEND_DATA_IF_D_NOT_SET,
1318                 new Instruction.Set(dock,Predicate.Default,SetDest.DataLatch,2),
1319                 new Instruction.Abort(dock, Predicate.FlagD),
1320                 new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter,SetSource.Decrement),
1321                 new Instruction.Tail(dock),
1322             }, true);
1323         
1324         for(int i=0; i<4; i++) {
1325             BitVector bv;
1326             
1327             model.waitNS(128 * CYCLE_TIME_NS);
1328             bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
1329             fatal(bv==null, "no data item found");
1330             prln("got " + bv.toLong());
1331             fatal(bv.toLong()!=1, "expected 1, got " + bv.toLong());
1332             
1333             model.waitNS(128 * CYCLE_TIME_NS);
1334             bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
1335             fatal(bv==null, "no data item found");
1336             prln("got " + bv.toLong());
1337             fatal(bv.toLong()!=1, "expected 1, got " + bv.toLong());
1338             
1339             model.waitNS(128 * CYCLE_TIME_NS);
1340             bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
1341             fatal(bv==null, "no data item found");
1342             prln("got " + bv.toLong());
1343             fatal(bv.toLong()!=2, "expected 2, got " + bv.toLong());
1344             
1345         }
1346     }
1347
1348     private void testAbortOutsideOfLoop(Marina marina) {
1349         marina.instrIn.fill(setIlc(1));
1350         marina.fillSouthProperStopper(new Instruction[] {
1351                 // ensure that an abort doesn't cause problems if no loop is in progress
1352                 new Instruction.Abort(dock, Predicate.IgnoreFlagD),
1353                 SEND_DATA,
1354             });
1355         expectNorthFifoExactly(1);
1356     }
1357
1358     private void testFlagAB(Marina marina) {
1359         prln("Begin testFlagAB");
1360         adjustIndent(2);
1361
1362         Instruction.Set.FlagFunction zero = Instruction.Set.FlagFunction.ZERO;
1363         Instruction.Set.FlagFunction one  = zero;
1364
1365         
1366         // we should be able to use any pair of FlagX+NotFlagX,
1367         // but we toss them all in to maximize the chances of the
1368         // test passing (later we will try the individual
1369         // combinations to maximize the chances of failure).
1370         one = one.add(Predicate.FlagA);
1371         one = one.add(Predicate.NotFlagA);
1372         one = one.add(Predicate.FlagB);
1373         one = one.add(Predicate.NotFlagB);
1374         one = one.add(Predicate.FlagC);
1375         one = one.add(Predicate.NotFlagC);
1376
1377         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1));
1378         for(boolean fast : new boolean[] { true, false }) {
1379             // clear the flags to a known state, then check both 0->1 and 1->0 transitions
1380             for(boolean b : new boolean[] { false, true, false }) {
1381                 prln("state: a="+marina.getFlagA()+", b="+marina.getFlagB());
1382                 prln((b?"Setting":"Clearing")+" flags");
1383                 
1384                 Instruction inst = new Instruction.Set(dock,Predicate.IgnoreFlagD,
1385                                                        b ? one : zero,
1386                                                        b ? one : zero
1387                                                        );
1388                 if (fast) {
1389                     marina.fillSouthProperStopper(new Instruction[] {
1390                             RECV_DATA,
1391                             inst,
1392                             NOP,
1393                         });
1394                     model.waitNS(64 * CYCLE_TIME_NS);
1395                     marina.fillNorthProperStopper();
1396                 } else {
1397                     marina.instrIn.fill(inst);
1398                 }
1399
1400                 fatal(marina.getFlagA()!=b,
1401                       "after "+(b?"setting":"clearing")+" FlagA, it was still "+(b?"clear":"set"));
1402                 fatal(marina.getFlagB()!=b,
1403                       "after "+(b?"setting":"clearing")+" FlagB, it was still "+(b?"clear":"set"));
1404             }
1405         }
1406
1407         adjustIndent(-2);
1408         prln("End testFlagAB");         
1409     }
1410
1411     /**
1412      *  WARNING: this is a very, very, very long test case -- it goes
1413      *  through 216 iterations.
1414      */
1415     private void testFlagTruthTable(Marina marina) {
1416         prln("Begin testFlagTruthTable");
1417         adjustIndent(2);
1418
1419         marina.instrIn.fill(setIlc(1));
1420         Instruction.Set.FlagFunction zero = Instruction.Set.FlagFunction.ZERO;
1421         Instruction.Set.FlagFunction one  = zero.add(Predicate.FlagA).add(Predicate.NotFlagA);
1422
1423         for(Predicate a_input : new Predicate[] { null, Predicate.FlagA, Predicate.NotFlagA })
1424             for(Predicate b_input : new Predicate[] { null, Predicate.FlagB, Predicate.NotFlagB })
1425                 for(Predicate c_input : new Predicate[] { null, Predicate.FlagC, Predicate.NotFlagC })
1426                     for(boolean a_state : new boolean[] { false, true })
1427                         for(boolean b_state : new boolean[] { false, true })
1428                             for(boolean c_state : new boolean[] { false, true }) {
1429                                 for(boolean which : new boolean[] { false, true }) {
1430
1431                                     prln("before instruction: a="+a_state+", b="+b_state+", c="+c_state);
1432                                     // set A,B flags to a_state and b_state
1433                                     marina.instrIn.fill(new 
1434                                                         Instruction.Set(dock,Predicate.IgnoreFlagD,
1435                                                                         a_state ? one : zero,
1436                                                                         b_state ? one : zero
1437                                                                         ));
1438                                     
1439                                     // set C flag to c_state
1440                                     BitVector data = new BitVector(37, "empty");
1441                                     BitVector addr = new BitVector(14, "empty");
1442                                     for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1443                                     for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1444                                     addr.set(Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE, c_state);
1445                                     marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1446                                     marina.instrIn.fill(RECV_DATA);
1447                                     
1448                                     Instruction.Set.FlagFunction func = zero;
1449                                     if (a_input!=null) func = func.add(a_input);
1450                                     if (b_input!=null) func = func.add(b_input);
1451                                     if (c_input!=null) func = func.add(c_input);
1452
1453                                     Instruction inst = new 
1454                                         Instruction.Set(dock,Predicate.IgnoreFlagD,
1455                                                         !which ? func : zero.add(Predicate.FlagA),
1456                                                         which  ? func : zero.add(Predicate.FlagB)
1457                                                         );
1458
1459                                     marina.instrIn.fill(inst);
1460
1461                                     boolean expected_a = !which ? func.evaluate(a_state, b_state, c_state, false) : a_state;
1462                                     boolean expected_b =  which ? func.evaluate(a_state, b_state, c_state, false) : b_state;
1463                                     fatal(expected_a != marina.getFlagA(),
1464                                           "expected A="+expected_a+", but got "+marina.getFlagA());
1465                                     fatal(expected_b != marina.getFlagB(),
1466                                           "expected B="+expected_b+", but got "+marina.getFlagB());
1467                                 }
1468                             }
1469         adjustIndent(-2);
1470         prln("End testFlagTruthTable");         
1471     }
1472
1473     private void recvData(Marina marina) {
1474         prln("Begin recvData");
1475         adjustIndent(2);
1476
1477         marina.instrIn.fill(setIlc(1));
1478         marina.fillSouthProperStopper(new Instruction[] {
1479                 new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG),
1480                 new Instruction.Move(dock,
1481                                      Predicate.IgnoreFlagD, // predicate   
1482                                      false,                 // torpedoable 
1483                                      null,                  // path        
1484                                      false,                 // tokenIn     
1485                                      true,                  // dataIn      
1486                                      false,                 // latchData   
1487                                      false,                 // latchPath   
1488                                      false,                 // dataOut     
1489                                      false                  // tokenOut    
1490                                      ),
1491                 new Instruction.Set(dock,Predicate.IgnoreFlagD, SET_FLAG, SET_FLAG),
1492             });
1493         model.waitNS(64 * CYCLE_TIME_NS);
1494
1495         prln("checking to confirm that A flag is cleared");
1496         fatal(marina.getFlagA(), "bad A flag: "+marina.getFlagA());
1497         
1498         prln("inserting data item in north fifo ring");
1499         BitVector data = new BitVector(37, "empty");
1500         BitVector addr = new BitVector(14, "empty");
1501         for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1502         for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1503         marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1504         model.waitNS(64 * CYCLE_TIME_NS);
1505
1506         prln("checking to see if A flag got set");
1507         fatal(!marina.getFlagA(), "bad A flag: "+marina.getFlagA());
1508
1509         adjustIndent(-2);
1510         prln("End recvData");           
1511     }
1512
1513
1514     private void testRecvAndSendWalkingOne(Marina marina) {
1515         prln("Begin testRecvAndSendWalkingOne");
1516         adjustIndent(2);
1517
1518         marina.instrIn.fill(setIlc(1));
1519
1520         List<BitVector> dataItems;
1521         for(int bit=0; bit<37; bit++) {
1522
1523             BitVector data = new BitVector(37, "empty");
1524             BitVector addr = new BitVector(14, "empty");
1525             for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1526             for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1527             data.set(bit, true);
1528             prln("testing with bit pattern " + data);
1529
1530             prln("inserting data item into north fifo ring");
1531             marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1532
1533             prln("stopping the north proper stopper");
1534             marina.data.stop();
1535
1536             dataItems = marina.data.drainMany(1);
1537             fatal(dataItems.size()!=0,
1538                   "found a data item waiting in the north proper stopper, but should not have");
1539
1540             marina.instrIn.fill(new Instruction.Move(dock,
1541                                                      Predicate.IgnoreFlagD,  // predicate   
1542                                                      false,                  // torpedoable 
1543                                                      null_path,              // path        
1544                                                      false,                  // tokenIn     
1545                                                      true,                   // dataIn      
1546                                                      true,                   // latchData   
1547                                                      false,                  // latchPath   
1548                                                      true,                   // dataOut     
1549                                                      false                   // tokenOut    
1550                                                      ));
1551
1552             dataItems = marina.data.drainMany(2);
1553             fatal(dataItems.size()!=1,
1554                   "found "+dataItems.size()+" data items in north fifo; expected one");
1555             MarinaPacket mp = new MarinaPacket(dataItems.get(0));
1556             fatalIfBitVectorsDoNotMatch(mp.data, data);
1557         }
1558
1559         adjustIndent(-2);
1560         prln("End testRecvAndSendWalkingOne");          
1561     }
1562
1563
1564
1565     private void setOlcFromDataLatch(Marina marina) {
1566         prln("Begin setOlcFromDataLatch");
1567         adjustIndent(2);
1568
1569         marina.instrIn.fill(setIlc(1));
1570
1571         // walk a bit from 0 to 5
1572         for(int bit=0; bit<6; bit++) {
1573             prln("inserting data item in north fifo ring");
1574             BitVector data = new BitVector(37, "empty");
1575             BitVector addr = new BitVector(14, "empty");
1576             for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1577             for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1578             data.set(bit, true);
1579             marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1580
1581             marina.fillSouthProperStopper(new Instruction[] {
1582                     RECV_DATA,
1583                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.DataLatch),
1584                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.DataLatch,-1),
1585                 });
1586
1587             model.waitNS(CYCLE_TIME_NS * 64);
1588
1589             expectOlc(1<<bit);
1590
1591             if (marina.kesselsCounter) {
1592                 // master clear on each iteration; otherwise we'd need to "run down" the olc
1593                 marina.masterClear();
1594                 marina.enableInstructionSend(true);
1595             }
1596         }
1597
1598         adjustIndent(-2);
1599         prln("End setOlcFromDataLatch");        
1600     }
1601
1602     private void setIlcFromDataLatch(Marina marina) {
1603         prln("Begin setIlcFromDataLatch");
1604         adjustIndent(2);
1605
1606         marina.instrIn.fill(setIlc(1));
1607
1608         // walk a bit from 0 to 5
1609         for(int bit=5; bit>=0; bit--) {
1610             prln("inserting data item in north fifo ring");
1611             BitVector data = new BitVector(37, "empty");
1612             BitVector addr = new BitVector(14, "empty");
1613             for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1614             for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1615             data.set(bit, true);
1616             marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1617
1618             marina.fillSouthProperStopper(new Instruction[] {
1619                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
1620                     RECV_DATA,
1621                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.DataLatch),
1622                 });
1623             model.waitNS(CYCLE_TIME_NS * 64);
1624
1625             int ilc = marina.getILC().getCount();
1626             fatal(ilc != (1<<bit), "expected ilc to be " + (1<<bit) + ", but got " + ilc); 
1627         }
1628
1629         adjustIndent(-2);
1630         prln("End setIlcFromDataLatch");        
1631     }
1632
1633     private void testSendAndRecvToken(Marina marina) {
1634         prln("Begin testSendAndRecvToken");
1635         adjustIndent(2);
1636
1637         marina.instrIn.fill(setIlc(1));
1638         marina.fillSouthProperStopper(new Instruction[] {
1639                 SEND_TOKEN,
1640                 RECV_TOKEN,
1641                 SEND_DATA,
1642             });
1643         expectNorthFifoExactly(1);
1644
1645         adjustIndent(-2);
1646         prln("End testSendAndRecvToken");       
1647     }
1648
1649     private void testSignExtendedLiteral(Marina marina) {
1650         prln("Begin testSignExtendedLiteral");
1651         adjustIndent(2);
1652
1653         marina.instrIn.fill(setIlc(1));
1654         for(long val : new long[] { (-1L << 14), -1, 0, 1 }) {
1655
1656             marina.fillSouthProperStopper(new Instruction[] {
1657                     new Instruction.Set(dock,Predicate.IgnoreFlagD,
1658                                         Instruction.Set.SetDest.DataLatch,
1659                                         val),
1660                     SEND_DATA,
1661                 });
1662             model.waitNS(CYCLE_TIME_NS * 64);
1663
1664             List<BitVector> dataItems = marina.data.drainMany(3);
1665             fatal(dataItems.size()!=1, "expected exactly one data item, got " + dataItems.size());
1666
1667             MarinaPacket mp = new MarinaPacket(dataItems.get(0));
1668             BitVector bv = mp.data;
1669             prln("got back " + mp);
1670
1671             boolean mismatch = false;
1672             String err = "";
1673             for(int i=0; i<37; i++) {
1674                 if (bv.get(i) != ( (val & (1L << i)) != 0 )) {
1675                     mismatch = true;
1676                     err += ""+i+", ";
1677                 }
1678             }
1679             fatal(mismatch, "data read back did not match inserted literal; mismatch on bits " + err);
1680         }
1681                 
1682         adjustIndent(-2);
1683         prln("End testSignExtendedLiteral");            
1684     }
1685
1686     private void testShiftedLiteral(Marina marina) {
1687         prln("Begin testShiftedLiteral");
1688         adjustIndent(2);
1689
1690         marina.instrIn.fill(setIlc(1));
1691         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,
1692                                                 Instruction.Set.SetDest.DataLatch,
1693                                                 0));
1694
1695         BitVector dreg = new BitVector(37, "what we think is in the d-register");
1696         for(int i=0; i<37; i++) dreg.set(i, false);
1697
1698         for(long val : new long[] { -1, 0, 1, (-1L << 18) }) {
1699
1700             edu.berkeley.fleet.api.BitVector immediate =
1701                 new edu.berkeley.fleet.api.BitVector(19);
1702             for(int i=0; i<immediate.length(); i++)
1703                 immediate.set(i, (val & (1L << i)) != 0);
1704
1705             // shift over 19 LSB's towards MSB
1706             for(int i=0; i<19; i++)
1707                 if (i+19 <= 36)  dreg.set(i+19, dreg.get(i));
1708             for(int i=0; i<19; i++)
1709                 dreg.set(i, immediate.get(i));
1710
1711             marina.fillSouthProperStopper(new Instruction[] {
1712                     new Instruction.Shift(dock,Predicate.IgnoreFlagD,immediate),
1713                     SEND_DATA,
1714                 });
1715
1716             model.waitNS(CYCLE_TIME_NS * 64);
1717             List<BitVector> dataItems = marina.data.drainMany(3);
1718             fatal(dataItems.size()!=1, "expected exactly one data item, got " + dataItems.size());
1719
1720             BitVector bv = new MarinaPacket(dataItems.get(0)).data;
1721             fatal(!bv.equals(dreg), "data read back did not match inserted literal.\n" +
1722                   "got:     "+bv.bitReverse().getState()+"\n"+
1723                   "expected:"+dreg.bitReverse().getState());
1724         }
1725                 
1726         adjustIndent(-2);
1727         prln("End testShiftedLiteral");         
1728     }
1729
1730     private void testFlagC(Marina marina) {
1731         prln("Begin testFlagC");
1732         adjustIndent(2);
1733
1734         // Russell says:
1735         // addr[14] == sigS
1736         // addr[1]  == sigA
1737         //
1738         // Adam says:
1739         // Dc=1 => sigS is copied into C-flag
1740         // Dc=0 => sigA is copied into C-flag
1741        
1742         marina.instrIn.fill(setIlc(1));
1743         for(boolean dc : new boolean[] { false, true }) {
1744             for(boolean c_flag : new boolean[] { true, false, true }) {
1745
1746                 prln("");
1747                 prln("****** checking case where dc="+dc+", cflag="+c_flag);
1748                 BitVector data = new BitVector(37, "empty");
1749                 BitVector addr = new BitVector(14, "empty");
1750                 for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
1751                 for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
1752
1753                 int whichbit = dc
1754                     ? Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE
1755                     : Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO;
1756                 prln("setting addr["+whichbit+"] to "+(c_flag?"1":"0"));
1757                 addr.set(whichbit, c_flag);
1758
1759                 prln("... and filling north fifo proper stopper");
1760                 marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
1761                 
1762                 prln("clearing flags");
1763                 prln("executing recv data with Dc="+dc);
1764                 prln("copying c-flag to a-flag");
1765                 marina.fillSouthProperStopper(new Instruction[] {
1766                         new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG),
1767                         new Instruction.Move(dock,
1768                                              Predicate.IgnoreFlagD,   /* predicate   */
1769                                              true,                  /* torpedoable */
1770                                              null,                  /* path        */
1771                                              false,                 /* tokenIn     */
1772                                              true,                  /* dataIn      */
1773                                              dc,                    /* latchData   */
1774                                              false,                 /* latchPath   */
1775                                              false,                 /* dataOut     */
1776                                              false                  /* tokenOut    */
1777                                              ),
1778                         FLAG_NOP,
1779                         new Instruction.Set(dock,Predicate.IgnoreFlagD,
1780                                             Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagC),
1781                                             CLEAR_FLAG
1782                                             ),
1783                     });
1784
1785                 model.waitNS(CYCLE_TIME_NS * 64);
1786                 
1787                 prln("checking to confirm that A flag is " + c_flag);
1788                 fatal(marina.getFlagA()!=c_flag, "bad A flag: "+marina.getFlagA());
1789             }
1790         }
1791         adjustIndent(-2);
1792         prln("End testFlagC");          
1793     }
1794
1795     private void sendDataWithPath(Marina marina) {
1796         prln("Begin sendDataWithPath");
1797         adjustIndent(2);
1798
1799         edu.berkeley.fleet.api.BitVector bv = new edu.berkeley.fleet.api.BitVector(13);
1800         marina.instrIn.fill(setIlc(1));
1801
1802         // alternating ones and zeroes
1803         for(int i=0; i<bv.length(); i+=2)
1804             bv.set(i, true);
1805         // and then ones in the lower four bits so it's not symmetric
1806         for(int i=0; i<4; i++)
1807             bv.set(i, true);
1808
1809         MarinaPath path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(), bv);
1810
1811         marina.fillSouthProperStopper(new Instruction[] {
1812                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
1813                 new Instruction.Move(dock,
1814                                      Predicate.IgnoreFlagD, /* predicate   */
1815                                      false,                 /* torpedoable */
1816                                      path,                  /* path        */
1817                                      false,                 /* tokenIn     */
1818                                      false,                 /* dataIn      */
1819                                      false,                 /* latchData   */
1820                                      false,                 /* latchPath   */
1821                                      true,                  /* dataOut     */
1822                                      false                  /* tokenOut    */
1823                                      ),
1824             });
1825
1826         List<BitVector> dataItems;
1827         MarinaPacket mp;
1828
1829         dataItems = marina.data.drainMany();
1830         fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
1831         mp = new MarinaPacket(dataItems.get(0));
1832
1833         // the 14th bit of the outbound address cannot be set by the
1834         // ship, so we don't care about it
1835         fatalIfBitVectorsDoNotMatch(MarinaUtils.berkToSun(bv), mp.path.get(0,13));
1836
1837         prln("send data with no change to path");
1838         marina.instrIn.fill(new Instruction.Move(dock,
1839                                                  Predicate.IgnoreFlagD, /* predicate   */
1840                                                  false,                 /* torpedoable */
1841                                                  null,                  /* path        */
1842                                                  false,                 /* tokenIn     */
1843                                                  false,                 /* dataIn      */
1844                                                  false,                 /* latchData   */
1845                                                  false,                 /* latchPath   */
1846                                                  true,                  /* dataOut     */
1847                                                  false                  /* tokenOut    */
1848                                                  ));
1849
1850         dataItems = marina.data.drainMany();
1851         fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
1852         mp = new MarinaPacket(dataItems.get(0));
1853
1854         // the 14th bit of the outbound address cannot be set by the
1855         // ship, so we don't care about it
1856         fatalIfBitVectorsDoNotMatch(MarinaUtils.berkToSun(bv), mp.path.get(0,13));
1857
1858         adjustIndent(-2);
1859         prln("End sendDataWithPath");
1860     }
1861
1862     private void recvPath(Marina marina) {
1863         prln("Begin recvPath");
1864         adjustIndent(2);
1865
1866         marina.instrIn.fill(setIlc(1));
1867         for(int bit=0; bit<11; bit++) {
1868             BitVector packet_data = new BitVector(37, "inbound data item");
1869             for(int i=0; i<37; i++) packet_data.set(i, false);
1870             packet_data.set(27+bit, true);
1871             BitVector packet_path = new BitVector(14, "inbound data item");
1872             for(int i=0; i<14; i++) packet_path.set(i, false);
1873
1874             marina.fillNorthProperStopper(new MarinaPacket(packet_data, false, packet_path));
1875                                            
1876             prln("recv path, send data (using recv'd path)");
1877             marina.instrIn.fill(new Instruction.Move(dock,
1878                                                      Predicate.IgnoreFlagD,   /* predicate   */
1879                                                      false,                 /* torpedoable */
1880                                                      null,                  /* path        */
1881                                                      false,                 /* tokenIn     */
1882                                                      true,                  /* dataIn      */
1883                                                      true,                  /* latchData   */
1884                                                      true,                  /* latchPath   */
1885                                                      true,                  /* dataOut     */
1886                                                      false                  /* tokenOut    */
1887                                                      ));
1888
1889             List<BitVector> dataItems = marina.data.drainMany();
1890             fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
1891             MarinaPacket mp = new MarinaPacket(dataItems.get(0));
1892             
1893             fatalIfBitVectorsDoNotMatch(packet_data.get(25,11), mp.path.get(0,11));
1894             fatalIfBitVectorsDoNotMatch(packet_data, mp.data);
1895         }
1896
1897         adjustIndent(-2);
1898         prln("End recvPath");
1899     }
1900
1901     private void testILC(Marina marina) {
1902         prln("Begin testILC");
1903         adjustIndent(2);
1904
1905         for(int bit=0; bit<6; bit++) {
1906             int ilc = bit<0 ? 0 : (1<<bit);
1907             marina.fillSouthProperStopper(new Instruction[] {
1908                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,ilc),
1909                     SEND_DATA,
1910                 });
1911             List<BitVector> dataItems = marina.data.drainMany();
1912             fatal(dataItems.size()!=ilc, "Expected "+ilc+" data item(s) to emerge but got: "+dataItems.size()+" data items");
1913         }
1914
1915         adjustIndent(-2);
1916         prln("End testILC");
1917     }
1918
1919     private void testILCZero(Marina marina) {
1920         adjustIndent(2);
1921         marina.fillSouthProperStopper(new Instruction[] {
1922                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,0),
1923                 SEND_DATA,
1924                 SEND_TOKEN,
1925             });
1926         expectNorthFifoNoMoreThan(0);
1927         expectTokensExactly(1);
1928         adjustIndent(-2);
1929     }
1930
1931     private void sendTorpedo(Marina marina) {
1932         prln("Begin sendTorpedo");
1933         adjustIndent(2);
1934         marina.instrIn.fill(setIlc(1));
1935         marina.instrIn.fill(setOlc(63));
1936
1937         model.waitNS(128 * CYCLE_TIME_NS);
1938         expectOlc(63);
1939
1940         marina.instrIn.fill(new 
1941                             Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG));
1942         fatal(marina.getFlagA(), "bad A flag: true");
1943         fatal(marina.getFlagB(), "bad B flag: true");
1944
1945         prln("execute a move instruction that does nothing but loops until torpedo arrives"); 
1946         prln("A=1, B=B This instruction should not execute because D-flag is set");
1947         prln("Set A=A, B=1 This instruction should execute because D-flag is set");
1948
1949         model.waitNS(128 * CYCLE_TIME_NS);
1950
1951         marina.fillSouthProperStopper(new Instruction[] {
1952                 new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, SetSource.Infinity),
1953                 new Instruction.Move(dock,
1954                                      Predicate.IgnoreFlagD, // predicate   
1955                                      true,                  // torpedoable 
1956                                      null,                  // path        
1957                                      false,                 // tokenIn     
1958                                      true,                  // dataIn      
1959                                      false,                 // latchData   
1960                                      false,                 // latchPath   
1961                                      false,                 // dataOut     
1962                                      false                  // tokenOut    
1963                                      ),
1964                 new Instruction.Set(dock,Predicate.Default,
1965                                     SET_FLAG,
1966                                     Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagB)
1967                                     ),
1968                 new Instruction.Set(dock, Predicate.FlagD,
1969                                     Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA),
1970                                     SET_FLAG
1971                                     ),
1972             });
1973
1974         model.waitNS(128 * CYCLE_TIME_NS);
1975
1976         prln("send torpedo. This should clear the OLC");
1977         marina.instrIn.fillTorpedo();
1978         model.waitNS(128 * CYCLE_TIME_NS);
1979
1980         model.waitNS(128 * CYCLE_TIME_NS);
1981                 
1982         prln("A should remain false, B should be true");
1983         fatal(marina.getFlagA(), "bad A flag: true");
1984         fatal(!marina.getFlagB(), "bad B flag: false");
1985         
1986         model.waitNS(128 * CYCLE_TIME_NS);
1987
1988         prln("Reload OLC after torpedo, clears D-flag");
1989         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63));
1990
1991         // FIXME: find another way to test this
1992         model.waitNS(128 * CYCLE_TIME_NS);
1993         expectOlc(63);
1994                 
1995         prln("Set A=1, B=1 This instruction should execute because OLC!=0");
1996         marina.instrIn.fill(new 
1997                             Instruction.Set(dock,Predicate.Default, SET_FLAG, SET_FLAG));
1998
1999         prln("A and B should be true");
2000         fatal(!marina.getFlagA(), "bad A flag: false");
2001         fatal(!marina.getFlagB(), "bad B flag: false");
2002                 
2003         adjustIndent(-2);
2004         prln("End sendTorpedo");        
2005     }    
2006
2007     private void testTorpedoOnAnInfinite(Marina marina) {
2008         prln("Begin testTorpedoOnAnInfinite");
2009         adjustIndent(2);
2010
2011         List<BitVector> dataItems;
2012
2013         marina.instrIn.fill(setIlc(1));
2014         for(boolean torpedoable : new boolean[] { true, false }) {
2015             
2016             marina.fillSouthProperStopper(new Instruction[] {
2017                     new Instruction.Move(dock,
2018                                          Predicate.IgnoreFlagD, // predicate   
2019                                          false,                 // torpedoable 
2020                                          null,                  // path        
2021                                          false,                 // tokenIn     
2022                                          false,                 // dataIn      
2023                                          false,                 // latchData   
2024                                          false,                 // latchPath   
2025                                          false,                 // dataOut     
2026                                          true                   // tokenOut    
2027                                          ),
2028                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.Infinity),
2029                     new Instruction.Move(dock,
2030                                          Predicate.IgnoreFlagD, // predicate   
2031                                          torpedoable,           // torpedoable 
2032                                          null,                  // path        
2033                                          true,                  // tokenIn     
2034                                          false,                 // dataIn      
2035                                          false,                 // latchData   
2036                                          false,                 // latchPath   
2037                                          false,                 // dataOut     
2038                                          true                   // tokenOut    
2039                                          ),
2040                     // FIXME: this probably should be removed, unless Ivan doesn't want to change the behavior
2041                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
2042
2043                     SEND_DATA,
2044                 });
2045             
2046             // expect nothing to come out, because the NOP is executing
2047             dataItems = marina.data.drainMany(2);
2048             fatal(dataItems.size()!=0, "Expected no data item(s) to emerge but got at least: "+dataItems.size()+" data items");
2049             
2050             marina.instrIn.fillTorpedo();
2051             
2052             int expected = torpedoable?1:0;
2053             dataItems = marina.data.drainMany(2);
2054             fatal(dataItems.size()!=expected, "Expected "+expected+" item to emerge but got: "+dataItems.size()+" data items");
2055
2056             fatal(!marina.getILC().getDone(), "Expected ilc=done, but got "+marina.getILC());
2057         }
2058
2059         adjustIndent(-2);
2060         prln("End testTorpedoOnAnInfinite");
2061     }
2062
2063     private void testDFlagWhenTorpedoLyingInWait(Marina marina) {
2064         marina.fillSouthProperStopper(new Instruction[] {
2065                 setOlc(1),
2066                 RECV_DATA,
2067                 TORPEDOABLE_RECV_DATA,
2068                 FLAG_NOP,
2069                 FLAG_NOP,
2070                 FLAG_NOP,
2071                 SEND_TOKEN_IF_D_SET,
2072             });
2073
2074         expectTokensExactly(0);
2075
2076         // changing the order of these lines should work, but it does not
2077         marina.fillNorthProperStopper();
2078         marina.instrIn.fillTorpedo();
2079
2080         expectTokensExactly(1);
2081     }
2082
2083     private void testSetOlcFollowedByDPredicated(Marina marina) {
2084         for(boolean d_set : new boolean[] { false, true }) {
2085             prln("");
2086             marina.fillSouthProperStopper(new Instruction[] {
2087                     setOlc(0),
2088                     marina.kesselsCounter ? null : FLAG_NOP,
2089                     d_set ? SEND_DATA_IF_D_SET : SEND_DATA_IF_D_NOT_SET,
2090                 });
2091             expectNorthFifoExactly(d_set ? 1 : 0);
2092
2093             prln("");
2094             marina.fillSouthProperStopper(new Instruction[] {
2095                     setOlc(32),
2096                     marina.kesselsCounter ? null : FLAG_NOP,
2097                     d_set ? SEND_DATA_IF_D_SET : SEND_DATA_IF_D_NOT_SET,
2098                 });
2099             expectNorthFifoExactly(d_set ? 0 : 1);
2100
2101             if (marina.kesselsCounter) {
2102                 marina.masterClear();
2103                 marina.enableInstructionSend(true);
2104             }
2105         }
2106     }
2107
2108     private void testOlcDecrementAtHighSpeed(Marina marina) {
2109         prln("Begin testOlcDecrementAtHighSpeed");
2110         adjustIndent(2);
2111
2112         List<BitVector> dataItems;
2113         
2114         // Each element of the following pair of arrays is one "test".
2115         // The OLC will be loaded with olcs[i] and then decremented
2116         // decr_amounts[i] times; after that has happened the zeroness
2117         // of the OLC will be checked by executing a MOVE with
2118         // [olc!=0] as the predicate.
2119
2120         int[] olcs         = new int[] { 3, 3, 3, 10, 41 };
2121         int[] decr_amounts = new int[] { 2, 3, 4, 9,  9  };
2122
2123         for(int which=0; which<olcs.length; which++) {
2124             int olc = olcs[which];
2125             int decr_amount = decr_amounts[which];
2126
2127             prln("inserting set olc="+olc);
2128             prln("inserting set ilc=1");
2129             marina.fillSouthProperStopper(new Instruction[] {
2130                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
2131                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,olc),
2132                 });
2133
2134             // commenting the following four lines causes this test to pass
2135
2136             prln("inserting: "+decr_amount+" olc-- instructions");
2137             prln("inserting: [!d] send data");
2138             Instruction[] instructions = new Instruction[decr_amount+1];
2139             for(int i=0; i<decr_amount; i++)
2140                 instructions[i] =
2141                     new Instruction.Set(dock,
2142                                         Predicate.Default,
2143                                         SetDest.OuterLoopCounter,
2144                                         SetSource.Decrement);
2145             instructions[instructions.length-1] =
2146                 new Instruction.Move(dock,
2147                                      Predicate.Default,     // predicate   
2148                                      false,                 // torpedoable 
2149                                      null,                  // path        
2150                                      false,                 // tokenIn     
2151                                      false,                 // dataIn      
2152                                      false,                 // latchData   
2153                                      false,                 // latchPath   
2154                                      true,                  // dataOut     
2155                                      false                  // tokenOut    
2156                                      );
2157
2158             marina.fillSouthProperStopper(instructions);
2159             model.waitNS(64 * CYCLE_TIME_NS);
2160
2161             int expected = decr_amount>=olc ? 0 : 1;
2162             dataItems = marina.data.drainMany(2);
2163             fatal(dataItems.size()!=expected, "Expected "+expected+" item to emerge but got: "+dataItems.size()+" data items");
2164             expectOlc(Math.max(0,olc-decr_amount));
2165
2166             if (marina.kesselsCounter) {
2167                 // master clear on each iteration; otherwise we'd need to "run down" the olc
2168                 marina.masterClear();
2169                 marina.enableInstructionSend(true);
2170             }
2171         }
2172
2173         adjustIndent(-2);
2174         prln("End testOlcDecrementAtHighSpeed");
2175     }
2176
2177     private void flipIlcBit(Marina marina) {
2178         prln("Begin flipIlcBit");
2179         adjustIndent(2);
2180         prln("Using the set ILC instruction, toggle a single bit between zero and one. \n" +
2181              "Check correct setting of the ILC zero bit");
2182
2183         for (int i=0; i<6; i++) {
2184             int notZero = 1<<i;
2185
2186             prln("Then immediately set ILC="+notZero);
2187             marina.fillSouthProperStopper(new Instruction[] {
2188                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 0),
2189                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, notZero),
2190                 });
2191                 
2192             model.waitNS(64 * CYCLE_TIME_NS);
2193
2194             prln("Verify ILC using scan chain");
2195             Ilc ilc = marina.getILC();
2196             int ilcCount = ilc.getCount();
2197             fatal(ilcCount!=notZero, "bad ILC count: "+ilcCount+" expected: "+notZero);
2198             fatal(ilc.getInfinity(), "bad ILC Infinity bit: true");
2199                    
2200             marina.fillSouthProperStopper(new Instruction[] {     
2201                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, notZero),
2202                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 0),
2203                 });
2204
2205             model.waitNS(64 * CYCLE_TIME_NS);
2206                         
2207             prln("Verify ILC using scan chain");
2208             ilc = marina.getILC();
2209             ilcCount = ilc.getCount();
2210             fatal(ilcCount!=0, "bad ILC count: "+ilcCount+" expected: 0");
2211             fatal(ilc.getInfinity(), "bad ILC Infinity bit: true");
2212         }
2213
2214         adjustIndent(-2);
2215         prln("End flipIlcBit");
2216     }
2217     private void flipOlcBit(Marina marina) {
2218         prln("Begin flipOlcBit");
2219         adjustIndent(2);
2220         prln("Using the set OLC instruction, toggle a single bit between zero and one. \n" +
2221              "Check correct setting of the OLC zero bit");
2222
2223         marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG));
2224
2225         for (int i=0; i<6; i++) {
2226             int notZero = 32 >> i;
2227
2228             if (marina.kesselsCounter) {
2229                 // master clear on each iteration; otherwise we'd need to "run down" the olc
2230                 marina.masterClear();
2231                 marina.enableInstructionSend(true);
2232             }
2233
2234             int outOlc;
2235             prln("Set OLC=0");
2236             prln("Then immediately set OLC="+notZero);
2237             marina.fillSouthProperStopper(new Instruction[] {
2238                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 0),
2239                     new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, notZero),
2240                 });
2241
2242             model.waitNS(64 * CYCLE_TIME_NS);
2243             prln("Verify OLC count using scan chain");
2244             expectOlc(notZero);
2245
2246             if (!marina.kesselsCounter) {
2247                 prln("Set OLC="+notZero);
2248                 prln("Then immediately set OLC=0");
2249                 marina.fillSouthProperStopper(new Instruction[] {
2250                         new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, notZero),
2251                         new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 0),
2252                     });
2253                 
2254                 model.waitNS(64 * CYCLE_TIME_NS);
2255                 prln("Verify OLC count using scan chain");
2256                 expectOlc(0);
2257             }
2258         }
2259         
2260         adjustIndent(-2);
2261         prln("End flipOlcBit");
2262     }
2263     private void testSouthRecirculate(Marina marina, int AMOUNT) {
2264         prln("Begin testSouthRecirculate("+AMOUNT+")");
2265         adjustIndent(2);
2266
2267         marina.enableInstructionSend(false);
2268         marina.enableInstructionRecirculate(true);
2269         
2270         prln("Completely fill south ring");
2271         adjustIndent(2);
2272         for (int i=0; i<AMOUNT; i++) {
2273             prln("inserting item " + (i+1) + " / " + AMOUNT);
2274             BitVector path = new BitVector(MarinaPacket.PATH_WIDTH, "path");
2275             BitVector data = new BitVector(MarinaPacket.WORD_WIDTH, "path");
2276             path.set(0, MarinaPacket.PATH_WIDTH, false);
2277             data.setFromLong(i+9);
2278             marina.instrIn.fill(new MarinaPacket(data, false, path));
2279         }
2280         adjustIndent(-2);
2281
2282         prln("Drain south ring and check contents");
2283         adjustIndent(2);
2284         List<BitVector> out = marina.instrIn.drainMany();
2285         boolean bad = false;
2286         for (int i=0; i<AMOUNT; i++) {
2287             prln("extracting item " + (i+1) + " / " + AMOUNT);
2288             //int expect = (i+Marina.SOUTH_RING_CAPACITY-1) % Marina.SOUTH_RING_CAPACITY;
2289             int expect = i+9;
2290             long got = new MarinaPacket(out.get(i)).data.toLong();
2291             if (got!=expect) {
2292                 bad = true;
2293                 prln("  bad instruction: "+got+" expected: "+expect);
2294             } else {
2295                 prln("  good instruction.");
2296             }
2297         }
2298         fatal(bad, "data inserted does not match data retrieved");
2299         adjustIndent(-2);
2300         
2301         for (int i=0; i<5; i++) {}
2302         
2303         adjustIndent(-2);
2304         prln("End testSouthRecirculate("+AMOUNT+")");
2305     }
2306
2307
2308     private void testOverfillTokens(Marina marina) {
2309         prln("Begin testOverfillTokens");
2310         adjustIndent(2);
2311
2312         for(int i=0; i<marina.TOKEN_FIFO_CAPACITY + 3; i++)
2313             marina.instrIn.fill(SEND_TOKEN);
2314         marina.instrIn.fill(SEND_DATA);
2315         expectNorthFifoExactly(0);
2316         
2317         adjustIndent(-2);
2318         prln("End testSouthRecirculate");
2319     }
2320
2321
2322
2323     private void doOneTest(int testNum) throws Exception {
2324         try {
2325             doOneTest_(testNum);
2326         } catch (MarinaUtils.FailureException fe) {
2327             System.out.println("******************************************************************************");
2328             System.out.println("******************************************************************************");
2329             System.out.println("******************************************************************************");
2330             System.out.println("******************************************************************************");
2331             fe.printStackTrace();
2332         }
2333     }
2334
2335     private void doOneTest_(int testNum) throws Exception {
2336         prln("");
2337         prln("============================================================");
2338         prln("MarinaTest: performing test: "+testNum);
2339
2340         if (testNum==999) {
2341             //vdd = 0.5f;
2342             vdd = 1.0f;
2343             int[] tests = new int[] { 1002, 1003, 1005, 3002, 3004, 3005, 3006, 3008, 3009, 3025, 3026, 3029 };
2344             try {
2345                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("test.out")));
2346                 while(vdd <= 1.3f) {
2347                     vdd10.setVoltageWait(vdd);
2348                     System.out.println("vdd10 = " + vdd10.readVoltage());
2349                     Thread.sleep(1000);
2350                     for(int i=0; i<tests.length; i++) {
2351                         try {
2352                             doOneTest_(tests[i]);
2353                             pw.println(vdd + " " + i + " " + "1");
2354                         } catch (MarinaUtils.FailureException fe) {
2355                             pw.println(vdd + " " + i + " " + "0");
2356                         }
2357                         pw.flush();
2358                     }
2359                     vdd -= 0.01f;
2360                 }
2361             } catch (Exception e) { throw new RuntimeException(e); }
2362         }
2363
2364         if (testNum!=0) {
2365             marina.masterClear();
2366             marina.enableInstructionSend(true);
2367         }
2368
2369         MarinaUtils.testnum = testNum;
2370
2371         switch (testNum) {
2372             case 0: {
2373
2374                 doOneTest(1);       // passes extracted parasitics
2375                 doOneTest(2);       // passes extracted parasitics
2376                 doOneTest(3);       // passes extracted parasitics
2377                 doOneTest(4);       // passes extracted parasitics
2378                 doOneTest(5);       // passes extracted parasitics
2379                 doOneTest(6);
2380
2381                 doOneTest(1000);    // passes extracted parasitics
2382                 doOneTest(1001);    // passes extracted parasitics
2383                 doOneTest(1003);    // passes extracted parasitics
2384                 doOneTest(1005);
2385                 doOneTest(3000);    // passes extracted parasitics
2386                 doOneTest(3001);    // passes extracted parasitics
2387                 doOneTest(3003);    // passes extracted parasitics
2388                 doOneTest(3004);    // passes extracted parasitics
2389                 doOneTest(3005);    // passes extracted parasitics
2390                 doOneTest(3006);    // passes extracted parasitics
2391                 doOneTest(3007);    // passes extracted parasitics
2392                 doOneTest(3008);    // passes extracted parasitics
2393                 doOneTest(3009);    // passes extracted parasitics
2394                 doOneTest(3010);    // passes extracted parasitics
2395                 doOneTest(3011);    // passes extracted parasitics
2396                 doOneTest(3012);    // passes extracted parasitics
2397                 doOneTest(3013);    // passes extracted parasitics
2398                 doOneTest(3014);    // passes extracted parasitics
2399                 doOneTest(3015);    // passes extracted parasitics
2400                 doOneTest(3019);    // passes extracted parasitics
2401                 doOneTest(3020);    // passes extracted parasitics
2402                 doOneTest(3022);    // passes extracted parasitics
2403                 doOneTest(3023);    // passes extracted parasitics
2404                 doOneTest(3025);    // passes extracted parasitics
2405                 doOneTest(3026);    // passes extracted parasitics
2406                 doOneTest(3027);    // passes extracted parasitics
2407                 doOneTest(3028);    // passes extracted parasitics
2408                 doOneTest(3029);    // passes extracted parasitics
2409                 //doOneTest(3030);    // passes extracted parasitics (questionable)
2410                 //doOneTest(3031);    // passes extracted parasitics should not pass!
2411                     
2412                 // these tests take a while and usually pass
2413                 doOneTest(1002);
2414                 doOneTest(1004);
2415                 doOneTest(1005);
2416                 doOneTest(1006);
2417                 doOneTest(3002);
2418                 doOneTest(3016);
2419                 doOneTest(3021);
2420                 doOneTest(3024);
2421                 doOneTest(3025);
2422                 doOneTest(3040);
2423                     
2424                 // this takes an insanely long time
2425                 doOneTest(3017);
2426                 break;
2427             }
2428             case 1:    testChains(marina);                     break; // passes, 24-Mar (+verilog)
2429             case 2:    testProperStoppers(marina);             break; // passes, 24-Mar (+verilog)
2430             case 3:    testSouthRecirculate(marina, 1);        break; // passes, 24-Mar (+verilog)
2431             case 4:    getCtrsFlags(marina);                   break; //         20-Apr (+verilog)
2432             case 5:    sendInstructions(marina);               break; // passes, 24-Mar (+verilog)
2433             case 6:    walkOneOLC(marina);                     break; //         21-Apr (+verilog)
2434                 
2435                 // Russell's tests begin with 1000
2436             case 1000: walkOneILC(marina);                     break; //         20-Apr (+verilog)
2437             case 1001: countIlc(marina);                       break; //         20-Apr (+verilog)
2438             case 1002: countOlc(marina);                       break; //         23-Apr (+verilog)
2439
2440             case 1003: sendTorpedo(marina);                    break; //         23-Apr (+verilog)  [with wor-hack]
2441
2442             case 1004: flipIlcBit(marina);                     break; //         20-Apr (+verilog)
2443             case 1005: flipOlcBit(marina);                     break; //         21-Apr (+verilog)
2444
2445             case 1006: testSouthRecirculate(marina, Marina.SOUTH_RING_CAPACITY-1);        break; // passes, 24-Mar (+verilog)
2446
2447                 // Adam's tests begin with 3000
2448             case 3000: sendToken(marina);                      break; // passes, 24-Mar (+verilog)
2449             case 3001: testFlagAB(marina);                     break; // passes, 08-Apr (+verilog)
2450             case 3002: testPredicationOnAB(marina);            break; //         22-Apr (+verilog)
2451             case 3003: testFlagC(marina);                      break; //         23-Apr (+verilog)
2452             case 3004: testFlagD(marina);                      break; //         23-Apr (+verilog)
2453             case 3005: testFlagDRecomputationTime(marina);     break;
2454
2455             case 3006: testTailWaitsForHead(marina);           break;
2456             case 3007: testTailWithoutHead(marina);            break;
2457             case 3008: testHeadWaitsForTail(marina);           break; //         22-Apr (+verilog)
2458             case 3009: testAbort(marina);                      break; //         22-Apr (+verilog)
2459
2460             case 3010: sendData(marina);                       break; // passes, 24-Mar (+verilog)
2461             case 3011: recvData(marina);                       break; //         21-Apr (+verilog)
2462             case 3012: sendDataWithPath(marina);               break; // passes, 13-Apr (+verilog)
2463
2464             case 3013: testSignExtendedLiteral(marina);        break; //         20-Apr (+verilog)
2465             case 3014: testShiftedLiteral(marina);             break; //         20-Apr (+verilog)
2466             case 3015: testSendAndRecvToken(marina);           break; //         21-Apr (+verilog)
2467
2468             case 3016: sendDataIlcInfinite(marina);            break; //         22-Apr (+verilog)
2469             case 3017: testFlagTruthTable(marina);             break; //         23-Apr (+verilog)
2470
2471             case 3019: setOlcFromDataLatch(marina);            break; //         23-Apr (+verilog)
2472             case 3020: setIlcFromDataLatch(marina);            break; //         23-Apr (+verilog)
2473             case 3021: recvPath(marina);                       break; //         22-Apr (+verilog)
2474             case 3022: testILC(marina);                        break; //         23-Apr (+verilog)
2475             case 3023: testTorpedoOnAnInfinite(marina);        break; //         23-Apr (+verilog)
2476             case 3024: testRecvAndSendWalkingOne(marina);      break; //         21-Apr (+verilog)
2477             case 3025: testOlcDecrementAtHighSpeed(marina);    break; //         23-Apr (+verilog)
2478
2479             case 3026: testNonTorpedoableMoveDoesNotResetDFlag(marina);        break; //         23-Apr (+verilog)
2480             case 3027: testILCZero(marina);                    break;
2481             case 3028: testAbortOutsideOfLoop(marina); break;
2482             case 3029: testDFlagWhenTorpedoLyingInWait(marina); break;
2483             case 3030: testSetOlcFollowedByDPredicated(marina); break;
2484             case 3031: testOverfillTokens(marina); break;
2485
2486             case 3040: loadEveryValueOLC(marina); break;
2487             case 6666: {
2488                 SubchainNode chainNode =
2489                     (SubchainNode)marina.cc.getChainControlFromPath(Marina.DUKE_CHAIN)
2490                     .findNode("marina.duke.marinaGu@0.dukeAll@1.dukePart@0.ring37sW@1.scanner@0.scanFx1@1.scanCell@3");
2491                 int bitIndex = chainNode.getBitIndex();
2492                 ChainNode root = chainNode.getParentChain();
2493
2494                 for(int i=0; i<13; i++) {
2495                     System.out.println("i="+i);
2496                     for(int j=0; j<12; j++)
2497                         root.getInBits().set(bitIndex+j, false);
2498                     root.getInBits().set(bitIndex+i, true);
2499                     marina.shiftDuke(false, true);
2500                     System.in.read();
2501                 }
2502                 break;
2503             }
2504
2505             case 7777: {
2506
2507                 int wait = 300;
2508
2509                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("out.dat")));
2510
2511                 vdd = 0.9f;
2512                 vdd18.setVoltageWait((float)Math.max(1.8,vdd));
2513                 //vdd10.setVoltageWait(vdd);
2514
2515                 if (!Marina.kesselsCounter) throw new RuntimeException();
2516                 if (!Marina.omegaCounter) throw new RuntimeException();
2517
2518                 for(int xx=1; xx<65; xx++) {
2519                 marina.masterClear();
2520                 marina.data.sink();
2521                 marina.stopAndResetCounters();
2522                     
2523                 marina.enableInstructionSend(true);
2524                 marina.fillSouthProperStopper(new Instruction.Set(dock,Predicate.IgnoreFlagD,
2525                                                                   Instruction.Set.FlagFunction.ZERO
2526                                                                   .add(Predicate.FlagA).add(Predicate.NotFlagA),
2527                                                                   Instruction.Set.FlagFunction.ZERO));
2528                 //int xx = 63;      // 1.802ms
2529                 //int xx = 1;         // 0.207ms  =>  24.3ns for 62 counts => 390ps cycle time => 2.5Ghz
2530                 marina.fillSouthProperStopper(new Instruction[] {
2531                         new Instruction.Head(dock),
2532                         setOlc(xx),
2533                         FLAG_NOP,
2534                         FLAG_NOP,
2535                         TORPEDOABLE_RECV_DATA,
2536                         FLAG_NOP,
2537                         FLAG_NOP,
2538                         SEND_DATA,
2539                         new Instruction.Tail(dock),
2540                     }, false, false);
2541
2542                 marina.fillSouthProperStopper(new Instruction[] {
2543                         /*
2544                           new Instruction.Set(dock,Predicate.FlagD,
2545                           Instruction.Set.FlagFunction.ZERO.add(Predicate.NotFlagA),
2546                           Instruction.Set.FlagFunction.ZERO),
2547                           setOlcIfZero(32),
2548                           setIlc(63),
2549                           SEND_DATA_IF_A_SET_AND_D_NOT_SET,
2550                           setIlc(63),
2551                           SEND_DATA_IF_A_SET_AND_D_NOT_SET,
2552                           DEC,
2553                           setIlc(63),
2554                           SEND_DATA_IF_A_SET_AND_D_NOT_SET,
2555                           setIlc(63),
2556                           SEND_DATA,
2557                         */
2558                         null,
2559                         null,
2560                         null,
2561                         null,
2562                         null,
2563                         null,
2564                         null,
2565                         null,
2566                     }, true, true);
2567
2568                 //marina.startCounters(false, false);
2569                     
2570                 marina.instrIn.run();
2571
2572                 vdd10.setVoltageWait(vdd);
2573                 marina.startCounters(false, true);
2574
2575                 try { Thread.sleep(wait); } catch (Exception e) { }
2576                 //marina.instrIn.stop();
2577                     
2578                 marina.stopAndResetCounters();
2579                 int countNorth = marina.getNorthCount();
2580                 int countSouth = marina.getSouthCount();
2581                 pw.println(xx + " " + countNorth + " " + vdd + " " + vdd10.readCurrent());
2582                 pw.flush();
2583                 System.out.println(xx + " " + countNorth + " " + vdd + " " + vdd10.readCurrent());
2584                 }
2585                 pw.close();
2586                 break;
2587             }
2588             case 8888: {
2589
2590                 //int wait = 1000;
2591                 int wait = 200;
2592                 //int toks = 1;
2593
2594                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("out.dat")));
2595                 for(double myvdd = 1.00; myvdd<1.01; myvdd += 0.05) {
2596                     vdd = (float)myvdd;
2597                     vdd18.setVoltageWait((float)Math.max(1.8,vdd));
2598                     vdd10.setVoltageWait(vdd);
2599                     Thread.sleep(1000);
2600
2601                     for(int toks = 0; toks < 13; toks++) {
2602                         int MAX_ITER = 10;
2603                         double total = 0;
2604                         for(int iter = 0; iter < MAX_ITER; iter++) {
2605
2606                             marina.masterClear();
2607                             marina.data.sink();
2608                             marina.stopAndResetCounters();
2609                                 
2610                             marina.enableInstructionSend(true);
2611                             marina.fillSouthProperStopper(setOlc(1));
2612                             marina.fillSouthProperStopper(new Instruction.Head(dock));
2613                             for(int i=0; i<toks; i++)
2614                                 marina.fillSouthProperStopper(/*SEND_DATA*/NOP);
2615                             marina.fillSouthProperStopper(new Instruction[] {
2616                                     new Instruction.Tail(dock),
2617                                 }, false, true);
2618                                 
2619                             marina.instrIn.run();
2620
2621                             // have to set the voltage while drawing current
2622                             vdd10.setVoltageWait(vdd);
2623
2624                             marina.startCounters();
2625                             try { Thread.sleep(wait); } catch (Exception e) { }
2626                             marina.stopAndResetCounters();
2627                             //marina.instrIn.stop();
2628
2629                             int countNorth = marina.getNorthCount();
2630                             int countSouth = marina.getSouthCount();
2631                             System.out.println();
2632                             System.out.println();
2633                             if (countSouth > (2<<29))
2634                                 System.out.println("warning: count was greater than 2^29...");
2635                             double gst = ((((double)countSouth*2)) / (1000000. * wait /* * toks*/));
2636                             System.out.println("south counter is: " + countSouth + ", which is " + gst + "Ginst/sec with toks="+toks + " @vdd="+vdd);
2637                             total += gst;
2638
2639                             System.out.println();
2640                             System.out.println();
2641                             /*
2642                               System.out.println("counters are " + count + " and " + countNorth + "; ratio is "+
2643                               (((double)countNorth)/((double)(count*2))) + " " +
2644                               (((double)countNorth)/((double)(count*2+1))) + " " +
2645                               "");
2646                             */
2647                         }
2648                         float vdd10v = vdd10.readVoltage();
2649                         float vdd18v = vdd18.readVoltage();
2650                         float vddsv  = vdds.readCurrent();
2651                         float vdd10c = vdd10.readCurrent();
2652                         float vdd18c = vdd18.readCurrent();
2653                         pw.println(vdd + " " +
2654                                    toks + " " +
2655                                    (((double)total) / MAX_ITER) + " " +
2656                                    //vddsv  + " " + 
2657                                    vdd10c + " " +
2658                                    vdd18v + " " +
2659                                    vdd18c + " " +
2660                                    "");
2661                         pw.flush();
2662                     }
2663                 }
2664                 break;
2665             }
2666             case 8889: {
2667
2668                 int wait = 1000;
2669                 //int wait = 200;
2670                 //int toks = 1;
2671
2672                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("out.dat")));
2673                 for(int toks = 0; toks < 13; toks++) {
2674                     int MAX_ITER = 10;
2675                     double total = 0;
2676                     for(int iter = 0; iter < MAX_ITER; iter++) {
2677                             
2678                         marina.masterClear();
2679                         marina.data.sink();
2680                         marina.stopAndResetCounters();
2681                             
2682                         marina.enableInstructionSend(true);
2683                         marina.fillSouthProperStopper(setOlc(1));
2684                         marina.fillSouthProperStopper(new Instruction.Set(dock,Predicate.IgnoreFlagD,
2685                                                                           Instruction.Set.FlagFunction.ZERO,
2686                                                                           Instruction.Set.FlagFunction.ZERO));
2687                         marina.fillSouthProperStopper(new Instruction.Head(dock));
2688                         //marina.fillSouthProperStopper(setIlc(31));
2689                         marina.fillSouthProperStopper(SEND_DATA);
2690                         for(int i=0; i<toks+1; i++) {
2691                             //marina.fillSouthProperStopper(FLAG_NOP_IF_FLAG_A);
2692                             marina.fillSouthProperStopper(FLAG_NOP);
2693                         }
2694                         marina.fillSouthProperStopper(new Instruction[] {
2695                                 new Instruction.Tail(dock),
2696                             }, false, true);
2697                         marina.startCounters();
2698                             
2699                         marina.instrIn.run();
2700                         try { Thread.sleep(wait); } catch (Exception e) { }
2701                             
2702                         marina.stopAndResetCounters();
2703                         int countNorth = marina.getNorthCount();
2704                         int count      = marina.getSouthCount();
2705                         System.out.println();
2706                         System.out.println();
2707                         if (count > (2<<29))
2708                             System.out.println("warning: count was greater than 2^29...");
2709                         double gst = ((((double)count*2)) / (1000000. * wait /* * toks*/));
2710                         System.out.println("south counter is: " + count + ", which is " + gst + "Ginst/sec with toks="+toks + " @vdd="+vdd);
2711                         total += gst;
2712                             
2713                         System.out.println();
2714                         System.out.println();
2715                     }
2716                     pw.println(vdd + " " + toks + " " + (((double)total) / MAX_ITER));
2717                     pw.flush();
2718                 }
2719                 break;
2720             }
2721             case 9999:
2722                 loadEveryValueOLC(marina);
2723                 countOlc(marina);
2724                 break;
2725
2726             default:
2727                 fatal(true, "Test number: "+testNum+" doesn't exist.");
2728                 break;
2729         }
2730         // If we get here then test passed
2731         prln("Test Result: Passed");
2732         printTestTime();
2733         //Infrastructure.exit(0);
2734     }
2735
2736
2737     //============================ for public use =============================
2738
2739     /** Exit codes:
2740      * 0: test detected success
2741      * 2: test detected failure
2742      * 1: test crashed
2743      */ 
2744     public static void main(String[] args) throws Exception {
2745         startTime = System.currentTimeMillis();
2746         new MarinaTest(args);
2747     }
2748
2749 }