8b06cbcf98765d5a072851199f711c51ed5d0760
[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.two.*;
5 import edu.berkeley.sbp.util.*;
6 import edu.berkeley.fleet.util.*;
7 import static edu.berkeley.fleet.util.BitManipulations.*;
8 import edu.berkeley.fleet.two.*;
9 import edu.berkeley.fleet.api.Instruction;
10
11 public class Outbox extends InstructionDock {
12
13     /** are we ready to accept another item from the ship? */
14     private boolean readyForDataFromShip = false;
15     private boolean haveDataFromShip     = false;
16
17     /** data which has been presented by the ship and is waiting to depart */
18     private long    itemPresentedByShip;
19
20     /** number of tokens queued on the trigger input */
21     private int     triggersReceived = 0;
22
23     /** the latched value */
24     private long register;
25
26     public Outbox(InterpreterShip ship, DockDescription dd) { this(ship, new String[] { "" }, dd); }
27     public Outbox(InterpreterShip ship, String[] ports, DockDescription dd) { super(ship, ports, dd); }
28
29     protected void setDataLatch(long value) { register = value; }
30     protected long peekDataLatch() { return register; }
31
32     protected final boolean service(Instruction instruction_) {
33         /*
34         if (instruction_ instanceof Instruction.Literal) {
35             register = ((Instruction.Literal)instruction_).literal;
36             return true;
37         } else if (instruction_ instanceof Instruction.HalfLiteral) {
38             Instruction.HalfLiteral ll = (Instruction.HalfLiteral)instruction_;
39             register =
40                 ll.high
41                 ? setField(36, 19, ll.literal, register)
42                 : setField(18,  0, ll.literal, register);
43             return true;
44         }
45         */
46         Instruction.Move instruction = (Instruction.Move)instruction_;
47
48         // if no instruction waiting, do nothing
49         if (instruction == null) return false;
50
51         // check firing conditions
52         if (instruction.tokenIn && triggersReceived <= 0) return false;
53         if (instruction.dataIn) {
54             if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
55         }
56         
57         // consume trigger
58         if (instruction.tokenIn) triggersReceived--;
59
60         // consume item
61         if (instruction.dataIn) {
62             haveDataFromShip = false;
63             if (instruction.latchData) 
64                 register = itemPresentedByShip;
65         }
66
67         if (instruction.dataOut) {
68
69             // if item to be transmitted, send it
70             InterpreterDestination dest = (InterpreterDestination)(Object)instruction.path;
71             if (instruction.latchPath) {
72                 // FIXME: still not supported
73                 long bits = FleetTwoFleet.DISPATCH_PATH.getval(register);
74                 getInterpreter().dispatch(((Interpreter)getInterpreter()).readInstruction(register, null), bits);
75                 /*
76                 dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
77                 if (dest == null) {
78                     if (pump != null) {
79                         
80                 Dock pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits);
81                     }
82                 }
83                 */
84                 //throw new RuntimeException();
85             } else {
86                 new Packet(getInterpreter(), this, register, dest).send();
87             }
88             if (instruction.tokenOut)
89                 throw new RuntimeException("outboxes may not send acks!");
90
91         } else if (instruction.tokenOut) {
92
93             // if no item was sent, we might still send an ack
94             new Packet(getInterpreter(), this, 0, (InterpreterDestination)(Object)instruction.path).send();
95         }
96
97         return true;
98     }
99
100     public final boolean readyForDataFromShip() { return readyForDataFromShip; }
101     public       void addDataFromShip(long data) { addItemFromShip(data); }
102     public       void addDataFromFabric(Packet packet) { triggersReceived++; }
103
104     /** subclass invokes this to add an item from the ship */
105     protected final void addItemFromShip(long data) {
106         if (!readyForDataFromShip)
107             throw new RuntimeException("tried to add an item to an outbox which was not ready!  you have a buggy ship!");
108         readyForDataFromShip = false;
109         haveDataFromShip = true;
110         itemPresentedByShip = data;
111     }
112
113     void shutdown() {
114         if (haveDataFromShip)
115             Log.println(ANSI.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
116         if (triggersReceived > 0)
117             Log.println(ANSI.red(" WARNING: you left a token on the trigger input to port " + this));
118         super.shutdown(false);
119     }
120
121 }