update internal encoding of Flush instruction
[fleet.git] / src / edu / berkeley / fleet / two / FleetTwoFleet.java
index e6af7f8..5482cbd 100644 (file)
@@ -10,73 +10,199 @@ import static edu.berkeley.fleet.api.Predicate.*;
 /** common subclass for the "FleetTwo" generation of processors, all 37-bit wide, with AM33 encoding */
 public abstract class FleetTwoFleet extends Fleet {
 
-    public static final Mask PACKET_TOKEN               = new Mask("v.................................................");
-    public static final Mask PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
-    public static final Mask PACKET_SIGNAL              = new Mask("......................................v...........");
-    public static final Mask PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
-
-    public static final Mask CBD_SIZE                   = new Mask("...............................vvvvvv");
-    public static final Mask CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
-
-    public static final int  WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
-    public static final int  WIDTH_PACKET               = PACKET_TOKEN.width;
-
-    public static final Mask WHOLE_WORD                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
-    public static final Mask DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
-    public static final Mask DISPATCH_INSTR             = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
-    public static final Mask I                          = new Mask("...........1.........................");
-    public static final Mask OS                         = new Mask("............1........................");
-    public static final Mask P                          = new Mask(".............vvv.....................");
-    public static final Mask P_NOT_A                    = new Mask(".............000.....................");
-    public static final Mask P_A                        = new Mask(".............001.....................");
-    public static final Mask P_NOT_B                    = new Mask(".............010.....................");
-    public static final Mask P_B                        = new Mask(".............011.....................");
-    public static final Mask P_UNUSED                   = new Mask(".............100.....................");
-    public static final Mask P_OLC_ZERO                 = new Mask(".............101.....................");
-    public static final Mask P_OLC_NONZERO              = new Mask(".............110.....................");
-    public static final Mask P_ALWAYS                   = new Mask(".............111.....................");
-
-    public static final Mask SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
-
-    public static final Mask TAIL                       = new Mask("................11...................");
-
-    public static final Mask MOVE                       = new Mask("................01...................");
-    public static final Mask TI                         = new Mask("................011..................");
-    public static final Mask DI                         = new Mask("................01.1.................");
-    public static final Mask FLUSH                      = new Mask("................01.01................");
-    public static final Mask DC                         = new Mask("................01.11................");
-    public static final Mask DO                         = new Mask("................01...1...............");
-    public static final Mask TO                         = new Mask("................01....1..............");
-    public static final Mask PATH_IMMEDIATE             = new Mask("................01.....1vvvvvvvvvvvvv");
-    public static final Mask PATH_DATA                  = new Mask("................01.....01............");
-    public static final Mask PATH_NOCHANGE              = new Mask("................01.....00............");
-
-    public static final Mask SET_OLC_FROM_IMMEDIATE     = new Mask("................101000100......vvvvvv");
-    public static final Mask SET_OLC_FROM_DATA_LATCH    = new Mask("................101000010............");
-    public static final Mask SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
-
-    public static final Mask SET_ILC_FROM_IMMEDIATE     = new Mask("................10010010......0vvvvvv");
-    public static final Mask SET_ILC_FROM_INFINITY      = new Mask("................10010010......1......");
-    public static final Mask SET_ILC_FROM_DATA_LATCH    = new Mask("................10010001.............");
-
-    public static final Mask SET_IMMEDIATE              = new Mask("................100010.vvvvvvvvvvvvvv");
-    public static final Mask SET_IMMEDIATE_EXTEND       = new Mask("................100010v..............");
-
-    public static final Mask SET_FLAGS                  = new Mask("................100001...............");
-    public static final Mask SET_FLAGS_A                = new Mask("................100001...vvvvvv......");
-    public static final Mask SET_FLAGS_B                = new Mask("................100001.........vvvvvv");
-    public static final Mask SET_FLAGS_VALUE_A          = new Mask("1.....");
-    public static final Mask SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
-    public static final Mask SET_FLAGS_VALUE_B          = new Mask("..1...");
-    public static final Mask SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
-    public static final Mask SET_FLAGS_VALUE_C          = new Mask("....1.");
-    public static final Mask SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
+    public final Mask PACKET_TOKEN;
+    public final Mask PACKET_DATA;
+    public final Mask PACKET_SIGNAL;
+    public final Mask PACKET_DEST;
+
+    public final Mask CBD_SIZE;
+    public final Mask CBD_OFFSET;
+
+    public final Mask WHOLE_WORD;
+    public final Mask DISPATCH_PATH;
+    public final Mask DISPATCH_INSTR;
+    public final Mask NOT_INTERRUPTIBLE;
+    public final Mask OS;
+    public final Mask P;
+    public final Mask P_NOT_A;
+    public final Mask P_A;
+    public final Mask P_NOT_B;
+    public final Mask P_B;
+    public final Mask P_UNUSED;
+    public final Mask P_OLC_ZERO;
+    public final Mask P_OLC_NONZERO;
+    public final Mask P_ALWAYS;
+
+    public final Mask SHIFT;
+
+    public final Mask TAIL;
+
+    public final Mask MOVE;
+    public final Mask TI;
+    public final Mask DI;
+    public final Mask FLUSH;
+    public final Mask DC;
+    public final Mask DO;
+    public final Mask TO;
+    public final Mask PATH_IMMEDIATE;
+    public final Mask PATH_DATA;
+    public final Mask PATH_NOCHANGE;
+
+    public final Mask SET_OLC_FROM_IMMEDIATE;
+    public final Mask SET_OLC_FROM_DATA_LATCH;
+    public final Mask SET_OLC_FROM_OLC_MINUS_ONE;
+
+    public final Mask SET_ILC_FROM_IMMEDIATE;
+    public final Mask SET_ILC_FROM_INFINITY;
+    public final Mask SET_ILC_FROM_DATA_LATCH;
+
+    public final Mask SET_IMMEDIATE;
+    public final Mask SET_IMMEDIATE_EXTEND;
+
+    public final Mask SET_FLAGS;
+    public final Mask SET_FLAGS_A;
+    public final Mask SET_FLAGS_B;
+    public final Mask SET_FLAGS_VALUE_A;
+    public final Mask SET_FLAGS_VALUE_NOT_A;
+    public final Mask SET_FLAGS_VALUE_B;
+    public final Mask SET_FLAGS_VALUE_NOT_B;
+    public final Mask SET_FLAGS_VALUE_C;
+    public final Mask SET_FLAGS_VALUE_NOT_C;
+
+    public final int  WIDTH_WORD;
+    public final int  WIDTH_PACKET;
+
+    public final long DataLatch_WIDTH;
+    private final long mask;
+
+    public FleetTwoFleet() { this(false); }
+
+    public FleetTwoFleet(boolean useInternalEncoding) {
+        PACKET_TOKEN               = new Mask("v.................................................");
+        PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
+        PACKET_SIGNAL              = new Mask("......................................v...........");
+        PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
+
+        CBD_SIZE                   = new Mask("...............................vvvvvv");
+        CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
+
+        WHOLE_WORD                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
+
+        if (useInternalEncoding) {
+
+            DISPATCH_PATH              = new Mask("v....................................");
+            DISPATCH_INSTR             = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
+            NOT_INTERRUPTIBLE          = new Mask(".................1...................");
+            OS                         = new Mask(".......1.............................");
+            P                          = new Mask(".vvvvvv..............................");
+            P_NOT_A                    = new Mask(".100001..............................");
+            P_A                        = new Mask(".100010..............................");
+            P_NOT_B                    = new Mask(".100100..............................");
+            P_B                        = new Mask(".101000..............................");
+            P_UNUSED                   = new Mask(".111111..............................");
+            P_OLC_ZERO                 = new Mask(".010000..............................");
+            P_OLC_NONZERO              = new Mask(".100000..............................");
+            P_ALWAYS                   = new Mask(".000000..............................");
+
+            SHIFT                      = new Mask("..........101111.1vvvvvvvvvvvvvvvvvvv");
+
+            TAIL                       = new Mask("................1....................");
+
+            MOVE                       = new Mask("..........110111.....................");
+            TI                         = new Mask("..........110111..1..................");
+            DI                         = new Mask("..........110111...1.................");
+            FLUSH                      = new Mask(".........1110111.....................");
+            DC                         = new Mask("..........110111...11................");
+            DO                         = new Mask("..........110111.....1...............");
+            TO                         = new Mask("..........110111......1..............");
+            PATH_IMMEDIATE             = new Mask("..........110111.......0vvvvvvvvvvvvv");
+            PATH_DATA                  = new Mask("..........110111.......11............");
+            PATH_NOCHANGE              = new Mask("..........110111.......10............");
+
+            SET_OLC_FROM_IMMEDIATE     = new Mask("..........111101.0.............vvvvvv");
+            SET_OLC_FROM_DATA_LATCH    = new Mask("..........111101.1...................");
+            SET_OLC_FROM_OLC_MINUS_ONE = new Mask("..........111011.....................");
+
+            SET_ILC_FROM_IMMEDIATE     = new Mask("..........011111.0...........0.vvvvvv");
+            SET_ILC_FROM_INFINITY      = new Mask("..........011111.............1.......");
+            SET_ILC_FROM_DATA_LATCH    = new Mask("..........011111.1...................");
+
+            SET_IMMEDIATE              = new Mask("..........101111.0.....vvvvvvvvvvvvvv");
+            SET_IMMEDIATE_EXTEND       = new Mask("..........101111.0....v..............");
+
+            SET_FLAGS                  = new Mask("..........111110.....................");
+            SET_FLAGS_A                = new Mask("..........111110...............vvvvvv");
+            SET_FLAGS_B                = new Mask("..........111110.........vvvvvv......");
+
+            SET_FLAGS_VALUE_A          = new Mask(".....1");
+            SET_FLAGS_VALUE_NOT_A      = new Mask("....1.");
+            SET_FLAGS_VALUE_B          = new Mask("...1..");
+            SET_FLAGS_VALUE_NOT_B      = new Mask("..1...");
+            SET_FLAGS_VALUE_C          = new Mask(".1....");
+            SET_FLAGS_VALUE_NOT_C      = new Mask("1.....");
+
+        } else {
+            DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
+            DISPATCH_INSTR             = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
+            NOT_INTERRUPTIBLE          = new Mask("...........1.........................");
+            OS                         = new Mask("............1........................");
+            P                          = new Mask(".............vvv.....................");
+            P_NOT_A                    = new Mask(".............000.....................");
+            P_A                        = new Mask(".............001.....................");
+            P_NOT_B                    = new Mask(".............010.....................");
+            P_B                        = new Mask(".............011.....................");
+            P_UNUSED                   = new Mask(".............100.....................");
+            P_OLC_ZERO                 = new Mask(".............101.....................");
+            P_OLC_NONZERO              = new Mask(".............110.....................");
+            P_ALWAYS                   = new Mask(".............111.....................");
+
+            SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
+
+            TAIL                       = new Mask("................11...................");
+
+            MOVE                       = new Mask("................01...................");
+            TI                         = new Mask("................011..................");
+            DI                         = new Mask("................01.1.................");
+            FLUSH                      = new Mask("................01.01................");
+            DC                         = new Mask("................01.11................");
+            DO                         = new Mask("................01...1...............");
+            TO                         = new Mask("................01....1..............");
+            PATH_IMMEDIATE             = new Mask("................01.....1vvvvvvvvvvvvv");
+            PATH_DATA                  = new Mask("................01.....01............");
+            PATH_NOCHANGE              = new Mask("................01.....00............");
+
+            SET_OLC_FROM_IMMEDIATE     = new Mask("................101000100......vvvvvv");
+            SET_OLC_FROM_DATA_LATCH    = new Mask("................101000010............");
+            SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
+
+            SET_ILC_FROM_IMMEDIATE     = new Mask("................10010010......0vvvvvv");
+            SET_ILC_FROM_INFINITY      = new Mask("................10010010......1......");
+            SET_ILC_FROM_DATA_LATCH    = new Mask("................10010001.............");
+
+            SET_IMMEDIATE              = new Mask("................100010.vvvvvvvvvvvvvv");
+            SET_IMMEDIATE_EXTEND       = new Mask("................100010v..............");
+
+            SET_FLAGS                  = new Mask("................100001...............");
+            SET_FLAGS_A                = new Mask("................100001...vvvvvv......");
+            SET_FLAGS_B                = new Mask("................100001.........vvvvvv");
+
+            SET_FLAGS_VALUE_A          = new Mask("1.....");
+            SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
+            SET_FLAGS_VALUE_B          = new Mask("..1...");
+            SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
+            SET_FLAGS_VALUE_C          = new Mask("....1.");
+            SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
+        }
+
+        WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
+        WIDTH_PACKET               = PACKET_TOKEN.width;
+        DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
+        mask  = ~(-1L << DataLatch_WIDTH);
+    }
 
     // Misc //////////////////////////////////////////////////////////////////////////////
 
-    public static final long DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
-    private static final long mask  = ~(-1L << DataLatch_WIDTH);
-    public static boolean isSmallEnoughToFit(long immediate) {
+    public boolean isSmallEnoughToFit(long immediate) {
         if ((immediate & ~mask) == 0)   return true;
         if ((immediate |  mask) == -1L) return true;
         return false;
@@ -87,49 +213,39 @@ public abstract class FleetTwoFleet extends Fleet {
     //////////////////////////////////////////////////////////////////////////////
 
     /** get the bits describing this box's location on the DESTINATION HORN */
-    // FIXME this should use a BitVector not a long!
-    protected abstract long getDestAddr(Path box);
+    protected abstract BitVector getDestAddr(Path box);
 
     private static final BitVector SIGNAL_ZERO = new BitVector(1);
-    private static final BitVector SIGNAL_ONE  = new BitVector(1);
-    static {
-        SIGNAL_ONE.set(0,true);
-    }
+    private static final BitVector SIGNAL_ONE  = new BitVector(1).set(0,true);
 
     /** decode a path, given the starting point and the bits that comprise it */
-    // FIXME this should use a BitVector not a long!
-    //protected abstract Path getPathByAddr(Dock source, long dest);
-    public Path getPathByAddr(Dock source, long dest) {
+    public Path getPathByAddr(Dock source, BitVector dest) {
         for(Ship ship : this)
             for(Dock bb : ship) {
                 for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) {
                     for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) {
                         Path p = (Path)source.getPath(d, signal);
-                        if (getDestAddr(p) == dest) return p;
+                        if (getDestAddr(p).equals(dest)) return p;
                     }
                 }
             }
         return null;
     }
 
-    /** read a machine-formatted instruction from a file (into a Java object) */
-    public Instruction readInstruction(DataInputStream is, Dock dispatchFrom) throws IOException {
-        long inst = 0;
-        try {
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            inst = (inst << 8) | (is.readByte() & 0xff);
-            return readInstruction(inst, dispatchFrom);
-        } catch (EOFException eof) {
-            return null;
-        }
+    public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) {
+        return readInstruction(instruction.toLong(), dispatchFrom);
     }
 
+    public BitVector   encodeInstruction(Instruction instr, Dock dispatchFrom) {
+        return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom));
+    }
+
+    public int getShiftWidth() { return SHIFT.valmaskwidth; }
+    public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; }
+
+    // FIXME: should use BitVector here
     public Instruction readInstruction(long inst, Dock dispatchFrom) {
-        Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getval(inst)).getDestination().getDock();
+        Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock();
 
         if (TAIL.get(inst))   return new Tail(dock);
 
@@ -145,7 +261,7 @@ public abstract class FleetTwoFleet extends Fleet {
         boolean looping = !OS.get(inst);
         if (FLUSH.get(inst))
             return new Flush(dock, looping, predicate);
-        if (SHIFT.get(inst))                return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getWordWidth()).set(SHIFT.getval(inst)));
+        if (SHIFT.get(inst))                return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst)));
         if (SET_IMMEDIATE.get(inst)) {
             boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
             long immediate = SET_IMMEDIATE.getval(inst);
@@ -188,8 +304,8 @@ public abstract class FleetTwoFleet extends Fleet {
             return new Move(dock,
                             looping,
                             predicate,
-                            I.get(inst),
-                            getPathByAddr(dock, PATH_IMMEDIATE.getval(inst)),
+                            !NOT_INTERRUPTIBLE.get(inst),
+                            getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)),
                             TI.get(inst),
                             DI.get(inst),
                             DC.get(inst),
@@ -200,11 +316,17 @@ public abstract class FleetTwoFleet extends Fleet {
         throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
     }
 
+    // FIXME: should use BitVector here
     public long writeInstruction(Instruction d, Dock dispatchFrom) {
         long instr = 0;
 
-        if (d.dock != null)
-            instr = DISPATCH_PATH.setval(instr, getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null)));
+        if (d.dock != null) {
+            BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null));
+            BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth);
+            for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
+                bv2.set(i, bv.get(i));
+            instr = DISPATCH_PATH.setval(instr, bv2);
+        }
 
         boolean dl = false;
         Instruction pi = d;
@@ -282,12 +404,18 @@ public abstract class FleetTwoFleet extends Fleet {
             if (inst.latchData)                  instr = DC.set(instr);
             if (inst.dataOut)                    instr = DO.set(instr);
             if (inst.tokenOut)                   instr = TO.set(instr);
-            if (inst.interruptible)              instr = I.set(instr);
+            if (!inst.interruptible)             instr = NOT_INTERRUPTIBLE.set(instr);
 
             if (inst.latchPath)                  instr = PATH_DATA.set(instr);
             else {
                 instr  = PATH_IMMEDIATE.set(instr);
-                instr  = PATH_IMMEDIATE.setval(instr, inst.path==null?0:getDestAddr(inst.path));
+                if (inst.path != null) {
+                    BitVector bv  = getDestAddr(inst.path);
+                    BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
+                    for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
+                        bv2.set(i, bv.get(i));
+                    instr  = PATH_IMMEDIATE.setval(instr, bv2);
+                }
             }
 
         } else {
@@ -297,13 +425,7 @@ public abstract class FleetTwoFleet extends Fleet {
         return instr;
     }
 
-    public void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction d) throws IOException {
-        long instr = writeInstruction(d, dispatchFrom);
-        for(int i=5; i>=0; i--)
-            os.write(BitManipulations.getIntField(i*8+7, i*8, instr));
-    }
-
-    private static long flagFunctionToLong(FlagFunction ff) {
+    private long flagFunctionToLong(FlagFunction ff) {
         long ret = 0;
         for(Predicate p : ff)
             switch(p) {