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