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