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