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