works
[fleet.git] / testCode / com / sun / vlsi / chips / marina / test / Marina.java
1 package com.sun.vlsi.chips.marina.test;
2 /* -*- tab-width: 4 -*- */
3 import com.sun.async.test.BitVector;
4 import com.sun.async.test.ChainControl;
5 import com.sun.async.test.ChipModel;
6 import com.sun.async.test.JtagTester;
7 import com.sun.async.test.NanosimModel;
8 import com.sun.async.test.VerilogModel;
9
10 import edu.berkeley.fleet.api.Instruction;
11 import edu.berkeley.fleet.marina.MarinaPath;
12
13 /** The Marina object will eventually represent the Marina test chip.  
14  * Right now, it doesn't do much of anything. It just helps me exercise
15  * my test infrastructure. */
16 public class Marina {
17
18     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE  = 5;
19     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO = MarinaPath.SIGNAL_BIT_INDEX;
20
21     public static final String DATA_CHAIN =    "marina.marina_data";      
22     public static final String CONTROL_CHAIN = "marina.marina_control";
23     public static final String REPORT_CHAIN =  "marina.marina_report";
24         
25     private static String prefix = "marinaGu@0.outDockW@3.marinaOu@1.";
26
27     private static final String OLC_PATH_EVEN = 
28         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@1"; // bits 2,4,6
29     private static final String OLC_PATH_ODD = 
30         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@2"; // bits 1,3,5
31     private static final String OLC_PATH_KESSEL = 
32         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.counte@0.adamScan@1.scanEx6h@";
33     private static final String ILC_PATH_ODD = 
34         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
35     private static final String ILC_PATH_EVEN = 
36         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
37     private static final String FLAGS_PATH = 
38         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.scanEx3h@0";
39
40     private static final String INSTR_RING_CONTROL_PATH = 
41         prefix+"southFif@1.tapPropS@1.tapStage@2";
42     private static final String TOK_FIFO_PATH =
43         prefix+"tokenFIF@1";
44     private static final String INSTRUCTION_COUNTER_PATH =
45         prefix+"southFif@1.tapPropS@1.instruct@0";
46     private static final String DATA_COUNTER_PATH =
47         prefix+"northFif@1.fillDrai@1.instruct@0";
48     private static final String TOK_PRED_PATH =
49         prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx2h@0.scanCell@10";
50
51     private static final int COUNTER_LENGTH = 34;
52     private static final int INSTRUCTION_SEND_NDX = 1;
53     private static final int INSTRUCTION_RECIRCULATE_NDX = 0;
54
55     public static final int INSTRUCTION_LENGTH = 36;
56         
57     private static final int A_FLAG_NDX = 0;
58     private static final int B_FLAG_NDX = 1;
59         
60     public static final int SOUTH_RING_CAPACITY = 11;
61         
62     // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
63     public class Ilc {
64         // value is bit reversed and complemented
65         private int value;
66         private Ilc() {
67             shiftReport(true, false);
68             BitVector odd  = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
69             BitVector even = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
70             BitVector ret  = new BitVector(8, "olc");
71             for(int i=0; i<4; i++) {
72                 ret.set(i*2+1, odd.get(i));
73                 ret.set(i*2,   even.get(i));
74             }
75             value = (int)ret.toLong();
76         }
77         /** Get the inner loop counter done bit. */
78         public boolean getDone() {
79             return (value & 0x40) != 0;
80         }
81         /** Get the inner loop counter infinity bit */
82         public boolean getInfinity() {
83             return (value & 0x80) != 0;
84         }
85         /** Get the 6 bits of count of the inner loop counter */
86         public int getCount() {
87             return value & 0x3f;
88         }
89         public String toString() {
90             return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
91         }
92     }
93         
94     private final Indenter indenter;
95
96     // The name of the scan chain
97     // The instance path, from the top cell of the netlist, of the instance of infinityWithCover 
98     private final ChainControls cc;           // specifies the scan chain
99     private final ChipModel model;
100     public final ProperStopper data;
101     public final InstructionStopper instrIn;
102     
103     private void prln(String msg) {indenter.prln(msg);}
104     private void pr(String msg) {indenter.pr(msg);}
105     
106     /** Shift the report scan chain */
107     private void shiftReport(boolean readEnable, boolean writeEnable) {
108         cc.shift(REPORT_CHAIN, readEnable, writeEnable);
109     }
110     
111     /** Shift the report scan chain */
112     private void shiftControl(boolean readEnable, boolean writeEnable) {
113         cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
114     }
115         
116     /** Shift the data scan chain */
117     private void shiftData(boolean readEnable, boolean writeEnable) {
118         cc.shift(DATA_CHAIN, readEnable, writeEnable);
119     }
120
121     public Marina(ChainControls cc, ChipModel model, boolean clockHack, Indenter indenter) {
122         this.cc = cc;
123         this.model = model;
124         this.indenter = indenter;
125         data = new ProperStopper("north fifo",
126                                  prefix+"northFif@1.fillDrai@1.properSt@1",
127                                  CONTROL_CHAIN, 
128                                  DATA_CHAIN,  
129                                  REPORT_CHAIN,
130                                  cc, model, clockHack, indenter);
131         instrIn = new InstructionStopper("south fifo",
132                                          prefix+"southFif@1.tapPropS@1.properSt@1", 
133                                          CONTROL_CHAIN,
134                                          DATA_CHAIN,
135                                          REPORT_CHAIN,
136                                          cc, model, clockHack, indenter);
137     }
138     public void masterClear() {
139         final double WIDTH = 10; // ns
140         // Put a high going pulse on the internal chip master clear signal
141         if (model instanceof VerilogModel) {
142
143             data.clear();
144             instrIn.clear();
145
146             VerilogModel vm = (VerilogModel)model;
147             //
148             // In real life the flags come up with some undefined
149             // value.  In verilog we need to prevent the X'es from
150             // propagating, so we force the flags to a known value
151             //
152             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_", 0);
153             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_", 1);
154             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_", 0);
155             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_", 1);
156
157             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_", 1);
158             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_", 0);
159
160             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50", 0);       // A
161             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50", 0);       // B
162             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
163
164             // possible C-flag inputs
165             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
166             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
167
168             // force the OLC to zero
169             if (!kesselsCounter)
170                 for(int i=1; i<=6; i++)
171                     vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
172
173             // set the ILC input to 1
174             for(int i=1; i<=8; i++) {
175                 if (i!=7)
176                     vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
177             }
178
179             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
180             model.waitNS(1000);
181             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
182             model.waitNS(1000);
183
184             vm.setNodeState("sid[9]", 1);
185             vm.setNodeState("sic[9]", 1);
186             vm.setNodeState("sir[9]", 1);
187             model.waitNS(1000);
188             vm.setNodeState("sid[9]", 0);
189             vm.setNodeState("sic[9]", 0);
190             vm.setNodeState("sir[9]", 0);
191             model.waitNS(1000);
192
193             // pulse ilc[load] and olc[load]
194             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_", 1);
195             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_", 1);
196             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
197             if (!kesselsCounter)
198                 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_", 1);
199             model.waitNS(100);
200             model.waitNS(1);
201             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_");
202             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_");
203             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_");
204             if (!kesselsCounter)
205                 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_");
206
207             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_");
208             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_");
209             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_");
210             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_");
211
212             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_");
213             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_");
214
215             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50");
216             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50");
217
218             // Every move instruction, even those with Ti=0,Di=0,
219             // loads the C-flag.  It will get loaded with an "X",
220             // which will then leak into the flags and from there the
221             // predicate.
222             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
223             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
224             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
225             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
226
227             for(int i=1; i<=8; i++) {
228                 if (i!=7)
229                     vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
230             }
231             model.waitNS(1000);
232
233             if (!kesselsCounter)
234                 for(int i=1; i<=6; i++)
235                     vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]");
236
237             // the proper stopper states come up in an undefined ("X")
238             // state, so under Verilog we need to force them to a
239             // known state
240
241             data.idle();
242             instrIn.idle();
243
244         } else {
245             NanosimModel nModel = (NanosimModel) model;
246             /*
247             nModel.setNodeVoltage(prefix+"sid[9]",1.0);
248             nModel.setNodeVoltage(prefix+"sic[9]",1.0);
249             nModel.setNodeVoltage(prefix+"sir[9]",1.0);
250             nModel.waitNS(WIDTH);
251             nModel.setNodeVoltage(prefix+"sid[9]",0.0);
252             nModel.setNodeVoltage(prefix+"sic[9]",0.0);
253             nModel.setNodeVoltage(prefix+"sir[9]",0.0);
254             nModel.waitNS(1);
255             */
256             nModel.setNodeVoltage("mc",1.0);
257             nModel.waitNS(WIDTH);
258             nModel.setNodeVoltage("mc",0.0);
259             nModel.waitNS(1);
260         }
261         resetAfterMasterClear();
262     }
263     private void resetAfterMasterClear() {
264         // The following call to ChainControl.resetInBits() is vital!
265         // If you forget, then the inBits member initializes 
266         // with random data. Then when you do your first write,
267         // some bits are written randomly.
268         cc.resetInBits();
269
270         // For reset, I want to clear all the stoppers simultaneously
271         data.clear();
272         //tokOut.clear();
273         instrIn.clear();
274         
275         data.stop();
276         //tokOut.stop();
277         instrIn.stop();
278         
279         data.resetAfterMasterClear();
280         //tokOut.resetAfterMasterClear();
281         instrIn.resetAfterMasterClear();
282     }
283     public static boolean kesselsCounter = true;
284
285     /** Get the 6 bit outer loop counter. */
286     public int getOLC() {
287         shiftReport(true, false);
288         if (kesselsCounter) {
289             BitVector bits = null;
290             for(int i=0; i<4; i++) {
291                 BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
292                 //System.out.println("bits are: " + x);
293                 bits = bits==null ? x : bits.cat(x);
294             }
295             //System.out.println("kesselsCounter = " + bits);
296             int first = 0;
297             int second = 0;
298             for(int i=0; i<6; i++) first  |= bits.get(4+i*3)   ? (1<<i) : 0;
299             for(int i=0; i<6; i++) second |= bits.get(4+i*3+2) ? (1<<i) : 0;
300             return (first+second);
301         } else {
302             BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
303             BitVector even = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
304             odd = odd.not();
305             even = even.not();
306             BitVector bv = new BitVector(6, "olc");
307             for(int i=0; i<3; i++) {
308                 bv.set(i*2,   odd.get(i));
309                 bv.set(i*2+1, even.get(i));
310             }
311             return (int)bv.toLong();
312         }
313     }
314     /** Get the 7 bit inner loop counter. The MSB is the zero bit.
315      * The low order 6 bits are the count */
316     public Ilc getILC() {
317         return new Ilc();
318     }
319     /** Get the A flag */
320     public boolean getFlagA() {
321         shiftReport(true, false);
322         return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(A_FLAG_NDX);
323     }
324     /** Get the B flag */
325     public boolean getFlagB() {
326         shiftReport(true, false);
327         return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(B_FLAG_NDX);
328     }
329     /** return value of instruction counter. Instruction counter counts 
330      * the instructions flowing through 1/2 of alternating FIFO.
331      * Caution: instruction counter is written by all scans, 
332      * regardless of readEnable or writeEnable! */
333     public long getInstructionCounter() {
334         shiftData(true, false);
335         BitVector count = cc.getOutBits(DATA_CHAIN+"."+INSTRUCTION_COUNTER_PATH);
336         int sz = count.getNumBits(); 
337         MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
338                          " expected: "+COUNTER_LENGTH);
339         return count.bitReverse().toLong();
340     }
341     /** return value of data counter. Data counter counts items flowing
342      * through drain stage of data proper stopper. 
343      * Caution: data counter is written by all scans, 
344      * regardless of readEnable or writeEnable! */
345     public long getDataCounter() {
346         shiftData(true, false);
347         BitVector count = cc.getOutBits(DATA_CHAIN+"."+DATA_COUNTER_PATH);
348         int sz = count.getNumBits(); 
349         MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
350                          " expected: "+COUNTER_LENGTH);
351         return count.bitReverse().toLong();
352     }
353     /** Fill the "North" Fifo ring */
354     public void fillNorthProperStopper() {
355         BitVector data = new BitVector(37, "empty");
356         BitVector addr = new BitVector(14, "empty");
357         for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
358         for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
359         fillNorthProperStopper(new MarinaPacket(data, false, addr));
360     }
361     /** Fill the "North" Fifo ring */
362     public void fillNorthProperStopper(MarinaPacket mp) {
363         prln("inserting into north: " + mp);
364         this.data.fill(mp.toSingleBitVector());
365     }
366     /** Enable the transmission of instructions from the instruction
367      * ring test structure to the EPI FIFO. */
368     public void enableInstructionSend(boolean b) {
369         BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
370         bv.set(INSTRUCTION_SEND_NDX, b);
371         cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
372         shiftControl(false, true);
373     } 
374     /** Enable the recirculation of instructions within the South FIFO */
375     public void enableInstructionRecirculate(boolean b) {
376         BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
377         bv.set(INSTRUCTION_RECIRCULATE_NDX, b);
378         cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
379         shiftControl(false, true);
380     }
381     /** get the number of tokens in the token FIFO.
382      * This includes the Token successor wire, the token FIFO wires,
383      * and Token predecessor wire.
384      * Master clear clears the token FIFO. */
385     public int getNumTokens() {
386         shiftReport(true, false);
387         // get the token successor and token FIFO wires
388         BitVector bv = cc.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
389         int sz = bv.getNumBits();
390         MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
391         
392         // get the token predecessor wire
393         BitVector pred = cc.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
394         sz = pred.getNumBits();
395         MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
396
397         // concatenate them
398         bv = bv.cat(pred);
399         sz = bv.getNumBits();
400         prln("Token state wires: "+bv.getState());
401         
402         int nbTok = 0;
403         for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
404         return nbTok;
405     }
406     /** Configure the test probe so it measures the throughput of
407      * the north data FIFO. The test probe frequency is 8192 
408      * times slower than the FIFO throughput. This control has
409      * highest priority. */
410     public void probeDataCounter(Boolean b) {
411         data.setGeneralPurposeOutput(b);
412     }
413     /** Configure the test probe so it measures the throughput of
414      * the alternating instruction FIFO. The test probe frequency is
415      * 1/16384 of the FIFO throughput. This control has second
416      * highest priority. Thus the following two calls probe the
417      * instruction counter: 
418      *      probeDataCounter(false);
419      *      probeInstructionCounter(true)
420      */
421     public void enableInstructionCounter(Boolean b) {
422         instrIn.setGeneralPurposeOutput(b);
423     }
424
425     public void fillSouthProperStopper(Instruction[] instructions) { fillSouthProperStopper(instructions, false); }
426     public void fillSouthProperStopper(Instruction[] instructions, boolean repeat) {
427         enableInstructionSend(false);
428         enableInstructionRecirculate(true);
429         for(Instruction i : instructions)
430             if (i!=null)
431                 instrIn.fill(i);
432         enableInstructionRecirculate(repeat);
433         enableInstructionSend(true);
434         instrIn.run();
435     }
436
437     
438 }