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.*;
10 /** anything that has a source (instruction horn) address on the switch fabric */
11 abstract class InstructionDock extends FleetTwoDock {
13 private final InterpreterShip ship;
14 private final Destination[] ports;
15 private final int addr = max_addr++;
18 public Path getPath(Destination d, BitVector signal) {
19 throw new RuntimeException();
22 public Iterable<Destination> getDestinations() {
23 HashSet<Destination> ret = new HashSet<Destination>();
24 for(Destination d : ports) ret.add(d);
28 public Destination getInstructionDestination() {
31 public Destination getDataDestination() {
36 /** adds the included datum to the port from the switch fabric side */
37 public abstract void addDataFromFabric(Packet packet);
40 abstract void shutdown();
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; }
47 Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
49 public long getDestAddr() { return addr; }
51 private static int max_addr;
52 private class InterpreterDockDestination extends InterpreterDestination {
54 public long addr = max_addr++;
55 public InterpreterDockDestination(String name, InstructionDock id, boolean isInstructionDestination) {
56 super(id, isInstructionDestination);
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; }
66 public int tailged = 0;
68 public boolean flag_a = false;
69 public boolean flag_b = false;
70 public boolean flag_c = false;
72 /** the currently executing instruction */
73 private Instruction executing = null;
75 /** all instructions waiting to be executed (excludes executing) */
76 private Queue<Instruction> instructions = new LinkedList<Instruction>();
78 public int loopCounter = 0;
79 private int repeatCounter = 1;
81 InstructionDock(InterpreterShip ship, String[] ports, DockDescription bbd) {
84 this.ports = new Destination[ports.length];
85 for(int i=0; i<ports.length; i++)
87 new InterpreterDockDestination(ports[i], this, false);
90 public void massacre() {
94 while(instructions.size() > 0)
95 instructions.remove();
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();
106 /** an instruction arrives from the instruction horn */
107 void addInstruction(Instruction instr) { instructions.add(instr); }
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);
119 // interface to subclass ///////////////////////////////////////////////////////////////////////
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();
125 protected final void service() {
127 if (tailged > 0) return;
128 if (executing==null && instructions.size() > 0) executing = instructions.remove();
129 if (executing==null) return;
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;
146 int oldLoopCounter = loopCounter;
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) {
162 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
163 repeatCounter = ic.source;
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;
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);
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) {
187 if (!service(executing)) return;
191 if (executing==null) return;
192 if ((executing instanceof Instruction.Move) && repeatCounter > 1) {
194 } else if ((executing instanceof Instruction.Move) && repeatCounter == -1) {
196 } else if ((executing instanceof Instruction.PredicatedInstruction && ((Instruction.PredicatedInstruction)executing).looping) && oldLoopCounter > 0) {
197 addInstruction(executing);