support for disabling terminal colors
[fleet.git] / src / edu / berkeley / fleet / interpreter / Outbox.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.api.Instruction;
5
6 public abstract class Outbox extends InstructionPort {
7
8     /** are we ready to accept another item from the ship? */
9     private boolean readyForItemFromShip = true;
10
11     /** data which has been presented by the ship and is waiting to depart */
12     private int     itemPresentedByShip;
13
14     /** number of tokens queued on the trigger input */
15     private int     triggersReceived = 0;
16
17     private Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
18
19     protected Outbox(InterpreterShip ship, String name) {
20         super(ship, name);
21     }
22
23     public final boolean readyForItemFromShip() {
24         return readyForItemFromShip;
25     }
26
27     void addDataFromFabric(int datum)  { addTokenFromFabric(); }
28     final void addTokenFromFabric() {
29         triggersReceived++;
30     }
31
32     int register;
33     protected final boolean service(Instruction.Executable instruction) {
34
35         // if no instruction waiting, do nothing
36         if (instruction == null) return false;
37
38         // check firing conditions
39         if (instruction.tokenIn && triggersReceived <= 0) return false;
40         if (instruction.dataIn && readyForItemFromShip) return false;
41         
42         // consume trigger
43         if (instruction.tokenIn) triggersReceived--;
44
45         // consume item
46         if (instruction.dataIn) {
47             readyForItemFromShip = true;
48             if (instruction.latch) 
49                 register = itemPresentedByShip;
50         }
51
52         if (instruction.dataOut) {
53
54             // if item to be transmitted, send it
55             send((InterpreterBenkoBox)instruction.dest, register);
56             if (instruction.tokenOut)
57                 throw new RuntimeException("outboxes may not send acks!");
58
59         } else if (instruction.tokenOut) {
60
61             // if no item was sent, we might still send an ack
62             getInterpreter().sendToken(this, (InterpreterBenkoBox)instruction.dest);
63         }
64
65         return true;
66     }
67
68     /** this is invoked to transmit data; the subclass decides if it is a token or not */
69     protected abstract void send(InterpreterBenkoBox port, int data);
70
71     /** subclass invokes this to add an item from the ship */
72     protected final void addItemFromShip(int data) {
73         if (!readyForItemFromShip)
74             throw new RuntimeException("tried to add an item to an outbox which was not ready!  you have a buggy ship!");
75         readyForItemFromShip = false;
76         itemPresentedByShip = data;
77     }
78
79     void shutdown() {
80         if (!readyForItemFromShip)
81             Log.println(ANSI.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
82         if (triggersReceived > 0)
83             Log.println(ANSI.red(" WARNING: you left a token on the trigger input to port " + this));
84         super.shutdown(false);
85     }
86 }