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