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