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