package edu.berkeley.fleet.ies44;
-import edu.berkeley.fleet.api.*;
-import edu.berkeley.fleet.*;
import java.io.*;
-import static edu.berkeley.fleet.util.BitManipulations.*;
+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 {
- 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_KILL = 21;
- public static final int WIDTH_MASK_KILL = 5;
- public static final int MASK_KILL = 5;
-
- 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_CLOG = 21;
- public static final int WIDTH_MASK_CLOG = 5;
- public static final int MASK_CLOG = 4;
-
- 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;
+ 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............");
+
+ public static final Mask SET = new Mask("................10...................");
+
+ 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(Destination box);
+ protected abstract long getDestAddr(Path box);
- /** get the bits describing this box's location on the INSTRUCTION HORN */
- protected abstract long getBoxInstAddr(Pump box);
+ /** decode a path, given the starting point and the bits that comprise it */
+ protected abstract Path getPathByAddr(Dock source, long dest);
- /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
- protected abstract Pump getBoxByInstAddr(long dest);
-
- /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
- protected abstract Destination getDestByAddr(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 inst) {
- 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, 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 = 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, getIntField(OFFSET_LITERAL+WIDTH_LITERAL-1, OFFSET_LITERAL, inst), count);
- if (latch & !dataIn && !tokenIn && !dataOut && !tokenOut) return new Instruction.Clog(name);
- if (latch & !dataIn && tokenIn) return new Instruction.UnClog(name);
- if (latch & !dataIn) return new Instruction.Kill(name, count);
- return new Instruction.Executable(name, dest, count, tokenIn, dataIn, latch, dataOutDest,
- dataOut, tokenOut, requeue, ignoreUntilLast);
+ public Instruction readInstruction(Dock dispatchFrom, long inst) {
+ Dock dock = getPathByAddr(getUniversalSource(), DISPATCH_PATH.getval(inst)).getDestination().getDock();
+
+ if (TAIL.get(inst)) return new Tail(dock);
+
+ 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));
+ }
+
+ 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;
- if (d.pump != null)
- instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, getBoxInstAddr(d.pump));
+ if (d.dock != null)
+ instr = DISPATCH_PATH.setval(instr, getDestAddr(getUniversalSource().getPath(d.dock.getInstructionDestination(),null)));
- 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);
+ 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.UnClog) {
- instr |= putField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG, MASK_UNCLOG);
-
- } else if (d instanceof Instruction.Kill) {
- Instruction.Kill k = (Instruction.Kill)d;
- 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.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);
- instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT, inst.count);
- } else {
- instr = inst.literal;
+ 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 if (d instanceof Instruction.Executable) {
- Instruction.Executable inst = (Instruction.Executable)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);
- instr |= putField(OFFSET_DI, OFFSET_DI, inst.dataIn?1:0);
- instr |= putField(OFFSET_DL, OFFSET_DL, inst.latch?1:0);
- 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 {
+ throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
}
return instr;
}
- public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
- long instr = writeInstruction(d);
+ 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(getIntField(i*8+7, i*8, instr));
- }
+ 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;
+ }
+}