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.api.Instruction;
7 public class Outbox extends InstructionBenkoBox {
9 /** are we ready to accept another item from the ship? */
10 private boolean readyForDataFromShip = false;
11 private boolean haveDataFromShip = false;
13 /** data which has been presented by the ship and is waiting to depart */
14 private long itemPresentedByShip;
16 /** number of tokens queued on the trigger input */
17 private int triggersReceived = 0;
19 /** the latched value */
20 private long register;
22 public boolean isInbox() { return false; }
23 public boolean isOutbox() { return true; }
24 public Outbox(InterpreterShip ship, String name) { this(ship, name, new String[] { "" }); }
25 public Outbox(InterpreterShip ship, String name, String[] ports) { super(ship, name, ports); }
27 protected final boolean service(Instruction.Executable instruction) {
29 // if no instruction waiting, do nothing
30 if (instruction == null) return false;
32 // check firing conditions
33 if (instruction.tokenIn && triggersReceived <= 0) return false;
34 if (instruction.dataIn) {
35 if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
39 if (instruction.tokenIn) triggersReceived--;
42 if (instruction.dataIn) {
43 haveDataFromShip = false;
44 if (instruction.latch)
45 register = itemPresentedByShip;
48 if (instruction.dataOut) {
50 // if item to be transmitted, send it
51 InterpreterDestination dest = (InterpreterDestination)instruction.dest;
52 if (instruction.dataOutDest) {
53 long bits = BitManipulations.getField(InstructionEncoder.WIDTH_WORD-1,
54 InstructionEncoder.WIDTH_WORD-InstructionEncoder.WIDTH_DEST_ADDR,
56 dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
58 new Packet(getInterpreter(), this, register, dest).send();
59 if (instruction.tokenOut)
60 throw new RuntimeException("outboxes may not send acks!");
62 } else if (instruction.tokenOut) {
64 // if no item was sent, we might still send an ack
65 new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send();
71 public final boolean readyForDataFromShip() { return readyForDataFromShip; }
72 public void addDataFromShip(long data) { addItemFromShip(data); }
73 public void addDataFromFabric(Packet packet) { triggersReceived++; }
75 /** subclass invokes this to add an item from the ship */
76 protected final void addItemFromShip(long data) {
77 if (!readyForDataFromShip)
78 throw new RuntimeException("tried to add an item to an outbox which was not ready! you have a buggy ship!");
79 readyForDataFromShip = false;
80 haveDataFromShip = true;
81 itemPresentedByShip = data;
86 Log.println(ANSI.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
87 if (triggersReceived > 0)
88 Log.println(ANSI.red(" WARNING: you left a token on the trigger input to port " + this));
89 super.shutdown(false);