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