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