add InterpreterDock.dumpState()
[fleet.git] / src / edu / berkeley / fleet / interpreter / InterpreterDock.java
1 package edu.berkeley.fleet.interpreter;
2 import java.util.*;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.sbp.util.ANSI;
6
7 /** anything that has a source (instruction horn) address on the switch fabric */
8 class InterpreterDock extends FleetTwoDock {
9
10     // Dock State //////////////////////////////////////////////////////////////////////////////
11     
12     boolean         flag_a = false;
13     boolean         flag_b = false;
14     boolean         flag_c = false;
15     boolean         flag_d = false;
16     int             ilc    = 1;
17     int             olc    = 1;
18     final BitVector dataLatch = new BitVector(getShip().getFleet().getWordWidth());
19     InterpreterPath pathLatch = null;
20     boolean         requeueStageInCirculatingState = false;
21     boolean         requeueStageHasTailInstruction = false;
22     boolean         torpedoWaiting = false;
23     boolean         flushing = false;
24
25     LinkedList<Instruction> instructions = new LinkedList<Instruction>();
26     LinkedList<Packet> dataPackets = new LinkedList<Packet>();
27
28     // HACK
29     private LinkedList<Instruction> instructionsBackedUpIntoSwitchFabric = new LinkedList<Instruction>();
30
31     boolean dataReadyForShip = false;
32     boolean readyForDataFromShip = true;
33
34     // FIXME: should be a BitVector
35     long dataFromShip;
36     boolean flagCFromShip;
37
38     protected void reset() {
39         ilc = 1;
40         olc = 1;
41         flag_a = false;
42         flag_b = false;
43         flag_c = false;
44         flag_d = false;
45         dataLatch.set(0);
46         pathLatch = null;
47         requeueStageInCirculatingState = false;
48         requeueStageHasTailInstruction = false;
49         instructions.clear();
50         dataPackets.clear();
51         instructionsBackedUpIntoSwitchFabric.clear();
52         dataReadyForShip = false;
53         readyForDataFromShip = true;
54         torpedoWaiting = false;
55         flushing = false;
56     }
57
58     // Destinations //////////////////////////////////////////////////////////////////////////////
59
60     /** includes the epilogue fifo */
61     public InterpreterDestination instructionDestination = new InterpreterDestination(this) {
62             public String toString() { return getDock()+":i"; }
63             public void addDataFromFabric(Packet p) {
64                 if (p.isToken()) {
65                     if (instructionsBackedUpIntoSwitchFabric.size()!=0)
66                         throw new RuntimeException("torpedo arrived while instructions were backed up into switch fabric");
67                     if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
68                     torpedoWaiting = true;
69                     return;
70                 }
71
72                 Instruction inst =
73                     getInterpreter().decodeInstruction(p.getValue(),
74                                                        InterpreterDock.this /* this is wrong, but harmless */);
75                 addInstruction(inst);
76             }
77         };
78     public InterpreterDestination dataDestination = new InterpreterDestination(this) {
79             public String toString() { return getDock()+""; }
80             public void addDataFromFabric(Packet packet) { dataPackets.add(packet); }
81         };
82
83     InterpreterDock(InterpreterShip ship, DockDescription bbd) {
84         super(ship, bbd);
85         ship.docks.put(bbd.getName(), this);
86     }
87
88     public Path getPath(Destination d, BitVector signal) { return new InterpreterPath(this, (InterpreterDestination)d, signal); }
89     public Destination getInstructionDestination() { return instructionDestination; }
90     public Destination getDataDestination() { return dataDestination; }
91     public int getInstructionFifoSize() { return Integer.MAX_VALUE; }
92     public Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
93
94     boolean trace = false;
95
96     private void addInstruction(Instruction inst) {
97         if (requeueStageInCirculatingState || requeueStageHasTailInstruction) {
98             // GROSS HACK
99             instructionsBackedUpIntoSwitchFabric.add(inst);
100             return;
101         }
102         if (inst instanceof Instruction.Tail) {
103             requeueStageHasTailInstruction = true;
104             return;
105         }
106         instructions.add(inst);
107     }
108     
109     protected final void service() {
110
111         if (dataReadyForShip || flushing) return;
112         if (instructions.size()==0) return;
113
114         if (instructions.peek() instanceof Instruction.Head) {
115             if (requeueStageInCirculatingState) { instructions.remove(); return; }
116             if (!requeueStageHasTailInstruction) return;
117             requeueStageHasTailInstruction = false;
118             requeueStageInCirculatingState = true;
119             instructions.remove();
120             return;
121         }
122
123         // in the while..false idiom block below, use "break" to
124         // consume the instruction at instructions.peek(), or "return"
125         // to leave it and retry on the next call.
126         do {
127             if (!instructions.peek().predicate.evaluate(flag_a, flag_b, flag_c, flag_d))
128                 break;
129
130             if (instructions.peek() instanceof Instruction.Move) {
131                 Instruction.Move move = (Instruction.Move)instructions.peek();
132
133                 if (ilc==0) { ilc = 1; break; }
134
135                 if (move.interruptible && torpedoWaiting) {
136                     torpedoWaiting = false;
137                     ilc = 1;
138                     flag_d = true;
139                     break;
140                 }
141
142                 if (move.dataIn  && !isInputDock() && readyForDataFromShip)  return;
143                 if (move.dataIn  &&  isInputDock() && dataPackets.size()==0) return;
144                 if (move.tokenIn &&                   dataPackets.size()==0) return;
145
146                 if (move.tokenIn) {
147                     Packet p = dataPackets.remove();
148                     flag_c = p.getSignal().get(0);
149                 }
150                 if (move.dataIn) {
151                     BitVector bv = null;
152                     if (isInputDock()) {
153                         Packet p = dataPackets.remove();
154                         bv = new BitVector(p.getValue());
155                         flag_c = p.getSignal().get(0);
156                     } else {
157                         bv = new BitVector(getInterpreter().getWordWidth()).set(dataFromShip);
158                         readyForDataFromShip = true;
159                         if (move.latchData) flag_c = flagCFromShip;
160                     }
161                     if (move.latchData) dataLatch.set(bv);
162                     if (move.latchPath) {
163                         BitVector bvp = ((FleetTwoFleet)getShip().getFleet()).DISPATCH_PATH.getvalAsBitVector(bv);
164                         pathLatch = (InterpreterPath)getInterpreter().getPathByAddr(this, bvp);
165                     }
166                 }
167                 
168                 if (move.path != null) pathLatch = (InterpreterPath)move.path;
169                 
170                 if (move.dataOut && isInputDock())  dataReadyForShip = true;
171                 if (move.dataOut && !isInputDock()) new Packet(pathLatch, new BitVector(dataLatch), false).send();
172                 if (move.tokenOut)                  new Packet(pathLatch, new BitVector(getInterpreter().getWordWidth()), true).send();
173                 
174                 if (ilc==1)  break;
175                 if (ilc!=-1) ilc--;
176                 return;
177
178             } else if (instructions.peek() instanceof Instruction.Abort) {
179                 requeueStageInCirculatingState = false;
180                 // HACK
181                 while (instructionsBackedUpIntoSwitchFabric.size()!=0) {
182                     Instruction i = instructionsBackedUpIntoSwitchFabric.remove();
183                     addInstruction(i);
184                     instructionsBackedUpIntoSwitchFabric.clear();
185                 }
186                 break;
187
188             } else if (instructions.peek() instanceof Instruction.Flush) {
189                 flushing = true;
190                 break;
191
192             } else if (instructions.peek() instanceof Instruction.Shift) {
193                 Instruction.Shift shift = (Instruction.Shift)instructions.peek();
194                 for(int i=dataLatch.length()-1; i>=getShip().getFleet().getShiftWidth(); i--)
195                     dataLatch.set(i, dataLatch.get(i-getShip().getFleet().getShiftWidth()));
196                 BitVector shift_immediate = shift.immediate.getBitVector();
197                 for(int i=getShip().getFleet().getShiftWidth()-1; i>=0; i--)
198                     dataLatch.set(i, shift_immediate.get(i));
199                 break;
200
201             } else if (instructions.peek() instanceof Instruction.Set) {
202                 Instruction.Set set = (Instruction.Set)instructions.peek();
203                 switch(set.dest) {
204                     case DataLatch: dataLatch.setAndSignExtend(set.immediate);
205                     break;
206                     case InnerLoopCounter:
207                         switch(set.source) {
208                             case Infinity:  ilc = -1; break;
209                             case Immediate: ilc = (int)set.immediate; break;
210                             case DataLatch:
211                                 ilc = 0;
212                                 for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_ILC_FROM_IMMEDIATE.valmaskwidth-1; i++)
213                                     if (dataLatch.get(i))
214                                         ilc |= (1 << i);
215                                 break;
216                             default: throw new RuntimeException("impossible");
217                         }
218                         break;
219                     case OuterLoopCounter:
220                         switch(set.source) {
221                             case Decrement: olc = Math.max(0,olc-1); break;
222                             case Immediate: olc = (int)set.immediate; break;
223                             case DataLatch:
224                                 olc = 0;
225                                 for(int i=0; i<getShip().getFleet().getWordWidth(); i++)
226                                     if (dataLatch.get(i))
227                                         olc |= (1 << i);
228                                 break;
229                             default: throw new RuntimeException("impossible");
230                         }
231                         flag_d = olc==0;
232                         break;
233                         
234                     case Flags: {
235                         boolean new_flag_a = set.newFlagA.evaluate(flag_a, flag_b, flag_c, flag_d);
236                         boolean new_flag_b = set.newFlagB.evaluate(flag_a, flag_b, flag_c, flag_d);
237                         flag_a = new_flag_a;
238                         flag_b = new_flag_b;
239                         break;
240                     }
241                     default: throw new RuntimeException("FIXME!");
242                 }
243             } else {
244                 throw new RuntimeException("unimplemented instruction: " + instructions.peek());
245             }
246         } while(false);
247
248         if (requeueStageInCirculatingState)
249             instructions.add(instructions.peek());
250         instructions.remove();
251         return;
252     }
253
254     // Interface for use by Subclasses ///////////////////////////////////////////////////////////////////////
255
256     // all the methods below convert 64-bit longs to/from
257     // getWordWidth()-bit BitVectors by truncation and sign-extension.
258
259     protected boolean dataReadyForShip() { return dataReadyForShip; }
260     protected final boolean readyForDataFromShip() { return readyForDataFromShip; }
261     protected long removeDataForShip() {
262         long val = peekDataForShip();
263         dataReadyForShip = false;
264         return val;
265     }
266     protected long peekDataForShip() {
267         if (!dataReadyForShip)
268             throw new RuntimeException("peekDataForShip() invoked when dataReadyForShip()==false");
269         return dataLatch.toLong();
270     }
271     protected void addDataFromShip(long data) { addDataFromShip(data, false); }
272     protected void addDataFromShip(long data, boolean pending_flag_c) {
273         if (!readyForDataFromShip())
274             throw new RuntimeException("addDataFromShip() invoked when readyForDataFromShip()");
275         readyForDataFromShip = false;
276         dataFromShip = data;
277         flagCFromShip = pending_flag_c;
278     }
279
280
281     // Debugging //////////////////////////////////////////////////////////////////////////////
282
283     public void dumpState() {
284         if (instructions.size()==0 &&
285             dataPackets.size()==0 &&
286             instructionsBackedUpIntoSwitchFabric.size()==0 &&
287             !requeueStageHasTailInstruction &&
288             !requeueStageInCirculatingState &&
289             !torpedoWaiting &&
290             !flushing &&
291             !dataReadyForShip &&
292             readyForDataFromShip)
293             return;
294         System.out.println("state of "+ANSI.green(this)+": "+
295                            (ilc==1?"":("[ilc="+(ilc==-1 ? "*" : (ilc+""))+"] "))+
296                            (olc==1?"":("[olc="+olc+"] "))+
297                            (flag_a?"[a] ":"")+
298                            (flag_b?"[b] ":"")+
299                            (flag_c?"[c] ":"")+
300                            (flag_d?"[d] ":"")+
301                            (requeueStageInCirculatingState?"[recirculating] ":"")+
302                            (requeueStageHasTailInstruction?"[tail waiting] ":"")+
303                            (torpedoWaiting?"[torpedo waiting] ":"")+
304                            (flushing?"[flushing] ":"")
305                            );
306         if (!readyForDataFromShip)
307             System.out.println(ANSI.cyan("  ship has proffered: " + dataFromShip));
308         if (dataReadyForShip)
309             System.out.println(ANSI.cyan("  waiting for ship to accept: " + dataLatch.toLong()));
310         for(Instruction i : instructions)
311             System.out.println(ANSI.red("  "+i));
312         for(Instruction i : instructionsBackedUpIntoSwitchFabric)
313             System.out.println(ANSI.red(ANSI.bold("  "+i+" BACKED UP")));
314         for(Packet p : dataPackets)
315             System.out.println(ANSI.cyan("  "+p));
316     }
317
318 }