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