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