implement am26 support for constants
[fleet.git] / src / edu / berkeley / fleet / interpreter / InstructionBenkoBox.java
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;
6
7 import java.util.*;
8
9 /** anything that has a source (instruction horn) address on the switch fabric */
10 abstract class InstructionBenkoBox extends InterpreterBenkoBox {
11
12     /** the currently executing instruction */
13     private Instruction.Executable executing = null;
14
15     /** all instructions waiting to be executed (excludes executing) */
16     private Queue<Instruction.Executable> instructions = new LinkedList<Instruction.Executable>();
17
18     /** count of how many "standing instruction only" kills remain to be executed */
19     private int killNextStandingInstruction = 0;
20
21     InstructionBenkoBox(InterpreterShip ship, String name, String[] ports) {
22         super(ship, name, ports);
23     }
24
25     public void kill(int count, boolean killOnlyStandingInstructions) {
26         if (count==0) return;
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();
33             }
34         } else {
35             if (count != 1) throw new RuntimeException("this should never happen");
36             this.killNextStandingInstruction++;
37         }
38     }
39
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);
44     }
45
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)
53             Log.println("   " + i);
54     }
55
56     // interface to subclass ///////////////////////////////////////////////////////////////////////
57
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);
60
61     protected final void service() {
62         if (executing == null)
63             if (instructions.size() > 0)
64                 executing = instructions.remove();
65             else
66                 return;
67
68         if (executing != null && killNextStandingInstruction>0 && executing.isStanding()) {
69             executing = null;
70             killNextStandingInstruction--;
71             return;
72         }
73
74         boolean ret = service(executing);
75         if (!ret) return;
76         if (executing.requeue) {
77             executing = executing.decrementCount();
78             if (executing != null)
79                 addInstruction(executing);
80             executing = null;
81
82         } else {
83             if (executing != null && !executing.isStanding())
84                 executing = executing.decrementCount();
85         }
86     }
87
88
89 }