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