add support for predicates to parser and interpreter
authoradam <adam@megacz.com>
Mon, 11 Feb 2008 15:04:56 +0000 (16:04 +0100)
committeradam <adam@megacz.com>
Mon, 11 Feb 2008 15:04:56 +0000 (16:04 +0100)
src/edu/berkeley/fleet/api/Instruction.java
src/edu/berkeley/fleet/assembler/Parser.java
src/edu/berkeley/fleet/assembler/fleet.g
src/edu/berkeley/fleet/ies44/InstructionEncoder.java
src/edu/berkeley/fleet/interpreter/InstructionPump.java

index 9a1cb08..788a3a1 100644 (file)
@@ -32,7 +32,27 @@ public abstract class Instruction {
         public String toString() { return super.toString() + "kill"+(count==1?"":(" "+count))+";"; }
     }
 
-    public static class SetFlags extends Instruction {
+    public static class PredicatedInstruction extends Instruction {
+        public static final int P_ALWAYS = 0x0001;
+        public static final int P_IF_A   = 0x0002;
+        public static final int P_IF_B   = 0x0003;
+        public static final int P_IF_Z   = 0x0004;
+
+        public final int predicate;
+        public PredicatedInstruction(Pump pump) { super(pump); this.predicate = P_ALWAYS; }
+        public PredicatedInstruction(Pump pump, int predicate) { super(pump); this.predicate = predicate; }
+        public String toString() {
+            switch(predicate) {
+                case P_ALWAYS: return        super.toString();
+                case P_IF_A:   return "[a] "+super.toString();
+                case P_IF_B:   return "[b] "+super.toString();
+                case P_IF_Z:   return "[z] "+super.toString();
+            }
+            throw new Error();
+        }
+    }
+
+    public static class SetFlags extends PredicatedInstruction {
         public static final int FLAG_Z     = 0x0001;
         public static final int FLAG_NOT_Z = 0x0002;
         public static final int FLAG_S     = 0x0004;
@@ -44,11 +64,12 @@ public abstract class Instruction {
 
         public final int flag_a;
         public final int flag_b;
-        public SetFlags(Pump pump, int flag_a, int flag_b) {
-            super(pump);
+        public SetFlags(Pump pump, int predicate, int flag_a, int flag_b) {
+            super(pump, predicate);
             this.flag_a = flag_a;
             this.flag_b = flag_b;
         }
+        public SetFlags(Pump pump, int flag_a, int flag_b) { this(pump, P_ALWAYS, flag_a, flag_b); }
 
         public boolean isLooping() { return true; }
         private String printFlag(int flag) {
@@ -73,20 +94,22 @@ public abstract class Instruction {
         }
     }
 
-    public static class DecrLoop extends Instruction {
+    public static class DecrLoop extends PredicatedInstruction {
         public DecrLoop(Pump pump) { super(pump); }
+        public DecrLoop(Pump pump, int predicate) { super(pump, predicate); }
         public boolean isDL() { return true; }
         public boolean isLooping() { return true; }
     }
 
-    public static class Counter extends Instruction {
+    public static class Counter extends PredicatedInstruction {
         public static final int DATA_LATCH = -1;
         public static final int REPEAT_COUNTER = -2;
         public static final int LOOP_COUNTER = -3;
         public final int source;
         public final int dest;
-        public Counter(Pump pump, int source, int dest) {
-            super(pump);
+        public Counter(Pump pump, int source, int dest) { this(pump, P_ALWAYS, source, dest); }
+        public Counter(Pump pump, int predicate, int source, int dest) {
+            super(pump, predicate);
             this.source = source;
             this.dest = dest;
         }
@@ -111,7 +134,7 @@ public abstract class Instruction {
         public boolean isLooping() { return true; }
     }
 
-    public static class Move extends Instruction {
+    public static class Move extends PredicatedInstruction {
         public final Destination dest;
 
         public final boolean     tokenIn;
@@ -126,17 +149,18 @@ public abstract class Instruction {
 
         /** count=0 denotes a standing move */
         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);
+                    int         predicate,
+                    Destination dest,
+                    int         count,
+                    boolean     tokenIn,
+                    boolean     dataIn,
+                    boolean     latch,
+                    boolean     dataOutDest,
+                    boolean     dataOut,
+                    boolean     tokenOut,
+                    boolean     requeue,
+                    boolean     ignoreUntilLast) {
+            super(pump, predicate);
             this.dest = dest;
             this.tokenIn = tokenIn;
             this.dataIn = dataIn;
@@ -199,11 +223,12 @@ public abstract class Instruction {
     }
     */
 
-    public static class HalfLiteral extends Instruction {
+    public static class HalfLiteral extends PredicatedInstruction {
         public final long literal;
         public final boolean high;
         public boolean isRequeueing() { return true; }
-        public HalfLiteral(Pump pump, long literal, int count, boolean high) {
+        public HalfLiteral(Pump pump, long literal, int count, boolean high) { this(pump, P_ALWAYS, literal, count, high); }
+        public HalfLiteral(Pump pump, int predicate, long literal, int count, boolean high) {
             super(pump);
             this.literal = literal;
             this.high = high;
@@ -211,12 +236,14 @@ public abstract class Instruction {
         public boolean isLooping() { return true; }
     }
 
-    public static class CodeBagDescriptor extends Instruction {
-        /** address of CBD, relative to address that this instruction was loaded from */
+
+    public static class CodeBagDescriptor extends PredicatedInstruction {
+        // 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);
+        public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, P_ALWAYS, offset, size); }
+        public CodeBagDescriptor(Pump pump, int predicate, long offset, long size) {
+            super(pump, predicate);
             this.offset = offset;
             this.size = size;
         }
index 05c5aaa..9a0ebaf 100644 (file)
@@ -275,6 +275,11 @@ public class Parser {
             
             OUTER: for(Tree tt : t.child(1)) {
                 int count = 1;
+                int predicate = Instruction.PredicatedInstruction.P_ALWAYS;
+                if ("[a]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_A;
+                if ("[b]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_B;
+                if ("[z]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_Z;
+                tt = tt.child(1);
                 if ("unclog".equals(tt.head()))    {
                     cb.add(new Instruction.UnClog(pump));
                     continue;
@@ -383,9 +388,9 @@ public class Parser {
                     else if ("notify".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
                     else if ("notifyLast".equals(ttt.head()))     { tokenOut = true; ignoreUntilLast = true; dest = portReference(ttt.child(0)); }
                 }
-                    cb.add(new Instruction.Move(pump,
-                                                dest, count, tokenIn, dataIn,
-                                                latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
+                cb.add(new Instruction.Move(pump, Instruction.PredicatedInstruction.P_ALWAYS,
+                                            dest, count, tokenIn, dataIn,
+                                            latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
             }
         }
     }
index bfe6a3b..b674b3a 100644 (file)
@@ -11,8 +11,11 @@ CodeBagBody::   = (Fiber | CodeBagDef) */ ws
 CodeBagDef::    = CodeBagName ":" "{" CodeBagBody "}" /ws
 Fiber::         = Pump        ":" Instructions        /ws
 
+// FIXME: should not have predicates on clog/unclog/kill/massacre
 Instructions::  = Instruction +/ ws
-Instruction     = ^"unclog"                          ";" /ws
+Instruction::   = Predicate InstructionX
+Predicate       = "" | ^"[a]" ws | ^"[b]" ws | ^"[z]" ws
+InstructionX    = ^"unclog"                          ";" /ws
                 | ^"clog"                            ";" /ws
                 | ^"massacre"                        ";" /ws
                 | ^"kill"                            ";" /ws
index 97f11ef..cbe8c76 100644 (file)
@@ -106,6 +106,7 @@ public abstract class InstructionEncoder {
         boolean standing    = STAND.get(inst);
         boolean dataOutDest = PATH_DATA.get(inst);
         return new Instruction.Move(name,
+                                    Instruction.PredicatedInstruction.P_ALWAYS,  /* FIXME */
                                     dest,
                                     standing?0:1,
                                     tokenIn,
index 498a14c..8e7fd82 100644 (file)
@@ -80,55 +80,69 @@ abstract class InstructionPump extends InterpreterPump {
         if (executing==null && instructions.size() > 0) executing = instructions.remove();
         if (executing==null) return;
 
-        int oldLoopCounter = loopCounter;
-        if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1);
-
-        if (executing instanceof Instruction.Counter) {
-            Instruction.Counter ic = (Instruction.Counter)executing;
-            if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
-                setDataLatch(oldLoopCounter); /* FIXME: which is correct here? */
-            } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
-                loopCounter = (int)peekDataLatch();
-            } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
-                repeatCounter = (int)peekDataLatch();
-            } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
-                loopCounter = ic.source;
-            } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
-                repeatCounter = ic.source;
-            }
-
-        } else if (executing instanceof Instruction.DecrLoop) {
-
-        } else if (executing instanceof Instruction.SetFlags) {
-            Instruction.SetFlags sf = (Instruction.SetFlags)executing;
-            boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0;
-            boolean old_z = oldLoopCounter == 0;
-            boolean old_a = flag_a;
-            boolean old_b = flag_b;
-            flag_a =
-                (((sf.flag_a & sf.FLAG_A)     != 0) ?  old_a : false) |
-                (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
-                (((sf.flag_a & sf.FLAG_B)     != 0) ?  old_b : false) |
-                (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
-                (((sf.flag_a & sf.FLAG_Z)     != 0) ?  old_z : false) |
-                (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
-                (((sf.flag_a & sf.FLAG_S)     != 0) ?  old_s : false) |
-                (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false);
-            flag_b =
-                (((sf.flag_b & sf.FLAG_A)     != 0) ?  old_a : false) |
-                (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
-                (((sf.flag_b & sf.FLAG_B)     != 0) ?  old_b : false) |
-                (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
-                (((sf.flag_b & sf.FLAG_Z)     != 0) ?  old_z : false) |
-                (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
-                (((sf.flag_b & sf.FLAG_S)     != 0) ?  old_s : false) |
-                (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false);
-        } else if (executing instanceof Instruction.Clog) {
+        if (executing instanceof Instruction.Clog) {
             clogged++;
             executing = null;
             return;
-        } else {
-            if (!service(executing)) return;
+        }
+
+        boolean enabled = true;
+        if (executing instanceof Instruction.PredicatedInstruction) {
+            Instruction.PredicatedInstruction ip = (Instruction.PredicatedInstruction)executing;
+            switch(ip.predicate) {
+                case Instruction.PredicatedInstruction.P_ALWAYS: enabled = true; break;
+                case Instruction.PredicatedInstruction.P_IF_A:   enabled = flag_a; break;
+                case Instruction.PredicatedInstruction.P_IF_B:   enabled = flag_b; break;
+                case Instruction.PredicatedInstruction.P_IF_Z:   enabled = loopCounter==0; break;
+            }
+        }
+
+        int oldLoopCounter = loopCounter;
+        if (enabled) {
+            if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1);
+
+            if (executing instanceof Instruction.Counter) {
+                Instruction.Counter ic = (Instruction.Counter)executing;
+                if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
+                    setDataLatch(oldLoopCounter); /* FIXME: which is correct here? */
+                } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
+                    loopCounter = (int)peekDataLatch();
+                } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
+                    repeatCounter = (int)peekDataLatch();
+                } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
+                    loopCounter = ic.source;
+                } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
+                    repeatCounter = ic.source;
+                }
+
+            } else if (executing instanceof Instruction.SetFlags) {
+                Instruction.SetFlags sf = (Instruction.SetFlags)executing;
+                boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0;
+                boolean old_z = oldLoopCounter == 0;
+                boolean old_a = flag_a;
+                boolean old_b = flag_b;
+                flag_a =
+                    (((sf.flag_a & sf.FLAG_A)     != 0) ?  old_a : false) |
+                    (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+                    (((sf.flag_a & sf.FLAG_B)     != 0) ?  old_b : false) |
+                    (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+                    (((sf.flag_a & sf.FLAG_Z)     != 0) ?  old_z : false) |
+                    (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+                    (((sf.flag_a & sf.FLAG_S)     != 0) ?  old_s : false) |
+                    (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false);
+                flag_b =
+                    (((sf.flag_b & sf.FLAG_A)     != 0) ?  old_a : false) |
+                    (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+                    (((sf.flag_b & sf.FLAG_B)     != 0) ?  old_b : false) |
+                    (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+                    (((sf.flag_b & sf.FLAG_Z)     != 0) ?  old_z : false) |
+                    (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+                    (((sf.flag_b & sf.FLAG_S)     != 0) ?  old_s : false) |
+                    (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false);
+            } else if (executing instanceof Instruction.DecrLoop) {
+            } else {
+                if (!service(executing)) return;
+            }
         }
 
         if (executing==null) return;