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 executing = null;
17 /** all instructions waiting to be executed (excludes executing) */
18 private Queue<Instruction> instructions = new LinkedList<Instruction>();
20 /** count of how many "standing instruction only" kills remain to be executed */
21 private int killNextStandingInstruction = 0;
23 public int loopCounter = 0;
24 public int repeatCounter = 1;
26 InstructionPump(InterpreterShip ship, String name, String[] ports) {
27 super(ship, name, ports);
30 public void massacre() {
32 while(instructions.size() > 0)
33 instructions.remove();
36 public void kill(int count, boolean killOnlyStandingInstructions) {
38 if (!killOnlyStandingInstructions) {
39 if (executing != null) { executing = null; count--; }
40 for(;count > 0;count--) {
41 if (instructions.size()==0)
42 throw new RuntimeException("deadlocked " + this + " by killing too many instructions");
43 instructions.remove();
46 if (count != 1) throw new RuntimeException("this should never happen");
47 this.killNextStandingInstruction++;
51 /** an instruction arrives from the instruction horn */
52 void addInstruction(Instruction instr) {
53 if (killNextStandingInstruction > 0) { /* FIXME technically we should refuse to take the next instruction here */ }
54 instructions.add(instr);
57 protected void shutdown(boolean leaveAsInbox) {
58 if (!(executing != null || instructions.size() > 0)) return;
59 Log.println(ANSI.red(" WARNING: you left instructions on the instruction queue of port " +
60 this + "; they are:"));
61 if (executing != null)
62 Log.println(" " + executing);
63 for(Instruction i : instructions)
67 // interface to subclass ///////////////////////////////////////////////////////////////////////
69 /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
70 protected abstract boolean service(Instruction instr);
72 protected abstract void setDataLatch(long value);
73 protected abstract long peekDataLatch();
75 protected final void service() {
76 if (clogged > 0) return;
77 if (executing==null && instructions.size() > 0) executing = instructions.remove();
78 if (executing==null) return;
80 int oldLoopCounter = loopCounter;
81 if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1);
83 if (executing instanceof Instruction.Counter) {
84 Instruction.Counter ic = (Instruction.Counter)executing;
85 if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
86 setDataLatch(loopCounter);
87 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
88 loopCounter = (int)peekDataLatch();
89 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
90 repeatCounter = (int)peekDataLatch();
91 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
92 loopCounter = ic.source;
93 } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
94 repeatCounter = ic.source;
96 } else if (executing instanceof Instruction.DecrLoop) {
99 } else if (executing instanceof Instruction.Clog) {
104 if (!service(executing)) return;
107 if (executing==null) return;
108 if (executing.isRepeating() && repeatCounter > 1) {
110 } else if (executing.isLooping() && oldLoopCounter > 0) {
111 addInstruction(executing);
113 } else if (executing.isStanding()) {