implement support (fpga+interp+test) for massacre instruction
[fleet.git] / src / edu / berkeley / fleet / ies44 / InstructionEncoder.java
index 722338b..7a3d3cd 100644 (file)
@@ -2,26 +2,69 @@ package edu.berkeley.fleet.ies44;
 import edu.berkeley.fleet.api.*;
 import edu.berkeley.fleet.*;
 import java.io.*;
-import static edu.berkeley.fleet.ies44.BitManipulations.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
 
 public abstract class InstructionEncoder {
 
-    public static final int WIDTH_WORD          = 37;   /* word width */
-    public static final int WIDTH_CODEBAG_SIZE  = 6;
-    public static final int WIDTH_PUMP_ADDR     = 11;
-    public static final int WIDTH_DEST_ADDR     = 11;
-    public static final int WIDTH_COUNT         = 7;
-
-    public static final int OFFSET_COUNT        = 0;
-    public static final int OFFSET_DEST         = OFFSET_COUNT+WIDTH_COUNT;
-    public static final int OFFSET_CONTROL      = OFFSET_DEST+WIDTH_DEST_ADDR;
-    public static final int OFFSET_RQ           = OFFSET_CONTROL+0;
-    public static final int OFFSET_TO           = OFFSET_CONTROL+1;
-    public static final int OFFSET_DO           = OFFSET_CONTROL+2;
-    public static final int OFFSET_DL           = OFFSET_CONTROL+3;
-    public static final int OFFSET_DI           = OFFSET_CONTROL+4;
-    public static final int OFFSET_TI           = OFFSET_CONTROL+5;
-    public static final int OFFSET_PUMP_ADDR    = OFFSET_TI+1;
+    public static final int WIDTH_WORD             = 37;   /* word width */
+    public static final int WIDTH_CODEBAG_SIZE     = 6;
+    public static final int WIDTH_PUMP_ADDR        = 11;
+    public static final int WIDTH_DEST_ADDR        = 11;
+    public static final int WIDTH_COUNT            = 7;
+
+    public static final int OFFSET_MASK_LITERAL    = 24;
+    public static final int WIDTH_MASK_LITERAL     = 2;
+    public static final int MASK_LITERAL           = 1;
+    /*
+    public static final int OFFSET_MASK_LITERAL    = 20;
+    public static final int WIDTH_MASK_LITERAL     = 6;
+    public static final int MASK_LITERAL           = 13;
+    */
+
+    public static final int OFFSET_MASK_MASSACRE   = 14;
+    public static final int WIDTH_MASK_MASSACRE    = 26-14;
+    public static final int MASK_MASSACRE          = 1;
+
+    //public static final int OFFSET_MASK_KILL       = 21;
+    //public static final int WIDTH_MASK_KILL        = 5;
+    //public static final int MASK_KILL              = 5;
+    public static final int OFFSET_MASK_KILL       = 14;
+    public static final int WIDTH_MASK_KILL        = 26-14;
+    public static final int MASK_KILL              = 0;
+
+    //public static final int OFFSET_MASK_UNCLOG     = 21;
+    //public static final int WIDTH_MASK_UNCLOG      = 5;
+    //public static final int MASK_UNCLOG            = 2;
+    public static final int OFFSET_MASK_UNCLOG     = 14;
+    public static final int WIDTH_MASK_UNCLOG      = 26-14;
+    public static final int MASK_UNCLOG            = 3;
+
+    //public static final int OFFSET_MASK_CLOG       = 21;
+    //public static final int WIDTH_MASK_CLOG        = 5;
+    //public static final int MASK_CLOG              = 4;
+    public static final int OFFSET_MASK_CLOG       = 14;
+    public static final int WIDTH_MASK_CLOG        = 26-14;
+    public static final int MASK_CLOG              = 2;
+
+    public static final int OFFSET_MASK_NORMAL     = 25;
+    public static final int WIDTH_MASK_NORMAL      = 1;
+    public static final int MASK_NORMAL            = 1;
+
+    public static final int OFFSET_COUNT           = 0;
+    public static final int OFFSET_DEST            = OFFSET_COUNT+WIDTH_COUNT;
+    public static final int OFFSET_CONTROL         = OFFSET_DEST+WIDTH_DEST_ADDR;
+    public static final int OFFSET_RQ              = OFFSET_CONTROL+0;
+    public static final int OFFSET_IG              = OFFSET_CONTROL+1;
+    public static final int OFFSET_TO              = OFFSET_CONTROL+2;
+    public static final int OFFSET_DO              = OFFSET_CONTROL+3;
+    public static final int OFFSET_DL              = OFFSET_CONTROL+4;
+    public static final int OFFSET_DI              = OFFSET_CONTROL+5;
+    public static final int OFFSET_TI              = OFFSET_CONTROL+6;
+    public static final int OFFSET_INSTRUCTIONTYPE = OFFSET_CONTROL+7;
+    public static final int OFFSET_PUMP_ADDR       = OFFSET_INSTRUCTIONTYPE+1;
+
+    public static final int OFFSET_LITERAL         = OFFSET_COUNT+WIDTH_COUNT;
+    public static final int WIDTH_LITERAL          = OFFSET_MASK_LITERAL - OFFSET_LITERAL;
 
     /** get the bits describing this box's location on the DESTINATION HORN */
     protected abstract long getDestAddr(Destination box);
@@ -51,60 +94,82 @@ public abstract class InstructionEncoder {
         }
     }
 
-    public Instruction readInstruction(long instr) {
-        long inst = instr;
-        switch((int)getField(WIDTH_WORD-1, WIDTH_WORD-2, inst)) {
-            case 0: {
-                Pump name    = getBoxByInstAddr(getIntField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, inst));
-                Destination dest = getDestByAddr   (getIntField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,      inst));
-                int count        = getIntField(                 OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,     inst);
-                boolean tokenIn     = getBit(OFFSET_TI, instr);
-                boolean dataIn      = getBit(OFFSET_DI, instr);
-                boolean latch       = getBit(OFFSET_DL, instr);
-                boolean dataOut     = getBit(OFFSET_DO, instr);
-                boolean tokenOut    = getBit(OFFSET_TO, instr);
-                boolean requeue     = getBit(OFFSET_RQ, instr);
-                boolean dataOutDest = dataOut && tokenOut;
-                if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
-                return new Instruction.Executable(name, dest, count, tokenIn, dataIn, latch, dataOutDest,
-                                                  dataOut, tokenOut, requeue);
-            }
-
-            case 1: {
-                Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, inst));
-                long offset = getSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, WIDTH_CODEBAG_SIZE, instr);
-                long size   = getSignedField(WIDTH_CODEBAG_SIZE-1,        0,                 instr);
-                return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
-            }
+    public Instruction readInstruction(long inst) {
+        Pump name           = getBoxByInstAddr(getIntField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, inst));
+        if (getIntField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG,inst)==MASK_UNCLOG)
+            return new Instruction.UnClog(name);
+        if (getIntField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG,inst)==MASK_CLOG)
+            return new Instruction.Clog(name);
+        if (getIntField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE,inst)==MASK_MASSACRE)
+            return new Instruction.Massacre(name);
+        int count           = getIntField(                 OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,     inst);
+        if (getIntField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL,inst)==MASK_KILL)
+            return new Instruction.Kill(name, count);
+        Destination dest    = getDestByAddr   (getIntField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,      inst));
+        boolean tokenIn     = getBit(OFFSET_TI, inst);
+        boolean dataIn      = getBit(OFFSET_DI, inst);
+        boolean latch       = getBit(OFFSET_DL, inst);
+        boolean dataOut     = getBit(OFFSET_DO, inst);
+        boolean tokenOut    = getBit(OFFSET_TO, inst);
+        boolean requeue     = getBit(OFFSET_RQ, inst);
+        boolean ignoreUntilLast = getBit(OFFSET_IG, inst);
+        boolean dataOutDest = name.isOutbox() && dataOut && tokenOut;
+        boolean isLiteral   = getIntField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL, inst)==MASK_LITERAL;
+        if (isLiteral)
+            return new Instruction.LocalLiteral(name, getSignedField(OFFSET_LITERAL+WIDTH_LITERAL-1, OFFSET_LITERAL, inst), 0);
+        if (dataOutDest) tokenOut = false;
+        return new Instruction.Move(name,
+                                    dest,
+                                    count,
+                                    tokenIn,
+                                    dataIn,
+                                    latch,
+                                    dataOutDest,
+                                    dataOut,
+                                    tokenOut,
+                                    requeue,
+                                    ignoreUntilLast);
+    }
 
-            case 2: {
-                Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_PUMP_ADDR+1, inst));
-                return new Instruction.Literal.Absolute(name, getSignedField(WIDTH_WORD-3-WIDTH_PUMP_ADDR, 0, instr));
-            }
+    public long writeInstruction(Instruction d) {
+        long instr = 0;
 
-            case 3: {
-                Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_PUMP_ADDR+1, inst));
-                return new Instruction.Literal.Relative(name, getSignedField(WIDTH_WORD-3-WIDTH_PUMP_ADDR, 0, instr));
-            }
+        if (d.pump != null)
+            instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, getBoxInstAddr(d.pump));
 
+        if (d instanceof Instruction.CodeBagDescriptor) {
+            Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
+            d = new Instruction.LocalLiteral(lc.pump, ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1);
         }
-        return null;
 
-    }
+        if (d instanceof Instruction.UnClog) {
+            instr |= putField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG,       MASK_UNCLOG);
 
-    public long writeInstruction(Instruction d) {
-        long instr = 0;
-
-        // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
-        if (d instanceof Instruction.Kill) {
+        } else if (d instanceof Instruction.Kill) {
             Instruction.Kill k = (Instruction.Kill)d;
-            d = new Instruction.Executable(k.pump, null, k.count, k.killOnlyStandingInstructions,
-                                           false, true, false, false, false, false);
-        }
+            instr |= putField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL,       MASK_KILL);
+            instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,           k.count-1);
+
+        } else if (d instanceof Instruction.Clog) {
+            instr |= putField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG,       MASK_CLOG);
+
+        } else if (d instanceof Instruction.Massacre) {
+            instr |= putField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE,       MASK_MASSACRE);
+
+        } else if (d instanceof Instruction.LocalLiteral) {
+            Instruction.LocalLiteral inst = (Instruction.LocalLiteral)d;
+            if (inst.pump != null) {
+                instr |= putField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL,    MASK_LITERAL);
+                instr |= putSignedField(OFFSET_LITERAL+WIDTH_LITERAL-1,           OFFSET_LITERAL,         inst.literal);
+                // FIXME remove soon
+                //instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,               OFFSET_COUNT,           inst.count);
+            } else {
+                instr = inst.literal;
+            }
 
-        if (d instanceof Instruction.Executable) {
-            Instruction.Executable inst = (Instruction.Executable)d;
-            instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR,   getBoxInstAddr(inst.pump));
+        } else if (d instanceof Instruction.Move) {
+            Instruction.Move inst = (Instruction.Move)d;
+            instr |= putField(OFFSET_MASK_NORMAL+WIDTH_MASK_NORMAL-1, OFFSET_MASK_NORMAL,       MASK_NORMAL);
             instr |= putField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,        inst.dest==null?0:getDestAddr(inst.dest));
             instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,       inst.count);
             instr |= putField(OFFSET_TI,                          OFFSET_TI,          inst.tokenIn?1:0);
@@ -113,26 +178,8 @@ public abstract class InstructionEncoder {
             instr |= putField(OFFSET_DO,                          OFFSET_DO,          (inst.dataOutDest||inst.dataOut)?1:0);
             instr |= putField(OFFSET_TO,                          OFFSET_TO,          (inst.dataOutDest||inst.tokenOut)?1:0);
             instr |= putField(OFFSET_RQ,                          OFFSET_RQ,          inst.requeue?1:0);
+            instr |= putField(OFFSET_IG,                          OFFSET_IG,          inst.ignoreUntilLast?1:0);
 
-        } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
-            Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
-            instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 1);
-            if (lc.dest != null) instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(lc.dest));
-            instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, WIDTH_CODEBAG_SIZE, lc.offset);
-            instr |= putField(WIDTH_CODEBAG_SIZE-1,        0,                 lc.size);
-
-        } else if (d instanceof Instruction.Literal.Absolute) {
-            Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
-            instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 2);
-            instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(ld.dest));
-            instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, 0, ld.value);
-
-        } else if (d instanceof Instruction.Literal.Relative) {
-            Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
-            instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 3);
-            instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(lr.dest));
-            instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, 0, lr.offset);
-            
         }
         return instr;
     }