further cleanup of MarinaTest
[fleet.git] / src / edu / berkeley / fleet / marina / Marina.java
1 package edu.berkeley.fleet.marina;
2 import edu.berkeley.fleet.api.*;
3 import com.sun.electric.tool.simulation.test.*;
4 import com.sun.electric.tool.simulation.test.BitVector;
5
6 public class Marina extends MarinaFleet {
7
8     JtagLogicLevel mc0;
9     JtagLogicLevel mc1;
10     private final Indenter indenter;
11
12     public final ChainControl controlChain;
13     public final ChainControl dataChain;
14     public final ChainControl dukeChain;
15     public final ChainControl reportChain;
16
17     private final ChipModel model;
18     public final ProperStopper      northRing;
19     public final InstructionStopper southRing;
20     int northCount = 0;
21     int southCount = 0;
22
23     public Marina(ChainControl controlChain,
24                   ChainControl dataChain,
25                   ChainControl dukeChain,
26                   ChainControl reportChain,
27                   ChipModel model,
28                   boolean clockHack,
29                   Indenter indenter) {
30         this.controlChain = controlChain;
31         this.dataChain = dataChain;
32         this.dukeChain = dukeChain;
33         this.reportChain = reportChain;
34         this.model = model;
35         this.indenter = indenter;
36         northRing = new ProperStopper(prefix+"northFif@1.fillDrai@1",
37                                       controlChain,
38                                       dataChain,
39                                       reportChain,
40                                       model,
41                                       clockHack,
42                                       indenter,
43                                       prefix+"northFif@1.fillDrai@1.instruct@0.cntScnTh@1.cntScnOn@1");
44         southRing = new InstructionStopper(prefix+"southFif@1.tapPropS@1", 
45                                            controlChain,
46                                            dataChain,
47                                            reportChain,
48                                            model,
49                                            clockHack,
50                                            indenter,
51                                            prefix+"southFif@1.tapPropS@1.instruct@0.cntScnTh@1.cntScnOn@1");
52     }
53
54     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE  = 5;
55     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO = MarinaPath.SIGNAL_BIT_INDEX;
56        
57     private static final int COUNTER_LENGTH = 34;
58     public static final int INSTRUCTION_LENGTH = 36;
59     public static final int SOUTH_RING_CAPACITY = 11;
60     public static final int TOKEN_FIFO_CAPACITY = 3;
61     public static final boolean kesselsCounter = false;
62     public static final boolean omegaCounter = false;
63     public static final String DATA_CHAIN =    kesselsCounter ? "marina.marina_data" : "marina.ivan_data";      
64     public static final String CONTROL_CHAIN = kesselsCounter ? "marina.marina_control" : "marina.ivan_control";
65     public static final String REPORT_CHAIN =  kesselsCounter ? "marina.marina_report" : "marina.ivan_report";
66     public static final String DUKE_CHAIN   = "marina.duke";
67
68     public static String prefix = "marinaGu@0.outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@"+(kesselsCounter?"1":"0")+".";
69     public static String MASTER_CLEAR = "mc";
70
71     private static final String CENTER_PATH = prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0";
72     private static final String OLC_PATH_EVEN = CENTER_PATH+".olcWcont@0.scanEx3h@1"; // bits 2,4,6
73     private static final String OLC_PATH_ODD = CENTER_PATH+".olcWcont@0.scanEx3h@2"; // bits 1,3,5
74     private static final String OLC_PATH_KESSEL = CENTER_PATH+".counte@0.adamScan@1.scanEx6h@";
75     private static final String ILC_PATH_ODD = CENTER_PATH+".ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
76     private static final String ILC_PATH_EVEN = CENTER_PATH+".ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
77     private static final String FLAGS_PATH = CENTER_PATH+".flags@0.scanEx3h@0";
78     private static final String TOK_FIFO_PATH = prefix+"tokenFIF@1";
79     private static final String INSTRUCTION_COUNTER_PATH = prefix+"southFif@1.tapPropS@1.instruct@0";
80     private static final String DATA_COUNTER_PATH =prefix+"northFif@1.fillDrai@1.instruct@0";
81     private static final String TOK_PRED_PATH = CENTER_PATH+".ilcMoveO@0.scanEx2h@0.scanCell@10";
82         
83     // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
84     private class Ilc {
85         // value is bit reversed and complemented
86         private int value;
87         private Ilc() {
88             reportChain.shift(REPORT_CHAIN, true, false);
89             BitVector odd  = reportChain.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
90             BitVector even = reportChain.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
91             BitVector ret  = new BitVector(8, "olc");
92             for(int i=0; i<4; i++) {
93                 ret.set(i*2+1, odd.get(i));
94                 ret.set(i*2,   even.get(i));
95             }
96             value = (int)ret.toLong();
97         }
98         /** Get the inner loop counter done bit. */
99         public boolean getDone() {
100             return (value & 0x40) != 0;
101         }
102         /** Get the inner loop counter infinity bit */
103         public boolean getInfinity() {
104             return (value & 0x80) != 0;
105         }
106         /** Get the 6 bits of count of the inner loop counter */
107         public int getCount() {
108             return value & 0x3f;
109         }
110         public String toString() {
111             return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
112         }
113     }
114         
115     public void stopAndResetCounters() {
116         southRing.setCounterEnable(false);
117         northRing.setCounterEnable(false);
118         dataChain.shift(DATA_CHAIN, true, false);        
119         northCount = northRing.getCounterValue();
120         southCount = southRing.getCounterValue();
121         northRing.setCounterValue(0);
122         southRing.setCounterValue(0);
123     }
124     public void startCounters() { startCounters(true, true); }
125     public void startCounters(boolean south, boolean north) {
126         southRing.setCounterEnable(south);
127         northRing.setCounterEnable(north);
128     }
129     public int getNorthCount() { return northCount; }
130     public int getSouthCount() { return southCount; }
131
132     public void masterClear() {
133         final double WIDTH = 10; // ns
134         // Put a high going pulse on the internal chip master clear signal
135         if (model instanceof VerilogModel) {
136
137             northRing.clear();
138             southRing.clear();
139
140             VerilogModel vm = (VerilogModel)model;
141             //
142             // In real life the flags come up with some undefined
143             // value.  In verilog we need to prevent the X'es from
144             // propagating, so we force the flags to a known value
145             //
146             vm.setNodeState(CENTER_PATH+".flag_A__set_", 0);
147             vm.setNodeState(CENTER_PATH+".flag_A__clr_", 1);
148             vm.setNodeState(CENTER_PATH+".flag_B__set_", 0);
149             vm.setNodeState(CENTER_PATH+".flag_B__clr_", 1);
150
151             vm.setNodeState(CENTER_PATH+".flag_D__set_", 1);
152             vm.setNodeState(CENTER_PATH+".flag_D__clr_", 0);
153
154             vm.setNodeState(CENTER_PATH+".flags@0.aFlag@0.net_50", 0);       // A
155             vm.setNodeState(CENTER_PATH+".flags@0.aFlag@1.net_50", 0);       // B
156             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
157
158             // possible C-flag inputs
159             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
160             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
161
162             // force the OLC to zero
163             if (!kesselsCounter)
164                 for(int i=1; i<=6; i++)
165                     vm.setNodeState(CENTER_PATH+".olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
166
167             // set the ILC input to 1
168             for(int i=1; i<=8; i++) {
169                 if (i!=7)
170                     vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
171             }
172
173             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
174             model.waitNS(1000);
175             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
176             model.waitNS(1000);
177
178             vm.setNodeState(MASTER_CLEAR, 1);
179             model.waitNS(1000);
180             vm.setNodeState(MASTER_CLEAR, 0);
181             model.waitNS(1000);
182
183             // pulse ilc[load] and olc[load]
184             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_load_", 1);
185             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_decLO_", 1);
186             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
187             if (!kesselsCounter)
188                 vm.setNodeState(CENTER_PATH+".olcWcont@0.olc@0.olc_load_", 1);
189             model.waitNS(100);
190             model.waitNS(1);
191             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_load_");
192             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_decLO_");
193             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_torpLO_");
194             if (!kesselsCounter)
195                 vm.releaseNode(CENTER_PATH+".olcWcont@0.olc@0.olc_load_");
196
197             vm.releaseNode(CENTER_PATH+".flag_A__set_");
198             vm.releaseNode(CENTER_PATH+".flag_A__clr_");
199             vm.releaseNode(CENTER_PATH+".flag_B__set_");
200             vm.releaseNode(CENTER_PATH+".flag_B__clr_");
201
202             vm.releaseNode(CENTER_PATH+".flag_D__set_");
203             vm.releaseNode(CENTER_PATH+".flag_D__clr_");
204
205             vm.releaseNode(CENTER_PATH+".flags@0.aFlag@0.net_50");
206             vm.releaseNode(CENTER_PATH+".flags@0.aFlag@1.net_50");
207
208             // Every move instruction, even those with Ti=0,Di=0,
209             // loads the C-flag.  It will get loaded with an "X",
210             // which will then leak into the flags and from there the
211             // predicate.
212             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
213             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
214             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
215             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
216
217             for(int i=1; i<=8; i++) {
218                 if (i!=7)
219                     vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
220             }
221             model.waitNS(1000);
222
223             if (!kesselsCounter)
224                 for(int i=1; i<=6; i++)
225                     vm.releaseNode(CENTER_PATH+".olcWcont@0.olc@0.inLO["+i+"]");
226
227             // the proper stopper states come up in an undefined ("X")
228             // state, so under Verilog we need to force them to a
229             // known state
230
231             northRing.idle();
232             southRing.idle();
233
234         } else if (model instanceof NanosimModel) {
235             NanosimModel nModel = (NanosimModel) model;
236             /*
237             nModel.setNodeVoltage(prefix+"sid[9]",1.0);
238             nModel.setNodeVoltage(prefix+"sic[9]",1.0);
239             nModel.setNodeVoltage(prefix+"sir[9]",1.0);
240             nModel.waitNS(WIDTH);
241             nModel.setNodeVoltage(prefix+"sid[9]",0.0);
242             nModel.setNodeVoltage(prefix+"sic[9]",0.0);
243             nModel.setNodeVoltage(prefix+"sir[9]",0.0);
244             nModel.waitNS(1);
245             */
246             nModel.setNodeVoltage(MASTER_CLEAR,1.0);
247             nModel.waitNS(WIDTH);
248             nModel.setNodeVoltage(MASTER_CLEAR,0.0);
249             nModel.waitNS(1);
250         } else {
251
252             mc0.setLogicState(true);
253             mc1.setLogicState(true);
254             model.waitNS(1000);
255             mc0.setLogicState(false);
256             mc1.setLogicState(false);
257             model.waitNS(1000);
258
259         }
260
261         // The following call to ChainControl.resetInBits() is vital!
262         // If you forget, then the inBits member initializes 
263         // with random northRing. Then when you do your first write,
264         // some bits are written randomly.
265         controlChain.resetInBits();
266         dataChain.resetInBits();
267         dukeChain.resetInBits();
268         reportChain.resetInBits();
269
270         northRing.clear();
271         southRing.clear();
272         northRing.stop();
273         southRing.stop();
274     }
275
276
277     /** Get the 6 bit outer loop counter. */
278     public int getOLC() {
279         reportChain.shift(REPORT_CHAIN, true, false);
280         if (omegaCounter) {
281             BitVector bits = null;
282             for(int i=0; i<4; i++) {
283                 BitVector x = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
284                 //System.out.println("bits are: " + x);
285                 bits = bits==null ? x : bits.cat(x);
286             }
287             System.out.print("  kesselsCounter = ");
288             int ret = 0;
289             boolean done = true;
290             boolean bad = false;
291             for(int bit=5; bit>=0; bit--) {
292                 boolean zeroOrTwo  = bits.get(4+bit*3);
293                 boolean zeroOrDone = bits.get(4+bit*3+1);
294                 if      ( zeroOrTwo && !zeroOrDone) {
295                     ret += (2<<bit);
296                     System.out.print("2");
297                     done = false;
298                 } else if (!zeroOrTwo && !zeroOrDone) {
299                     ret += (1<<bit);
300                     System.out.print("1");
301                     done = false;
302                 } else if ( zeroOrTwo &&  zeroOrDone) {
303                     System.out.print("0");
304                     bad = true;
305                     done = false;
306                 } else if (!zeroOrTwo &&  zeroOrDone) {
307                     System.out.print("_");
308                     if (!done) bad = true;
309                 }
310                 // FIXME: check for unreduced counter and warn about it
311             }
312             if (bad) System.out.print("  WARNING: UNREDUCED COUNTER VALUE!!!!!!");
313             System.out.println();
314             return ret;
315         } else if (kesselsCounter) {
316             BitVector bits = null;
317             for(int i=0; i<4; i++) {
318                 BitVector x = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
319                 //System.out.println("bits are: " + x);
320                 bits = bits==null ? x : bits.cat(x);
321             }
322             //System.out.println("kesselsCounter = " + bits);
323             int first = 0;
324             int second = 0;
325             String hi="";
326             String lo="";
327             String latched="";
328             String res="";
329             for(int i=0; i<6; i++) {
330                 first  |= bits.get(4+i*3)   ? (1<<i) : 0;
331                 second |= bits.get(4+i*3+2) ? (1<<i) : 0;
332                 hi = (bits.get(4+i*3)   ? "1" : "0") + hi;
333                 lo = (bits.get(4+i*3+2)   ? "1" : "0") + lo;
334                 res =
335                     (   bits.get(4+i*3) && !bits.get(4+i*3+2) ? "X"
336                      : !bits.get(4+i*3) && !bits.get(4+i*3+2) ? "0"
337                      : !bits.get(4+i*3) &&  bits.get(4+i*3+2) ? "1"
338                      : "2")
339                     +res;
340                 latched = (bits.get(4+i*3+1)   ? "0" : "1") + latched;
341             }
342             System.out.println("kesselsCounter: "+
343                                "s[1]="+hi+
344                                " s[3]="+lo+
345                                " latched="+latched +
346                                " res="+res+
347                                " do[ins]="+(bits.get(0) ? "1" : "0")+
348                                " dec="+(bits.get(1) ? "1" : "0")+
349                                " flag[D][set]="+(bits.get(2) ? "1" : "0")+
350                                " resetting="+(bits.get(3) ? "1" : "0")+
351                                ""
352                                );
353             return (first+second);
354         } else {
355             BitVector odd = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
356             BitVector even = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
357             odd = odd.not();
358             even = even.not();
359             BitVector bv = new BitVector(6, "olc");
360             for(int i=0; i<3; i++) {
361                 bv.set(i*2,   odd.get(i));
362                 bv.set(i*2+1, even.get(i));
363             }
364             return (int)bv.toLong();
365         }
366     }
367     public boolean getILCInfinity() { return new Ilc().getInfinity(); }
368     public boolean getILCDone() { return new Ilc().getDone(); }
369     public int getILC() { return new Ilc().getCount(); }
370     public boolean getFlagA() {
371         reportChain.shift(REPORT_CHAIN, true, false);
372         return reportChain.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(0);
373     }
374     public boolean getFlagB() {
375         reportChain.shift(REPORT_CHAIN, true, false);
376         return reportChain.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(1);
377     }
378     /** get the number of tokens in the token FIFO.
379      * This includes the Token successor wire, the token FIFO wires,
380      * and Token predecessor wire.
381      * Master clear clears the token FIFO. */
382     public int getNumTokens() {
383         reportChain.shift(REPORT_CHAIN, true, false);
384         // get the token successor and token FIFO wires
385         BitVector bv = reportChain.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
386         int sz = bv.getNumBits();
387         MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
388         
389         // get the token predecessor wire
390         BitVector pred = reportChain.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
391         sz = pred.getNumBits();
392         MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
393
394         // concatenate them
395         bv = bv.cat(pred);
396         sz = bv.getNumBits();
397         
398         int nbTok = 0;
399         for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
400         return nbTok;
401     }
402 }