utilize DeferredBitVector functionality in Fleet implementations
[fleet.git] / src / edu / berkeley / fleet / api / Instruction.java
index 963e57b..a9698ed 100644 (file)
@@ -7,24 +7,23 @@ public abstract class Instruction {
     /** the dock which is to execute this instruction */
     public final Dock      dock;
 
-    /** true if the instruction is an outer-looping instruction */
-    public final boolean   looping;
-
     /** the instruction's predicate */
     public final Predicate predicate;
 
-    Instruction(Dock dock, boolean looping, Predicate predicate) {
+    Instruction(Dock dock, Predicate predicate) {
         if (dock==null)      throw new RuntimeException("dock may not be null");
         if (predicate==null) throw new RuntimeException("predicate may not be null");
         this.dock = dock;
-        this.looping = looping;
         this.predicate = predicate;
     }
 
+    //public abstract Instruction withLooping(boolean newLooping);
+    //public abstract Instruction withPredicate(Predicate newPredicate);
+
     public String toString() {
         String s = predicate.toString();
         if (s.length()>0) s = "["+s+"] ";
-        return s+dock+": ";
+        return dock+": "+s;
     }
 
     /**
@@ -48,9 +47,6 @@ public abstract class Instruction {
         /** if <tt>source</tt> is <tt>Immediate</tt>, this is the immediate value; an integer */
         public final long           immediate;
 
-        /** if <tt>source</tt> is <tt>ImmediatePath</tt>, this is the immediate path */
-        public final Path           path;
-
         /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "a" */
         public final FlagFunction   newFlagA;
 
@@ -58,8 +54,9 @@ public abstract class Instruction {
         public final FlagFunction   newFlagB;
 
         /** basic constructor */
-        public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, SetSource source) {
-            super(dock, looping, predicate);
+        public Set(Dock dock, SetDest dest, SetSource source) { this(dock, Predicate.Default, dest, source); }
+        public Set(Dock dock, Predicate predicate, SetDest dest, SetSource source) {
+            super(dock, predicate);
             OUTER: switch(dest) {
                 case InnerLoopCounter:
                     switch(source) {
@@ -78,55 +75,41 @@ public abstract class Instruction {
             this.source = source;
             this.dest = dest;
             this.immediate = 0;
-            this.path = null;
             this.newFlagA = null;
             this.newFlagB = null;
         }
 
         /** constructor for set instructions with immediates */
-        public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, long immediate) {
-            super(dock, looping, predicate);
+        public Set(Dock dock, SetDest dest, long immediate) { this(dock, Predicate.Default, dest, immediate); }
+        public Set(Dock dock, Predicate predicate, SetDest dest, long immediate) {
+            super(dock, predicate);
             if (dest!=SetDest.InnerLoopCounter && dest!=SetDest.OuterLoopCounter && dest!=SetDest.DataLatch)
                 throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate");
             this.source = SetSource.Immediate;
             this.dest = dest;
             this.immediate = immediate;
-            this.path = null;
-            this.newFlagA = null;
-            this.newFlagB = null;
-        }
-
-        /** constructor for set instructions with immediate paths */
-        public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, Path path) {
-            super(dock, looping, predicate);
-            if (dest!=SetDest.TAPL)
-                throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate path");
-            this.source = SetSource.ImmediatePath;
-            this.dest = dest;
-            this.immediate = 0;
-            this.path = path;
             this.newFlagA = null;
             this.newFlagB = null;
         }
 
         /** constructor for <tt>set flags</tt> instructions */
-        public Set(Dock dock, boolean looping, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) {
-            super(dock, looping, predicate);
+        public Set(Dock dock, FlagFunction newFlagA, FlagFunction newFlagB) { this(dock, Predicate.Default, newFlagA, newFlagB); }
+        public Set(Dock dock, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) {
+            super(dock, predicate);
             this.source = SetSource.Immediate;
             this.dest = SetDest.Flags;
             this.immediate = 0;
-            this.path = null;
             this.newFlagA = newFlagA;
             this.newFlagB = newFlagB;
         }
 
         /** possible sources for the Set instruction */
         public static enum SetSource {
-            Infinity, DataLatch, Immediate, ImmediatePath, Decrement;
+            Infinity, DataLatch, Immediate, Decrement;
         }
         /** possible destinations for the Set instruction */
         public static enum SetDest {
-            InnerLoopCounter, OuterLoopCounter, TAPL, Flags, DataLatch;
+            InnerLoopCounter, OuterLoopCounter, Flags, DataLatch;
         }
 
         /**
@@ -199,25 +182,31 @@ public abstract class Instruction {
                     }
                 return ret.toString();
             }
+
+            public boolean evaluate(boolean flag_a, boolean flag_b, boolean flag_c, boolean olc_zero) {
+                boolean ret = false;
+                for(Predicate p : this)
+                    ret |= p.evaluate(flag_a, flag_b, flag_c, olc_zero);
+                return ret;
+            }
         }
 
         public String toString() {
             switch(dest) {
                 case InnerLoopCounter:
                     switch(source) {
-                        case Infinity: return super.toString()+"set ilc=*";
-                        case DataLatch: return super.toString()+"set ilc=data";
-                        case Immediate: return super.toString()+"set ilc="+immediate;
+                        case Infinity: return super.toString()+"set ilc=*;";
+                        case DataLatch: return super.toString()+"set ilc=data;";
+                        case Immediate: return super.toString()+"set ilc="+immediate+";";
                     }
                 case OuterLoopCounter:
                     switch(source) {
-                        case Decrement: return super.toString()+"set olc--";
-                        case DataLatch: return super.toString()+"set olc=data";
-                        case Immediate: return super.toString()+"set olc="+immediate;
+                        case Decrement: return super.toString()+"set olc--;";
+                        case DataLatch: return super.toString()+"set olc=data;";
+                        case Immediate: return super.toString()+"set olc="+immediate+";";
                     }
-                case TAPL: return super.toString()+"set tapl="+path;
-                case Flags: return super.toString()+"set flags a="+newFlagA+" b="+newFlagB;
-                case DataLatch: return super.toString()+"set data="+immediate;
+                case Flags: return super.toString()+"set flags a="+newFlagA+", b="+newFlagB+";";
+                case DataLatch: return super.toString()+"set word="+immediate+";";
             }
             throw new Error("impossible");
         }
@@ -225,13 +214,32 @@ public abstract class Instruction {
 
     /** shifts an immediate into the low-order bits of the data latch */
     public static class Shift extends Instruction {
-        public final BitVector immediate;
-        public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) {
-            super(dock, looping, predicate);
-            this.immediate = immediate;
-            this.immediate.setImmutable();
+        public final DeferredBitVector immediate;
+        public Shift(Dock dock, DeferredBitVector immediate) { this(dock, Predicate.Default, immediate); }
+        public Shift(final Dock dock, Predicate predicate, final DeferredBitVector arg) {
+            super(dock, predicate);
+            this.immediate = new DeferredBitVector() {
+                    public BitVector getBitVector() {
+                        BitVector ret = arg.getBitVector();
+                        if (ret.length() != dock.getShip().getFleet().getShiftWidth())
+                            throw new RuntimeException("attempt to create a Shift instruction with a "+ret.length()+
+                                                       "-bit immediate on a Fleet that uses "+dock.getShip().getFleet().getShiftWidth()+
+                                                       "-bit shift instructions");
+                        return ret;
+                    }
+                };
         }
-        public String toString() { return super.toString()+"shift "+immediate; }
+        public String toString() { return super.toString()+"shift "+immediate.getBitVector(); }
+    }
+
+    /** a flush instruction */
+    public static class Flush extends Instruction {
+        public Flush(Dock dock) { this(dock, Predicate.Default); }
+        public Flush(Dock dock, Predicate predicate) {
+            super(dock, predicate);
+            if (!dock.isInputDock()) throw new RuntimeException("Flush is only allowed at input docks");
+        }
+        public String toString() { return super.toString()+"flush;"; }
     }
 
     /** all communication is performed with this instruction */
@@ -262,7 +270,16 @@ public abstract class Instruction {
         public final boolean     tokenOut;
 
         public Move(Dock        dock,
-                    boolean     looping,
+                    Path        path,
+                    boolean     tokenIn,
+                    boolean     dataIn,
+                    boolean     latchData,
+                    boolean     latchPath,
+                    boolean     dataOut,
+                    boolean     tokenOut
+                    ) {
+            this(dock, Predicate.Default, false, path, tokenIn, dataIn, latchData, latchPath, dataOut, tokenOut); }
+        public Move(Dock        dock,
                     Predicate   predicate,
                     boolean     interruptible,
                     Path        path,
@@ -273,7 +290,7 @@ public abstract class Instruction {
                     boolean     dataOut,
                     boolean     tokenOut
                     ) {
-            super(dock, looping, predicate);
+            super(dock, predicate);
             this.path = path;
             this.tokenIn = tokenIn;
             this.dataIn = dataIn;
@@ -283,9 +300,9 @@ public abstract class Instruction {
             this.tokenOut = tokenOut;
             this.interruptible = interruptible;
             if (dock != null && dock.isInputDock() && tokenIn && dataIn)
-                throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an input dock: " + this);
+                throw new RuntimeException("cannot have two \"recv\"s: " + this);
             if (dock != null && dock.isOutputDock() && tokenOut && dataOut)
-                throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an output dock: " + this);
+                throw new RuntimeException("cannot have two \"send\"s: " + this);
             if (latchData && !dataIn)
                 throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this);
             if (latchPath && !dataIn)
@@ -296,26 +313,48 @@ public abstract class Instruction {
 
         public String toString() {
             StringBuffer ret = new StringBuffer();
-            if (tokenIn)                        ret.append(", wait");
+            if (tokenIn)                        ret.append(", recv token");
             if (dataIn) {
-                if (latchPath)                  ret.append(dock.isInputDock() ? ", collect path" : ", recv path");
-                if (latchData)                  ret.append(dock.isInputDock() ? ", collect"      : ", recv");
-                if (!latchPath && !latchData)   ret.append(", discard");
+                if      (latchPath && latchData) ret.append(!dock.isInputDock() ? ", collect packet"  : ", recv packet");
+                if      (latchPath)              ret.append(!dock.isInputDock() ? ", collect path"    : ", recv path");
+                else if (latchData)              ret.append(!dock.isInputDock() ? ", collect"         : ", recv");
+                else                             ret.append(!dock.isInputDock() ? ", collect nothing" : ", recv nothing");
             }
             if (dataOut && dock.isInputDock())  ret.append(", deliver");
-            if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send"  : "sendto "  + path);
-            if (tokenOut)                       ret.append(path==null ? ", token" : "tokento " + path);
+            if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send"  : ", send to "  + pathToString(path));
+            if (tokenOut)                       ret.append(path==null ? ", token" : ", send token to " + pathToString(path));
             String s = ret.toString();
             s = s.equals("") ? "nop" : s.substring(2);
-            if (interruptible) s = "[i] " + s;
-            return super.toString()+s;
+            if (interruptible) s = "[T] " + s;
+            return super.toString()+s+";";
+        }
+
+        private String pathToString(Path path) {
+            BitVector signal = path.getSignal();
+            if (signal!=null)
+                for(int i=0; i<signal.length(); i++)
+                    if (signal.get(i))
+                        return (path.getDestination()+":"+signal.toLong());
+            return (path.getDestination()+"");
         }
     }
 
+    /** a flush instruction */
+    public static class Abort extends Instruction {
+        public Abort(Dock dock, Predicate predicate) { super(dock, predicate); }
+        public String toString() { return super.toString()+"abort;"; }
+    }
+
+    /** marks the start of a loop; closes the hatch */
+    public static class Head extends Instruction {
+        public Head(Dock dock) { super(dock, Predicate.IgnoreFlagD); }
+        public String toString() { return dock+": head;"; }
+    }
+
     /** marks the end of a loop; closes the hatch */
     public static class Tail extends Instruction {
-        public Tail(Dock dock) { super(dock, false, Predicate.IgnoreOLC); }
-        public String toString() { return super.toString() + "tail;"; }
+        public Tail(Dock dock) { super(dock, Predicate.IgnoreFlagD); }
+        public String toString() { return dock+": tail;"; }
     }
 
 }