1 package edu.berkeley.fleet.ies44;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.*;
5 import static edu.berkeley.fleet.util.BitManipulations.*;
7 public abstract class InstructionEncoder {
9 public static final int WIDTH_WORD = 37; /* word width */
10 public static final int WIDTH_CODEBAG_SIZE = 6;
11 public static final int WIDTH_PUMP_ADDR = 11;
12 public static final int WIDTH_DEST_ADDR = 11;
13 public static final int WIDTH_COUNT = 7;
15 public static final int OFFSET_MASK_LITERAL = 20;
16 public static final int WIDTH_MASK_LITERAL = 6;
17 public static final int MASK_LITERAL = 13; // this is an excessive approximation
19 public static final int OFFSET_MASK_MASSACRE = 14;
20 public static final int WIDTH_MASK_MASSACRE = 26-14;
21 public static final int MASK_MASSACRE = 1;
23 public static final int OFFSET_MASK_KILL = 14;
24 public static final int WIDTH_MASK_KILL = 26-14;
25 public static final int MASK_KILL = 0;
27 public static final int OFFSET_MASK_UNCLOG = 14;
28 public static final int WIDTH_MASK_UNCLOG = 26-14;
29 public static final int MASK_UNCLOG = 3;
31 public static final int OFFSET_MASK_CLOG = 14;
32 public static final int WIDTH_MASK_CLOG = 26-14;
33 public static final int MASK_CLOG = 2;
35 public static final int OFFSET_MASK_LOAD_LOOP_TO_DATA = 14;
36 public static final int WIDTH_MASK_LOAD_LOOP_TO_DATA = 12;
37 public static final int MASK_LOAD_LOOP_TO_DATA = 0;
39 public static final int OFFSET_MASK_LOAD_LITERAL_TO_LOOP = 14;
40 public static final int WIDTH_MASK_LOAD_LITERAL_TO_LOOP = 12;
41 public static final int MASK_LOAD_LITERAL_TO_LOOP = 1;
43 public static final int OFFSET_MASK_LOAD_LITERAL_TO_REPEAT = 14;
44 public static final int WIDTH_MASK_LOAD_LITERAL_TO_REPEAT = 12;
45 public static final int MASK_LOAD_LITERAL_TO_REPEAT = 2;
47 public static final int OFFSET_MASK_LOAD_DATA_TO_REPEAT = 14;
48 public static final int WIDTH_MASK_LOAD_DATA_TO_REPEAT = 12;
49 public static final int MASK_LOAD_DATA_TO_REPEAT = 3;
51 public static final int OFFSET_MASK_LOAD_DATA_TO_LOOP = 14;
52 public static final int WIDTH_MASK_LOAD_DATA_TO_LOOP = 12;
53 public static final int MASK_LOAD_DATA_TO_LOOP = 4;
55 public static final int OFFSET_MASK_DECR_LOOP = 14;
56 public static final int WIDTH_MASK_DECR_LOOP = 12;
57 public static final int MASK_DECR_LOOP = 5;
59 public static final int OFFSET_MASK_NORMAL = 25;
60 public static final int WIDTH_MASK_NORMAL = 1;
61 public static final int MASK_NORMAL = 1;
63 public static final int OFFSET_COUNTER_LITERAL = 0;
64 public static final int WIDTH_COUNTER_LITERAL = 6;
66 public static final int OFFSET_COUNT = 0;
67 public static final int OFFSET_DEST = OFFSET_COUNT+WIDTH_COUNT;
68 public static final int OFFSET_CONTROL = OFFSET_DEST+WIDTH_DEST_ADDR;
69 public static final int OFFSET_RQ = OFFSET_CONTROL+0;
70 public static final int OFFSET_IG = OFFSET_CONTROL+1;
71 public static final int OFFSET_TO = OFFSET_CONTROL+2;
72 public static final int OFFSET_DO = OFFSET_CONTROL+3;
73 public static final int OFFSET_DL = OFFSET_CONTROL+4;
74 public static final int OFFSET_DI = OFFSET_CONTROL+5;
75 public static final int OFFSET_TI = OFFSET_CONTROL+6;
76 public static final int OFFSET_LITERAL_LOADHIGH = 19;
77 public static final int OFFSET_INSTRUCTIONTYPE = OFFSET_CONTROL+7;
78 public static final int OFFSET_PUMP_ADDR = OFFSET_INSTRUCTIONTYPE+1;
80 public static final int OFFSET_LITERAL = 0;
81 public static final int WIDTH_LITERAL = 19;
84 /** get the bits describing this box's location on the DESTINATION HORN */
85 protected abstract long getDestAddr(Destination box);
87 /** get the bits describing this box's location on the INSTRUCTION HORN */
88 protected abstract long getBoxInstAddr(Pump box);
90 /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
91 protected abstract Pump getBoxByInstAddr(long dest);
93 /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
94 protected abstract Destination getDestByAddr(long dest);
96 /** read a machine-formatted instruction from a file (into a Java object) */
97 public Instruction readInstruction(DataInputStream is) throws IOException {
100 inst = (inst << 8) | (is.readByte() & 0xff);
101 inst = (inst << 8) | (is.readByte() & 0xff);
102 inst = (inst << 8) | (is.readByte() & 0xff);
103 inst = (inst << 8) | (is.readByte() & 0xff);
104 inst = (inst << 8) | (is.readByte() & 0xff);
105 inst = (inst << 8) | (is.readByte() & 0xff);
106 return readInstruction(inst);
107 } catch (EOFException eof) {
112 public Instruction readInstruction(long inst) {
113 Pump name = getBoxByInstAddr(getIntField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, inst));
115 int count_literal = getIntField(OFFSET_COUNTER_LITERAL+WIDTH_COUNTER_LITERAL-1, OFFSET_COUNTER_LITERAL, inst);
116 if (getIntField(OFFSET_MASK_LOAD_LOOP_TO_DATA+WIDTH_MASK_LOAD_LOOP_TO_DATA-1, OFFSET_MASK_LOAD_LOOP_TO_DATA,inst)==MASK_LOAD_LOOP_TO_DATA)
117 return new Instruction.Counter(name, Instruction.Counter.LOOP_COUNTER, Instruction.Counter.DATA_LATCH);
118 else if (getIntField(OFFSET_MASK_LOAD_DATA_TO_REPEAT+WIDTH_MASK_LOAD_DATA_TO_REPEAT-1, OFFSET_MASK_LOAD_DATA_TO_REPEAT,inst)==MASK_LOAD_DATA_TO_REPEAT)
119 return new Instruction.Counter(name, Instruction.Counter.DATA_LATCH, Instruction.Counter.REPEAT_COUNTER);
120 else if (getIntField(OFFSET_MASK_LOAD_DATA_TO_LOOP+WIDTH_MASK_LOAD_DATA_TO_LOOP-1, OFFSET_MASK_LOAD_DATA_TO_LOOP,inst)==MASK_LOAD_DATA_TO_LOOP)
121 return new Instruction.Counter(name, Instruction.Counter.DATA_LATCH, Instruction.Counter.LOOP_COUNTER);
122 else if (getIntField(OFFSET_MASK_LOAD_LITERAL_TO_LOOP+WIDTH_MASK_LOAD_LITERAL_TO_LOOP-1, OFFSET_MASK_LOAD_LITERAL_TO_LOOP,inst)==MASK_LOAD_LITERAL_TO_LOOP)
123 return new Instruction.Counter(name, count_literal, Instruction.Counter.LOOP_COUNTER);
124 else if (getIntField(OFFSET_MASK_LOAD_LITERAL_TO_REPEAT+WIDTH_MASK_LOAD_LITERAL_TO_REPEAT-1, OFFSET_MASK_LOAD_LITERAL_TO_REPEAT,inst)==MASK_LOAD_LITERAL_TO_REPEAT)
125 return new Instruction.Counter(name, count_literal, Instruction.Counter.REPEAT_COUNTER);
126 else if (getIntField(OFFSET_MASK_DECR_LOOP+WIDTH_MASK_DECR_LOOP-1, OFFSET_MASK_DECR_LOOP,inst)==MASK_DECR_LOOP)
127 return new Instruction.DecrLoop(name);
129 if (getIntField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG,inst)==MASK_UNCLOG)
130 return new Instruction.UnClog(name);
131 if (getIntField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG,inst)==MASK_CLOG)
132 return new Instruction.Clog(name);
133 if (getIntField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE,inst)==MASK_MASSACRE)
134 return new Instruction.Massacre(name);
135 int count = getIntField( OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT, inst);
136 if (getIntField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL,inst)==MASK_KILL)
137 return new Instruction.Kill(name, count);
138 Destination dest = getDestByAddr (getIntField(OFFSET_DEST+WIDTH_DEST_ADDR-1, OFFSET_DEST, inst));
139 boolean tokenIn = getBit(OFFSET_TI, inst);
140 boolean dataIn = getBit(OFFSET_DI, inst);
141 boolean latch = getBit(OFFSET_DL, inst);
142 boolean dataOut = getBit(OFFSET_DO, inst);
143 boolean tokenOut = getBit(OFFSET_TO, inst);
144 boolean requeue = getBit(OFFSET_RQ, inst);
145 boolean ignoreUntilLast = getBit(OFFSET_IG, inst);
146 boolean dataOutDest = name.isOutbox() && dataOut && tokenOut;
147 boolean isLiteral = getIntField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL, inst)==MASK_LITERAL;
149 return new Instruction.LocalLiteral(name, getField(OFFSET_LITERAL+WIDTH_LITERAL-1, OFFSET_LITERAL, inst), 0,
150 getField(OFFSET_LITERAL_LOADHIGH, OFFSET_LITERAL_LOADHIGH, inst)!=0);
151 if (dataOutDest) tokenOut = false;
152 return new Instruction.Move(name,
165 public long writeInstruction(Instruction d) {
169 instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, getBoxInstAddr(d.pump));
171 if (d instanceof Instruction.CodeBagDescriptor) {
172 Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
173 // MAJOR MAJOR FIXME: upper half here...
174 d = new Instruction.LocalLiteral(lc.pump, ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1, false);
177 if (d instanceof Instruction.UnClog) {
178 instr |= putField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG, MASK_UNCLOG);
180 } else if (d instanceof Instruction.Kill) {
181 Instruction.Kill k = (Instruction.Kill)d;
182 instr |= putField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL, MASK_KILL);
183 instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT, k.count-1);
185 } else if (d instanceof Instruction.Clog) {
186 instr |= putField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG, MASK_CLOG);
188 } else if (d instanceof Instruction.Massacre) {
189 instr |= putField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE, MASK_MASSACRE);
191 } else if (d instanceof Instruction.LocalLiteral) {
192 Instruction.LocalLiteral inst = (Instruction.LocalLiteral)d;
193 if (inst.pump != null) {
194 instr |= putField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL, MASK_LITERAL);
195 instr |= putField(OFFSET_LITERAL+WIDTH_LITERAL-1, OFFSET_LITERAL, inst.literal);
196 instr |= putField(OFFSET_LITERAL_LOADHIGH, OFFSET_LITERAL_LOADHIGH, (inst.high?1:0));
198 instr = inst.literal;
201 } else if (d instanceof Instruction.DecrLoop) {
202 instr |= putField(OFFSET_MASK_DECR_LOOP+WIDTH_MASK_DECR_LOOP-1, OFFSET_MASK_DECR_LOOP, MASK_DECR_LOOP);
204 } else if (d instanceof Instruction.Counter) {
205 Instruction.Counter ic = (Instruction.Counter)d;
206 if (ic.dest == Instruction.Counter.DATA_LATCH && ic.source == Instruction.Counter.LOOP_COUNTER)
207 instr |= putField(OFFSET_MASK_LOAD_LOOP_TO_DATA+WIDTH_MASK_LOAD_LOOP_TO_DATA-1,
208 OFFSET_MASK_LOAD_LOOP_TO_DATA, MASK_LOAD_LOOP_TO_DATA);
209 else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH)
210 instr |= putField(OFFSET_MASK_LOAD_DATA_TO_REPEAT+WIDTH_MASK_LOAD_DATA_TO_REPEAT-1,
211 OFFSET_MASK_LOAD_DATA_TO_REPEAT, MASK_LOAD_DATA_TO_REPEAT);
212 else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH)
213 instr |= putField(OFFSET_MASK_LOAD_DATA_TO_LOOP+WIDTH_MASK_LOAD_DATA_TO_LOOP-1,
214 OFFSET_MASK_LOAD_DATA_TO_LOOP, MASK_LOAD_DATA_TO_LOOP);
215 else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
216 instr |= putField(OFFSET_MASK_LOAD_LITERAL_TO_REPEAT+WIDTH_MASK_LOAD_LITERAL_TO_REPEAT-1,
217 OFFSET_MASK_LOAD_LITERAL_TO_REPEAT, MASK_LOAD_LITERAL_TO_REPEAT);
218 instr |= putField(OFFSET_COUNTER_LITERAL+WIDTH_COUNTER_LITERAL-1,
219 OFFSET_COUNTER_LITERAL, ic.source);
220 } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
221 instr |= putField(OFFSET_MASK_LOAD_LITERAL_TO_LOOP+WIDTH_MASK_LOAD_LITERAL_TO_LOOP-1,
222 OFFSET_MASK_LOAD_LITERAL_TO_LOOP, MASK_LOAD_LITERAL_TO_LOOP);
223 instr |= putField(OFFSET_COUNTER_LITERAL+WIDTH_COUNTER_LITERAL-1,
224 OFFSET_COUNTER_LITERAL, ic.source);
225 } else throw new RuntimeException();
227 } else if (d instanceof Instruction.Move) {
228 Instruction.Move inst = (Instruction.Move)d;
229 instr |= putField(OFFSET_MASK_NORMAL+WIDTH_MASK_NORMAL-1, OFFSET_MASK_NORMAL, MASK_NORMAL);
230 instr |= putField(OFFSET_DEST+WIDTH_DEST_ADDR-1, OFFSET_DEST, inst.dest==null?0:getDestAddr(inst.dest));
231 instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT, inst.count);
232 instr |= putField(OFFSET_TI, OFFSET_TI, inst.tokenIn?1:0);
233 instr |= putField(OFFSET_DI, OFFSET_DI, inst.dataIn?1:0);
234 instr |= putField(OFFSET_DL, OFFSET_DL, inst.latch?1:0);
235 instr |= putField(OFFSET_DO, OFFSET_DO, (inst.dataOutDest||inst.dataOut)?1:0);
236 instr |= putField(OFFSET_TO, OFFSET_TO, (inst.dataOutDest||inst.tokenOut)?1:0);
237 instr |= putField(OFFSET_RQ, OFFSET_RQ, inst.requeue?1:0);
238 instr |= putField(OFFSET_IG, OFFSET_IG, inst.ignoreUntilLast?1:0);
244 public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
245 long instr = writeInstruction(d);
246 for(int i=5; i>=0; i--)
247 os.write(getIntField(i*8+7, i*8, instr));