updated to AM14, AM15
[fleet.git] / src / edu / berkeley / fleet / interpreter / InstructionPort.java
1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.api.Instruction;
4
5 import java.util.*;
6
7 /** anything that has a source (instruction horn) address on the switch fabric */
8 public abstract class InstructionPort extends InterpreterBenkoBox {
9
10     /** the currently executing instruction */
11     Instruction.Executable currentlyExecuting = null;
12
13     /** all instructions waiting to be executed (excludes currentlyExecuting) */
14     Queue<Instruction.Executable> instructions = new LinkedList<Instruction.Executable>();
15
16     /** the count field of currentlyExecuting, taking into account actions already performed */
17     int currentlyExecutingCount;
18
19     InstructionPort(InterpreterShip ship, String name) {
20         super(ship, name);
21     }
22
23     public void kill(int count) {
24         if (currentlyExecuting != null) {
25             currentlyExecuting = null;
26             count--;
27         }
28         for(; count > 0; count--) {
29             if (instructions.size() == 0) {
30                 if (currentlyExecuting == null) {
31                     Log.error("You have deadlocked ship " + this +
32                               " by sending a kill to an empty ififo.  I feel sorry for you.");
33                     return;
34                 }
35             } else {
36                 instructions.remove();
37             }
38         }
39     }
40
41     /** an instruction arrives from the instruction horn */
42     void addInstruction(Instruction.Executable instr) {
43         instructions.add(instr);
44     }
45
46     protected void shutdown(boolean leaveAsInbox) {
47         if (currentlyExecuting != null || instructions.size() > 0) {
48             Log.println(Log.red(" WARNING: you left instructions on the instruction queue of port " +
49                                 this + "; they are:"));
50             if (currentlyExecuting != null)
51                 Log.println("   " + currentlyExecuting);
52             for(Instruction.Executable i : instructions)
53                 Log.println("   " + i);
54         }
55     }
56
57     // interface to subclass ///////////////////////////////////////////////////////////////////////
58
59     /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
60     protected abstract boolean service(Instruction.Executable instr);
61
62     protected final void service() {
63         if (currentlyExecutingCount <= 0)
64             currentlyExecuting = null;
65         if (currentlyExecuting == null && instructions.size() > 0) {
66             currentlyExecuting = instructions.remove();
67             currentlyExecutingCount = currentlyExecuting.count;
68             if (currentlyExecutingCount == 0) currentlyExecutingCount = Integer.MAX_VALUE;
69         }
70
71         boolean ret = service(currentlyExecuting);
72         if (!ret) return;
73         if (currentlyExecuting.recycle) {
74             currentlyExecuting = currentlyExecuting.decrementCount();
75             if (currentlyExecuting != null)
76                 addInstruction(currentlyExecuting);
77             currentlyExecuting = null;
78
79         } else {
80             if (currentlyExecuting != null && currentlyExecutingCount != Integer.MAX_VALUE)
81                 currentlyExecutingCount--;
82         }
83     }
84
85
86 }