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;
10 public class Outbox extends InstructionPump {
12 /** are we ready to accept another item from the ship? */
13 private boolean readyForDataFromShip = false;
14 private boolean haveDataFromShip = false;
16 /** data which has been presented by the ship and is waiting to depart */
17 private long itemPresentedByShip;
19 /** number of tokens queued on the trigger input */
20 private int triggersReceived = 0;
22 /** the latched value */
23 private long register;
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); }
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_;
37 ? setField(36, 19, ll.literal, register)
38 : setField(18, 0, ll.literal, register);
41 Instruction.Move instruction = (Instruction.Move)instruction_;
43 // if no instruction waiting, do nothing
44 if (instruction == null) return false;
46 // check firing conditions
47 if (instruction.tokenIn && triggersReceived <= 0) return false;
48 if (instruction.dataIn) {
49 if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
53 if (instruction.tokenIn) triggersReceived--;
56 if (instruction.dataIn) {
57 haveDataFromShip = false;
58 if (instruction.latch)
59 register = itemPresentedByShip;
62 if (instruction.dataOut) {
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,
71 getInterpreter().dispatch(((Interpreter)getInterpreter()).iie.readInstruction(register), bits);
73 dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
77 Pump pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits);
81 //throw new RuntimeException();
83 new Packet(getInterpreter(), this, register, dest).send();
85 if (instruction.tokenOut)
86 throw new RuntimeException("outboxes may not send acks!");
88 } else if (instruction.tokenOut) {
90 // if no item was sent, we might still send an ack
91 new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send();
97 public final boolean readyForDataFromShip() { return readyForDataFromShip; }
98 public void addDataFromShip(long data) { addItemFromShip(data); }
99 public void addDataFromFabric(Packet packet) { triggersReceived++; }
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;
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);