marina: add some additional control over the proper stopper counter
[fleet.git] / src / edu / berkeley / fleet / marina / Marina.java
1 package edu.berkeley.fleet.marina;
2 import com.sun.electric.tool.simulation.test.*;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.api.BitVector;
5 import edu.berkeley.fleet.two.*;
6 import edu.berkeley.fleet.*;
7 import java.util.*;
8
9 public class Marina extends FleetTwoFleet {
10
11     MarinaShip fakeShip = new MarinaShip(this);
12     MarinaDock onlyDock = new MarinaDock(fakeShip, true);
13
14     public BitVector   encodeInstruction(Dock dispatchFrom, Instruction instruction) {
15         return encodeInstruction(instruction, dispatchFrom);
16     }
17
18     public Iterator<Ship> iterator() {
19         HashSet hs = new HashSet<Ship>();
20         hs.add(fakeShip);
21         return hs.iterator();
22     }
23
24     public Ship getShip(String type, int ordinal) {
25         throw new RuntimeException("not implemented");
26     }
27
28     public FleetProcess run(Instruction[] instructions) {
29         throw new RuntimeException("not implemented");
30     }
31
32     public BitVector getDestAddr(Path path) {
33         if (path==null) return new BitVector(0);
34         return ((MarinaPath)path).bv;
35     }
36
37     public Dock getOnlyDock() {
38         return onlyDock;
39     }
40
41     ////////////////////////////////////////////////////////////////////////////////
42
43     JtagLogicLevel mc0;
44     JtagLogicLevel mc1;
45     private final Indenter indenter;
46
47     public final ChainControl controlChain;
48     public final ChainControl dataChain;
49     public final ChainControl dukeChain;
50     public final ChainControl reportChain;
51
52     private final ChipModel model;
53     public final ProperStopper      northRing;
54     public final InstructionStopper southRing;
55     int northCount = 0;
56     int southCount = 0;
57
58     public Marina(ChainControl controlChain,
59                   ChainControl dataChain,
60                   ChainControl dukeChain,
61                   ChainControl reportChain,
62                   ChipModel model,
63                   boolean clockHack,
64                   Indenter indenter) {
65         // use "internal encoding"
66         super(true);
67
68         this.controlChain = controlChain;
69         this.dataChain = dataChain;
70         this.dukeChain = dukeChain;
71         this.reportChain = reportChain;
72         this.model = model;
73         this.indenter = indenter;
74         northRing = new ProperStopper(prefix+"northFif@1.fillDrai@1",
75                                       controlChain,
76                                       dataChain,
77                                       reportChain,
78                                       model,
79                                       clockHack,
80                                       indenter);
81         southRing = new InstructionStopper(prefix+"southFif@1.tapPropS@1", 
82                                            controlChain,
83                                            dataChain,
84                                            reportChain,
85                                            model,
86                                            clockHack,
87                                            indenter);
88     }
89
90     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE  = 5;
91     public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO = MarinaPath.SIGNAL_BIT_INDEX;
92        
93     private static final int COUNTER_LENGTH = 34;
94     public static final int INSTRUCTION_LENGTH = 36;
95     public static final int SOUTH_RING_CAPACITY = 11;
96     public static final int TOKEN_FIFO_CAPACITY = 3;
97     public static final boolean kesselsCounter = false;
98     public static final boolean omegaCounter = false;
99     public static final String DATA_CHAIN =    kesselsCounter ? "marina.marina_data" : "marina.ivan_data";      
100     public static final String CONTROL_CHAIN = kesselsCounter ? "marina.marina_control" : "marina.ivan_control";
101     public static final String REPORT_CHAIN =  kesselsCounter ? "marina.marina_report" : "marina.ivan_report";
102     public static final String DUKE_CHAIN   = "marina.duke";
103
104     public static String prefix = "marinaGu@0.outDockW@"+(kesselsCounter?"3":"0")+".marinaOu@"+(kesselsCounter?"1":"0")+".";
105     public static String MASTER_CLEAR = "mc";
106
107     private static final String CENTER_PATH = prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0";
108     private static final String OLC_PATH_EVEN = CENTER_PATH+".olcWcont@0.scanEx3h@1"; // bits 2,4,6
109     private static final String OLC_PATH_ODD = CENTER_PATH+".olcWcont@0.scanEx3h@2"; // bits 1,3,5
110     private static final String OLC_PATH_KESSEL = CENTER_PATH+".counte@0.adamScan@1.scanEx6h@";
111     private static final String ILC_PATH_ODD = CENTER_PATH+".ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
112     private static final String ILC_PATH_EVEN = CENTER_PATH+".ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
113     private static final String FLAGS_PATH = CENTER_PATH+".flags@0.scanEx3h@0";
114     private static final String TOK_FIFO_PATH = prefix+"tokenFIF@1";
115     private static final String INSTRUCTION_COUNTER_PATH = prefix+"southFif@1.tapPropS@1.instruct@0";
116     private static final String DATA_COUNTER_PATH =prefix+"northFif@1.fillDrai@1.instruct@0";
117     private static final String TOK_PRED_PATH = CENTER_PATH+".ilcMoveO@0.scanEx2h@0.scanCell@10";
118         
119     // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
120     private class Ilc {
121         // value is bit reversed and complemented
122         private int value;
123         private Ilc() {
124             reportChain.shift(REPORT_CHAIN, true, false);
125             com.sun.electric.tool.simulation.test.BitVector odd  = reportChain.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
126             com.sun.electric.tool.simulation.test.BitVector even = reportChain.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
127             com.sun.electric.tool.simulation.test.BitVector ret  = new com.sun.electric.tool.simulation.test.BitVector(8, "olc");
128             for(int i=0; i<4; i++) {
129                 ret.set(i*2+1, odd.get(i));
130                 ret.set(i*2,   even.get(i));
131             }
132             value = (int)ret.toLong();
133         }
134         /** Get the inner loop counter done bit. */
135         public boolean getDone() {
136             return (value & 0x40) != 0;
137         }
138         /** Get the inner loop counter infinity bit */
139         public boolean getInfinity() {
140             return (value & 0x80) != 0;
141         }
142         /** Get the 6 bits of count of the inner loop counter */
143         public int getCount() {
144             return value & 0x3f;
145         }
146         public String toString() {
147             return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
148         }
149     }
150         
151     public void stopAndResetCounters() {
152         southRing.setCounterEnable(false);
153         northRing.setCounterEnable(false);
154         dataChain.shift(DATA_CHAIN, true, false);        
155         northCount = northRing.getCounterValue();
156         southCount = southRing.getCounterValue();
157         northRing.setCounterValue(0);
158         southRing.setCounterValue(0);
159     }
160     public void startCounters() { startCounters(true, true); }
161     public void startCounters(boolean south, boolean north) {
162         southRing.setCounterEnable(south);
163         northRing.setCounterEnable(north);
164     }
165     public int getNorthCount() { return northCount; }
166     public int getSouthCount() { return southCount; }
167
168     public void masterClear() {
169         final double WIDTH = 10; // ns
170         // Put a high going pulse on the internal chip master clear signal
171         if (model instanceof VerilogModel) {
172
173             northRing.clear();
174             southRing.clear();
175
176             VerilogModel vm = (VerilogModel)model;
177             //
178             // In real life the flags come up with some undefined
179             // value.  In verilog we need to prevent the X'es from
180             // propagating, so we force the flags to a known value
181             //
182             vm.setNodeState(CENTER_PATH+".flag_A__set_", 0);
183             vm.setNodeState(CENTER_PATH+".flag_A__clr_", 1);
184             vm.setNodeState(CENTER_PATH+".flag_B__set_", 0);
185             vm.setNodeState(CENTER_PATH+".flag_B__clr_", 1);
186
187             vm.setNodeState(CENTER_PATH+".flag_D__set_", 1);
188             vm.setNodeState(CENTER_PATH+".flag_D__clr_", 0);
189
190             vm.setNodeState(CENTER_PATH+".flags@0.aFlag@0.net_50", 0);       // A
191             vm.setNodeState(CENTER_PATH+".flags@0.aFlag@1.net_50", 0);       // B
192             vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
193
194             // possible C-flag inputs
195             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
196             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
197
198             // force the OLC to zero
199             if (!kesselsCounter)
200                 for(int i=1; i<=6; i++)
201                     vm.setNodeState(CENTER_PATH+".olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
202
203             // set the ILC input to 1
204             for(int i=1; i<=8; i++) {
205                 if (i!=7)
206                     vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
207             }
208
209             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
210             model.waitNS(1000);
211             vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
212             model.waitNS(1000);
213
214             vm.setNodeState(MASTER_CLEAR, 1);
215             model.waitNS(1000);
216             vm.setNodeState(MASTER_CLEAR, 0);
217             model.waitNS(1000);
218
219             // pulse ilc[load] and olc[load]
220             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_load_", 1);
221             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_decLO_", 1);
222             vm.setNodeState(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
223             if (!kesselsCounter)
224                 vm.setNodeState(CENTER_PATH+".olcWcont@0.olc@0.olc_load_", 1);
225             model.waitNS(100);
226             model.waitNS(1);
227             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_load_");
228             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_decLO_");
229             vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.ilc_torpLO_");
230             if (!kesselsCounter)
231                 vm.releaseNode(CENTER_PATH+".olcWcont@0.olc@0.olc_load_");
232
233             vm.releaseNode(CENTER_PATH+".flag_A__set_");
234             vm.releaseNode(CENTER_PATH+".flag_A__clr_");
235             vm.releaseNode(CENTER_PATH+".flag_B__set_");
236             vm.releaseNode(CENTER_PATH+".flag_B__clr_");
237
238             vm.releaseNode(CENTER_PATH+".flag_D__set_");
239             vm.releaseNode(CENTER_PATH+".flag_D__clr_");
240
241             vm.releaseNode(CENTER_PATH+".flags@0.aFlag@0.net_50");
242             vm.releaseNode(CENTER_PATH+".flags@0.aFlag@1.net_50");
243
244             // Every move instruction, even those with Ti=0,Di=0,
245             // loads the C-flag.  It will get loaded with an "X",
246             // which will then leak into the flags and from there the
247             // predicate.
248             vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
249             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
250             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
251             vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
252
253             for(int i=1; i<=8; i++) {
254                 if (i!=7)
255                     vm.releaseNode(CENTER_PATH+".ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
256             }
257             model.waitNS(1000);
258
259             if (!kesselsCounter)
260                 for(int i=1; i<=6; i++)
261                     vm.releaseNode(CENTER_PATH+".olcWcont@0.olc@0.inLO["+i+"]");
262
263             // the proper stopper states come up in an undefined ("X")
264             // state, so under Verilog we need to force them to a
265             // known state
266
267             northRing.idle();
268             southRing.idle();
269
270         } else if (model instanceof NanosimModel) {
271             NanosimModel nModel = (NanosimModel) model;
272             /*
273             nModel.setNodeVoltage(prefix+"sid[9]",1.0);
274             nModel.setNodeVoltage(prefix+"sic[9]",1.0);
275             nModel.setNodeVoltage(prefix+"sir[9]",1.0);
276             nModel.waitNS(WIDTH);
277             nModel.setNodeVoltage(prefix+"sid[9]",0.0);
278             nModel.setNodeVoltage(prefix+"sic[9]",0.0);
279             nModel.setNodeVoltage(prefix+"sir[9]",0.0);
280             nModel.waitNS(1);
281             */
282             nModel.setNodeVoltage(MASTER_CLEAR,1.0);
283             nModel.waitNS(WIDTH);
284             nModel.setNodeVoltage(MASTER_CLEAR,0.0);
285             nModel.waitNS(1);
286         } else {
287
288             mc0.setLogicState(true);
289             mc1.setLogicState(true);
290             model.waitNS(1000);
291             mc0.setLogicState(false);
292             mc1.setLogicState(false);
293             model.waitNS(1000);
294
295         }
296
297         // The following call to ChainControl.resetInBits() is vital!
298         // If you forget, then the inBits member initializes 
299         // with random northRing. Then when you do your first write,
300         // some bits are written randomly.
301         controlChain.resetInBits();
302         dataChain.resetInBits();
303         dukeChain.resetInBits();
304         reportChain.resetInBits();
305
306         northRing.clear();
307         southRing.clear();
308         northRing.stop();
309         southRing.stop();
310     }
311
312
313     /** Get the 6 bit outer loop counter. */
314     public int getOLC() {
315         reportChain.shift(REPORT_CHAIN, true, false);
316         if (omegaCounter) {
317             com.sun.electric.tool.simulation.test.BitVector bits = null;
318             for(int i=0; i<4; i++) {
319                 com.sun.electric.tool.simulation.test.BitVector x = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
320                 //System.out.println("bits are: " + x);
321                 bits = bits==null ? x : bits.cat(x);
322             }
323             System.out.print("  kesselsCounter = ");
324             int ret = 0;
325             boolean done = true;
326             boolean bad = false;
327             for(int bit=5; bit>=0; bit--) {
328                 boolean zeroOrTwo  = bits.get(4+bit*3);
329                 boolean zeroOrDone = bits.get(4+bit*3+1);
330                 if      ( zeroOrTwo && !zeroOrDone) {
331                     ret += (2<<bit);
332                     System.out.print("2");
333                     done = false;
334                 } else if (!zeroOrTwo && !zeroOrDone) {
335                     ret += (1<<bit);
336                     System.out.print("1");
337                     done = false;
338                 } else if ( zeroOrTwo &&  zeroOrDone) {
339                     System.out.print("0");
340                     bad = true;
341                     done = false;
342                 } else if (!zeroOrTwo &&  zeroOrDone) {
343                     System.out.print("_");
344                     if (!done) bad = true;
345                 }
346                 // FIXME: check for unreduced counter and warn about it
347             }
348             if (bad) System.out.print("  WARNING: UNREDUCED COUNTER VALUE!!!!!!");
349             System.out.println();
350             return ret;
351         } else if (kesselsCounter) {
352             com.sun.electric.tool.simulation.test.BitVector bits = null;
353             for(int i=0; i<4; i++) {
354                 com.sun.electric.tool.simulation.test.BitVector x = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
355                 //System.out.println("bits are: " + x);
356                 bits = bits==null ? x : bits.cat(x);
357             }
358             //System.out.println("kesselsCounter = " + bits);
359             int first = 0;
360             int second = 0;
361             String hi="";
362             String lo="";
363             String latched="";
364             String res="";
365             for(int i=0; i<6; i++) {
366                 first  |= bits.get(4+i*3)   ? (1<<i) : 0;
367                 second |= bits.get(4+i*3+2) ? (1<<i) : 0;
368                 hi = (bits.get(4+i*3)   ? "1" : "0") + hi;
369                 lo = (bits.get(4+i*3+2)   ? "1" : "0") + lo;
370                 res =
371                     (   bits.get(4+i*3) && !bits.get(4+i*3+2) ? "X"
372                      : !bits.get(4+i*3) && !bits.get(4+i*3+2) ? "0"
373                      : !bits.get(4+i*3) &&  bits.get(4+i*3+2) ? "1"
374                      : "2")
375                     +res;
376                 latched = (bits.get(4+i*3+1)   ? "0" : "1") + latched;
377             }
378             System.out.println("kesselsCounter: "+
379                                "s[1]="+hi+
380                                " s[3]="+lo+
381                                " latched="+latched +
382                                " res="+res+
383                                " do[ins]="+(bits.get(0) ? "1" : "0")+
384                                " dec="+(bits.get(1) ? "1" : "0")+
385                                " flag[D][set]="+(bits.get(2) ? "1" : "0")+
386                                " resetting="+(bits.get(3) ? "1" : "0")+
387                                ""
388                                );
389             return (first+second);
390         } else {
391             com.sun.electric.tool.simulation.test.BitVector odd = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
392             com.sun.electric.tool.simulation.test.BitVector even = reportChain.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
393             odd = odd.not();
394             even = even.not();
395             com.sun.electric.tool.simulation.test.BitVector bv = new com.sun.electric.tool.simulation.test.BitVector(6, "olc");
396             for(int i=0; i<3; i++) {
397                 bv.set(i*2,   odd.get(i));
398                 bv.set(i*2+1, even.get(i));
399             }
400             return (int)bv.toLong();
401         }
402     }
403     public boolean getILCInfinity() { return new Ilc().getInfinity(); }
404     public boolean getILCDone() { return new Ilc().getDone(); }
405     public int getILC() { return new Ilc().getCount(); }
406     public boolean getFlagA() {
407         reportChain.shift(REPORT_CHAIN, true, false);
408         return reportChain.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(0);
409     }
410     public boolean getFlagB() {
411         reportChain.shift(REPORT_CHAIN, true, false);
412         return reportChain.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(1);
413     }
414     /** get the number of tokens in the token FIFO.
415      * This includes the Token successor wire, the token FIFO wires,
416      * and Token predecessor wire.
417      * Master clear clears the token FIFO. */
418     public int getNumTokens() {
419         reportChain.shift(REPORT_CHAIN, true, false);
420         // get the token successor and token FIFO wires
421         com.sun.electric.tool.simulation.test.BitVector bv = reportChain.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
422         int sz = bv.getNumBits();
423         MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
424         
425         // get the token predecessor wire
426         com.sun.electric.tool.simulation.test.BitVector pred = reportChain.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
427         sz = pred.getNumBits();
428         MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
429
430         // concatenate them
431         bv = bv.cat(pred);
432         sz = bv.getNumBits();
433         
434         int nbTok = 0;
435         for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
436         return nbTok;
437     }
438 }