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