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