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