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