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