1 package edu.berkeley.fleet.two;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.util.*;
5 import edu.berkeley.fleet.api.Instruction.Set;
6 import static edu.berkeley.fleet.api.Instruction.Set.*;
7 import static edu.berkeley.fleet.api.Instruction.*;
8 import static edu.berkeley.fleet.api.Predicate.*;
10 /** common subclass for the "FleetTwo" generation of processors, all 37-bit wide, with AM33 encoding */
11 public abstract class FleetTwoFleet extends Fleet {
13 private final boolean hack = "true".equals(System.getProperty("inverted-dc-bit-hack", "false"));
15 public final Mask PACKET_TOKEN;
16 public final Mask PACKET_IS_TOKEN;
17 public final Mask PACKET_DATA;
18 public final Mask PACKET_SIGNAL;
19 public final Mask PACKET_DEST;
21 public final Mask CBD_SIZE;
22 public final Mask CBD_OFFSET;
24 public final Mask WHOLE_WORD;
25 public final Mask DISPATCH_PATH;
26 public final Mask DISPATCH_INSTR;
27 public final Mask NOT_INTERRUPTIBLE;
28 public final Mask IS_INTERRUPTIBLE;
30 public final Mask P_NOT_A;
31 public final Mask P_A;
32 public final Mask P_NOT_B;
33 public final Mask P_B;
34 public final Mask P_UNUSED;
35 public final Mask P_OLC_ZERO;
36 public final Mask P_OLC_NONZERO;
37 public final Mask P_ALWAYS;
39 public final Mask SHIFT;
41 public final Mask TAIL;
42 public final Mask HEAD;
43 public final Mask ABORT;
45 public final Mask MOVE;
48 public final Mask FLUSH;
52 public final Mask PATH_IMMEDIATE;
53 public final Mask PATH_DATA;
54 public final Mask PATH_NOCHANGE;
56 public final Mask SET_OLC_FROM_IMMEDIATE;
57 public final Mask SET_OLC_FROM_DATA_LATCH;
58 public final Mask SET_OLC_FROM_OLC_MINUS_ONE;
60 public final Mask SET_ILC_FROM_IMMEDIATE;
61 public final Mask SET_ILC_FROM_INFINITY;
62 public final Mask SET_ILC_FROM_DATA_LATCH;
64 public final Mask SET_IMMEDIATE;
65 public final Mask SET_IMMEDIATE_EXTEND;
67 public final Mask SET_FLAGS;
68 public final Mask SET_FLAGS_A;
69 public final Mask SET_FLAGS_B;
70 public final Mask SET_FLAGS_VALUE_A;
71 public final Mask SET_FLAGS_VALUE_NOT_A;
72 public final Mask SET_FLAGS_VALUE_B;
73 public final Mask SET_FLAGS_VALUE_NOT_B;
74 public final Mask SET_FLAGS_VALUE_C;
75 public final Mask SET_FLAGS_VALUE_NOT_C;
77 public final int WIDTH_WORD;
78 public final int WIDTH_PACKET;
80 public final int DataLatch_WIDTH;
81 private final long mask;
83 public FleetTwoFleet() { this(false); }
85 public FleetTwoFleet(boolean useInternalEncoding) {
86 PACKET_TOKEN = new Mask("v.................................................");
87 PACKET_IS_TOKEN = new Mask("1.................................................");
88 PACKET_DATA = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
89 PACKET_SIGNAL = new Mask("......................................v...........");
90 PACKET_DEST = new Mask(".......................................vvvvvvvvvvv");
92 CBD_SIZE = new Mask("............................vvvvvvvvv");
93 CBD_OFFSET = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvv.........");
95 WHOLE_WORD = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
97 if (useInternalEncoding) {
99 DISPATCH_PATH = new Mask("v....................................");
100 DISPATCH_INSTR = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
101 P = new Mask(".vvvvvv..............................");
102 P_NOT_A = new Mask(".010001..............................");
103 P_A = new Mask(".010010..............................");
104 P_NOT_B = new Mask(".010100..............................");
105 P_B = new Mask(".011000..............................");
106 P_UNUSED = new Mask(".111111..............................");
107 P_OLC_ZERO = new Mask(".100000..............................");
108 P_OLC_NONZERO = new Mask(".010000..............................");
109 P_ALWAYS = new Mask(".000000..............................");
111 HEAD = new Mask(".......1.............................");
112 ABORT = new Mask("........1......1.........000100000001");
113 TAIL = new Mask(".........1...........................");
115 // actually "is interruptible"
116 NOT_INTERRUPTIBLE = new Mask("...........0....0....................");
117 IS_INTERRUPTIBLE = new Mask("...........1....1....................");
119 SHIFT = new Mask("..........1......1vvvvvvvvvvvvvvvvvvv");
120 SET_IMMEDIATE = new Mask("..........1......0.....vvvvvvvvvvvvvv");
121 SET_IMMEDIATE_EXTEND = new Mask("..........1......0....v..............");
122 MOVE = new Mask("............1........................");
123 TI = new Mask("............1.....1..................");
124 DI = new Mask("............1......1.................");
125 FLUSH = new Mask("..........1......0.....011...........");
126 DC = new Mask("............1.......1................");
127 DO = new Mask("............1........1...............");
128 TO = new Mask("............1.........1..............");
129 PATH_IMMEDIATE = new Mask("............1..........1vvvvvvvvvvvvv");
130 PATH_DATA = new Mask("............1..........00............");
131 PATH_NOCHANGE = new Mask("............1..........01............");
133 SET_OLC_FROM_OLC_MINUS_ONE = new Mask(".............1..1....................");
134 SET_OLC_FROM_DATA_LATCH = new Mask("..............1.11...................");
135 SET_OLC_FROM_IMMEDIATE = new Mask("..............1.10.............vvvvvv");
137 SET_ILC_FROM_DATA_LATCH = new Mask("..............1.01...................");
138 SET_ILC_FROM_IMMEDIATE = new Mask("..............1.00...........0.vvvvvv");
139 SET_ILC_FROM_INFINITY = new Mask("..............1.0............1.......");
141 SET_FLAGS = new Mask("...............1.....................");
142 SET_FLAGS_A = new Mask("...............1...............vvvvvv");
143 SET_FLAGS_B = new Mask("...............1.........vvvvvv......");
145 SET_FLAGS_VALUE_A = new Mask(".....1");
146 SET_FLAGS_VALUE_NOT_A = new Mask("....1.");
147 SET_FLAGS_VALUE_B = new Mask("...1..");
148 SET_FLAGS_VALUE_NOT_B = new Mask("..1...");
149 SET_FLAGS_VALUE_C = new Mask(".1....");
150 SET_FLAGS_VALUE_NOT_C = new Mask("1.....");
153 DISPATCH_PATH = new Mask("vvvvvvvvvvv..........................");
154 DISPATCH_INSTR = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
155 NOT_INTERRUPTIBLE = new Mask("...........1.........................");
156 IS_INTERRUPTIBLE = new Mask("...........0.........................");
157 P = new Mask(".............vvv.....................");
158 P_NOT_A = new Mask(".............000.....................");
159 P_A = new Mask(".............001.....................");
160 P_NOT_B = new Mask(".............010.....................");
161 P_B = new Mask(".............011.....................");
162 P_UNUSED = new Mask(".............100.....................");
163 P_OLC_ZERO = new Mask(".............101.....................");
164 P_OLC_NONZERO = new Mask(".............110.....................");
165 P_ALWAYS = new Mask(".............111.....................");
167 SHIFT = new Mask("................00vvvvvvvvvvvvvvvvvvv");
169 ABORT = new Mask("................1100................."); // note: has a predicate!
171 HEAD = new Mask("................1110.................");
172 TAIL = new Mask("................1111.................");
174 MOVE = new Mask("................01...................");
175 TI = new Mask("................011..................");
176 DI = new Mask("................01.1.................");
177 FLUSH = new Mask("................01.01................");
178 DC = new Mask("................01.11................");
179 DO = new Mask("................01...1...............");
180 TO = new Mask("................01....1..............");
181 PATH_IMMEDIATE = new Mask("................01.....1vvvvvvvvvvvvv");
182 PATH_DATA = new Mask("................01.....01............");
183 PATH_NOCHANGE = new Mask("................01.....00............");
185 SET_OLC_FROM_IMMEDIATE = new Mask("................101000100......vvvvvv");
186 SET_OLC_FROM_DATA_LATCH = new Mask("................101000010............");
187 SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
189 SET_ILC_FROM_IMMEDIATE = new Mask("................10010010......0vvvvvv");
190 SET_ILC_FROM_INFINITY = new Mask("................10010010......1......");
191 SET_ILC_FROM_DATA_LATCH = new Mask("................10010001.............");
193 SET_IMMEDIATE = new Mask("................100010.vvvvvvvvvvvvvv");
194 SET_IMMEDIATE_EXTEND = new Mask("................100010v..............");
196 SET_FLAGS = new Mask("................100001...............");
197 SET_FLAGS_A = new Mask("................100001...vvvvvv......");
198 SET_FLAGS_B = new Mask("................100001.........vvvvvv");
200 SET_FLAGS_VALUE_A = new Mask("1.....");
201 SET_FLAGS_VALUE_NOT_A = new Mask(".1....");
202 SET_FLAGS_VALUE_B = new Mask("..1...");
203 SET_FLAGS_VALUE_NOT_B = new Mask("...1..");
204 SET_FLAGS_VALUE_C = new Mask("....1.");
205 SET_FLAGS_VALUE_NOT_C = new Mask(".....1");
208 WIDTH_WORD = PACKET_DATA.valmaskwidth;
209 WIDTH_PACKET = PACKET_TOKEN.width;
210 DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1; // FIXME: this is an abstraction breakage
211 mask = ~(-1L << DataLatch_WIDTH);
214 // Misc //////////////////////////////////////////////////////////////////////////////
216 public boolean isSmallEnoughToFit(long immediate) {
217 if ((immediate & ~mask) == 0) return true;
218 if ((immediate | mask) == -1L) return true;
222 public boolean isSmallEnoughToFit(BitVector immediate) {
223 boolean b = immediate.get((int)DataLatch_WIDTH);
224 for(int i=DataLatch_WIDTH+1; i<immediate.length(); i++)
225 if (immediate.get(i) != b) return false;
229 public int getWordWidth() { return 37; }
231 //////////////////////////////////////////////////////////////////////////////
233 /** get the bits describing this box's location on the DESTINATION HORN */
234 protected abstract BitVector getDestAddr(Path box);
236 private static final BitVector SIGNAL_ZERO = new BitVector(1);
237 private static final BitVector SIGNAL_ONE = new BitVector(1).set(0,true);
239 /** decode a path, given the starting point and the bits that comprise it */
240 public Path getPathByAddr(Dock source, BitVector dest) {
241 for(Ship ship : this)
242 for(Dock bb : ship) {
243 for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) {
244 for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) {
245 Path p = (Path)source.getPath(d, signal);
246 if (getDestAddr(p).equalsZeroExtended(dest)) return p;
253 public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) {
254 return readInstruction(instruction.toLong(), dispatchFrom);
257 public BitVector encodeInstruction(Instruction instr, Dock dispatchFrom) {
258 return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom));
261 public int getShiftWidth() { return SHIFT.valmaskwidth; }
262 public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; }
265 public int getMaxCodeBagSize() {
266 return (1<<CBD_SIZE.valmaskwidth)-1;
268 public BitVector makeCodeBagDescriptor(long offset, long length) {
269 BitVector descriptor = new BitVector(getWordWidth());
270 CBD_OFFSET.setval(descriptor, offset);
271 CBD_SIZE.setval(descriptor, length);
277 // FIXME: should use BitVector here
278 public Instruction readInstruction(long inst, Dock dispatchFrom) {
279 Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock();
281 if (TAIL.get(inst)) return new Tail(dock);
282 if (HEAD.get(inst)) return new Head(dock);
284 Predicate predicate = Default;
285 if (P_ALWAYS.get(inst)) predicate = IgnoreFlagD;
286 if (P_OLC_NONZERO.get(inst)) predicate = Default;
287 if (P_OLC_ZERO.get(inst)) predicate = FlagD;
288 if (P_A.get(inst)) predicate = FlagA;
289 if (P_B.get(inst)) predicate = FlagB;
290 if (P_NOT_A.get(inst)) predicate = NotFlagA;
291 if (P_NOT_B.get(inst)) predicate = NotFlagB;
294 return new Flush(dock, predicate);
296 return new Abort(dock, predicate);
297 if (SHIFT.get(inst)) return new Shift(dock, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst)));
298 if (SET_IMMEDIATE.get(inst)) {
299 boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
300 long immediate = SET_IMMEDIATE.getval(inst);
301 if (extend) immediate |= (-1L << DataLatch_WIDTH);
302 return new Set(dock, predicate, SetDest.DataLatch, (immediate));
305 if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
306 return new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
307 if (SET_OLC_FROM_IMMEDIATE.get(inst))
308 return new Set(dock, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
309 if (SET_ILC_FROM_IMMEDIATE.get(inst))
310 return new Set(dock, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
311 if (SET_OLC_FROM_DATA_LATCH.get(inst))
312 return new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
313 if (SET_ILC_FROM_DATA_LATCH.get(inst))
314 return new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
315 if (SET_ILC_FROM_INFINITY.get(inst))
316 return new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
317 if (SET_FLAGS.get(inst)) {
318 long flag_a = SET_FLAGS_A.getval(inst);
319 long flag_b = SET_FLAGS_B.getval(inst);
320 FlagFunction ap = FlagFunction.ZERO;
321 FlagFunction bp = FlagFunction.ZERO;
322 if (SET_FLAGS_VALUE_A .get(flag_a)) ap = ap.add(FlagA );
323 if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
324 if (SET_FLAGS_VALUE_B .get(flag_a)) ap = ap.add(FlagB );
325 if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
326 if (SET_FLAGS_VALUE_C .get(flag_a)) ap = ap.add(FlagC );
327 if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
328 if (SET_FLAGS_VALUE_A .get(flag_b)) bp = bp.add(FlagA );
329 if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
330 if (SET_FLAGS_VALUE_B .get(flag_b)) bp = bp.add(FlagB );
331 if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
332 if (SET_FLAGS_VALUE_C .get(flag_b)) bp = bp.add(FlagC );
333 if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
334 return new Set(dock, predicate, ap, bp);
337 return new Move(dock,
339 !NOT_INTERRUPTIBLE.get(inst),
340 PATH_DATA.get(inst)?null:getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)),
343 hack?(!DC.get(inst)):DC.get(inst),
348 throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
351 // FIXME: should use BitVector here
352 public long writeInstruction(Instruction d, Dock dispatchFrom) {
355 if (d.dock != null) {
356 BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null));
357 BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth);
358 for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
359 bv2.set(i, bv.get(i));
360 instr = DISPATCH_PATH.setval(instr, bv2);
365 switch(pi.predicate) {
366 case IgnoreFlagD: instr = P_ALWAYS.set(instr); break;
367 case FlagD: instr = P_OLC_ZERO.set(instr); break;
368 case Default: instr = P_OLC_NONZERO.set(instr); break;
369 case FlagA: instr = P_A.set(instr); break;
370 case FlagB: instr = P_B.set(instr); break;
371 case NotFlagA: instr = P_NOT_A.set(instr); break;
372 case NotFlagB: instr = P_NOT_B.set(instr); break;
373 default: throw new RuntimeException("error!");
376 if (d instanceof Tail) {
377 instr = TAIL.set(instr);
379 } else if (d instanceof Head) {
380 instr = HEAD.set(instr);
382 } else if (d instanceof Shift) {
383 Shift shift = (Shift)d;
384 instr = SHIFT.set(instr);
385 instr = SHIFT.setval(instr, shift.immediate.getBitVector());
387 } else if (d instanceof Flush) {
388 instr = FLUSH.set(instr);
390 } else if (d instanceof Abort) {
391 instr = ABORT.set(instr);
393 } else if (d instanceof Set) {
396 case InnerLoopCounter:
399 instr = SET_ILC_FROM_DATA_LATCH.set(instr);
402 instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
405 instr = SET_ILC_FROM_INFINITY.set(instr);
409 case OuterLoopCounter:
412 instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
415 instr = SET_OLC_FROM_DATA_LATCH.set(instr);
418 instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
423 instr = SET_FLAGS.set(instr);
424 instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
425 instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
429 instr = SET_IMMEDIATE.set(instr);
430 instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
431 instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
436 } else if (d instanceof Move) {
438 instr = MOVE.set(instr);
439 if (inst.tokenIn) instr = TI.set(instr);
440 if (inst.dataIn) instr = DI.set(instr);
442 if (!inst.latchData) instr = DC.set(instr);
443 System.err.println("WARNING: employing inverted-Dc-bit hack -- DO NOT FORGET TO DISABLE THIS WHEN THE NETLIST GETS UPDATED!");
445 if (inst.latchData) instr = DC.set(instr);
447 if (inst.dataOut) instr = DO.set(instr);
448 if (inst.tokenOut) instr = TO.set(instr);
449 if (!inst.interruptible) instr = NOT_INTERRUPTIBLE.set(instr);
450 else instr = IS_INTERRUPTIBLE.set(instr);
452 if (inst.latchPath) instr = PATH_DATA.set(instr);
453 else if (inst.path!=null) {
454 instr = PATH_IMMEDIATE.set(instr);
455 BitVector bv = getDestAddr(inst.path);
456 BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
457 for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
458 bv2.set(i, bv.get(i));
459 instr = PATH_IMMEDIATE.setval(instr, bv2);
461 instr = PATH_NOCHANGE.set(instr);
465 throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
471 private long flagFunctionToLong(FlagFunction ff) {
473 for(Predicate p : ff)
475 case FlagA : ret = SET_FLAGS_VALUE_A .set(ret); break;
476 case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
477 case FlagB : ret = SET_FLAGS_VALUE_B .set(ret); break;
478 case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
479 case FlagC : ret = SET_FLAGS_VALUE_C .set(ret); break;
480 case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
481 default: throw new RuntimeException();