mild overhaul of Interpreter; now capable of performing MergeSort
[fleet.git] / src / edu / berkeley / fleet / interpreter / InterpreterDock.java
index 9dad01b..5c7e9ec 100644 (file)
@@ -2,6 +2,7 @@ package edu.berkeley.fleet.interpreter;
 import java.util.*;
 import edu.berkeley.fleet.two.*;
 import edu.berkeley.fleet.api.*;
+import edu.berkeley.sbp.util.ANSI;
 
 /** anything that has a source (instruction horn) address on the switch fabric */
 class InterpreterDock extends FleetTwoDock {
@@ -17,14 +18,18 @@ class InterpreterDock extends FleetTwoDock {
     final BitVector dataLatch = new BitVector(getShip().getFleet().getWordWidth());
     InterpreterPath pathLatch = null;
     boolean         requeueStageInCirculatingState = false;
-    boolean         requeueStageHasTailInstruction = false;
-    boolean         torpedoWaiting = false;
     boolean         flushing = false;
 
-    Queue<Instruction> instructions = new LinkedList<Instruction>();
-    Queue<Packet> dataPackets = new LinkedList<Packet>();
+    LinkedList<Instruction> instructions = new LinkedList<Instruction>();
+    LinkedList<Packet> dataPackets = new LinkedList<Packet>();
+
+    // HACK
+    private LinkedList<Packet> instructionsBackedUpIntoSwitchFabric = new LinkedList<Packet>();
+
     boolean dataReadyForShip = false;
     boolean readyForDataFromShip = true;
+
+    // FIXME: should be a BitVector
     long dataFromShip;
     boolean flagCFromShip;
 
@@ -38,12 +43,11 @@ class InterpreterDock extends FleetTwoDock {
         dataLatch.set(0);
         pathLatch = null;
         requeueStageInCirculatingState = false;
-        requeueStageHasTailInstruction = false;
         instructions.clear();
         dataPackets.clear();
+        instructionsBackedUpIntoSwitchFabric.clear();
         dataReadyForShip = false;
         readyForDataFromShip = true;
-        torpedoWaiting = false;
         flushing = false;
     }
 
@@ -52,39 +56,7 @@ class InterpreterDock extends FleetTwoDock {
     /** includes the epilogue fifo */
     public InterpreterDestination instructionDestination = new InterpreterDestination(this) {
             public String toString() { return getDock()+":i"; }
-            public void addDataFromFabric(Packet p) {
-                if (p.isToken()) {
-                    if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
-                    torpedoWaiting = true;
-                    return;
-                }
-
-                Instruction inst =
-                    getInterpreter().decodeInstruction(p.getValue(),
-                                                       InterpreterDock.this /* this is wrong, but harmless */);
-
-                // FIXME: this is a bit too conservative.  In theory,
-                // it's okay to dispatch new instructions to the dock
-                // as long as we know that it will reach the updating
-                // state without any further input from the outside
-                // world -- ie that the instructions which remain to
-                // be executed before the requeue stage transitions to
-                // the updating state are all "non-blocking" (no moves
-                // with Ti=1 or Di=1)
-                if (requeueStageInCirculatingState || requeueStageHasTailInstruction)
-                    throw new RuntimeException("An instruction arrived while the requeue stage was circulating -- "+
-                                               "this means that instructions have backed up into "+
-                                               "the switch fabric, which nearly always risks deadlock! "+
-                                               "Fix your program!"+
-                                               "\n  dock: " + InterpreterDock.this +
-                                               "\n  instruction: " + inst
-                                               );
-                if (inst instanceof Instruction.Tail) {
-                    requeueStageHasTailInstruction = true;
-                    return;
-                }
-                instructions.add(inst);
-            }
+            public void addDataFromFabric(Packet p) { addInstruction(p); }
         };
     public InterpreterDestination dataDestination = new InterpreterDestination(this) {
             public String toString() { return getDock()+""; }
@@ -102,6 +74,24 @@ class InterpreterDock extends FleetTwoDock {
     public int getInstructionFifoSize() { return Integer.MAX_VALUE; }
     public Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
 
+    boolean trace = false;
+
+    private void addInstruction(Packet p) {
+        if (p.isToken() ||
+            instructionsBackedUpIntoSwitchFabric.size()!=0 ||
+            requeueStageInCirculatingState ||
+            (p2i(p) instanceof Instruction.Tail)) {
+            instructionsBackedUpIntoSwitchFabric.add(p);
+        } else {
+            instructions.add(p2i(p));
+        }
+    }
+    
+    private Instruction p2i(Packet p) {
+        if (p.isToken()) throw new RuntimeException();
+        return getInterpreter().decodeInstruction(p.getValue(), InterpreterDock.this /* this is wrong, but harmless */);
+    }
+
     protected final void service() {
 
         if (dataReadyForShip || flushing) return;
@@ -109,10 +99,12 @@ class InterpreterDock extends FleetTwoDock {
 
         if (instructions.peek() instanceof Instruction.Head) {
             if (requeueStageInCirculatingState) { instructions.remove(); return; }
-            if (!requeueStageHasTailInstruction) return;
-            requeueStageHasTailInstruction = false;
-            requeueStageInCirculatingState = true;
-            instructions.remove();
+            Packet p = instructionsBackedUpIntoSwitchFabric.peek();
+            if (p!=null && !p.isToken() && p2i(p) instanceof Instruction.Tail) {
+                instructionsBackedUpIntoSwitchFabric.remove();
+                requeueStageInCirculatingState = true;
+                instructions.remove();
+            }
             return;
         }
 
@@ -128,11 +120,14 @@ class InterpreterDock extends FleetTwoDock {
 
                 if (ilc==0) { ilc = 1; break; }
 
-                if (move.interruptible && torpedoWaiting) {
-                    torpedoWaiting = false;
-                    ilc = 1;
-                    flag_d = true;
-                    break;
+                if (move.interruptible) {
+                    Packet p = instructionsBackedUpIntoSwitchFabric.peek();
+                    if (p!=null && p.isToken()) {
+                        instructionsBackedUpIntoSwitchFabric.remove();
+                        ilc = 1;
+                        flag_d = true;
+                        break;
+                    }
                 }
 
                 if (move.dataIn  && !isInputDock() && readyForDataFromShip)  return;
@@ -152,7 +147,7 @@ class InterpreterDock extends FleetTwoDock {
                     } else {
                         bv = new BitVector(getInterpreter().getWordWidth()).set(dataFromShip);
                         readyForDataFromShip = true;
-                        flag_c = flagCFromShip;
+                        if (move.latchData) flag_c = flagCFromShip;
                     }
                     if (move.latchData) dataLatch.set(bv);
                     if (move.latchPath) {
@@ -173,6 +168,11 @@ class InterpreterDock extends FleetTwoDock {
 
             } else if (instructions.peek() instanceof Instruction.Abort) {
                 requeueStageInCirculatingState = false;
+                LinkedList<Packet> temp = new LinkedList<Packet>();
+                while (instructionsBackedUpIntoSwitchFabric.size()!=0)
+                    temp.add(instructionsBackedUpIntoSwitchFabric.remove());
+                while (temp.size()!=0)
+                    addInstruction(temp.remove());
                 break;
 
             } else if (instructions.peek() instanceof Instruction.Flush) {
@@ -183,8 +183,9 @@ class InterpreterDock extends FleetTwoDock {
                 Instruction.Shift shift = (Instruction.Shift)instructions.peek();
                 for(int i=dataLatch.length()-1; i>=getShip().getFleet().getShiftWidth(); i--)
                     dataLatch.set(i, dataLatch.get(i-getShip().getFleet().getShiftWidth()));
+                BitVector shift_immediate = shift.immediate.getBitVector();
                 for(int i=getShip().getFleet().getShiftWidth()-1; i>=0; i--)
-                    dataLatch.set(i, shift.immediate.get(i));
+                    dataLatch.set(i, shift_immediate.get(i));
                 break;
 
             } else if (instructions.peek() instanceof Instruction.Set) {
@@ -211,7 +212,7 @@ class InterpreterDock extends FleetTwoDock {
                             case Immediate: olc = (int)set.immediate; break;
                             case DataLatch:
                                 olc = 0;
-                                for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_OLC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+                                for(int i=0; i<getShip().getFleet().getWordWidth(); i++)
                                     if (dataLatch.get(i))
                                         olc |= (1 << i);
                                 break;
@@ -255,12 +256,7 @@ class InterpreterDock extends FleetTwoDock {
     protected long peekDataForShip() {
         if (!dataReadyForShip)
             throw new RuntimeException("peekDataForShip() invoked when dataReadyForShip()==false");
-        BitVector bv = dataLatch;
-        long val = 0;
-        for(int i=0; i<bv.length(); i++)
-            if (bv.get(i))
-                val |= (1L << i);
-        return val;
+        return dataLatch.toLong();
     }
     protected void addDataFromShip(long data) { addDataFromShip(data, false); }
     protected void addDataFromShip(long data, boolean pending_flag_c) {
@@ -270,4 +266,39 @@ class InterpreterDock extends FleetTwoDock {
         dataFromShip = data;
         flagCFromShip = pending_flag_c;
     }
+
+
+    // Debugging //////////////////////////////////////////////////////////////////////////////
+
+    public void dumpState() {
+        if (instructions.size()==0 &&
+            dataPackets.size()==0 &&
+            instructionsBackedUpIntoSwitchFabric.size()==0 &&
+            !requeueStageInCirculatingState &&
+            !flushing &&
+            !dataReadyForShip &&
+            readyForDataFromShip)
+            return;
+        System.out.println("state of "+ANSI.green(this)+": "+
+                           (ilc==1?"":("[ilc="+(ilc==-1 ? "*" : (ilc+""))+"] "))+
+                           (olc==1?"":("[olc="+olc+"] "))+
+                           (flag_a?"[a] ":"")+
+                           (flag_b?"[b] ":"")+
+                           (flag_c?"[c] ":"")+
+                           (flag_d?"[d] ":"")+
+                           (requeueStageInCirculatingState?"[recirculating] ":"")+
+                           (flushing?"[flushing] ":"")
+                           );
+        if (!readyForDataFromShip)
+            System.out.println(ANSI.cyan("  ship has proffered: " + dataFromShip));
+        if (dataReadyForShip)
+            System.out.println(ANSI.cyan("  waiting for ship to accept: " + dataLatch.toLong()));
+        for(Instruction i : instructions)
+            System.out.println(ANSI.red("  "+i));
+        for(Packet i : instructionsBackedUpIntoSwitchFabric)
+            System.out.println(ANSI.red(ANSI.bold("  "+i+" BACKED UP")));
+        for(Packet p : dataPackets)
+            System.out.println(ANSI.cyan("  "+p));
+    }
+
 }