1 package edu.berkeley.fleet.marina;
2 import com.sun.electric.tool.simulation.test.*;
3 import java.util.ArrayList;
5 import edu.berkeley.fleet.marina.MarinaUtils.StateWireState;
7 public class ProperStopper {
8 // position of strobes in the control chain
9 private static final int BLOCK_STROBE_NDX = 0;
10 private static final int FILL_STROBE_NDX = 1;
11 private static final int GO_STROBE_NDX = 2;
12 private static final int SILENT_STROBE_NDX = 3;
13 private static final int CLEAR_STROBE_NDX = 4;
14 private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
16 // position of inputs in report chain
17 private static final int PREV_STATE_IN_NDX = 0;
18 private static final int FILL_STROBE_IN_NDX = 1;
19 private static final int FILL_STATE_IN_NDX = 2;
20 private static final int STOPPED_IN_NDX = 3;
22 //private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
23 private final String captureClockRelPath = "fillStag@1";
24 // test library direct write mode doesn't understand per register write
25 // enables. We get simulation to work by toggling write clock.
26 private final boolean clockHack;
27 private final String captureClockName = "sx[4]";
30 private boolean traceFill = true;
31 private boolean traceDrain = true;
33 private boolean traceFill = false;
34 private boolean traceDrain = false;
36 private final String controlPath, dataPath, reportPath;
37 protected final ChainControl controlChain;
38 protected final ChainControl dataChain;
39 protected final ChainControl reportChain;
40 private final String captureClock;
41 private final ChipModel model;
42 private final Indenter indenter;
44 private final String pathToCounter;
46 protected static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
47 private void prln(String msg) { indenter.prln(msg); }
48 private void adjustIndent(int n) { indenter.adjustIndent(n); }
50 /** NanosimModel.setNodeState() requires special path names.
51 * Each instance name in the path must begin with the character 'x'.
52 * Return a path with the added X's. */
53 private String prefixInstNamesInPathWithX(String path) {
54 if (model==null) throw new RuntimeException();
55 if (!(model instanceof NanosimModel)) return path;
56 StringBuffer sb = new StringBuffer();
58 for (int i=0; i<path.length(); i++) {
59 char c = path.charAt(i);
61 if (c=='.') sb.append('x');
66 private void shiftControl(boolean readEnable, boolean writeEnable) {
67 controlChain.shift(Marina.CONTROL_CHAIN, readEnable, writeEnable);
69 private void shiftData(boolean readEnable, boolean writeEnable) {
70 dataChain.shift(Marina.DATA_CHAIN, readEnable, writeEnable);
72 if (clockHack && model instanceof NanosimModel) {
73 NanosimModel nanoModel = (NanosimModel) model;
74 nanoModel.setNodeState(captureClock, 1);
76 nanoModel.setNodeState(captureClock, 0);
77 } else if (clockHack && model instanceof VerilogModel) {
78 VerilogModel nanoModel = (VerilogModel) model;
79 nanoModel.setNodeState(captureClock, 1);
81 nanoModel.setNodeState(captureClock, 0);
85 private void shiftReport(boolean readEnable, boolean writeEnable) {
86 reportChain.shift(Marina.REPORT_CHAIN, readEnable, writeEnable);
89 private StateWireState boolToState(boolean b) {
90 return b ? StateWireState.FULL : StateWireState.EMPTY;
93 private CommandCodes fdcstate = null;
95 public void setCounterEnable(boolean enable) {
97 setFillDrainControl(fdcstate);
100 public void setCounterValue(int val) {
101 SubchainNode chainNode = (SubchainNode) dataChain.findNode(pathToCounter);
102 int bitIndex = chainNode.getBitIndex();
103 ChainNode root = chainNode.getParentChain();
104 for(int i=0; i<31; i++)
105 root.getInBits().set(bitIndex+i, ((1<<i) & val)!=0);
106 shiftData(false, true);
109 // DOES NOT SHIFT THE CHAIN!!!!
110 public int getCounterValue() {
111 SubchainNode chainNode = (SubchainNode) dataChain.findNode(pathToCounter);
112 int bitIndex = chainNode.getBitIndex();
113 ChainNode root = chainNode.getParentChain();
114 return (int)root.getOutBits().get(bitIndex, 30).bitReverse().toLong();
117 // The first 5 bits of the control chain control the fill and drain stages
118 private void setFillDrainControl(CommandCodes ccc) {
119 BitVector fdCtl = ccc.bits(extra);
121 fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
122 BitVector val = controlChain.getInBits(controlPath);
123 for (int i=0; i<fdCtl.getNumBits(); i++) {
124 val.set(i, fdCtl.get(i));
126 controlChain.setInBits(controlPath, val);
127 shiftControl(false, true);
129 // The last bit of the control chain controls the general purpose
131 public void setGeneralPurposeOutput(Boolean b) {
132 BitVector val = controlChain.getInBits(controlPath);
133 val.set(GENERAL_PURPOSE_STROBE_NDX,b);
134 shiftControl(false, true);
137 //-------------------------- public methods ----------------------------
139 /** Put stopper in RUN state */
141 setFillDrainControl(CommandCodes.RUN);
143 /** Put stopper in IDLE state */
145 setFillDrainControl(CommandCodes.IDLE);
147 /** Put stopper in FILL state */
148 private void fillMode() {
149 setFillDrainControl(CommandCodes.FILL);
151 /** Put stopper in BLOCK state */
152 public void block() {
153 setFillDrainControl(CommandCodes.BLOCK);
155 /** Put stopper in STOP state */
157 setFillDrainControl(CommandCodes.STOP);
159 /** Put stopper in CLEAR state */
160 public void clear() {
161 setFillDrainControl(CommandCodes.CLEAR);
163 /** Put stopper in SOURCE state */
164 public void source() {
165 setFillDrainControl(CommandCodes.SOURCE);
167 /** Put stopper in STOPSOURCE state */
168 public void stopSource() {
169 setFillDrainControl(CommandCodes.STOPSOURCE);
171 /** Put stopper in SINK state */
173 setFillDrainControl(CommandCodes.SINK);
175 /** Put stopper in STOPSINK state */
176 public void stopSink() {
177 setFillDrainControl(CommandCodes.STOPSINK);
180 public boolean extra = false;
182 /** Stop a running stopper in order to add items. Ensure that we don't
183 * lose the item in the fill stage.
184 * Exit state: block */
185 public void stopToFill() {
192 /** get value of the state wire preceding the fill stage */
193 public StateWireState getPrevStateWire() {
194 shiftReport(true, false);
195 BitVector b = reportChain.getOutBits(reportPath);
196 int n = b.getNumBits();
197 fatal(n!=4, "Bad number of Stopper report bits: "+n);
198 return boolToState(reportChain.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
201 /** get the value of drain stage fill wire.
202 * The fill wire will be interesting if we doubt that the
203 * scan chain works. */
204 public boolean getFillStrobe() {
205 shiftReport(true, false);
206 return reportChain.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
209 /** get value of state wire between the fill and drain stages */
210 public StateWireState getFillStateWire() {
211 shiftReport(true, false);
212 return boolToState(reportChain.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
215 /** get value of drain stage stopped wire */
216 public boolean getStopped() {
217 shiftReport(true, false);
218 return reportChain.getOutBits(reportPath).get(STOPPED_IN_NDX);
221 public String getReportString() {
222 StringBuffer sb = new StringBuffer();
223 sb.append("Stopper's prev state: ");
224 sb.append(getPrevStateWire()+"\n");
225 sb.append("Stopper's fill stage: ");
226 sb.append(getFillStateWire()+"\n");
227 sb.append("Stopper's stopped: ");
228 sb.append(getStopped()+"\n");
229 return sb.toString();
232 /** construct a ProperStopper */
233 public ProperStopper(String propInst,
234 ChainControl controlChain,
235 ChainControl dataChain,
236 ChainControl reportChain,
240 String pathToCounter) {
241 propInst += ".properSt@1";
242 this.controlPath = Marina.CONTROL_CHAIN+'.'+propInst;
243 this.dataPath = Marina.DATA_CHAIN+'.'+propInst;
244 this.reportPath = Marina.REPORT_CHAIN+'.'+propInst;
247 prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
248 +'.'+captureClockName;
249 this.clockHack = clockHack;
250 this.indenter = indenter;
251 this.pathToCounter = Marina.DATA_CHAIN+'.'+pathToCounter;
252 this.controlChain = controlChain;
253 this.dataChain = dataChain;
254 this.reportChain = reportChain;
257 /** Insert one item into the fill stage.
258 * Fill stage must be empty.
259 * You must stop stopper before calling fill.
260 * exit state: block */
261 private void fill_(BitVector dta) {
264 int n = dta.getNumBits();
265 fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
267 // make sure fill stage is empty
268 StateWireState myState = getFillStateWire();
269 fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
271 idle(); // block = 1, go = 0
273 BitVector wrEn = new BitVector(2, "write enable");
275 dataChain.setInBits(dataPath, wrEn.cat(dta));
276 shiftData(false, true);
278 fillMode(); // fill = 1
286 if (traceFill) prln(getReportString());
288 // if data chain is shifted in the future, don't write!
290 dataChain.setInBits(dataPath, wrEn.cat(dta));
293 if (traceFill) prln("End fill");
297 BitVector data = new BitVector(37, "empty");
298 BitVector addr = new BitVector(14, "empty");
299 for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
300 for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
301 fill(new MarinaPacket(data, false, addr));
304 public void fill(BitVector dat) {
305 if (traceFill) prln("Begin fill.");
306 if (traceFill) prln("writing data: "+new MarinaPacket(dat));
310 public void fill(MarinaPacket mp) {
311 if (traceFill) prln("Begin fill.");
312 if (traceFill) prln("writing data: "+mp);
313 fill_(mp.toSingleBitVector());
316 /** Insert items from a list, one by one.
317 * You must stop stopper before calling fillMany()
318 * exit state: block */
319 public void fillMany(List<BitVector> data) {
320 prln("Begin fillMany. numWords="+data.size());
323 for (BitVector bv : data) {
324 if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
328 prln("end fillMany");
331 /** Remove one item from fill stage. Return that item.
332 * An item must be available.
333 * drain() will stop cleanly.
334 * exit state: stop */
335 public BitVector drain() {
336 stop(); // all zero, block = 0, go = 0
338 // make sure an item is available
339 StateWireState myState=getFillStateWire();
340 fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
342 return drainNoCheck();
345 /** Remove one item from fill stage. Return that item.
346 * Assume that an item is available.
348 * exit state: stop */
349 private BitVector drainNoCheck() {
350 shiftData(true, false);
352 // strip the two write enable bits
353 BitVector ans = dataChain.getOutBits(dataPath).get(2, 52);
356 clear(); // clear = 1
360 if (traceDrain) prln("drain data="+new MarinaPacket(ans));
364 /** Remove as many items as possible from the fill stage.
365 * drainStopperMany() will stop cleanly.
366 * exit state: stop */
367 public List<BitVector> drainMany() {
368 return drainMany(Integer.MAX_VALUE);
371 /** Remove up to maxNbItems items from the fill stage.
372 * drainStopperMany() will stop cleanly.
373 * exit state: stop */
374 public List<BitVector> drainMany(int maxNbItems) {
379 List<BitVector> ans = new ArrayList<BitVector>();
383 StateWireState myState=getFillStateWire();
386 if (traceDrain) prln(getReportString());
388 if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
391 indenter.pr(" drain"+(maxNbItems==0?"":"Many")+
392 ": reading word"+(maxNbItems==0?":":" number "+cnt+
393 "/"+(maxNbItems==Integer.MAX_VALUE
394 ?"unlimited":("at-most-"+maxNbItems))+": "));
396 BitVector d = drainNoCheck();
398 prln(" got "+new MarinaPacket(d));
403 prln("end drainMany, got "+ans.size()+" items");
409 // proper stopper ring occupancy bits
410 //southFif@1.upDown8w@1.weakStag@18.scanEx1@0 REPORT chain
411 //18, 22, 19, 23, 20, 24, 21, 25
412 //northFif@1.upDown8w@2...
413 // south fifo tap stage:
414 // southFif@1.tapPropS@1.tapStage@2.scanEx1@0 (also REPORT chain)
417 * (Note by Bill and Adam: Ivan has struck again!)
418 * As of 05 March 2009 the new bits are:
419 * Block Extra Fill Go Clear Silent
420 * => Note: "Extra" gets fed to the mux in the counter
421 * that selects the frequency output that goes off-chip
423 * Caution: Ivan changes the order of the ProperStopper control bits
424 * from chip to chip. Here is the current order for Marina
426 * Block, Fill, Go, Silent, Clear
428 * The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
430 private static enum CommandCodes {
431 RUN ("000100","010100"),
432 IDLE ("100000","110000"),
433 FILL ("101000","111000"),
434 BLOCK ("100100","110100"),
435 STOP ("000000","010000"),
436 CLEAR ("100010","110010"),
437 SOURCE ("001100","011100"),
438 STOPSOURCE ("001000","011000"),
439 SINK ("000101","010101"),
440 STOPSINK ("000001","010001");
441 private BitVector scanBits0;
442 private BitVector scanBits1;
443 CommandCodes(String bits0,String bits1) {
444 scanBits0 = new BitVector(bits0,"CommandCodes");
445 scanBits1 = new BitVector(bits1,"CommandCodes");
447 public BitVector bits(boolean extra) {
448 return extra ? scanBits1 : scanBits0;