added ies44 instruction encoder
authoradam <adam@megacz.com>
Mon, 5 Feb 2007 19:04:19 +0000 (20:04 +0100)
committeradam <adam@megacz.com>
Mon, 5 Feb 2007 19:04:19 +0000 (20:04 +0100)
src/edu/berkeley/fleet/ies44/InstructionEncoder.java [new file with mode: 0644]

diff --git a/src/edu/berkeley/fleet/ies44/InstructionEncoder.java b/src/edu/berkeley/fleet/ies44/InstructionEncoder.java
new file mode 100644 (file)
index 0000000..9fda1a0
--- /dev/null
@@ -0,0 +1,149 @@
+package edu.berkeley.fleet.ies44;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.*;
+import java.io.*;
+
+public abstract class InstructionEncoder {
+
+    /** get the bits describing this box's location on the DESTINATION HORN */
+    public abstract long getBoxAddr(BenkoBox box);
+
+    /** get the bits describing this box's location on the INSTRUCTION HORN */
+    public abstract long getBoxInstAddr(BenkoBox box);
+
+    /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
+    public abstract BenkoBox getBoxByAddr(long dest);
+
+    /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
+    public abstract BenkoBox getBoxByInstAddr(long dest);
+
+    /** read a machine-formatted instruction from a file (into a Java object) */
+    public Instruction readInstruction(DataInputStream is) 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);
+        } catch (EOFException eof) {
+            return null;
+        }
+    }
+
+    public Instruction readInstruction(long instr) {
+        long inst = instr;
+        long head = inst & (0x3L << (24+11));
+        head = head >> (24+11);
+        switch((int)head) {
+            case 0: {
+                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
+                BenkoBox dest = getBoxByAddr    ((inst >>  1) & 0x7ff);
+                int count        = ((int)(instr >> 12)) & 0x7f;
+                boolean tokenIn  = (instr & (1L << (11+1+7+0))) != 0;
+                boolean dataIn   = ( instr & (1L << (11+1+7+1))) != 0;
+                boolean latch    = (  instr & (1L << (11+1+7+2))) != 0;
+                boolean dataOut  = (instr & (1L << (11+1+7+3))) != 0;
+                boolean tokenOut = (instr & (1L << (11+1+7+4))) != 0;
+                boolean recycle  = (instr & (1L)) != 0;
+                if (latch & !dataIn) return new Instruction.Kill(name, count);
+                return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
+                                                  latch, dataOut, tokenOut, recycle);
+            }
+
+            case 1: {
+                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
+                int offset = ((int)(instr >> 6)) & ~(0xffffffff << 18);
+                if ((offset & (1<<17)) != 0) offset |= (0xffffffff << 18);
+                int size   = ((int)(instr     )) & ~(0xffffffff << 6);
+                return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
+            }
+
+            case 2: {
+                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
+                int val   = ((int)(instr     )) & ~(0xffffffff << 24);
+                return new Instruction.Literal.Absolute(name, val);
+            }
+
+            case 3: {
+                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
+                int val   = ((int)(instr     )) & ~(0xffffffff << 24);
+                return new Instruction.Literal.Relative(name, val);
+            }
+
+        }
+        return null;
+
+    }
+
+    public long writeInstruction(Instruction d) {
+        long instr = 0;
+
+        // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
+        if (d instanceof Instruction.Kill) {
+            Instruction.Kill k = (Instruction.Kill)d;
+            d = new Instruction.Executable(k.benkoBox, null, k.count, false, false, true, false, false, false);
+        }
+
+        if (d instanceof Instruction.Executable) {
+            Instruction.Executable inst = (Instruction.Executable)d;
+            BenkoBox dest = inst.dest;
+            instr = dest==null ? 0 : (getBoxAddr(dest) << 1);
+            if (inst.count >= (1<<8))
+                throw new RuntimeException("count field must be less than 128");
+            instr |= (((long)inst.count) << (11+1));
+            if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
+            if (inst.dataIn)   instr |= (1L << (11+1+7+1));
+            if (inst.latch)    instr |= (1L << (11+1+7+2));
+            if (inst.dataOut)  instr |= (1L << (11+1+7+3));
+            if (inst.tokenOut) instr |= (1L << (11+1+7+4));
+            if (inst.recycle)  instr |= (1L);
+            instr |= (getBoxInstAddr(inst.benkoBox) << (11+5+7+1));
+
+        } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
+            Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
+            instr = (1L << (11+24));
+            if (lc.dest != null)
+                instr |= (getBoxAddr(lc.dest)) << 24;
+            if (lc.size >= (1<<6))
+                throw new RuntimeException("codebag sizes must be less than 2^6");
+            if (lc.offset >= (1<<17) || lc.offset <= (-1 * (1<<17)))
+                throw new RuntimeException("codebag offsets must be in the range -(2^17)..2^17");
+            int off = (int)lc.offset;
+            off &= ~(0xffffffff << 18);
+            instr |= (off << 6);
+            instr |= (((long)lc.size));
+
+        } else if (d instanceof Instruction.Literal.Absolute) {
+            Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
+            instr = (2L << (11+24));
+            instr |= (getBoxAddr(ld.dest)) << 24;
+            if (ld.value >= (1<<25))
+                throw new RuntimeException("literals must be less than 2^24");
+            instr |= ((long)ld.value);
+
+        } else if (d instanceof Instruction.Literal.Relative) {
+            Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
+            instr = (3L << (11+24));
+            instr |= (getBoxAddr(lr.dest)) << 24;
+            if (lr.offset >= (1<<25))
+                throw new RuntimeException("literals must be less than 2^24");
+            instr |= ((long)lr.offset);
+            
+        }
+        return instr;
+    }
+
+    public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
+        long instr = writeInstruction(d);
+        os.write((int)((instr >> (5*8)) & 0xff));
+        os.write((int)((instr >> (4*8)) & 0xff));
+        os.write((int)((instr >> (3*8)) & 0xff));
+        os.write((int)((instr >> (2*8)) & 0xff));
+        os.write((int)((instr >> (1*8)) & 0xff));
+        os.write((int)((instr >> (0*8)) & 0xff));
+   }
+
+}
\ No newline at end of file