package edu.berkeley.fleet.interpreter;
+import edu.berkeley.sbp.util.ANSI;
import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.ies44.*;
+import edu.berkeley.sbp.util.*;
+import edu.berkeley.fleet.util.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
import edu.berkeley.fleet.api.Instruction;
-public abstract class Outbox extends InstructionPort {
+public class Outbox extends InstructionPump {
/** are we ready to accept another item from the ship? */
- private boolean readyForItemFromShip = true;
+ private boolean readyForDataFromShip = false;
+ private boolean haveDataFromShip = false;
/** data which has been presented by the ship and is waiting to depart */
- private int itemPresentedByShip;
+ private long itemPresentedByShip;
/** number of tokens queued on the trigger input */
private int triggersReceived = 0;
- private Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
-
- protected Outbox(InterpreterShip ship, String name) {
- super(ship, name);
- }
-
- public final boolean readyForItemFromShip() {
- return readyForItemFromShip;
- }
-
- void addDataFromFabric(int datum) { addTokenFromFabric(); }
- final void addTokenFromFabric() {
- triggersReceived++;
- }
-
- int register;
- protected final boolean service(Instruction.Executable instruction) {
+ /** the latched value */
+ private long register;
+
+ public boolean isInbox() { return false; }
+ public boolean isOutbox() { return true; }
+ public Outbox(InterpreterShip ship, String name) { this(ship, name, new String[] { "" }); }
+ public Outbox(InterpreterShip ship, String name, String[] ports) { super(ship, name, ports); }
+
+ protected void setDataLatch(long value) { register = value; }
+ protected long peekDataLatch() { return register; }
+
+ protected final boolean service(Instruction.Executable instruction_) {
+ if (clogged>0) return false;
+ if (instruction_ instanceof Instruction.Clog) { clogged++; return true; }
+ if (instruction_ instanceof Instruction.LocalLiteral) {
+ Instruction.LocalLiteral ll = (Instruction.LocalLiteral)instruction_;
+ register =
+ ll.high
+ ? setField(36, 19, ll.literal, register)
+ : setField(18, 0, ll.literal, register);
+ return true;
+ }
+ Instruction.Move instruction = (Instruction.Move)instruction_;
// if no instruction waiting, do nothing
if (instruction == null) return false;
// check firing conditions
if (instruction.tokenIn && triggersReceived <= 0) return false;
- if (instruction.dataIn && readyForItemFromShip) return false;
+ if (instruction.dataIn) {
+ if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
+ }
// consume trigger
if (instruction.tokenIn) triggersReceived--;
// consume item
if (instruction.dataIn) {
- readyForItemFromShip = true;
+ haveDataFromShip = false;
if (instruction.latch)
register = itemPresentedByShip;
}
if (instruction.dataOut) {
// if item to be transmitted, send it
- send((InterpreterBenkoBox)instruction.dest, register);
+ InterpreterDestination dest = (InterpreterDestination)instruction.dest;
+ if (instruction.dataOutDest) {
+ // FIXME: still not supported
+ long bits = BitManipulations.getField(InstructionEncoder.OFFSET_PUMP_ADDR+InstructionEncoder.WIDTH_PUMP_ADDR-1,
+ InstructionEncoder.OFFSET_PUMP_ADDR,
+ register);
+ getInterpreter().dispatch(((Interpreter)getInterpreter()).iie.readInstruction(register), bits);
+ /*
+ dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
+ if (dest == null) {
+ if (pump != null) {
+
+ Pump pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits);
+ }
+ }
+ */
+ //throw new RuntimeException();
+ } else {
+ new Packet(getInterpreter(), this, register, dest).send();
+ }
if (instruction.tokenOut)
throw new RuntimeException("outboxes may not send acks!");
} else if (instruction.tokenOut) {
// if no item was sent, we might still send an ack
- getInterpreter().sendToken(this, (InterpreterBenkoBox)instruction.dest);
+ new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send();
}
return true;
}
- /** this is invoked to transmit data; the subclass decides if it is a token or not */
- protected abstract void send(InterpreterBenkoBox port, int data);
+ public final boolean readyForDataFromShip() { return readyForDataFromShip; }
+ public void addDataFromShip(long data) { addItemFromShip(data); }
+ public void addDataFromFabric(Packet packet) { triggersReceived++; }
/** subclass invokes this to add an item from the ship */
- protected final void addItemFromShip(int data) {
- if (!readyForItemFromShip)
+ protected final void addItemFromShip(long data) {
+ if (!readyForDataFromShip)
throw new RuntimeException("tried to add an item to an outbox which was not ready! you have a buggy ship!");
- readyForItemFromShip = false;
+ readyForDataFromShip = false;
+ haveDataFromShip = true;
itemPresentedByShip = data;
}
void shutdown() {
- if (!readyForItemFromShip)
- Log.println(Log.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
+ if (haveDataFromShip)
+ Log.println(ANSI.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
if (triggersReceived > 0)
- Log.println(Log.red(" WARNING: you left a token on the trigger input to port " + this));
+ Log.println(ANSI.red(" WARNING: you left a token on the trigger input to port " + this));
super.shutdown(false);
}
+
}