make getDestAddr() return a BitVector
[fleet.git] / src / edu / berkeley / fleet / interpreter / InterpreterDock.java
index a0e8dc5..d1c6968 100644 (file)
 package edu.berkeley.fleet.interpreter;
-import edu.berkeley.fleet.api.*;
-import edu.berkeley.fleet.api.Dock;
-import edu.berkeley.fleet.two.*;
 import java.util.*;
+import edu.berkeley.sbp.util.ANSI;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction;
+import static edu.berkeley.fleet.api.Predicate.*;
 
+/** anything that has a source (instruction horn) address on the switch fabric */
+class InterpreterDock extends FleetTwoDock {
 
-/** anything that has a destination address on the switch fabric */
-public abstract class InterpreterDock extends FleetTwoDock {
-        
-    private final InterpreterShip ship;
-    private final Destination[] ports;
-    private final int addr = max_addr++;
+    // Dock State //////////////////////////////////////////////////////////////////////////////
     
-    public InterpreterDock(InterpreterShip ship, String[] ports, DockDescription bbd) {
-        super(ship, bbd);
-        this.ship = ship;
-        this.ports = new Destination[ports.length];
-        for(int i=0; i<ports.length; i++)
-            this.ports[i] =
-                new InterpreterDockDestination(ports[i], this, false);
-    }
+    public boolean flag_a = false;
+    public boolean flag_b = false;
+    public boolean flag_c = false;
+    public int ilc = 1;
+    public int olc = 1;
+    public BitVector dataLatch = new BitVector(getShip().getFleet().getWordWidth());
+    public InterpreterPath pathLatch = null;
+    public InterpreterPath tapl = null;
+    public boolean hatchIsOpen = true;
+    private Instruction executing = null;
+    private Queue<Instruction> instructions = new LinkedList<Instruction>();
+    private Queue<Instruction> epilogue = new LinkedList<Instruction>();
+    private boolean dataReadyForShip = false;
+    private boolean readyForDataFromShip = true;
+    private long dataFromShip;
+    private boolean torpedoWaiting = false;
 
-    public Path getPath(Destination d, BitVector signal) {
-        throw new RuntimeException();
+    protected void reset() {
+        ilc = 1;
+        olc = 1;
+        flag_a = false;
+        flag_b = false;
+        flag_c = false;
+        dataLatch = new BitVector(getShip().getFleet().getWordWidth());
+        pathLatch = null;
+        hatchIsOpen = true;
+        executing = null;
+        instructions.clear();
+        epilogue.clear();
+        dataReadyForShip = false;
+        readyForDataFromShip = true;
+        tapl = null;
+        torpedoWaiting = false;
     }
 
-    public Iterable<Destination> getDestinations() {
-        HashSet<Destination> ret = new HashSet<Destination>();
-        for(Destination d : ports) ret.add(d);
-        return ret;
+    // Destinations //////////////////////////////////////////////////////////////////////////////
+
+    /** includes the epilogue fifo */
+    public InterpreterDestination instructionDestination = new InterpreterDestination(this, true);
+    public InterpreterDestination dataDestination = new InterpreterDestination(this, false);
+
+    InterpreterDock(InterpreterShip ship, DockDescription bbd) {
+        super(ship, bbd);
     }
 
-    public Destination getInstructionDestination() {
-        return ports[0];
+    public Path getPath(Destination d, BitVector signal) { return new InterpreterPath(this, (InterpreterDestination)d, signal); }
+    public Destination getInstructionDestination() { return instructionDestination; }
+    public Destination getDataDestination() { return dataDestination; }
+    public int getInstructionFifoSize() { return Integer.MAX_VALUE; }
+    public Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
+
+    // interface to subclass ///////////////////////////////////////////////////////////////////////
+
+    /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
+
+    public boolean dataReadyForShip() { return dataReadyForShip; }
+    public final boolean readyForDataFromShip() { return readyForDataFromShip; }
+
+    public long removeDataForShip() {
+        long val = peekDataForShip();
+        dataReadyForShip = false;
+        return val;
     }
-    public Destination getDataDestination() {
-        return ports[0];
+    public long peekDataForShip() {
+        if (!dataReadyForShip) throw new RuntimeException();
+        BitVector bv = dataLatch;
+        long val = 0;
+        for(int i=0; i<bv.length(); i++)
+            if (bv.get(i))
+                val |= (1L << i);
+        return val;
+    }
+    public void addDataFromShip(long data) {
+        if (!readyForDataFromShip()) throw new RuntimeException();
+        readyForDataFromShip = false;
+        dataFromShip = data;
     }
 
+    protected final void service() {
 
-    /** adds the included datum to the port from the switch fabric  side */
-    public abstract void addDataFromFabric(Packet packet);
+        if (instructionDestination.packets.size() > 0) {
+            Packet p = instructionDestination.packets.remove();
+            if (p.isToken) {
+                if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
+                torpedoWaiting = true;
+            } else {
+                BitVector bv = p.value;
+                long val = 0;
+                for(int i=0; i<bv.length(); i++)
+                    if (bv.get(i))
+                        val |= (1L << i);
+                epilogue.add(getInterpreter().readInstruction(val, this));
+            }
+        }
 
-    abstract void service();
+        if (hatchIsOpen && epilogue.size() > 0) {
+            Instruction inst = epilogue.remove();
+            if (inst instanceof Instruction.Tail)
+                hatchIsOpen = false;
+            else
+                instructions.add(inst);
+        }
 
-    abstract void   shutdown();
+        if (dataReadyForShip) return;
 
-    public   Ship   getShip()                  { return ship; }
-    public   Fleet  getFleet()                 { return getShip().getFleet(); }
-    public   String toString()                 { return ship+"."+getName(); }
-    public   int    getInstructionFifoSize() { return 4; }
-    
-    Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
+        if (executing==null && instructions.size() > 0) executing = instructions.remove();
+        if (executing==null) return;
 
-    public long getDestAddr() { return addr; }
+        if (executing.looping && hatchIsOpen && olc>0) return;
 
-    private static int max_addr;
-    private class InterpreterDockDestination extends InterpreterDestination {
-        public String name;
-        public long addr = max_addr++;
-        public InterpreterDockDestination(String name, InterpreterDock id, boolean isInstructionDestination) {
-            super(id, isInstructionDestination);
-            this.name = name;
+        boolean enabled = true;
+        switch(executing.predicate) {
+            case IgnoreOLC:  enabled =  true;   break;
+            case Default:    enabled =  olc>0;  break;
+            case FlagA:      enabled =  flag_a; break;
+            case FlagB:      enabled =  flag_b; break;
+            case FlagC:      enabled =  flag_c; break;
+            case NotFlagA:   enabled = !flag_a; break;
+            case NotFlagB:   enabled = !flag_b; break;
+            case NotFlagC:   enabled = !flag_c; break;
+            default: throw new RuntimeException();
         }
-        public String getDestinationName()               { return name; }
-        public Ship getShip()                    { return InterpreterDock.this.getShip(); }
-        public void addDataFromFabric(Packet packet) { InterpreterDock.this.addDataFromFabric(packet); }
-        public String toString()                 { return getShip()+"."+getName(); }
-        public long getDestAddr() { return addr; }
+        if (!enabled) {
+            if (executing.looping && olc>0)
+                instructions.add(executing);
+            executing = null;
+            return;
+        }
+
+        if (executing instanceof Instruction.Move) {
+            Instruction.Move move = (Instruction.Move)executing;
+
+            if (move.interruptible && torpedoWaiting) {
+                torpedoWaiting = false;
+                executing = null;
+                ilc = 1;
+                olc = 0;
+                if (tapl != null)
+                    new Packet(tapl, new BitVector(getInterpreter().getWordWidth()), true).send();
+                hatchIsOpen = true;
+                return;
+            }
+
+            if (move.dataIn  && !isInputDock() && readyForDataFromShip) return;
+            if (move.dataIn  &&  isInputDock() && dataDestination.packets.size()==0) return;
+            if (move.tokenIn &&                   dataDestination.packets.size()==0) return;
+        }
+
+        if (executing.looping && olc>0)
+            instructions.add(executing);
+
+        if (executing instanceof Instruction.Shift) {
+            /*
+            Instruction.Shift shift = (Instruction.Shift)executing;
+            for(int i=dataLatch.length()-1; i>=getShip().getFleet().getShiftWidth(); i--)
+                dataLatch.set(i, dataLatch.get(i-getShip().getFleet().getShiftWidth()));
+            for(int i=getShip().getFleet().getShiftWidth()-1; i>=0; i--)
+                dataLatch.set(i, shift.immediate.get(i));
+            executing = null;
+            return;
+            */
+            throw new RuntimeException("FIXME");
+        }
+
+        if (executing instanceof Instruction.Set) {
+            Instruction.Set set = (Instruction.Set)executing;
+            switch(set.dest) {
+                case DataLatch:
+                    dataLatch = new BitVector(getInterpreter().getWordWidth()).setAndSignExtend(set.immediate);
+                    break;
+                case InnerLoopCounter:
+                    switch(set.source) {
+                        case Infinity:
+                            ilc = -1;
+                            break;
+                        case DataLatch:
+                            ilc = 0;
+                            for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_ILC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+                                if (dataLatch.get(i))
+                                    ilc |= (1 << i);
+                            break;
+                        case Immediate:
+                            ilc = (int)set.immediate;
+                            break;
+                        default:
+                            throw new RuntimeException("FIXME!");
+                    }
+                    break;
+                case OuterLoopCounter:
+                    switch(set.source) {
+                        case Decrement:
+                            olc = Math.max(0,olc-1);
+                            if (olc==0) hatchIsOpen = true;
+                            break;
+                        case DataLatch:
+                            olc = 0;
+                            for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_OLC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+                                if (dataLatch.get(i))
+                                    olc |= (1 << i);
+                            if (olc==0) hatchIsOpen = true;
+                            break;
+                        case Immediate:
+                            olc = (int)set.immediate;
+                            if (olc==0) hatchIsOpen = true;
+                            break;
+                        default:
+                            throw new RuntimeException("FIXME!");
+                    }
+                    break;
+
+                case Flags: {
+                    boolean new_flag_a = false;
+                    boolean new_flag_b = false;
+                    for(Predicate p : set.newFlagA)
+                        switch(p) {
+                            case FlagA: new_flag_a |= flag_a; break;
+                            case FlagB: new_flag_a |= flag_b; break;
+                            case FlagC: new_flag_a |= flag_c; break;
+                            case NotFlagA: new_flag_a |= !flag_a; break;
+                            case NotFlagB: new_flag_a |= !flag_b; break;
+                            case NotFlagC: new_flag_a |= !flag_c; break;
+                        }
+                    for(Predicate p : set.newFlagB)
+                        switch(p) {
+                            case FlagA: new_flag_b |= flag_a; break;
+                            case FlagB: new_flag_b |= flag_b; break;
+                            case FlagC: new_flag_b |= flag_c; break;
+                            case NotFlagA: new_flag_b |= !flag_a; break;
+                            case NotFlagB: new_flag_b |= !flag_b; break;
+                            case NotFlagC: new_flag_b |= !flag_c; break;
+                        }
+                    flag_a = new_flag_a;
+                    flag_b = new_flag_b;
+                    break;
+                }
+                default:
+                    throw new RuntimeException("FIXME!");
+            }
+            executing = null;
+            return;
+        }
+
+        Instruction.Move move = (Instruction.Move)executing;
+
+        // if ILC==0, don't even bother
+        if (ilc==0) { ilc = 1; executing = null; return; }
+
+        if (ilc==-1)     { }
+        else if (ilc==1) executing = null;
+        else             ilc--;
+
+        Packet p = null;
+        if (move.tokenIn) {
+            p = dataDestination.packets.remove();
+            if (p.path.signal != null) flag_c = p.path.signal.get(0);
+        }
+        if (move.dataIn) {
+            BitVector bv = null;
+            if (isInputDock()) {
+                p = dataDestination.packets.remove();
+                bv = new BitVector(p.value);
+                if (p.path.signal != null) flag_c = p.path.signal.get(0);
+            } else {
+                bv = new BitVector(getInterpreter().getWordWidth()).set(dataFromShip);
+                readyForDataFromShip = true;
+            }
+            if (move.latchData) dataLatch = bv;
+            if (move.latchPath)
+                pathLatch = (InterpreterPath)getInterpreter().getPathByAddr(this, ((FleetTwoFleet)getShip().getFleet()).DISPATCH_PATH.getvalAsBitVector(bv.toLong()));
+            // FIXME: c-flag at output docks
+        }
+
+        if (move.path != null) pathLatch = (InterpreterPath)move.path;
+
+        if (move.dataOut && isInputDock()) dataReadyForShip = true;
+        if (move.dataOut && !isInputDock())
+            new Packet(pathLatch, new BitVector(dataLatch), true).send();
+        if (move.tokenOut)
+            new Packet(pathLatch, new BitVector(getInterpreter().getWordWidth()), true).send();
+
+        return;
     }
 }