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