add interpreter code and tests for loop counter instructions
[fleet.git] / src / edu / berkeley / fleet / interpreter / Outbox.java
index b154fc2..85b3926 100644 (file)
@@ -1,49 +1,63 @@
 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;
         }
@@ -51,35 +65,57 @@ public abstract class Outbox extends InstructionPort {
         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);
     }
+
 }