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