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