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