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