update software to match new inner loop counter scan chain bits
[fleet.git] / testCode / com / sun / vlsi / chips / marina / test / MarinaTest.java
1 package com.sun.vlsi.chips.marina.test;
2 /* -*- tab-width: 4 -*- */
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import com.sun.async.test.BitVector;
7 import com.sun.async.test.ChainControl;
8 import com.sun.async.test.ChainTest;
9 import com.sun.async.test.ChipModel;
10 import com.sun.async.test.HP34401A;
11 import com.sun.async.test.Infrastructure;
12 import com.sun.async.test.JtagTester;
13 import com.sun.async.test.ManualPowerChannel;
14 import com.sun.async.test.NanosimModel;
15 import com.sun.async.test.Netscan4;
16 import com.sun.async.test.PowerChannel;
17 import com.sun.async.test.Pst3202Channel;
18 import com.sun.async.test.SiliconChip;
19 import com.sun.async.test.SimulationModel;
20 import com.sun.async.test.VoltageReadable;
21 import com.sun.vlsi.chips.marina.test.Marina.Ilc;
22 import com.sun.vlsi.chips.marina.test.MarinaUtils.CmdArgs;
23 import com.sun.vlsi.chips.marina.test.MarinaUtils.Station;
24 import com.sun.vlsi.chips.marina.test.MarinaUtils.CmdArgs.Mode;
25
26 import edu.berkeley.fleet.api.Dock;
27 import edu.berkeley.fleet.api.Instruction;
28 import edu.berkeley.fleet.api.Predicate;
29 import edu.berkeley.fleet.api.Instruction.Set.SetDest;
30 import edu.berkeley.fleet.api.Instruction.Set.SetSource;
31
32 /**
33  * Tests for Marina
34  */
35 public class MarinaTest {
36         //--------------------------  constants -----------------------------------
37         public static final boolean NEW = true;
38         private static final String SCAN_CHAIN = false ? "marinaNew.xml" : "marina.xml";
39         private static final String NET_LIST = false ? "marinaNew.spi" : "marina.spi";
40
41         public static final int INSTR_SZ = 36;
42         
43         public static final Dock DOCK = InstructionStopper.DOCK;
44     public static final Instruction.Set.FlagFunction CLEAR_FLAG 
45         = Instruction.Set.FlagFunction.ZERO;
46     public static final Instruction.Set.FlagFunction SET_FLAG 
47         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA)
48                                            .add(Predicate.NotFlagA);
49     public static final Instruction.Set.FlagFunction A_FLAG 
50         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA);
51
52     public static final Instruction.Set.FlagFunction B_FLAG 
53         = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagB);
54     
55         // COLUMN_LATENCY is a delay that is larger than the latency through an Infinity column
56         private static final int COLUMN_LATENCY = 10; // nanoseconds
57
58
59     // Officially, this should be the number of requeueing no-ops that
60     // can be inserted into an idle dock whose OLC is nonzero.
61     //
62     // Less formally, this is roughly the number of stages of
63     // buffering between the instruction insertion point and the
64     // instruction ring, plus the capacity of the instruction ring.
65     private static final int INSTRUCTION_IN_SATURATION_AMOUNT = 19;
66
67     // This is some number which is significantly greater than
68     // INSTRUCTION_IN_SATURATION_AMOUNT.  Increasing it may slow the tests down, but
69     // will never cause them to operate incorrectly.
70     private static final int MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT = 25;
71         
72     // Officially, this should be the number of data items which can
73     // be sent from the dock while the "data" proper stopper is in
74     // the "stopped" state
75     //
76     // Less formally, this is roughly the number of stages of
77     // buffering between the dock's data successor and the "data"
78     // proper stopper
79     /*
80       FIXME: what is the correct value here?
81     private static final int DATA_OUT_SATURATION_AMOUNT = XXX;
82     */
83
84     // This is some number which is significantly greater than
85     // DATA_OUT_SATURATION_AMOUNT.  Increasing it may slow the tests down, but
86     // will never cause them to operate incorrectly.
87     private static final int MORE_THAN_DATA_OUT_SATURATION_AMOUNT = 16;
88         
89         // Nominal cycle time assuming 4 GHz throughput
90         private static final double CYCLE_TIME_NS = 0.250;
91
92         //--------------------------------  types ---------------------------------
93
94         //--------------------------  private data --------------------------------
95         private static long startTime;
96
97         private Indenter indenter = new Indenter();
98         private Marina marina;
99         private ChipModel model;
100         private ChainControl cc;
101         private JtagTester tester;
102         private CmdArgs cmdArgs;
103         private PowerChannel corePowerSupply, padsPowerSupply;
104     private VoltageReadable coreVoltmeter, voltmeterForCurrent;
105         
106         //--------------------------  private methods -----------------------------
107     /** @return true if simulation. Return false if we're testing silicon. */
108         private boolean sim() {return model instanceof SimulationModel;}
109         
110         private void prln(String msg) {indenter.prln(msg);}
111         private void pr(String msg) {indenter.pr(msg);}
112         private void adjustIndent(int n) {indenter.adjustIndent(n);}
113         
114         private static void fatal(boolean pred, String msg) {
115                 if (pred) {
116                         System.out.println("Test Failed");
117                         printTestTime();
118                         Infrastructure.fatal(msg);
119                 }
120         }
121         private static void printTestTime() {
122         long endTime = System.currentTimeMillis();
123         System.out.println("Test took: "+(endTime-startTime)/1000.0+"  sec");
124         }
125     
126         // Tell user what we're about to do
127         private static void reportTask(CmdArgs args) {
128                 System.out.println("Begin testing Marina");
129         switch (args.mode) {
130         case WHOLE_CHIP_SCHEMATIC_PARASITICS:
131                 System.out.println("  Simulate whole chip, schematic parasitics");
132                 break;
133         case WHOLE_CHIP_LAYOUT_PARASITICS:
134                 System.out.println("  Simulate whole chip, layout parasitics");
135                 break;
136         case TEST_SILICON:
137                 System.out.println("  Test silicon");
138                 break;
139         default:
140                 fatal(true, "unrecognized CmdArgs.Mode");
141                 return;
142         }
143         }
144         private void setUpSuppliesAndMeters(Station station) {
145                 // set up power supplies and meters
146                 if (!sim()) {
147                         prln("Testing station: "+station);
148                   Infrastructure.gpibControllers = new int[] {0};
149                   switch (cmdArgs.station) {
150                   case ONE:
151                                 corePowerSupply = new Pst3202Channel("ch1", "HPST3202", 1);
152                             padsPowerSupply = new Pst3202Channel("ch2", "HPST3202", 2);
153                             break;
154                   case TWO:
155                                 corePowerSupply = new Pst3202Channel("ch1", "HPST3202B", 1);
156                             padsPowerSupply = new Pst3202Channel("ch2", "HPST3202B", 2);
157                         break;
158                   default:
159                         fatal(true, "Unrecognized station: "+cmdArgs.station);
160                   }
161                   corePowerSupply.setCurrent((float)1.7);
162                   corePowerSupply.setVoltageWait((float)1.0);
163                   
164                   padsPowerSupply.setCurrent((float)0.100);
165                   padsPowerSupply.setVoltageWait((float)1.8);
166                   
167                   coreVoltmeter = new HP34401A(station.coreVoltmeter);
168                   voltmeterForCurrent = new HP34401A(station.currentVoltmenter);
169                 }
170         }
171         
172         private MarinaTest(String[] args) {
173         cmdArgs = new MarinaUtils.CmdArgs(args);
174         reportTask(cmdArgs);
175         boolean sim = cmdArgs.mode != Mode.TEST_SILICON;
176         if (sim) {
177                 model = new NanosimModel();
178                 tester = ((SimulationModel)model).createJtagTester("TCK", "TMS", "TRSTb", "TDI", "TDO");
179         } else {
180                 model = new SiliconChip();
181                 String ip = cmdArgs.station.ipAddr;
182                 tester = new Netscan4(ip, cmdArgs.station.jtagChannel);
183         }
184         tester.printInfo = false;
185         int khz = sim ? 1000000 : 1000;
186
187         String netListName;
188         switch (cmdArgs.mode) {
189         case WHOLE_CHIP_SCHEMATIC_PARASITICS:
190                 netListName = NET_LIST; 
191             cc = new ChainControl(SCAN_CHAIN, tester, 1.8f, khz);
192             marina = new Marina(cc, model, indenter);
193                 break;
194         case WHOLE_CHIP_LAYOUT_PARASITICS:
195                 netListName = "marina_pads_guts.spi"; 
196             cc = new ChainControl("???", tester, 1.8f, khz);
197             marina = null;
198                 break;
199         case TEST_SILICON:
200                 netListName = "marina_pads_guts.spi"; 
201             cc = new ChainControl("???", tester, 1.8f, khz);
202             marina = null;
203                 break;
204         default:
205                 fatal(true, "unrecognized CmdArgs.Mode");
206                 return;
207         }
208         cc.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
209         
210         PowerChannel pc = new ManualPowerChannel("pc", false);
211         ChainTest ct = new ChainTest(cc, pc);
212         
213         setUpSuppliesAndMeters(cmdArgs.station);
214         
215         if (sim) ((SimulationModel)model).start("nanosim -c cfg", netListName, 0, true);
216         ct.testAllChains("marina", Infrastructure.SEVERITY_WARNING);
217
218         doOneTest(cmdArgs.testNum);
219         
220         if (sim) ((SimulationModel)model).finish();
221 }
222
223         /** In the absence of looping, the longest path through Infinity is 4 column delays */
224         private void waitUntilQuiescent() {
225                 model.waitNS(4*COLUMN_LATENCY);
226         }
227     
228     private double readCurrent() {
229         return voltmeterForCurrent.readVoltage() / cmdArgs.station.ammeterShuntResistance;
230     }
231     
232     /** Generate List of BitVectors where Token=true, high 25 data bits  
233      * are alternating ones and zeros, low 12 data bits increment from 
234      * zero, and address is given by addr. */
235     private List<BitVector> makeIncrDataConstAdr(int num, int addr) {
236         List<BitVector> ans = new ArrayList<BitVector>();
237         BitVector dHi = new BitVector(25, "dataHi");
238         BitVector dLo = new BitVector(12, "dataLo");
239         BitVector t = new BitVector("1", "token");
240         BitVector a = new BitVector(14, "addr");
241         dHi.setFromLong(0x00aaaaa);
242         a.setFromLong(addr);
243         for (int i=0; i<num; i++) {
244                 dLo.setFromLong(i);
245                 ans.add(dHi.cat(dLo).cat(t).cat(a));
246                 dHi = dHi.not();
247         }
248         return ans;
249     }
250     private void stopToStop(ProperStopper s1, ProperStopper s2, 
251                                 Counter ctr,
252                                 List<BitVector> din) {
253         prln("Begin stopToStop");
254         adjustIndent(2);
255         
256         s1.stop();
257         
258         long ctrStart = ctr==null ? 0 : ctr.getCount();
259         
260         s1.fillMany(din);
261         waitUntilQuiescent();
262         
263         List<BitVector> dout = s2.drainMany();
264         
265         MarinaUtils.compareItemsOrdered(din, dout);
266         
267         if (ctr!=null) {
268                 long ctrEnd = ctr.getCount();
269                 long delta = ctrEnd - ctrStart;
270             long expect = din.size();
271             fatal(delta!=expect, 
272                   "counter delta wrong: expected delta: "+expect+
273                   " counter before:"+ctrStart+" counter after:"+ctrEnd);
274         }
275         
276         adjustIndent(-2);
277         prln("End stopToStop");
278     }
279     /** Burst data from src to dst. gate is stopped while loading src. gate
280      * is then run to allow the burst to flow. */
281     private void stopToStopBurst(ProperStopper src, ProperStopper gate, 
282                                      ProperStopper dst,
283                                      Counter ctr,
284                                      List<BitVector> din) {
285                 prln("Begin stopToStopBurst test");
286                 adjustIndent(2);
287                 
288                 src.stop();
289                 gate.stop();
290                 
291         long ctrStart = ctr==null ? 0 : ctr.getCount();
292                 
293                 src.fillMany(din);
294                 waitUntilQuiescent();
295
296                 // open the gate to start the burst
297                 gate.run();
298                 waitUntilQuiescent();
299                 
300                 List<BitVector> dout = dst.drainMany();
301                 
302                 MarinaUtils.compareItemsOrdered(din, dout);
303                 
304                 if (ctr!=null) {
305                 long ctrEnd = ctr.getCount();
306                 long delta = ctrEnd - ctrStart;
307                 
308                 long expectA = din.size();
309                 fatal(delta!=expectA, 
310                           "counter delta wrong: expected delta: "+expectA+
311                           " counter before:"+ctrStart+" counter after:"+ctrEnd);
312                 }
313                 
314                 adjustIndent(-2);
315                 prln("End stopToStopBurst test");
316 }
317
318     private void stopToStopOne(ProperStopper s1, ProperStopper s2, 
319                                    Counter ctr, int adr) {
320         prln("Begin stopToStopOne");
321         adjustIndent(2);
322         
323         List<BitVector> din = makeIncrDataConstAdr(1, adr);
324         stopToStop(s1, s2, ctr, din);
325
326         adjustIndent(-2);
327         prln("End stopToStopOne");
328     }
329     
330     private void stopToStopThree(ProperStopper s1, ProperStopper s2, 
331                                      Counter ctr, int adr) {
332         prln("Begin stopToStopOne");
333         adjustIndent(2);
334         
335         List<BitVector> din = makeIncrDataConstAdr(3, adr);
336         stopToStop(s1, s2, ctr, din);
337
338         adjustIndent(-2);
339         prln("End stopToStopOne");
340     }
341
342     private int indexOf(BitVector o, List<BitVector> dIn) {
343                 for (int i=0; i<dIn.size(); i++) {
344                         if (o.equals(dIn.get(i)))  return i;
345                 }
346                 return -1;
347     }
348     private String ringDump(List<BitVector> dIn, List<BitVector> dOut) {
349         StringBuffer sb = new StringBuffer();
350         sb.append("  ring dump: ");
351         for (BitVector o : dOut) {
352                 sb.append(indexOf(o, dIn)+" ");
353         }
354         return sb.toString();
355     }
356
357     private int[][] makeIntArray2D(int a, int b) {
358         int[][] ans = new int[a][];
359         for (int i=0; i<a; i++) ans[i] = new int[b];
360         return ans;
361     }
362
363     //=========================================================================
364     // Put top level tests here
365     private void stopToStopOneItem(Marina marina) {
366         stopToStopOne(marina.data, marina.tokOut, null, -1);
367     }
368     private void stopToStopThreeItems(Marina marina) {
369         stopToStopThree(marina.data, marina.tokOut, null, -1);
370     }
371     private void sendInstructions(Marina marina) {
372         prln("Begin sendInstructions");
373         adjustIndent(2);
374         
375         List<BitVector> din = new ArrayList<BitVector>();
376
377         BitVector count = new BitVector(36,"count");
378         BitVector one = new BitVector(36, "one");
379         count.setFromLong(0);
380         one.setFromLong(1);
381         for (int i=0; i<3; i++) {
382                 din.add(count);
383                 count = count.add(one);
384         }
385
386         marina.instrIn.fillMany(din);
387
388         adjustIndent(-2);
389         prln("End sendInstructions");
390     }
391
392     private void sendToken(Marina marina) {
393         prln("Begin sendToken");
394         adjustIndent(2);
395         
396         prln("ILC=1");
397         marina.instrIn.fill(
398                 new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
399
400         getCtrsFlags(marina);
401         
402         prln("send token");
403         marina.instrIn.fill(
404             new Instruction.Move(DOCK,
405                                  false,                 /* requeueing  */
406                                  Predicate.IgnoreOLC,   /* predicate   */
407                                  false,                 /* torpedoable */
408                                  null,                  /* path        */
409                                  false,                 /* tokenIn     */
410                                  false,                 /* dataIn      */
411                                  false,                 /* latchData   */
412                                  false,                 /* latchPath   */
413                                  false,                 /* dataOut     */
414                                  true                   /* tokenOut    */
415                                  ));
416         
417         getCtrsFlags(marina);
418         
419         List<BitVector> toks = marina.tokOut.drainMany();
420         fatal(toks.size()!=1, "Expected one token to emerge but got: "+toks.size()+" tokens");
421         
422         prln("Token="+MarinaUtils.formatDataTokAddr(toks.get(0)));
423
424         adjustIndent(-2);
425         prln("End sendToken");
426     }
427
428     private void sendData(Marina marina) {
429         prln("Begin sendData");
430         adjustIndent(2);
431         
432         prln("ILC=1");
433         marina.instrIn.fill(
434                 new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
435
436         getCtrsFlags(marina);
437         
438         prln("send data");
439         marina.instrIn.fill(
440             new Instruction.Move(DOCK,
441                                  false,                 /* requeueing  */
442                                  Predicate.IgnoreOLC,   /* predicate   */
443                                  false,                 /* torpedoable */
444                                  null,                  /* path        */
445                                  false,                 /* tokenIn     */
446                                  false,                 /* dataIn      */
447                                  false,                 /* latchData   */
448                                  false,                 /* latchPath   */
449                                  true,                  /* dataOut     */
450                                  false                  /* tokenOut    */
451                                  ));
452         
453         getCtrsFlags(marina);
454         
455         List<BitVector> dataItems = marina.data.drainMany();
456         fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
457         
458         prln("Datum="+MarinaUtils.formatDataTokAddr(dataItems.get(0)));
459
460         adjustIndent(-2);
461         prln("End sendData");
462     }
463
464     private void testFlagZ(Marina marina) {
465         prln("Begin testFlagZ");
466         adjustIndent(2);
467         
468         List<BitVector> toks;
469
470         Predicate only_if_olc_zero    = Predicate.OLCZero;
471         Predicate only_if_olc_nonzero = Predicate.Default;
472
473         for(int olc : new int[] { 1, 0 }) {
474             for(boolean predicate_olc_nonzero : new boolean[] { true, false }) {
475                 prln("Attempting send token with "+
476                      "olc=="+olc+" and "+
477                      "predicate olc"+(predicate_olc_nonzero?"!=0":"==0"));
478                 adjustIndent(2);
479                 marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, 1));
480                 if (olc==0)
481                     marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC, SetDest.OuterLoopCounter, SetSource.Decrement));
482                 marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
483                 marina.instrIn.fill(new Instruction.Move(DOCK,
484                                                          false,                 /* requeueing  */
485                                                          predicate_olc_nonzero  /* predicate   */
486                                                          ? only_if_olc_nonzero
487                                                          : only_if_olc_zero
488                                                          ,
489                                                          false,                 /* torpedoable */
490                                                          null,                  /* path        */
491                                                          false,                 /* tokenIn     */
492                                                          false,                 /* dataIn      */
493                                                          false,                 /* latchData   */
494                                                          false,                 /* latchPath   */
495                                                          false,                 /* dataOut     */
496                                                          true                   /* tokenOut    */
497                                                          ));
498                 toks = marina.tokOut.drainMany();
499                 int expected = (predicate_olc_nonzero == (olc!=0)) ? 1 : 0;
500                 fatal(toks.size()!=expected, "Expected "+expected+" token to emerge but got: "+toks.size()+" token(s)");
501                 adjustIndent(-2);
502             }
503         }
504         adjustIndent(-2);
505         prln("End testFlagZ");
506     }
507
508     private void testPredicationOnAB(Marina marina) {
509         prln("Begin testPredicationOnAB");
510         adjustIndent(2);
511         
512         List<BitVector> toks;
513
514         prln("Setting OLC=63");
515         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, 63));
516
517         for(boolean flag_a : new boolean[] { false, true }) {
518             for(boolean flag_b : new boolean[] { false, true }) {
519                 prln("Setting flags, a="+flag_a+" b="+flag_b);
520                 marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,
521                                                         flag_a
522                                                         ? Instruction.Set.FlagFunction.ONE
523                                                         : Instruction.Set.FlagFunction.ZERO,
524                                                         flag_b
525                                                         ? Instruction.Set.FlagFunction.ONE
526                                                         : Instruction.Set.FlagFunction.ZERO
527                                                         ));
528                 getCtrsFlags(marina);
529
530                 adjustIndent(2);
531                 for(Predicate predicate : new Predicate[] {
532                         Predicate.Default,
533                         Predicate.FlagA,
534                         Predicate.FlagB,
535                         Predicate.NotFlagA,
536                         Predicate.NotFlagB,
537                     }) {
538
539                     prln("Attempting send token with a="+flag_a+", b="+flag_b+", predicate="+predicate.getClass().getName());
540                     adjustIndent(2);
541                     marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
542                     marina.instrIn.fill(new Instruction.Move(DOCK,
543                                                              false,                 /* requeueing  */
544                                                              predicate,             /* predicate   */
545                                                              false,                 /* torpedoable */
546                                                              null,                  /* path        */
547                                                              false,                 /* tokenIn     */
548                                                              false,                 /* dataIn      */
549                                                              false,                 /* latchData   */
550                                                              false,                 /* latchPath   */
551                                                              false,                 /* dataOut     */
552                                                              true                   /* tokenOut    */
553                                                              ));
554                     adjustIndent(-2);
555                     toks = marina.tokOut.drainMany();
556                     int expected = predicate.evaluate(flag_a, flag_b, false, false) ? 1 : 0;
557                     fatal(toks.size()!=expected, "Expected "+expected+" token to emerge but got: "+
558                           toks.size()+" token(s)");
559                 }
560                 adjustIndent(-2);
561             }
562         }
563         adjustIndent(-2);
564         prln("End testPredicationOnAB");
565     }
566
567     private void getCtrsFlags(Marina marina) {
568         prln("begin getCtrsFlags");
569         adjustIndent(2);
570         
571         int olc = marina.getOLC();
572         prln("OLC=="+olc);
573         
574         Ilc ilc = marina.getILC();
575         prln("ILC.done=="+ilc.getDone()+
576                  " ILC.infinity=="+ilc.getInfinity()+
577                  " ILC.zero=="+ilc.getZero()+
578                  " ILC.count=="+ilc.getCount());
579         
580         boolean a = marina.getFlagA();
581         prln("flagA=="+a);
582         
583         boolean b = marina.getFlagB();
584         prln("flagB=="+b);
585         
586         boolean c = marina.getFlagC();
587         prln("flagC=="+c);
588         
589         adjustIndent(-2);
590         prln("end getCtrsFlags");
591     }
592     private void walkOneOLC(Marina marina) {
593         prln("Begin walkOneOLC");
594         adjustIndent(2);
595         for (int i=0; i<7; i++) {
596                 int inOlc = 0x20 >> i;
597                 prln("inOlc="+inOlc);
598                 marina.instrIn.fill(new 
599                         Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, inOlc));
600                 int outOlc = marina.getOLC();
601                 fatal(outOlc!=inOlc, "walkOneOLC: got="+outOlc+" expected="+inOlc);
602         }
603         adjustIndent(-2);
604         prln("End walkOneOLC");
605     }
606     private void walkOneILC(Marina marina) {
607         prln("Begin walkOneILC");
608         adjustIndent(2);
609         for (int i=0; i<7; i++) {
610                 // Mask off the "zero" bit position
611                 int inIlc = 0x20 >> i;
612                         prln("inIlc="+inIlc);
613
614                 marina.instrIn.fill(new 
615                         Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, inIlc));
616
617                 Ilc ilc = marina.getILC();
618                 int outIlc = ilc.getCount();
619                 fatal(outIlc!=inIlc, "bad ILC count: "+outIlc+" expected: "+outIlc);
620                 
621                 boolean inZero = inIlc==0;
622                 boolean outZero = ilc.getZero();
623                 fatal(outZero!=inZero, "bad ILC zero: "+outZero);
624         }
625         adjustIndent(-2);
626         prln("End walkOneILC");
627     }
628     private void countIlc(Marina marina) {
629         final int maxIlc = 63;
630         prln("Begin countIlc");
631         adjustIndent(2);
632         
633                 marina.instrIn.fill(new 
634                         Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, maxIlc));
635
636                 int ilc = marina.getILC().getCount();
637                 fatal(ilc!=maxIlc, "bad ILC count: "+ilc+" expected: "+maxIlc);
638                 
639                 // execute a move instruction that does nothing except decrement the ILC to zero
640         marina.instrIn.fill(
641             new Instruction.Move(DOCK,
642                                  false,                                 /* requeueing */
643                                  Predicate.IgnoreOLC,   /* predicate   */
644                                  false,                 /* torpedoable */
645                                  null,                  /* path        */
646                                  false,                 /* tokenIn     */
647                                  false,                 /* dataIn      */
648                                  false,                 /* latchData   */
649                                  false,                 /* latchPath   */
650                                  false,                 /* dataOut     */
651                                  false                  /* tokenOut    */
652                                  ));
653         
654                 // wait for ILC to count from 63 to 0
655         model.waitNS(64 * CYCLE_TIME_NS);
656
657                 ilc = marina.getILC().getCount();
658                 fatal(ilc!=0, "bad ILC count: "+ilc+" expected: "+0);
659         
660         adjustIndent(-2);
661         prln("End countIlc");
662     }
663     // Note: countOlc takes 44 minutes to run on nanosim
664     private void countOlc(Marina marina) {
665         final int maxOlc = 63;
666         prln("Begin countOlc");
667         adjustIndent(2);
668         
669                 marina.instrIn.fill(new 
670                         Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, maxOlc));
671                 for (int i=maxOlc; i>=0; i--) {
672                         prln("OLC should be: "+i);
673                         int olc = marina.getOLC();
674                         fatal(olc!=i, "bad OLC: "+olc+" expected: "+i);
675                         marina.instrIn.fill(new 
676                                 Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, SetSource.Decrement));
677                 }
678
679         adjustIndent(-2);
680         prln("End countOlc");
681     }
682
683     private void saturateInstructionFifo(Marina marina, Instruction instruction, int quantity, boolean expect_it_to_jam_up) {
684         prln("Inserting "+quantity+" copies of \"" + instruction + "\"");
685         adjustIndent(2);
686         int i=0;
687         for(i=0; i<quantity; i++) {
688             prln("Inserting instruction " + (i+1) +"/"+ quantity);
689             marina.instrIn.fill(instruction);
690             boolean jammed = (marina.instrIn.getFillStateWire()==MarinaUtils.StateWireState.FULL);
691             if (jammed && expect_it_to_jam_up) {
692                 prln("Stopper remained full after inserting instruction; this was expected; we are happy.");
693                 adjustIndent(-2);
694                 return;
695             }
696             fatal(jammed, "Instruction stopper did not drain after inserting " + (i+1) + " instructions; not good!");
697         }
698         fatal(expect_it_to_jam_up, "Expected instruction stopper to jam up, but it did not");
699         adjustIndent(-2);
700         prln("Successfully inserted " + i + " instructions");
701     }
702
703     private static final Instruction NOP =
704         new Instruction.Move(DOCK,
705                              false,                  /* requeueing  */
706                              Predicate.IgnoreOLC,   /* predicate   */
707                              false,                 /* torpedoable */
708                              null,                  /* path        */
709                              false,                 /* tokenIn     */
710                              false,                 /* dataIn      */
711                              false,                 /* latchData   */
712                              false,                 /* latchPath   */
713                              false,                 /* dataOut     */
714                              false                  /* tokenOut    */
715                              );
716
717     private static final Instruction REQUEUEING_NOP =
718         new Instruction.Move(DOCK,
719                              true,                  /* requeueing  */
720                              Predicate.IgnoreOLC,   /* predicate   */
721                              false,                 /* torpedoable */
722                              null,                  /* path        */
723                              false,                 /* tokenIn     */
724                              false,                 /* dataIn      */
725                              false,                 /* latchData   */
726                              false,                 /* latchPath   */
727                              false,                 /* dataOut     */
728                              false                  /* tokenOut    */
729                              );
730
731     private static final Instruction SEND_DATA =
732         new Instruction.Move(DOCK,
733                              false,                 /* requeueing  */
734                              Predicate.IgnoreOLC,   /* predicate   */
735                              false,                 /* torpedoable */
736                              null,                  /* path        */
737                              false,                 /* tokenIn     */
738                              false,                 /* dataIn      */
739                              false,                 /* latchData   */
740                              false,                 /* latchPath   */
741                              true,                  /* dataOut     */
742                              false                  /* tokenOut    */
743                              );
744
745     private static final Instruction REQUEUEING_SEND_DATA =
746         new Instruction.Move(DOCK,
747                              true,                  /* requeueing  */
748                              Predicate.IgnoreOLC,   /* predicate   */
749                              false,                 /* torpedoable */
750                              null,                  /* path        */
751                              false,                 /* tokenIn     */
752                              false,                 /* dataIn      */
753                              false,                 /* latchData   */
754                              false,                 /* latchPath   */
755                              true,                  /* dataOut     */
756                              false                  /* tokenOut    */
757                              );
758
759     private void testRequeueStage0(Marina marina) {
760         prln("Begin testRequeueStage0");
761         adjustIndent(2);
762
763         prln("Executing Set OLC=1");
764         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,1));
765         prln("Executing Set OLC--");
766         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,SetSource.Decrement));
767         saturateInstructionFifo(marina, REQUEUEING_NOP, MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT, false);
768         adjustIndent(-2);
769         prln("End testRequeueStage0");
770     }
771
772     private void testRequeueStage0to1(Marina marina) {
773         prln("Begin testRequeueStage0to1");
774         adjustIndent(2);
775
776         prln("Executing Set OLC=63");
777         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,63));
778         saturateInstructionFifo(marina, REQUEUEING_NOP, MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT, true);
779         adjustIndent(-2);
780         prln("End testRequeueStage0to1");
781     }
782
783     /**
784      *  This test brings the requeue stage through the 0->1->3 state
785      *  transition sequence.
786      *
787
788      *  According to the diagram in IES50, there are two transitions
789      *  (0->1, 1->3) to perform, and in each state there are two
790      *  behaviors to verify (the two notations in each oval of the
791      *  state diagram).  The "OD->drain" behavior of state 0 is
792      *  verified by testRequeueStage0().
793      */
794     private void testRequeueStage0to1to3to0(Marina marina) {
795         List<BitVector> dataItems;
796
797         int olc_value = 63;
798
799         prln("Begin testRequeueStage0to1to3to0");
800         adjustIndent(2);
801
802         // State 0 //////////////////////////////////////////////////////////////////////////////
803
804         prln("Executing Set OLC="+olc_value);
805         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,olc_value));
806         prln("Executing Set ILC=1");
807         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
808
809         // verify state0 "EPI->ring" and 0->1 transition
810         prln("Executing Send Data (requeueable); this will cause 0->1 transition and be discarded");
811         marina.instrIn.fill(REQUEUEING_SEND_DATA);
812
813         // State 1 //////////////////////////////////////////////////////////////////////////////
814
815         // verify state1 "EPI->ring"
816         prln("Executing Set ILC=1; this will be recirculated");
817         marina.instrIn.fill(new Instruction.Set(DOCK,true,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, 1));
818
819         prln("Executing Send Data; this will be recirculated");
820         marina.instrIn.fill(REQUEUEING_SEND_DATA);
821
822         prln("Executing Set OLC--; this will be recirculated");
823         marina.instrIn.fill(new Instruction.Set(DOCK,true,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,SetSource.Decrement));
824
825         // verify state1 "OD waits"
826         dataItems = marina.data.drainMany(2);
827         fatal(dataItems.size()!=1, "Expected exactly one data item to emerge but got: "+dataItems.size()+" data items");
828
829         // verify 1->3 transition
830         prln("Executing Tail; this will cause the 2->3 transition and be discarded");
831         marina.instrIn.fill(new Instruction.Tail(DOCK));
832
833         // State 3 //////////////////////////////////////////////////////////////////////////////
834
835         // verify state3 "OD->ring"
836         dataItems = marina.data.drainMany(MORE_THAN_DATA_OUT_SATURATION_AMOUNT);
837         fatal(dataItems.size()<MORE_THAN_DATA_OUT_SATURATION_AMOUNT,
838               "Expected an endless supply of data items, but only got: "+dataItems.size()+" of them");
839
840         // verify state3 "OD->ring"
841         saturateInstructionFifo(marina, NOP, MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT, true);
842
843         // verify state3->state0
844         dataItems = marina.data.drainMany(olc_value);
845         fatal(dataItems.size()>=olc_value,
846               "Expected less than " + olc_value + " items to emerge, but got at least : "+dataItems.size()+" of them");
847
848         // State 0 //////////////////////////////////////////////////////////////////////////////
849
850         // verify that we are back in state0
851         saturateInstructionFifo(marina, REQUEUEING_NOP, MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT, false);
852
853         adjustIndent(-2);
854         prln("End testRequeueStage0to1to3to0");
855     }
856
857     private void testWaitForTail(Marina marina) {
858         List<BitVector> dataItems;
859
860         prln("Begin testWaitForTail");
861         adjustIndent(2);
862
863         prln("inserting instruction: Set OLC=63");
864         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,63));
865
866         prln("inserting instruction: [Rq] Nop; this will cause 0->1 transition and possibly be discarded");
867         marina.instrIn.fill(REQUEUEING_NOP);
868
869         // just in case there is some capacity between the execution
870         // stage and the requeue stage, we stick in a whole bunch of
871         // NOPs.
872         for(int i=0; i<4; i++) {
873             prln("inserting instruction: [Rq] Nop; this (and subsequent instructions) should not execute until Tail is inserted");
874             marina.instrIn.fill(REQUEUEING_NOP);
875         }
876
877         prln("inserting instruction: [Rq] Set ILC=1");
878         marina.instrIn.fill(new Instruction.Set(DOCK,true,Predicate.IgnoreOLC,SetDest.InnerLoopCounter,1));
879
880         prln("inserting instruction: [Rq] Send Data");
881         marina.instrIn.fill(REQUEUEING_SEND_DATA);
882
883         dataItems = marina.data.drainMany(1);
884         fatal(dataItems.size()!=0, "Expected exactly no data items to emerge but got at least: "+dataItems.size());
885
886         adjustIndent(-2);
887         prln("End testWaitForTail");
888     }
889
890     private void testRequeueStageDrop(Marina marina) {
891         List<BitVector> dataItems;
892
893         prln("Begin testRequeueStageDrop");
894         adjustIndent(2);
895
896         prln("inserting instruction: Set OLC=63");
897         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter,63));
898
899         prln("inserting instruction: Set ILC=1");
900         marina.instrIn.fill(new Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter,1));
901
902         // if you uncomment this, then the NOP will be dropped and the test will pass
903         /*
904         prln("inserting instruction: [Rq] Nop; this will cause 0->1 transition and possibly be discarded");
905         marina.instrIn.fill(REQUEUEING_NOP);
906         */
907
908         prln("inserting instruction: [Rq] Send Data; this will cause 0->1 transition and be discarded");
909         marina.instrIn.fill(REQUEUEING_SEND_DATA);
910
911         prln("inserting instruction: [Rq] Set ILC=1");
912         marina.instrIn.fill(new Instruction.Set(DOCK,true,Predicate.IgnoreOLC,SetDest.InnerLoopCounter,1));
913
914         prln("inserting instruction: Tail");
915         marina.instrIn.fill(new Instruction.Tail(DOCK));
916
917         dataItems = marina.data.drainMany(3);
918         fatal(dataItems.size()<3, "Expected exactly unlimited data items to emerge but got only: "+dataItems.size());
919
920         adjustIndent(-2);
921         prln("End testRequeueStageDrop");
922     }
923
924
925     private void testFlagAB(Marina marina) {
926         prln("Begin testFlagAB");
927         adjustIndent(2);
928
929         Instruction.Set.FlagFunction zero = Instruction.Set.FlagFunction.ZERO;
930         Instruction.Set.FlagFunction one  = zero;
931
932         
933         // we should be able to use any pair of FlagX+NotFlagX,
934         // but we toss them all in to maximize the chances of the
935         // test passing (later we will try the individual
936         // combinations to maximize the chances of failure).
937         one = one.add(Predicate.FlagA);
938         one = one.add(Predicate.NotFlagA);
939         one = one.add(Predicate.FlagB);
940         one = one.add(Predicate.NotFlagB);
941         one = one.add(Predicate.FlagC);
942         one = one.add(Predicate.NotFlagC);
943
944         // clear the flags to a known state, then check both 0->1 and 1->0 transitions
945         for(boolean b : new boolean[] { false, true, false }) {
946             prln((b?"Setting":"Clearing")+" flags");
947
948             marina.instrIn.fill(new 
949                                 Instruction.Set(DOCK,false,Predicate.IgnoreOLC,
950                                                 b ? one : zero,
951                                                 b ? one : zero
952                                                 ));
953             fatal(marina.getFlagA()!=b, "after "+(b?"setting":"clearing")+" FlagA, it was still "+(b?"clear":"set"));
954             fatal(marina.getFlagB()!=b, "after "+(b?"setting":"clearing")+" FlagB, it was still "+(b?"clear":"set"));
955         }
956
957         adjustIndent(-2);
958         prln("End testFlagAB");         
959     }
960     private void sendTorpedo(Marina marina) {
961         prln("Begin sendTorpedo");
962         adjustIndent(2);
963         
964         prln("OLC = 63");
965                 marina.instrIn.fill(new 
966                 Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, 63));
967
968                 int olc = marina.getOLC();
969                 fatal(olc!=63, "bad OLC: "+olc+" expected: 63");
970
971                 prln("A=0, B=0");
972                 marina.instrIn.fill(new 
973             Instruction.Set(DOCK,false,Predicate.IgnoreOLC, CLEAR_FLAG, CLEAR_FLAG));
974
975                 fatal(marina.getFlagA(), "bad A flag: true");
976                 fatal(marina.getFlagB(), "bad B flag: true");
977                 
978                 prln("ILC = Infinity");
979                 marina.instrIn.fill(new 
980                 Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.InnerLoopCounter, SetSource.Infinity));
981                 
982                 prln("execute a move instruction that does nothing but loops until torpedo arrives"); 
983         marina.instrIn.fill(
984             new Instruction.Move(DOCK,
985                                      false,                             /* requeueing */
986                                  Predicate.IgnoreOLC,   /* predicate   */
987                                  true,                 /* torpedoable */
988                                  null,                  /* path        */
989                                  false,                 /* tokenIn     */
990                                  false,                 /* dataIn      */
991                                  false,                 /* latchData   */
992                                  false,                 /* latchPath   */
993                                  false,                 /* dataOut     */
994                                  false                  /* tokenOut    */
995                                  ));
996         
997                 prln("NOP This instruction can't predicate on OLC because of a hardware bug");
998                 marina.instrIn.fill(new 
999             Instruction.Set(DOCK,false,Predicate.Default, A_FLAG, B_FLAG));
1000
1001                 prln("A=1, B=1 This instruction should get torpedoed along with the Move");
1002                 marina.instrIn.fill(new 
1003                 Instruction.Set(DOCK,false,Predicate.Default, SET_FLAG, SET_FLAG));
1004
1005                 prln("send torpedo. This should clear the OLC");
1006                 marina.instrIn.fill(InstructionStopper.TORPEDO);
1007                 
1008                 getCtrsFlags(marina);
1009                 
1010                 prln("A and B should remain false");
1011                 fatal(marina.getFlagA(), "bad A flag: true");
1012                 fatal(marina.getFlagB(), "bad B flag: true");
1013         
1014         prln("OLC = 63. Reload OLC after torpedo");
1015                 marina.instrIn.fill(new 
1016                 Instruction.Set(DOCK,false,Predicate.IgnoreOLC,SetDest.OuterLoopCounter, 63));
1017
1018                 olc = marina.getOLC();
1019                 fatal(olc!=63, "bad OLC: "+olc+" expected: 63");
1020                 
1021                 prln("A=1, B=1 This instruction should execute because OLC!=0");
1022                 marina.instrIn.fill(new 
1023                         Instruction.Set(DOCK,false,Predicate.Default, SET_FLAG, SET_FLAG));
1024
1025                 prln("A and B should be true");
1026                 fatal(!marina.getFlagA(), "bad A flag: false");
1027                 fatal(!marina.getFlagB(), "bad B flag: false");
1028                 
1029                 adjustIndent(-2);
1030         prln("End sendTorpedo");        
1031     }    
1032         private void doOneTest(int testNum) {
1033         prln("MarinaTest: performing test: "+testNum);
1034         marina.masterClear(tester);
1035         
1036         marina.enableInstructionSend(true);
1037         
1038                 switch (testNum) {
1039                 case 2:                 sendInstructions(marina);               break;
1040                 case 3:                 sendToken(marina);                              break;
1041                 case 4:                 getCtrsFlags(marina);                   break;
1042                 case 5:                 walkOneOLC(marina);                             break;
1043                 
1044                 // Russell's tests begin with 1000
1045                 case 1000:              walkOneILC(marina);                     break;
1046                 case 1001:              countIlc(marina);                               break;
1047                 case 1002:              countOlc(marina);                               break;
1048                 case 1003:              sendTorpedo(marina);                    break;
1049                 
1050                 // Bill's tests begin with 2000
1051                 case 2000: break;
1052                     
1053                 // Adam's tests begin with 3000
1054                 case 3000: sendToken(marina); break;
1055                 case 3001: testFlagAB(marina); break;
1056                 case 3002: testRequeueStage0(marina); break;
1057                 case 3003: testRequeueStage0to1(marina); break;
1058                 case 3004: testFlagZ(marina); break;
1059                 case 3005: testPredicationOnAB(marina); break;
1060         case 3006: sendData(marina); break;
1061                 case 3007: testRequeueStage0to1to3to0(marina); break;
1062                 case 3008: testWaitForTail(marina); break;
1063                 case 3009: testRequeueStageDrop(marina); break;         
1064
1065                 default:
1066                         fatal(true, "Test number: "+testNum+" doesn't exist.");
1067                         break;
1068                 }
1069                 // If we get here then test passed
1070                 prln("Passed");
1071         }
1072
1073
1074     //============================ for public use =============================
1075
1076         
1077     public static void main(String[] args) {
1078         startTime = System.currentTimeMillis();
1079                 new MarinaTest(args);
1080                 printTestTime();
1081     }
1082
1083 }