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;
10 import edu.berkeley.fleet.api.Instruction;
11 import edu.berkeley.fleet.marina.MarinaPath;
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. */
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;
22 public static int TOKEN_FIFO_CAPACITY = 3;
24 //public static boolean kesselsCounter = true;
25 public static boolean kesselsCounter = false;
26 public static boolean omegaCounter = false;
28 public static final String DATA_CHAIN = kesselsCounter ? "marina.marina_data" : "marina.ivan_data";
29 public static final String CONTROL_CHAIN = kesselsCounter ? "marina.marina_control" : "marina.ivan_control";
30 public static final String REPORT_CHAIN = kesselsCounter ? "marina.marina_report" : "marina.ivan_report";
32 public static String prefix = "marinaGu@0.outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@"+(kesselsCounter?"1":"0")+".";
33 public static String MASTER_CLEAR = "mc";
37 private static String prefix = "outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@1.";
38 private static String MASTER_CLEAR = "EXTmasterClear";
41 private static final String OLC_PATH_EVEN =
42 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@1"; // bits 2,4,6
43 private static final String OLC_PATH_ODD =
44 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@2"; // bits 1,3,5
45 private static final String OLC_PATH_KESSEL =
46 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.counte@0.adamScan@1.scanEx6h@";
47 private static final String ILC_PATH_ODD =
48 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
49 private static final String ILC_PATH_EVEN =
50 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
51 private static final String FLAGS_PATH =
52 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.scanEx3h@0";
54 private static final String INSTR_RING_CONTROL_PATH =
55 prefix+"southFif@1.tapPropS@1.tapStage@2";
56 private static final String TOK_FIFO_PATH =
58 private static final String INSTRUCTION_COUNTER_PATH =
59 prefix+"southFif@1.tapPropS@1.instruct@0";
60 private static final String DATA_COUNTER_PATH =
61 prefix+"northFif@1.fillDrai@1.instruct@0";
62 private static final String TOK_PRED_PATH =
63 prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx2h@0.scanCell@10";
65 private static final int COUNTER_LENGTH = 34;
66 private static final int INSTRUCTION_SEND_NDX = 1;
67 private static final int INSTRUCTION_RECIRCULATE_NDX = 0;
69 public static final int INSTRUCTION_LENGTH = 36;
71 private static final int A_FLAG_NDX = 0;
72 private static final int B_FLAG_NDX = 1;
74 public static final int SOUTH_RING_CAPACITY = 11;
76 // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
78 // value is bit reversed and complemented
81 shiftReport(true, false);
82 BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
83 BitVector even = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
84 BitVector ret = new BitVector(8, "olc");
85 for(int i=0; i<4; i++) {
86 ret.set(i*2+1, odd.get(i));
87 ret.set(i*2, even.get(i));
89 value = (int)ret.toLong();
91 /** Get the inner loop counter done bit. */
92 public boolean getDone() {
93 return (value & 0x40) != 0;
95 /** Get the inner loop counter infinity bit */
96 public boolean getInfinity() {
97 return (value & 0x80) != 0;
99 /** Get the 6 bits of count of the inner loop counter */
100 public int getCount() {
103 public String toString() {
104 return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
108 private final Indenter indenter;
110 // The name of the scan chain
111 // The instance path, from the top cell of the netlist, of the instance of infinityWithCover
112 private final ChainControls cc; // specifies the scan chain
113 private final ChipModel model;
114 public final ProperStopper data;
115 public final InstructionStopper instrIn;
117 private void prln(String msg) {indenter.prln(msg);}
118 private void pr(String msg) {indenter.pr(msg);}
120 /** Shift the report scan chain */
121 private void shiftReport(boolean readEnable, boolean writeEnable) {
122 cc.shift(REPORT_CHAIN, readEnable, writeEnable);
125 /** Shift the report scan chain */
126 private void shiftControl(boolean readEnable, boolean writeEnable) {
127 cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
130 /** Shift the data scan chain */
131 private void shiftData(boolean readEnable, boolean writeEnable) {
132 cc.shift(DATA_CHAIN, readEnable, writeEnable);
135 public Marina(ChainControls cc, ChipModel model, boolean clockHack, Indenter indenter) {
138 this.indenter = indenter;
139 data = new ProperStopper("north fifo",
140 prefix+"northFif@1.fillDrai@1.properSt@1",
144 cc, model, clockHack, indenter);
145 instrIn = new InstructionStopper("south fifo",
146 prefix+"southFif@1.tapPropS@1.properSt@1",
150 cc, model, clockHack, indenter);
152 public void masterClear() {
153 final double WIDTH = 10; // ns
154 // Put a high going pulse on the internal chip master clear signal
155 if (model instanceof VerilogModel) {
160 VerilogModel vm = (VerilogModel)model;
162 // In real life the flags come up with some undefined
163 // value. In verilog we need to prevent the X'es from
164 // propagating, so we force the flags to a known value
166 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_", 0);
167 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_", 1);
168 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_", 0);
169 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_", 1);
171 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_", 1);
172 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_", 0);
174 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50", 0); // A
175 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50", 0); // B
176 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
178 // possible C-flag inputs
179 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
180 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
182 // force the OLC to zero
184 for(int i=1; i<=6; i++)
185 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
187 // set the ILC input to 1
188 for(int i=1; i<=8; i++) {
190 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
193 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
195 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
198 vm.setNodeState(MASTER_CLEAR, 1);
200 vm.setNodeState(MASTER_CLEAR, 0);
203 // pulse ilc[load] and olc[load]
204 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_", 1);
205 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_", 1);
206 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
208 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_", 1);
211 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_");
212 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_");
213 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_");
215 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_");
217 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_");
218 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_");
219 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_");
220 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_");
222 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_");
223 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_");
225 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50");
226 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50");
228 // Every move instruction, even those with Ti=0,Di=0,
229 // loads the C-flag. It will get loaded with an "X",
230 // which will then leak into the flags and from there the
232 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
233 vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
234 vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
235 vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
237 for(int i=1; i<=8; i++) {
239 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
244 for(int i=1; i<=6; i++)
245 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]");
247 // the proper stopper states come up in an undefined ("X")
248 // state, so under Verilog we need to force them to a
254 } else if (model instanceof NanosimModel) {
255 NanosimModel nModel = (NanosimModel) model;
257 nModel.setNodeVoltage(prefix+"sid[9]",1.0);
258 nModel.setNodeVoltage(prefix+"sic[9]",1.0);
259 nModel.setNodeVoltage(prefix+"sir[9]",1.0);
260 nModel.waitNS(WIDTH);
261 nModel.setNodeVoltage(prefix+"sid[9]",0.0);
262 nModel.setNodeVoltage(prefix+"sic[9]",0.0);
263 nModel.setNodeVoltage(prefix+"sir[9]",0.0);
266 nModel.setNodeVoltage(MASTER_CLEAR,1.0);
267 nModel.waitNS(WIDTH);
268 nModel.setNodeVoltage(MASTER_CLEAR,0.0);
273 resetAfterMasterClear();
275 private void resetAfterMasterClear() {
276 // The following call to ChainControl.resetInBits() is vital!
277 // If you forget, then the inBits member initializes
278 // with random data. Then when you do your first write,
279 // some bits are written randomly.
282 // For reset, I want to clear all the stoppers simultaneously
291 data.resetAfterMasterClear();
292 //tokOut.resetAfterMasterClear();
293 instrIn.resetAfterMasterClear();
297 /** Get the 6 bit outer loop counter. */
298 public int getOLC() {
299 shiftReport(true, false);
301 BitVector bits = null;
302 for(int i=0; i<4; i++) {
303 BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
304 //System.out.println("bits are: " + x);
305 bits = bits==null ? x : bits.cat(x);
307 System.out.print(" kesselsCounter = ");
311 for(int bit=5; bit>=0; bit--) {
312 boolean zeroOrTwo = bits.get(4+bit*3);
313 boolean zeroOrDone = bits.get(4+bit*3+1);
314 if ( zeroOrTwo && !zeroOrDone) {
316 System.out.print("2");
318 } else if (!zeroOrTwo && !zeroOrDone) {
320 System.out.print("1");
322 } else if ( zeroOrTwo && zeroOrDone) {
323 System.out.print("0");
326 } else if (!zeroOrTwo && zeroOrDone) {
327 System.out.print("_");
328 if (!done) bad = true;
330 // FIXME: check for unreduced counter and warn about it
332 if (bad) System.out.print(" WARNING: UNREDUCED COUNTER VALUE!!!!!!");
333 System.out.println();
335 } else if (kesselsCounter) {
336 BitVector bits = null;
337 for(int i=0; i<4; i++) {
338 BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
339 //System.out.println("bits are: " + x);
340 bits = bits==null ? x : bits.cat(x);
342 //System.out.println("kesselsCounter = " + bits);
345 for(int i=0; i<6; i++) first |= bits.get(4+i*3) ? (1<<i) : 0;
346 for(int i=0; i<6; i++) second |= bits.get(4+i*3+2) ? (1<<i) : 0;
347 return (first+second);
349 BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
350 BitVector even = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
353 BitVector bv = new BitVector(6, "olc");
354 for(int i=0; i<3; i++) {
355 bv.set(i*2, odd.get(i));
356 bv.set(i*2+1, even.get(i));
358 return (int)bv.toLong();
361 /** Get the 7 bit inner loop counter. The MSB is the zero bit.
362 * The low order 6 bits are the count */
363 public Ilc getILC() {
366 /** Get the A flag */
367 public boolean getFlagA() {
368 shiftReport(true, false);
369 return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(A_FLAG_NDX);
371 /** Get the B flag */
372 public boolean getFlagB() {
373 shiftReport(true, false);
374 return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(B_FLAG_NDX);
376 /** return value of instruction counter. Instruction counter counts
377 * the instructions flowing through 1/2 of alternating FIFO.
378 * Caution: instruction counter is written by all scans,
379 * regardless of readEnable or writeEnable! */
380 public long getInstructionCounter() {
381 shiftData(true, false);
382 BitVector count = cc.getOutBits(DATA_CHAIN+"."+INSTRUCTION_COUNTER_PATH);
383 int sz = count.getNumBits();
384 MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
385 " expected: "+COUNTER_LENGTH);
386 return count.bitReverse().toLong();
388 /** return value of data counter. Data counter counts items flowing
389 * through drain stage of data proper stopper.
390 * Caution: data counter is written by all scans,
391 * regardless of readEnable or writeEnable! */
392 public long getDataCounter() {
393 shiftData(true, false);
394 BitVector count = cc.getOutBits(DATA_CHAIN+"."+DATA_COUNTER_PATH);
395 int sz = count.getNumBits();
396 MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
397 " expected: "+COUNTER_LENGTH);
398 return count.bitReverse().toLong();
400 /** Fill the "North" Fifo ring */
401 public void fillNorthProperStopper() {
402 BitVector data = new BitVector(37, "empty");
403 BitVector addr = new BitVector(14, "empty");
404 for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
405 for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
406 fillNorthProperStopper(new MarinaPacket(data, false, addr));
408 /** Fill the "North" Fifo ring */
409 public void fillNorthProperStopper(MarinaPacket mp) {
410 prln("inserting into north: " + mp);
411 this.data.fill(mp.toSingleBitVector());
413 /** Enable the transmission of instructions from the instruction
414 * ring test structure to the EPI FIFO. */
415 public void enableInstructionSend(boolean b) {
416 BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
417 bv.set(INSTRUCTION_SEND_NDX, b);
418 cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv);
419 shiftControl(false, true);
421 /** Enable the recirculation of instructions within the South FIFO */
422 public void enableInstructionRecirculate(boolean b) {
423 BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
424 bv.set(INSTRUCTION_RECIRCULATE_NDX, b);
425 cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv);
426 shiftControl(false, true);
428 /** get the number of tokens in the token FIFO.
429 * This includes the Token successor wire, the token FIFO wires,
430 * and Token predecessor wire.
431 * Master clear clears the token FIFO. */
432 public int getNumTokens() {
433 shiftReport(true, false);
434 // get the token successor and token FIFO wires
435 BitVector bv = cc.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
436 int sz = bv.getNumBits();
437 MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
439 // get the token predecessor wire
440 BitVector pred = cc.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
441 sz = pred.getNumBits();
442 MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
446 sz = bv.getNumBits();
447 prln("Token state wires: "+bv.getState());
450 for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
453 /** Configure the test probe so it measures the throughput of
454 * the north data FIFO. The test probe frequency is 8192
455 * times slower than the FIFO throughput. This control has
456 * highest priority. */
457 public void probeDataCounter(Boolean b) {
458 data.setGeneralPurposeOutput(b);
460 /** Configure the test probe so it measures the throughput of
461 * the alternating instruction FIFO. The test probe frequency is
462 * 1/16384 of the FIFO throughput. This control has second
463 * highest priority. Thus the following two calls probe the
464 * instruction counter:
465 * probeDataCounter(false);
466 * probeInstructionCounter(true)
468 public void enableInstructionCounter(Boolean b) {
469 instrIn.setGeneralPurposeOutput(b);
472 public void fillSouthProperStopper(Instruction[] instructions) { fillSouthProperStopper(instructions, false); }
473 public void fillSouthProperStopper(Instruction[] instructions, boolean repeat) {
474 enableInstructionSend(false);
475 enableInstructionRecirculate(true);
476 for(Instruction i : instructions)
479 enableInstructionRecirculate(repeat);
480 enableInstructionSend(true);