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;
11 public class Outbox extends InstructionDock {
13 /** are we ready to accept another item from the ship? */
14 private boolean readyForDataFromShip = false;
15 private boolean haveDataFromShip = false;
17 /** data which has been presented by the ship and is waiting to depart */
18 private long itemPresentedByShip;
20 /** number of tokens queued on the trigger input */
21 private int triggersReceived = 0;
23 /** the latched value */
24 private long register;
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); }
29 protected void setDataLatch(long value) { register = value; }
30 protected long peekDataLatch() { return register; }
32 protected final boolean service(Instruction instruction_) {
34 if (instruction_ instanceof Instruction.Literal) {
35 register = ((Instruction.Literal)instruction_).literal;
37 } else if (instruction_ instanceof Instruction.HalfLiteral) {
38 Instruction.HalfLiteral ll = (Instruction.HalfLiteral)instruction_;
41 ? setField(36, 19, ll.literal, register)
42 : setField(18, 0, ll.literal, register);
46 Instruction.Move instruction = (Instruction.Move)instruction_;
48 // if no instruction waiting, do nothing
49 if (instruction == null) return false;
51 // check firing conditions
52 if (instruction.tokenIn && triggersReceived <= 0) return false;
53 if (instruction.dataIn) {
54 if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
58 if (instruction.tokenIn) triggersReceived--;
61 if (instruction.dataIn) {
62 haveDataFromShip = false;
63 if (instruction.latchData)
64 register = itemPresentedByShip;
67 if (instruction.dataOut) {
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);
76 dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
80 Dock pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits);
84 //throw new RuntimeException();
86 new Packet(getInterpreter(), this, register, dest).send();
88 if (instruction.tokenOut)
89 throw new RuntimeException("outboxes may not send acks!");
91 } else if (instruction.tokenOut) {
93 // if no item was sent, we might still send an ack
94 new Packet(getInterpreter(), this, 0, (InterpreterDestination)(Object)instruction.path).send();
100 public final boolean readyForDataFromShip() { return readyForDataFromShip; }
101 public void addDataFromShip(long data) { addItemFromShip(data); }
102 public void addDataFromFabric(Packet packet) { triggersReceived++; }
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;
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);