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