implement support (fpga+interp+test) for massacre instruction
[fleet.git] / src / edu / berkeley / fleet / api / Instruction.java
index 5e3c106..f021242 100644 (file)
@@ -2,78 +2,107 @@ package edu.berkeley.fleet.api;
 
 public abstract class Instruction {
 
-    public static class Kill extends Instruction {
-
-        public final BenkoBox benkoBox;
-        public final int      count;
-        public final boolean  killOnlyStandingInstructions;
-        public Kill(BenkoBox benkoBox, int count, boolean killOnlyStandingInstructions) {
-            this.benkoBox=benkoBox;
-            this.count=count;
-            this.killOnlyStandingInstructions = killOnlyStandingInstructions;
+    public final Pump pump;
+    public Instruction(Pump pump) { this.pump = pump; }
+    public String toString() { return pump+": "; }
+
+    public static abstract class CountingInstruction extends Instruction {
+        public final int count;
+        public CountingInstruction(Pump pump, int count) {
+            super(pump);
+            this.count = count;
         }
-        public String toString() { return (count>1 ? "["+count+"] " : "") + "kill"; }
+        public boolean isStanding() { return count==0; }
+        public abstract boolean isRequeueing();
+        public String toString() { return super.toString()+(count==1?"":(isRequeueing()?("("+(count==0?"*":(count+""))+")"):("["+(count==0?"*":(count+""))+"]")))+" "; }
+    }
 
+    public static class UnClog extends Instruction {
+        public UnClog(Pump pump) { super(pump); }
+        public String toString() { return super.toString() + "unclog;"; }
     }
 
-    public static class Executable extends Instruction {
+    public static class Massacre extends Instruction {
+        public Massacre(Pump pump) { super(pump); }
+    }
 
-        public final BenkoBox benkoBox;
-        public final BenkoBox dest;
-        public final int      count;
+    public static class Clog extends Executable {
+        public Clog(Pump pump) { super(pump, 1); }
+        public String toString() { return super.toString() + "clog;"; }
+        public Instruction.Executable decrementCount() { return null; }
+        public boolean isRequeueing() { return false; }
+    }
 
-        public final boolean  tokenIn;
-        public final boolean  dataIn;
-        public final boolean  latch;
-        public final boolean  dataOut;
-        public final boolean  tokenOut;
-        public final boolean  recycle;
+    public static class Kill extends CountingInstruction {
+        public Kill(Pump pump, int count) { super(pump, count); }
+        public boolean isRequeueing() { return false; }
+        public String toString() { return super.toString() + "kill;"; }
+    }
+
+    public static abstract class Executable extends CountingInstruction {
+        public Executable(Pump pump, int count) { super(pump, count); }
+        public abstract Instruction.Executable decrementCount();
+    }
+
+    public static class Move extends Executable {
+        public final Destination dest;
+
+        public final boolean     tokenIn;
+        public final boolean     dataIn;
+        public final boolean     latch;
+        public final boolean     dataOutDest;
+        public final boolean     dataOut;
+        public final boolean     tokenOut;
+        public final boolean     requeue;
+        public final boolean     ignoreUntilLast;
+
+        public boolean isRequeueing() { return requeue; }
 
         /** count=0 denotes a standing move */
-        public Executable(BenkoBox benkoBox,
-                          BenkoBox dest,
-                          int      count,
-                          boolean  tokenIn,
-                          boolean  dataIn,
-                          boolean  latch,
-                          boolean  dataOut,
-                          boolean  tokenOut,
-                          boolean  recycle) {
-            this.benkoBox = benkoBox;
+        public Move(Pump        pump,
+                          Destination dest,
+                          int         count,
+                          boolean     tokenIn,
+                          boolean     dataIn,
+                          boolean     latch,
+                          boolean     dataOutDest,
+                          boolean     dataOut,
+                          boolean     tokenOut,
+                          boolean     requeue,
+                          boolean     ignoreUntilLast) {
+            super(pump, count);
             this.dest = dest;
-            this.count = count;
             this.tokenIn = tokenIn;
             this.dataIn = dataIn;
             this.latch = latch;
+            this.dataOutDest = dataOutDest;
             this.dataOut = dataOut;
             this.tokenOut = tokenOut;
-            this.recycle = recycle;
+            this.requeue = requeue;
+            this.ignoreUntilLast = ignoreUntilLast;
             if (count < 0)
                 throw new RuntimeException("count field of an instruction must be >=0");
-        }
-
-        public boolean isStanding() {
-            return count==0;
+            if (pump.isInbox() && tokenIn && dataIn)
+                throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
+            if (pump.isOutbox() && tokenOut && dataOut)
+                throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
+            if (latch && !dataIn)
+                throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
         }
 
         public Instruction.Executable decrementCount() {
             if (count==1) return null;
-            return new Executable(benkoBox, dest, count==0 ? 0 : count-1,
-                                  tokenIn, dataIn, latch, dataOut, tokenOut, recycle);
+            return new Move(pump, dest, count==0 ? 0 : count-1,
+                            tokenIn, dataIn, latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast);
         }
 
         public String toString() {
-            String ret = benkoBox.toString() + ": ";
-            if (count==0 || count>1 || recycle) {
-                ret += recycle ? "(" : "[";
-                if (count>1) ret += count;
-                if (count==0) ret += "*";
-                ret += recycle ? ")" : "] ";
-            }
+            // FIXME
+            String ret = super.toString();
             boolean needcomma = false;
             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
             if (dataIn && latch)  {
-                if (benkoBox instanceof BenkoBox.Inbox)
+                if (pump.isInbox())
                     ret += (needcomma ? ", " : "") + "receive";
                 else
                     ret += (needcomma ? ", " : "") + "take";
@@ -81,7 +110,7 @@ public abstract class Instruction {
             }
             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
             if (dataOut)  {
-                if (benkoBox instanceof BenkoBox.Inbox || dest==null)
+                if (pump.isInbox() || dest==null)
                     ret += (needcomma ? ", " : "") + "deliver";
                 else
                     ret += (needcomma ? ", " : "") + "sendto "+dest;
@@ -93,40 +122,33 @@ public abstract class Instruction {
 
     }
 
-    public static class Literal extends Instruction {
-        public final BenkoBox dest;
-        protected Literal(BenkoBox dest) { this.dest = dest; }
-
-        public static class Absolute extends Literal {
-            public final long value;
-            public Absolute(BenkoBox dest, long value) { super(dest); this.value = value; }
-            public String toString() {
-                return value + ": sendto " + dest;
-            }
+    public static class LocalLiteral extends Executable {
+        public final long literal;
+        public boolean isRequeueing() { return true; }
+        public LocalLiteral(Pump pump, long literal, int count) {
+            super(pump, count);
+            this.literal = literal;
         }
-
-        public static class Relative extends Literal {
-            /** value transmitted will be offset plus the address from which this instruction was loaded */
-            public final long offset;
-            public Relative(BenkoBox dest, long offset) { super(dest); this.offset = offset; }
-            public String toString() {
-                String off = ""+offset;
-                if (offset > 0) off = "+"+off;
-                return "(@"+offset+"): sendto " + dest;
-            }
+        public Instruction.Executable decrementCount() {
+            if (count==1) return null;
+            return new LocalLiteral(pump, literal, count-1);
         }
+    }
 
-        public static class CodeBagDescriptor extends Literal {
-            /** address of CBD, relative to address that this instruction was loaded from */
-            public final long offset;
-            public final long size;
-            public CodeBagDescriptor(BenkoBox dest, long offset, long size) {
-                super(dest); this.offset = offset; this.size = size; }
-            public String toString() {
-                String off = ""+offset;
-                if (offset > 0) off = "+"+off;
-                return "(@"+off+":"+size+"): sendto " + dest;
-            }
+    public static class CodeBagDescriptor extends Instruction {
+        /** address of CBD, relative to address that this instruction was loaded from */
+        public final long offset;
+        public final long size;
+        public CodeBagDescriptor(Pump pump, long offset, long size) {
+            super(pump);
+            this.offset = offset;
+            this.size = size;
+        }
+        public String toString() {
+            String off = ""+offset;
+            if (offset > 0) off = "+"+off;
+            return "(CBD @"+off+"+"+size+"): sendto " + pump;
         }
     }
+
 }