collapse InterpreterDock and InstructionDock into one class
[fleet.git] / src / edu / berkeley / fleet / interpreter / InterpreterDock.java
1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.sbp.util.ANSI;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.fleet.api.Instruction;
6 import static edu.berkeley.fleet.api.Predicate.*;
7
8 import java.util.*;
9
10 /** anything that has a source (instruction horn) address on the switch fabric */
11 abstract class InstructionDock extends FleetTwoDock {
12
13     private final InterpreterShip ship;
14     private final Destination[] ports;
15     private final int addr = max_addr++;
16     
17
18     public Path getPath(Destination d, BitVector signal) {
19         throw new RuntimeException();
20     }
21
22     public Iterable<Destination> getDestinations() {
23         HashSet<Destination> ret = new HashSet<Destination>();
24         for(Destination d : ports) ret.add(d);
25         return ret;
26     }
27
28     public Destination getInstructionDestination() {
29         return ports[0];
30     }
31     public Destination getDataDestination() {
32         return ports[0];
33     }
34
35
36     /** adds the included datum to the port from the switch fabric  side */
37     public abstract void addDataFromFabric(Packet packet);
38
39
40     abstract void   shutdown();
41
42     public   Ship   getShip()                  { return ship; }
43     public   Fleet  getFleet()                 { return getShip().getFleet(); }
44     public   String toString()                 { return ship+"."+getName(); }
45     public   int    getInstructionFifoSize() { return 4; }
46     
47     Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
48
49     public long getDestAddr() { return addr; }
50
51     private static int max_addr;
52     private class InterpreterDockDestination extends InterpreterDestination {
53         public String name;
54         public long addr = max_addr++;
55         public InterpreterDockDestination(String name, InstructionDock id, boolean isInstructionDestination) {
56             super(id, isInstructionDestination);
57             this.name = name;
58         }
59         public String getDestinationName()               { return name; }
60         public Ship getShip()                    { return InstructionDock.this.getShip(); }
61         public void addDataFromFabric(Packet packet) { InstructionDock.this.addDataFromFabric(packet); }
62         public String toString()                 { return getShip()+"."+getName(); }
63         public long getDestAddr() { return addr; }
64     }
65
66     public int tailged = 0;
67
68     public boolean flag_a = false;
69     public boolean flag_b = false;
70     public boolean flag_c = false;
71
72     /** the currently executing instruction */
73     private Instruction executing = null;
74
75     /** all instructions waiting to be executed (excludes executing) */
76     private Queue<Instruction> instructions = new LinkedList<Instruction>();
77
78     public int loopCounter = 0;
79     private int repeatCounter = 1;
80
81     InstructionDock(InterpreterShip ship,  String[] ports, DockDescription bbd) {
82         super(ship, bbd);
83         this.ship = ship;
84         this.ports = new Destination[ports.length];
85         for(int i=0; i<ports.length; i++)
86             this.ports[i] =
87                 new InterpreterDockDestination(ports[i], this, false);
88     }
89
90     public void massacre() {
91         executing = null;
92         loopCounter = 0;
93         repeatCounter = 1;
94         while(instructions.size() > 0)
95             instructions.remove();
96     }
97
98     public void kill() {
99         repeatCounter = 1;
100         if (executing != null) { executing = null; return; }
101         if (instructions.size()==0)
102             throw new RuntimeException("deadlocked " + this + " by killing too many instructions");
103         instructions.remove();
104     }
105
106     /** an instruction arrives from the instruction horn */
107     void addInstruction(Instruction instr) { instructions.add(instr); }
108
109     protected void shutdown(boolean leaveAsInbox) {
110         if (!(executing != null || instructions.size() > 0)) return;
111         Log.println(ANSI.red(" WARNING: you left instructions on the instruction queue of port " +
112                              this + "; they are:"));
113         if (executing != null)
114             Log.println("   " + executing);
115         for(Instruction i : instructions)
116             Log.println("   " + i);
117     }
118
119     // interface to subclass ///////////////////////////////////////////////////////////////////////
120
121     /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
122     protected abstract void setDataLatch(long value);
123     protected abstract long peekDataLatch();
124
125     protected final void service() {
126             /*
127         if (tailged > 0) return;
128         if (executing==null && instructions.size() > 0) executing = instructions.remove();
129         if (executing==null) return;
130
131         boolean enabled = true;
132         if (executing instanceof Instruction.PredicatedInstruction) {
133             Instruction.PredicatedInstruction ip = (Instruction.PredicatedInstruction)executing;
134             switch(ip.predicate) {
135                 case IgnoreOLC:      enabled = true; break;
136                 case Default:  enabled = loopCounter!=0; break;
137                 case FlagA:   enabled = flag_a; break;
138                 case FlagB:   enabled = flag_b; break;
139                     //case FlagC:   enabled = ; break;
140                 case NotFlagA:   enabled = !flag_a; break;
141                 case NotFlagB:   enabled = !flag_b; break;
142                     //case NotFlagC:   enabled = loopCounter==0; break;
143             }
144         }
145
146         int oldLoopCounter = loopCounter;
147         if (enabled) {
148             if (executing instanceof Instruction.Set.OLC.Decrement) loopCounter = Math.max(0, loopCounter-1);
149             if (executing instanceof Instruction.Counter) {
150                 Instruction.Counter ic = (Instruction.Counter)executing;
151                 if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
152                     setDataLatch(oldLoopCounter); // FIXME: which is correct here?
153                 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
154                     loopCounter = (int)peekDataLatch();
155                 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
156                     // FIXME: is there any way to load the "standing" value?
157                     repeatCounter = (int)peekDataLatch();
158                 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
159                     loopCounter = ic.source;
160                 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source==Instruction.Counter.STANDING) {
161                     repeatCounter = -1;
162                 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
163                     repeatCounter = ic.source;
164                 }
165
166                 } else if (executing instanceof Instruction.Set.Flags) {
167                 Instruction.Set.Flags sf = (Instruction.Set.Flags)executing;
168                 boolean old_c = oldLoopCounter == 0;
169                 boolean old_a = flag_a;
170                 boolean old_b = flag_b;
171                 flag_a =
172                     (((sf.flag_a & sf.FLAG_A)     != 0) ?  old_a : false) |
173                     (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
174                     (((sf.flag_a & sf.FLAG_B)     != 0) ?  old_b : false) |
175                     (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
176                     (((sf.flag_a & sf.FLAG_C)     != 0) ?  old_c : false) |
177                     (((sf.flag_a & sf.FLAG_NOT_C) != 0) ? !old_c : false);
178                 flag_b =
179                     (((sf.flag_b & sf.FLAG_A)     != 0) ?  old_a : false) |
180                     (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
181                     (((sf.flag_b & sf.FLAG_B)     != 0) ?  old_b : false) |
182                     (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
183                     (((sf.flag_b & sf.FLAG_C)     != 0) ?  old_c : false) |
184                     (((sf.flag_b & sf.FLAG_NOT_C) != 0) ? !old_c : false);
185             } else if (executing instanceof Instruction.Set.OLC.Decrement) {
186             } else {
187                 if (!service(executing)) return;
188             }
189         }
190
191         if (executing==null) return;
192         if ((executing instanceof Instruction.Move) && repeatCounter > 1) {
193             repeatCounter--;
194         } else if ((executing instanceof Instruction.Move) && repeatCounter == -1) {
195             // repeat
196         } else if ((executing instanceof Instruction.PredicatedInstruction && ((Instruction.PredicatedInstruction)executing).looping) && oldLoopCounter > 0) {
197             addInstruction(executing);
198             executing = null;
199         } else {
200             executing = null;
201         }
202             */
203     }
204
205
206
207 }