--- /dev/null
+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