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