package edu.berkeley.fleet.ies44;
-import edu.berkeley.fleet.api.*;
-import edu.berkeley.fleet.*;
import java.io.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.util.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Instruction.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+
public abstract class InstructionEncoder {
- /** get the bits describing this box's location on the DESTINATION HORN */
- public abstract long getBoxAddr(Destination box);
+ 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 DISPATCH_PATH = new Mask("vvvvvvvvvvv..........................");
+ 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_NOT_C = new Mask(".............100.....................");
+ public static final Mask P_C = new Mask(".............101.....................");
+ public static final Mask P_OLC = 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("..................1..................");
+ public static final Mask DI = new Mask("...................1.................");
+ public static final Mask DC = new Mask("....................1................");
+ public static final Mask DO = new Mask(".....................1...............");
+ public static final Mask TO = new Mask("......................1..............");
+ public static final Mask PATH_IMMEDIATE = new Mask(".......................1vvvvvvvvvvvvv");
+ public static final Mask PATH_DATA = new Mask(".......................01............");
+ public static final Mask PATH_NOCHANGE = new Mask(".......................00............");
- /** get the bits describing this box's location on the INSTRUCTION HORN */
- public abstract long getBoxInstAddr(BenkoBox box);
+ public static final Mask SET = new Mask("................10...................");
- /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
- public abstract BenkoBox getBoxByAddr(long dest);
+ public static final Mask SET_OLC_FROM_IMMEDIATE = new Mask("................1010000100.....vvvvvv");
+ public static final Mask SET_OLC_FROM_DATA_LATCH = new Mask("................1010000010...........");
+ public static final Mask SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................1010000001...........");
+
+ public static final Mask SET_ILC_FROM_IMMEDIATE = new Mask("................1001000100.....vvvvvv");
+ public static final Mask SET_ILC_FROM_INFINITY = new Mask("................1001000010...........");
+ public static final Mask SET_ILC_FROM_DATA_LATCH = new Mask("................1001000001...........");
+
+ public static final Mask SET_IMMEDIATE = new Mask("................1000100.vvvvvvvvvvvvv");
+ public static final Mask SET_IMMEDIATE_EXTEND = new Mask("................1000100v.............");
+
+ public static final Mask SET_FLAGS = new Mask("................1000010..............");
+ public static final Mask SET_FLAGS_A = new Mask("................1000010..vvvvvv......");
+ public static final Mask SET_FLAGS_B = new Mask("................1000010........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 static final Mask SET_TAPL_FROM_IMMEDIATE = new Mask("................1000001.vvvvvvvvvvvvv");
+
+
+ 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) {
+ if ((immediate & ~mask) == 0) return true;
+ if ((immediate | mask) == -1L) return true;
+ return false;
+ }
+
+ /** get the bits describing this box's location on the DESTINATION HORN */
+ protected abstract long getDestAddr(Path box);
- /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
- public abstract BenkoBox getBoxByInstAddr(long dest);
+ /** decode a path, given the starting point and the bits that comprise it */
+ protected abstract Path getPathByAddr(Dock source, long dest);
+
+ /** FIXME: this is a hack for now */
+ protected abstract Dock getUniversalSource();
/** read a machine-formatted instruction from a file (into a Java object) */
- public Instruction readInstruction(DataInputStream is) throws IOException {
+ public Instruction readInstruction(Dock dispatchFrom, 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);
- return readInstruction(inst);
+ return readInstruction(dispatchFrom, 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, tokenIn);
- return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
- latch, dataOut, tokenOut, recycle);
- }
+ public Instruction readInstruction(Dock dispatchFrom, long inst) {
+ Dock dock = getPathByAddr(getUniversalSource(), DISPATCH_PATH.getval(inst)).getDestination().getDock();
- 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);
- }
+ if (TAIL.get(inst)) return new Tail(dock);
- case 2: {
- BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
- int val = ((int)(instr )) & ~(0xffffffff << 24);
- val = signExtend24(val);
- 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);
- }
+ Predicate predicate = Default;
+ if (P_ALWAYS.get(inst)) predicate = IgnoreOLC;
+ if (P_OLC.get(inst)) predicate = Default;
+ if (P_A.get(inst)) predicate = FlagA;
+ if (P_B.get(inst)) predicate = FlagB;
+ if (P_C.get(inst)) predicate = FlagC;
+ if (P_NOT_A.get(inst)) predicate = NotFlagA;
+ if (P_NOT_B.get(inst)) predicate = NotFlagB;
+ if (P_NOT_C.get(inst)) predicate = NotFlagC;
+ boolean looping = !OS.get(inst);
+ if (SHIFT.get(inst)) return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getWordWidth()).set(SHIFT.getval(inst)));
+ if (SET_IMMEDIATE.get(inst)) {
+ boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
+ long immediate = SET_IMMEDIATE.getval(inst);
+ if (extend) immediate |= (-1L << DataLatch_WIDTH);
+ return new Set(dock, looping, predicate, SetDest.DataLatch, (immediate));
}
- return null;
+ if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
+ return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
+ if (SET_OLC_FROM_IMMEDIATE.get(inst))
+ return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
+ if (SET_ILC_FROM_IMMEDIATE.get(inst))
+ return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
+ if (SET_OLC_FROM_DATA_LATCH.get(inst))
+ return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
+ if (SET_ILC_FROM_DATA_LATCH.get(inst))
+ return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
+ if (SET_ILC_FROM_INFINITY.get(inst))
+ return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
+ if (SET_FLAGS.get(inst)) {
+ long flag_a = SET_FLAGS_A.getval(inst);
+ long flag_b = SET_FLAGS_B.getval(inst);
+ FlagFunction ap = FlagFunction.ZERO;
+ FlagFunction bp = FlagFunction.ZERO;
+ if (SET_FLAGS_VALUE_A .get(flag_a)) ap = ap.add(FlagA );
+ if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
+ if (SET_FLAGS_VALUE_B .get(flag_a)) ap = ap.add(FlagB );
+ if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
+ if (SET_FLAGS_VALUE_C .get(flag_a)) ap = ap.add(FlagC );
+ if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
+ if (SET_FLAGS_VALUE_A .get(flag_b)) bp = bp.add(FlagA );
+ if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
+ if (SET_FLAGS_VALUE_B .get(flag_b)) bp = bp.add(FlagB );
+ if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
+ if (SET_FLAGS_VALUE_C .get(flag_b)) bp = bp.add(FlagC );
+ if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
+ return new Set(dock, looping, predicate, ap, bp);
+ }
+ if (SET_TAPL_FROM_IMMEDIATE.get(inst))
+ return new Set(dock, looping, predicate, SetDest.TAPL, getPathByAddr(dock, SET_TAPL_FROM_IMMEDIATE.getval(inst)));
+ if (MOVE.get(inst))
+ return new Move(dock,
+ looping,
+ predicate,
+ I.get(inst),
+ getPathByAddr(dock, PATH_IMMEDIATE.getval(inst)),
+ TI.get(inst),
+ DI.get(inst),
+ DC.get(inst),
+ PATH_DATA.get(inst),
+ DO.get(inst),
+ TO.get(inst)
+ );
+ throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
}
- public long writeInstruction(Instruction d) {
+ public long writeInstruction(Dock dispatchFrom, 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, k.killOnlyStandingInstructions,
- false, true, false, false, false);
+ if (d.dock != null)
+ instr = DISPATCH_PATH.setval(instr, getDestAddr(getUniversalSource().getPath(d.dock.getInstructionDestination(),null)));
+
+ boolean dl = false;
+ Instruction pi = d;
+ if (!pi.looping) instr = OS.set(instr);
+ switch(pi.predicate) {
+ case IgnoreOLC: instr = P_ALWAYS.set(instr); break;
+ case Default: instr = P_OLC.set(instr); break;
+ case FlagA: instr = P_A.set(instr); break;
+ case FlagB: instr = P_B.set(instr); break;
+ case FlagC: instr = P_C.set(instr); break;
+ case NotFlagA: instr = P_NOT_A.set(instr); break;
+ case NotFlagB: instr = P_NOT_B.set(instr); break;
+ case NotFlagC: instr = P_NOT_C.set(instr); break;
}
- if (d instanceof Instruction.Executable) {
- Instruction.Executable inst = (Instruction.Executable)d;
- Destination 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) & ~(0xffffffff << 24);
-
- } 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);
-
+ if (d instanceof Tail) {
+ instr = TAIL.set(instr);
+
+ } else if (d instanceof Shift) {
+ Shift shift = (Shift)d;
+ instr = SHIFT.set(instr);
+ instr = SHIFT.setval(instr, shift.immediate);
+
+ } else if (d instanceof Set) {
+ Set s = (Set)d;
+ switch(s.dest) {
+ case InnerLoopCounter:
+ switch(s.source) {
+ case DataLatch:
+ instr = SET_ILC_FROM_DATA_LATCH.set(instr);
+ break;
+ case Immediate:
+ instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
+ break;
+ case Infinity:
+ instr = SET_ILC_FROM_INFINITY.set(instr);
+ break;
+ }
+ break;
+ case OuterLoopCounter:
+ switch(s.source) {
+ case Decrement:
+ instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
+ break;
+ case DataLatch:
+ instr = SET_OLC_FROM_DATA_LATCH.set(instr);
+ break;
+ case Immediate:
+ instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
+ break;
+ }
+ break;
+ case TAPL: {
+ instr = SET_TAPL_FROM_IMMEDIATE.set(instr);
+ instr = SET_TAPL_FROM_IMMEDIATE.setval(instr, getDestAddr(s.path));
+ break;
+ }
+ case Flags: {
+ instr = SET_FLAGS.set(instr);
+ instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
+ instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
+ break;
+ }
+ case DataLatch: {
+ instr = SET_IMMEDIATE.set(instr);
+ instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
+ instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
+ break;
+ }
+ }
+
+ } else if (d instanceof Move) {
+ Move inst = (Move)d;
+ instr = MOVE.set(instr);
+ if (inst.tokenIn) instr = TI.set(instr);
+ if (inst.dataIn) instr = DI.set(instr);
+ 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.latchPath) instr = PATH_DATA.set(instr);
+ else {
+ instr = PATH_IMMEDIATE.set(instr);
+ instr = PATH_IMMEDIATE.setval(instr, inst.path==null?0:getDestAddr(inst.path));
+ }
+
+ } else {
+ throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
+
}
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));
- }
-
- public static int signExtend24(int val) {
- if ((val & (1 << 23)) != 0)
- val = val | (0xffffffff << 24);
- return val;
+ public void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction d) throws IOException {
+ long instr = writeInstruction(dispatchFrom, d);
+ for(int i=5; i>=0; i--)
+ os.write(BitManipulations.getIntField(i*8+7, i*8, instr));
}
-}
\ No newline at end of file
+ private static long flagFunctionToLong(FlagFunction ff) {
+ long ret = 0;
+ for(Predicate p : ff)
+ switch(p) {
+ case FlagA : ret = SET_FLAGS_VALUE_A .set(ret); break;
+ case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
+ case FlagB : ret = SET_FLAGS_VALUE_B .set(ret); break;
+ case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
+ case FlagC : ret = SET_FLAGS_VALUE_C .set(ret); break;
+ case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
+ default: throw new RuntimeException();
+ }
+ return ret;
+ }
+}