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 InstructionBenkoBox extends InterpreterBenkoBox {
12 /** the currently executing instruction */
13 private Instruction.Executable executing = null;
15 /** all instructions waiting to be executed (excludes executing) */
16 private Queue<Instruction.Executable> instructions = new LinkedList<Instruction.Executable>();
18 /** count of how many "standing instruction only" kills remain to be executed */
19 private int killNextStandingInstruction = 0;
21 InstructionBenkoBox(InterpreterShip ship, String name, String[] ports) {
22 super(ship, name, ports);
25 public void kill(int count, boolean killOnlyStandingInstructions) {
27 if (!killOnlyStandingInstructions) {
28 if (executing != null) { executing = null; count--; }
29 for(;count > 0;count--) {
30 if (instructions.size()==0)
31 throw new RuntimeException("deadlocked " + this + " by killing too many instructions");
32 instructions.remove();
35 if (count != 1) throw new RuntimeException("this should never happen");
36 this.killNextStandingInstruction++;
40 /** an instruction arrives from the instruction horn */
41 void addInstruction(Instruction.Executable instr) {
42 if (killNextStandingInstruction > 0) { /* FIXME technically we should refuse to take the next instruction here */ }
43 instructions.add(instr);
46 protected void shutdown(boolean leaveAsInbox) {
47 if (!(executing != null || instructions.size() > 0)) return;
48 Log.println(ANSI.red(" WARNING: you left instructions on the instruction queue of port " +
49 this + "; they are:"));
50 if (executing != null)
51 Log.println(" " + executing);
52 for(Instruction.Executable i : instructions)
56 // interface to subclass ///////////////////////////////////////////////////////////////////////
58 /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
59 protected abstract boolean service(Instruction.Executable instr);
61 protected final void service() {
62 if (executing == null)
63 if (instructions.size() > 0)
64 executing = instructions.remove();
68 if (executing != null && killNextStandingInstruction>0 && executing.isStanding()) {
70 killNextStandingInstruction--;
74 boolean ret = service(executing);
76 if (executing.requeue) {
77 executing = executing.decrementCount();
78 if (executing != null)
79 addInstruction(executing);
83 if (executing != null && !executing.isStanding())
84 executing = executing.decrementCount();