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