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