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;
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";
25 private static String prefix = "marinaGu@0.outDockW@3.marinaOu@1.";
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";
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 =
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";
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;
55 public static final int INSTRUCTION_LENGTH = 36;
57 private static final int A_FLAG_NDX = 0;
58 private static final int B_FLAG_NDX = 1;
60 public static final int SOUTH_RING_CAPACITY = 11;
62 // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
64 // value is bit reversed and complemented
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));
75 value = (int)ret.toLong();
77 /** Get the inner loop counter done bit. */
78 public boolean getDone() {
79 return (value & 0x40) != 0;
81 /** Get the inner loop counter infinity bit */
82 public boolean getInfinity() {
83 return (value & 0x80) != 0;
85 /** Get the 6 bits of count of the inner loop counter */
86 public int getCount() {
89 public String toString() {
90 return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
94 private final Indenter indenter;
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;
103 private void prln(String msg) {indenter.prln(msg);}
104 private void pr(String msg) {indenter.pr(msg);}
106 /** Shift the report scan chain */
107 private void shiftReport(boolean readEnable, boolean writeEnable) {
108 cc.shift(REPORT_CHAIN, readEnable, writeEnable);
111 /** Shift the report scan chain */
112 private void shiftControl(boolean readEnable, boolean writeEnable) {
113 cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
116 /** Shift the data scan chain */
117 private void shiftData(boolean readEnable, boolean writeEnable) {
118 cc.shift(DATA_CHAIN, readEnable, writeEnable);
121 public Marina(ChainControls cc, ChipModel model, boolean clockHack, Indenter indenter) {
124 this.indenter = indenter;
125 data = new ProperStopper("north fifo",
126 prefix+"northFif@1.fillDrai@1.properSt@1",
130 cc, model, clockHack, indenter);
131 instrIn = new InstructionStopper("south fifo",
132 prefix+"southFif@1.tapPropS@1.properSt@1",
136 cc, model, clockHack, indenter);
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) {
146 VerilogModel vm = (VerilogModel)model;
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
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);
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);
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
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);
168 // force the OLC to zero
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);
173 // set the ILC input to 1
174 for(int i=1; i<=8; i++) {
176 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
179 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
181 vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
184 vm.setNodeState("sid[9]", 1);
185 vm.setNodeState("sic[9]", 1);
186 vm.setNodeState("sir[9]", 1);
188 vm.setNodeState("sid[9]", 0);
189 vm.setNodeState("sic[9]", 0);
190 vm.setNodeState("sir[9]", 0);
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);
198 vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_", 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_");
205 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_");
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_");
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_");
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");
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
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");
227 for(int i=1; i<=8; i++) {
229 vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
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+"]");
237 // the proper stopper states come up in an undefined ("X")
238 // state, so under Verilog we need to force them to a
245 NanosimModel nModel = (NanosimModel) model;
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);
256 nModel.setNodeVoltage("mc",1.0);
257 nModel.waitNS(WIDTH);
258 nModel.setNodeVoltage("mc",0.0);
261 resetAfterMasterClear();
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.
270 // For reset, I want to clear all the stoppers simultaneously
279 data.resetAfterMasterClear();
280 //tokOut.resetAfterMasterClear();
281 instrIn.resetAfterMasterClear();
283 public static boolean kesselsCounter = true;
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);
295 //System.out.println("kesselsCounter = " + bits);
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);
302 BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
303 BitVector even = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
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));
311 return (int)bv.toLong();
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() {
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);
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);
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();
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();
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));
361 /** Fill the "North" Fifo ring */
362 public void fillNorthProperStopper(MarinaPacket mp) {
363 prln("inserting into north: " + mp);
364 this.data.fill(mp.toSingleBitVector());
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);
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);
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");
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");
399 sz = bv.getNumBits();
400 prln("Token state wires: "+bv.getState());
403 for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
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);
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)
421 public void enableInstructionCounter(Boolean b) {
422 instrIn.setGeneralPurposeOutput(b);
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)
432 enableInstructionRecirculate(repeat);
433 enableInstructionSend(true);