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