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