1 package edu.berkeley.fleet.ies44;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.*;
4 import edu.berkeley.fleet.util.*;
6 import static edu.berkeley.fleet.util.BitManipulations.*;
7 import static edu.berkeley.fleet.api.Instruction.*;
8 import static edu.berkeley.fleet.api.Instruction.Counter.*;
10 public abstract class InstructionEncoder {
12 public static final int WIDTH_WORD = 37;
13 public static final int WIDTH_ADDR = 11;
14 public static final int WIDTH_CODEBAG_SIZE = 6;
15 public static final int WIDTH_COUNTER_LITERAL = 6;
17 public static final Mask FLAGS = new Mask("...............000000................");
18 public static final Mask FLAGS_A = new Mask("...............000000vvvvvvvv........");
19 public static final Mask FLAGS_B = new Mask("...............000000........vvvvvvvv");
20 public static final Mask REPEAT_FROM_DATA = new Mask("...............000001........00......");
21 public static final Mask REPEAT_FROM_LITERAL = new Mask("...............000001........10vvvvvv");
22 public static final Mask REPEAT_FROM_STANDING = new Mask("...............000001........11......");
23 public static final Mask LOOP_FROM_DATA = new Mask("...............000010.........0......");
24 public static final Mask LOOP_FROM_LITERAL = new Mask("...............000010.........1vvvvvv");
25 public static final Mask TAKE_LOOP = new Mask("...............000011................");
26 public static final Mask KILL = new Mask("...............000100................");
27 public static final Mask MASSACRE = new Mask("...............000101................");
28 public static final Mask CLOG = new Mask("...............000110................");
29 public static final Mask UNCLOG = new Mask("...............000111................");
31 public static final Mask SK = new Mask("...........1.........................");
32 public static final Mask DL = new Mask("............1........................");
33 public static final Mask P = new Mask(".............vv......................");
34 public static final Mask P_A = new Mask(".............00......................");
35 public static final Mask P_B = new Mask(".............10......................");
36 public static final Mask P_Z = new Mask(".............01......................");
37 public static final Mask P_ALWAYS = new Mask(".............11......................");
38 public static final Mask MOVE = new Mask("...............001...................");
39 public static final Mask TI = new Mask("....................1................");
40 public static final Mask DI = new Mask(".....................1...............");
41 public static final Mask DC = new Mask("......................1..............");
42 public static final Mask DO = new Mask(".......................1.............");
43 public static final Mask TO = new Mask("........................1............");
44 public static final Mask PATH_LITERAL = new Mask(".........................1vvvvvvvvvvv");
45 public static final Mask PATH_DATA = new Mask(".........................01..........");
46 public static final Mask PATH_NOCHANGE = new Mask(".........................00..........");
48 public static final Mask TOP_HALF_LITERAL = new Mask("vvvvvvvvvvvvvvvvvv...................");
49 public static final Mask BOT_HALF_LITERAL = new Mask("..................vvvvvvvvvvvvvvvvvvv");
50 public static final Mask TOP_HALF_ONE = new Mask("111111111111111111...................");
51 public static final Mask BOT_HALF_ONE = new Mask("..................1111111111111111111");
52 public static final Mask LITERAL_LO = new Mask("...............010vvvvvvvvvvvvvvvvvvv");
53 public static final Mask LITERAL_HI = new Mask("...............011vvvvvvvvvvvvvvvvvvv");
54 public static final Mask LITERAL = new Mask("...............1..vvvvvvvvvvvvvvvvvvv");
55 public static final Mask LITERAL_SEL = new Mask("................vv...................");
56 public static final Mask LITERAL_LOW_ZERO = new Mask("...............100...................");
57 public static final Mask LITERAL_LOW_ONE = new Mask("...............101...................");
58 public static final Mask LITERAL_HIGH_ZERO = new Mask("...............110...................");
59 public static final Mask LITERAL_HIGH_ONE = new Mask("...............111...................");
60 public static final Mask PUMP_NAME = new Mask("vvvvvvvvvvv..........................");
63 /** get the bits describing this box's location on the DESTINATION HORN */
64 protected abstract long getDestAddr(Destination box);
66 /** get the bits describing this box's location on the INSTRUCTION HORN */
67 protected abstract long getBoxInstAddr(Pump box);
69 /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
70 protected abstract Pump getBoxByInstAddr(long dest);
72 /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
73 protected abstract Destination getDestByAddr(long dest);
75 /** read a machine-formatted instruction from a file (into a Java object) */
76 public Instruction readInstruction(DataInputStream is) throws IOException {
79 inst = (inst << 8) | (is.readByte() & 0xff);
80 inst = (inst << 8) | (is.readByte() & 0xff);
81 inst = (inst << 8) | (is.readByte() & 0xff);
82 inst = (inst << 8) | (is.readByte() & 0xff);
83 inst = (inst << 8) | (is.readByte() & 0xff);
84 inst = (inst << 8) | (is.readByte() & 0xff);
85 return readInstruction(inst);
86 } catch (EOFException eof) {
91 public Instruction readInstruction(long inst) {
92 Pump name = getBoxByInstAddr(PUMP_NAME.getval(inst));
94 if (UNCLOG.get(inst)) return new Instruction.UnClog(name);
95 if (CLOG.get(inst)) return new Instruction.Clog(name);
96 if (MASSACRE.get(inst)) return new Instruction.Massacre(name);
97 if (KILL.get(inst)) return new Instruction.Kill(name, (int)(KILL.getval(inst)+1));
100 if (P_ALWAYS.get(inst)) predicate = Instruction.PredicatedInstruction.P_ALWAYS;
101 if (P_A.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_A;
102 if (P_B.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_B;
103 if (P_Z.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_Z;
106 if (DL.get(inst)) dl = true;
108 if (LOOP_FROM_LITERAL.get(inst)) return new Counter(name, dl, predicate, (int)LOOP_FROM_LITERAL.getval(inst), LOOP_COUNTER);
109 if (REPEAT_FROM_LITERAL.get(inst)) return new Counter(name, dl, predicate, (int)REPEAT_FROM_LITERAL.getval(inst), REPEAT_COUNTER);
110 if (LOOP_FROM_DATA.get(inst)) return new Counter(name, dl, predicate, DATA_LATCH, LOOP_COUNTER);
111 if (REPEAT_FROM_DATA.get(inst)) return new Counter(name, dl, predicate, DATA_LATCH, REPEAT_COUNTER);
112 if (REPEAT_FROM_STANDING.get(inst)) return new Counter(name, dl, predicate, STANDING, REPEAT_COUNTER);
113 if (TAKE_LOOP.get(inst)) return new Counter(name, dl, predicate, LOOP_COUNTER, DATA_LATCH);
115 if (LITERAL_LO.get(inst)) return new Instruction.HalfLiteral(name, dl, predicate, LITERAL_LO.getval(inst), 0, false);
116 if (LITERAL_HI.get(inst)) return new Instruction.HalfLiteral(name, dl, predicate, LITERAL_HI.getval(inst), 0, true);
117 if (LITERAL.get(inst)) {
118 long literal = LITERAL.getval(inst);
119 if (LITERAL_LOW_ZERO.get(inst)) literal = TOP_HALF_LITERAL.setval(0, literal);
120 else if (LITERAL_LOW_ONE.get(inst)) literal = BOT_HALF_ONE.set(TOP_HALF_LITERAL.setval(0, literal));
121 else if (LITERAL_HIGH_ZERO.get(inst)) literal = BOT_HALF_LITERAL.setval(0, literal);
122 else if (LITERAL_HIGH_ONE.get(inst)) literal = TOP_HALF_ONE.set(BOT_HALF_LITERAL.setval(0, literal));
123 return new Instruction.Literal(name, dl, predicate, Mask.signExtend(literal, WIDTH_WORD));
125 if (FLAGS.get(inst)) return new Instruction.SetFlags(name, dl, predicate, (int)FLAGS_A.getval(inst), (int)FLAGS_B.getval(inst));
127 if (!MOVE.get(inst)) throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
129 Destination dest = getDestByAddr(PATH_LITERAL.getval(inst));
130 boolean tokenIn = TI.get(inst);
131 boolean dataIn = DI.get(inst);
132 boolean latch = DC.get(inst);
133 boolean dataOut = DO.get(inst);
134 boolean tokenOut = TO.get(inst);
135 boolean dataOutDest = PATH_DATA.get(inst);
136 return new Instruction.Move(name,
150 public long writeInstruction(Instruction d) {
154 instr = PUMP_NAME.setval(instr, getBoxInstAddr(d.pump));
157 if (d instanceof Instruction.PredicatedInstruction) {
158 Instruction.PredicatedInstruction pi = (Instruction.PredicatedInstruction)d;
159 if (pi.dl) instr = DL.set(instr);
160 switch(pi.predicate) {
161 case Instruction.PredicatedInstruction.P_ALWAYS: instr = P_ALWAYS.set(instr); break;
162 case Instruction.PredicatedInstruction.P_IF_A: instr = P_A.set(instr); break;
163 case Instruction.PredicatedInstruction.P_IF_B: instr = P_B.set(instr); break;
164 case Instruction.PredicatedInstruction.P_IF_Z: instr = P_Z.set(instr); break;
168 if (d instanceof Instruction.CodeBagDescriptor) {
169 Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
170 // MAJOR MAJOR FIXME: upper half here...
171 d = new Instruction.HalfLiteral(lc.pump, dl, Instruction.PredicatedInstruction.P_ALWAYS,
172 ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1, false);
175 if (d instanceof Instruction.UnClog) {
176 instr = UNCLOG.set(instr);
178 } else if (d instanceof Instruction.Kill) {
179 Instruction.Kill k = (Instruction.Kill)d;
180 instr = KILL.set(instr);
181 instr = KILL.setval(instr, k.count);
183 } else if (d instanceof Instruction.Clog) {
184 instr = CLOG.set(instr);
186 } else if (d instanceof Instruction.Massacre) {
187 instr = MASSACRE.set(instr);
189 } else if (d instanceof Instruction.SetFlags) {
190 Instruction.SetFlags sf = (Instruction.SetFlags)d;
191 instr = FLAGS.set(instr);
192 instr = FLAGS_A.setval(instr, sf.flag_a);
193 instr = FLAGS_B.setval(instr, sf.flag_b);
195 } else if (d instanceof Instruction.Literal) {
196 long il = ((Instruction.Literal)d).literal;
197 long literal = ((Instruction.Literal)d).literal;
198 long allones = ~(-1L << WIDTH_WORD);
199 il = literal = literal & allones;
200 long top_half = il >> LITERAL_HIGH_ZERO.getWidth();
201 long bot_half = il & ~(-1L << LITERAL_HIGH_ZERO.getWidth());
202 if (((il & (-1L << 19)) & allones) == 0) instr = LITERAL.setval(LITERAL_HIGH_ZERO.set(instr), il);
203 else if (((il | ~(-1L << 19)) & allones) == allones) instr = LITERAL.setval(LITERAL_HIGH_ONE.set(instr), il & ~(-1L<<19));
204 else if (((il & ~(-1L << 19)) & allones) == 0) instr = LITERAL.setval(LITERAL_LOW_ZERO.set(instr), il >> 19);
205 else if (((il | (-1L << 19)) & allones) == allones) instr = LITERAL.setval(LITERAL_LOW_ONE.set(instr), (il >> 19));
207 } else if (d instanceof Instruction.HalfLiteral) {
208 Instruction.HalfLiteral inst = (Instruction.HalfLiteral)d;
209 if (inst.pump != null) {
211 instr = LITERAL_HI.set(instr);
212 instr = LITERAL_HI.setval(instr, inst.literal);
214 instr = LITERAL_LO.set(instr);
215 instr = LITERAL_LO.setval(instr, inst.literal);
218 instr = inst.literal;
221 } else if (d instanceof Instruction.DecrLoop) {
222 instr = DL.set(instr);
224 } else if (d instanceof Instruction.Counter) {
225 Instruction.Counter ic = (Instruction.Counter)d;
226 if (ic.dest == DATA_LATCH && ic.source == LOOP_COUNTER) instr = TAKE_LOOP.set(instr);
227 else if (ic.dest == LOOP_COUNTER && ic.source == DATA_LATCH) instr = LOOP_FROM_DATA.set(instr);
228 else if (ic.dest == REPEAT_COUNTER && ic.source == DATA_LATCH) instr = REPEAT_FROM_DATA.set(instr);
229 else if (ic.dest == REPEAT_COUNTER && ic.source == STANDING) instr = REPEAT_FROM_STANDING.set(instr);
230 else if (ic.dest == REPEAT_COUNTER) instr = REPEAT_FROM_LITERAL.setval(REPEAT_FROM_LITERAL.set(instr), ic.source);
231 else if (ic.dest == LOOP_COUNTER) instr = LOOP_FROM_LITERAL.setval(LOOP_FROM_LITERAL.set(instr), ic.source);
232 else throw new RuntimeException();
234 } else if (d instanceof Instruction.Move) {
235 Instruction.Move inst = (Instruction.Move)d;
236 instr = MOVE.set(instr);
237 if (inst.tokenIn) instr = TI.set(instr);
238 if (inst.dataIn) instr = DI.set(instr);
239 if (inst.latch) instr = DC.set(instr);
240 if (inst.dataOut) instr = DO.set(instr);
241 if (inst.tokenOut) instr = TO.set(instr);
242 if (inst.dataOutDest) instr = PATH_DATA.set(instr);
244 instr = PATH_LITERAL.set(instr);
245 instr = PATH_LITERAL.setval(instr, inst.dest==null?0:getDestAddr(inst.dest));
249 throw new RuntimeException("unrecognized instruction " + d);
255 public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
256 long instr = writeInstruction(d);
257 for(int i=5; i>=0; i--)
258 os.write(getIntField(i*8+7, i*8, instr));