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