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