1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.sbp.util.ANSI;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.doc.*;
5 import edu.berkeley.fleet.api.Instruction;
9 /** anything that has a source (instruction horn) address on the switch fabric */
10 abstract class InstructionPump extends InterpreterPump {
12 public int clogged = 0;
14 /** the currently executing instruction */
15 private Instruction.Executable executing = null;
17 /** all instructions waiting to be executed (excludes executing) */
18 private Queue<Instruction.Executable> instructions = new LinkedList<Instruction.Executable>();
20 /** count of how many "standing instruction only" kills remain to be executed */
21 private int killNextStandingInstruction = 0;
23 public int loopCounter = 0;
25 InstructionPump(InterpreterShip ship, String name, String[] ports) {
26 super(ship, name, ports);
29 public void massacre() {
31 while(instructions.size() > 0)
32 instructions.remove();
35 public void kill(int count, boolean killOnlyStandingInstructions) {
37 if (!killOnlyStandingInstructions) {
38 if (executing != null) { executing = null; count--; }
39 for(;count > 0;count--) {
40 if (instructions.size()==0)
41 throw new RuntimeException("deadlocked " + this + " by killing too many instructions");
42 instructions.remove();
45 if (count != 1) throw new RuntimeException("this should never happen");
46 this.killNextStandingInstruction++;
50 /** an instruction arrives from the instruction horn */
51 void addInstruction(Instruction.Executable instr) {
52 if (killNextStandingInstruction > 0) { /* FIXME technically we should refuse to take the next instruction here */ }
53 instructions.add(instr);
56 protected void shutdown(boolean leaveAsInbox) {
57 if (!(executing != null || instructions.size() > 0)) return;
58 Log.println(ANSI.red(" WARNING: you left instructions on the instruction queue of port " +
59 this + "; they are:"));
60 if (executing != null)
61 Log.println(" " + executing);
62 for(Instruction.Executable i : instructions)
66 // interface to subclass ///////////////////////////////////////////////////////////////////////
68 /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
69 protected abstract boolean service(Instruction.Executable instr);
71 protected abstract void setDataLatch(long value);
72 protected abstract long peekDataLatch();
73 public boolean _service(Instruction.Executable instr) {
74 if (instr instanceof Instruction.DecrLoop) {
75 if (loopCounter >= 0) loopCounter--;
78 if (instr instanceof Instruction.Counter) {
79 Instruction.Counter ic = (Instruction.Counter)instr;
80 if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
81 setDataLatch(loopCounter);
82 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
83 loopCounter = (int)peekDataLatch();
85 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
86 loopCounter = ic.source;
91 return service(instr);
94 protected final void service() {
95 if (executing == null)
96 if (instructions.size() > 0)
97 executing = instructions.remove();
101 if (executing != null && killNextStandingInstruction>0 && executing.isStanding()) {
103 killNextStandingInstruction--;
107 boolean ret = _service(executing);
109 if (executing == null) return;
110 if (executing.isRequeueing() || (loopCounter > 0)) {
111 if (loopCounter == 0) executing = executing.decrementCount();
112 if (executing != null)
113 addInstruction(executing);
117 if (executing != null && !executing.isStanding())
118 executing = executing.decrementCount();