fix ArrayIndexOutOfBoundsException in FleetTwoFleet
[fleet.git] / src / edu / berkeley / fleet / two / FleetTwoFleet.java
1 package edu.berkeley.fleet.two;
2 import java.io.*;
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.*;
9
10 /** common subclass for the "FleetTwo" generation of processors, all 37-bit wide, with AM33 encoding */
11 public abstract class FleetTwoFleet extends Fleet {
12
13     public final Mask PACKET_TOKEN;
14     public final Mask PACKET_DATA;
15     public final Mask PACKET_SIGNAL;
16     public final Mask PACKET_DEST;
17
18     public final Mask CBD_SIZE;
19     public final Mask CBD_OFFSET;
20
21     public final Mask WHOLE_WORD;
22     public final Mask DISPATCH_PATH;
23     public final Mask DISPATCH_INSTR;
24     public final Mask NOT_INTERRUPTIBLE;
25     public final Mask OS;
26     public final Mask P;
27     public final Mask P_NOT_A;
28     public final Mask P_A;
29     public final Mask P_NOT_B;
30     public final Mask P_B;
31     public final Mask P_UNUSED;
32     public final Mask P_OLC_ZERO;
33     public final Mask P_OLC_NONZERO;
34     public final Mask P_ALWAYS;
35
36     public final Mask SHIFT;
37
38     public final Mask TAIL;
39
40     public final Mask MOVE;
41     public final Mask TI;
42     public final Mask DI;
43     public final Mask FLUSH;
44     public final Mask DC;
45     public final Mask DO;
46     public final Mask TO;
47     public final Mask PATH_IMMEDIATE;
48     public final Mask PATH_DATA;
49     public final Mask PATH_NOCHANGE;
50
51     public final Mask SET_OLC_FROM_IMMEDIATE;
52     public final Mask SET_OLC_FROM_DATA_LATCH;
53     public final Mask SET_OLC_FROM_OLC_MINUS_ONE;
54
55     public final Mask SET_ILC_FROM_IMMEDIATE;
56     public final Mask SET_ILC_FROM_INFINITY;
57     public final Mask SET_ILC_FROM_DATA_LATCH;
58
59     public final Mask SET_IMMEDIATE;
60     public final Mask SET_IMMEDIATE_EXTEND;
61
62     public final Mask SET_FLAGS;
63     public final Mask SET_FLAGS_A;
64     public final Mask SET_FLAGS_B;
65     public final Mask SET_FLAGS_VALUE_A;
66     public final Mask SET_FLAGS_VALUE_NOT_A;
67     public final Mask SET_FLAGS_VALUE_B;
68     public final Mask SET_FLAGS_VALUE_NOT_B;
69     public final Mask SET_FLAGS_VALUE_C;
70     public final Mask SET_FLAGS_VALUE_NOT_C;
71
72     public final int  WIDTH_WORD;
73     public final int  WIDTH_PACKET;
74
75     public final long DataLatch_WIDTH;
76     private final long mask;
77
78     public FleetTwoFleet() { this(false); }
79
80     public FleetTwoFleet(boolean useInternalEncoding) {
81         PACKET_TOKEN               = new Mask("v.................................................");
82         PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
83         PACKET_SIGNAL              = new Mask("......................................v...........");
84         PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
85
86         CBD_SIZE                   = new Mask("...............................vvvvvv");
87         CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
88
89         WHOLE_WORD                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
90
91         if (useInternalEncoding) {
92
93             DISPATCH_PATH              = new Mask("v....................................");
94             DISPATCH_INSTR             = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
95             NOT_INTERRUPTIBLE          = new Mask(".................1...................");
96             OS                         = new Mask(".......1.............................");
97             P                          = new Mask(".vvvvvv..............................");
98             P_NOT_A                    = new Mask(".100001..............................");
99             P_A                        = new Mask(".100010..............................");
100             P_NOT_B                    = new Mask(".100100..............................");
101             P_B                        = new Mask(".101000..............................");
102             P_UNUSED                   = new Mask(".111111..............................");
103             P_OLC_ZERO                 = new Mask(".010000..............................");
104             P_OLC_NONZERO              = new Mask(".100000..............................");
105             P_ALWAYS                   = new Mask(".000000..............................");
106
107             SHIFT                      = new Mask("..........101111.1vvvvvvvvvvvvvvvvvvv");
108
109             TAIL                       = new Mask("................1....................");
110
111             MOVE                       = new Mask("..........110111.....................");
112             TI                         = new Mask("..........110111..1..................");
113             DI                         = new Mask("..........110111...1.................");
114             FLUSH                      = new Mask("..........110111...01................");
115             DC                         = new Mask("..........110111...11................");
116             DO                         = new Mask("..........110111.....1...............");
117             TO                         = new Mask("..........110111......1..............");
118             PATH_IMMEDIATE             = new Mask("..........110111.......0vvvvvvvvvvvvv");
119             PATH_DATA                  = new Mask("..........110111.......11............");
120             PATH_NOCHANGE              = new Mask("..........110111.......10............");
121
122             SET_OLC_FROM_IMMEDIATE     = new Mask("..........111101.0.............vvvvvv");
123             SET_OLC_FROM_DATA_LATCH    = new Mask("..........111101.1...................");
124             SET_OLC_FROM_OLC_MINUS_ONE = new Mask("..........111011.....................");
125
126             SET_ILC_FROM_IMMEDIATE     = new Mask("..........011111.0...........0.vvvvvv");
127             SET_ILC_FROM_INFINITY      = new Mask("..........011111.............1.......");
128             SET_ILC_FROM_DATA_LATCH    = new Mask("..........011111.1...................");
129
130             SET_IMMEDIATE              = new Mask("..........101111.0.....vvvvvvvvvvvvvv");
131             SET_IMMEDIATE_EXTEND       = new Mask("..........101111.0....v..............");
132
133             SET_FLAGS                  = new Mask("..........111110.....................");
134             SET_FLAGS_A                = new Mask("..........111110.........vvvvvv......");
135             SET_FLAGS_B                = new Mask("..........111110...............vvvvvv");
136         } else {
137             DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
138             DISPATCH_INSTR             = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
139             NOT_INTERRUPTIBLE          = new Mask("...........1.........................");
140             OS                         = new Mask("............1........................");
141             P                          = new Mask(".............vvv.....................");
142             P_NOT_A                    = new Mask(".............000.....................");
143             P_A                        = new Mask(".............001.....................");
144             P_NOT_B                    = new Mask(".............010.....................");
145             P_B                        = new Mask(".............011.....................");
146             P_UNUSED                   = new Mask(".............100.....................");
147             P_OLC_ZERO                 = new Mask(".............101.....................");
148             P_OLC_NONZERO              = new Mask(".............110.....................");
149             P_ALWAYS                   = new Mask(".............111.....................");
150
151             SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
152
153             TAIL                       = new Mask("................11...................");
154
155             MOVE                       = new Mask("................01...................");
156             TI                         = new Mask("................011..................");
157             DI                         = new Mask("................01.1.................");
158             FLUSH                      = new Mask("................01.01................");
159             DC                         = new Mask("................01.11................");
160             DO                         = new Mask("................01...1...............");
161             TO                         = new Mask("................01....1..............");
162             PATH_IMMEDIATE             = new Mask("................01.....1vvvvvvvvvvvvv");
163             PATH_DATA                  = new Mask("................01.....01............");
164             PATH_NOCHANGE              = new Mask("................01.....00............");
165
166             SET_OLC_FROM_IMMEDIATE     = new Mask("................101000100......vvvvvv");
167             SET_OLC_FROM_DATA_LATCH    = new Mask("................101000010............");
168             SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
169
170             SET_ILC_FROM_IMMEDIATE     = new Mask("................10010010......0vvvvvv");
171             SET_ILC_FROM_INFINITY      = new Mask("................10010010......1......");
172             SET_ILC_FROM_DATA_LATCH    = new Mask("................10010001.............");
173
174             SET_IMMEDIATE              = new Mask("................100010.vvvvvvvvvvvvvv");
175             SET_IMMEDIATE_EXTEND       = new Mask("................100010v..............");
176
177             SET_FLAGS                  = new Mask("................100001...............");
178             SET_FLAGS_A                = new Mask("................100001...vvvvvv......");
179             SET_FLAGS_B                = new Mask("................100001.........vvvvvv");
180         }
181         SET_FLAGS_VALUE_A          = new Mask("1.....");
182         SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
183         SET_FLAGS_VALUE_B          = new Mask("..1...");
184         SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
185         SET_FLAGS_VALUE_C          = new Mask("....1.");
186         SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
187
188         WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
189         WIDTH_PACKET               = PACKET_TOKEN.width;
190         DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
191         mask  = ~(-1L << DataLatch_WIDTH);
192     }
193
194     // Misc //////////////////////////////////////////////////////////////////////////////
195
196     public boolean isSmallEnoughToFit(long immediate) {
197         if ((immediate & ~mask) == 0)   return true;
198         if ((immediate |  mask) == -1L) return true;
199         return false;
200     }
201
202     public int getWordWidth() { return 37; }
203
204     //////////////////////////////////////////////////////////////////////////////
205
206     /** get the bits describing this box's location on the DESTINATION HORN */
207     protected abstract BitVector getDestAddr(Path box);
208
209     private static final BitVector SIGNAL_ZERO = new BitVector(1);
210     private static final BitVector SIGNAL_ONE  = new BitVector(1).set(0,true);
211
212     /** decode a path, given the starting point and the bits that comprise it */
213     public Path getPathByAddr(Dock source, BitVector dest) {
214         for(Ship ship : this)
215             for(Dock bb : ship) {
216                 for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) {
217                     for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) {
218                         Path p = (Path)source.getPath(d, signal);
219                         if (getDestAddr(p).equals(dest)) return p;
220                     }
221                 }
222             }
223         return null;
224     }
225
226     public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) {
227         return readInstruction(instruction.toLong(), dispatchFrom);
228     }
229
230     public BitVector   encodeInstruction(Instruction instr, Dock dispatchFrom) {
231         return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom));
232     }
233
234     public int getShiftWidth() { return SHIFT.valmaskwidth; }
235     public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; }
236
237     // FIXME: should use BitVector here
238     public Instruction readInstruction(long inst, Dock dispatchFrom) {
239         Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock();
240
241         if (TAIL.get(inst))   return new Tail(dock);
242
243         Predicate predicate = Default;
244         if (P_ALWAYS.get(inst)) predicate = IgnoreOLC;
245         if (P_OLC_NONZERO.get(inst))    predicate = Default;
246         if (P_OLC_ZERO.get(inst))    predicate = OLCZero;
247         if (P_A.get(inst))      predicate = FlagA;
248         if (P_B.get(inst))      predicate = FlagB;
249         if (P_NOT_A.get(inst))  predicate = NotFlagA;
250         if (P_NOT_B.get(inst))  predicate = NotFlagB;
251
252         boolean looping = !OS.get(inst);
253         if (FLUSH.get(inst))
254             return new Flush(dock, looping, predicate);
255         if (SHIFT.get(inst))                return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst)));
256         if (SET_IMMEDIATE.get(inst)) {
257             boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
258             long immediate = SET_IMMEDIATE.getval(inst);
259             if (extend) immediate |= (-1L << DataLatch_WIDTH);
260             return new Set(dock, looping, predicate, SetDest.DataLatch, (immediate));
261         }
262
263         if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
264             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
265         if (SET_OLC_FROM_IMMEDIATE.get(inst))
266             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
267         if (SET_ILC_FROM_IMMEDIATE.get(inst))
268             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
269         if (SET_OLC_FROM_DATA_LATCH.get(inst))
270             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
271         if (SET_ILC_FROM_DATA_LATCH.get(inst))
272             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
273         if (SET_ILC_FROM_INFINITY.get(inst))
274             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
275         if (SET_FLAGS.get(inst)) {
276             long flag_a = SET_FLAGS_A.getval(inst);
277             long flag_b = SET_FLAGS_B.getval(inst);
278             FlagFunction ap = FlagFunction.ZERO;
279             FlagFunction bp = FlagFunction.ZERO;
280             if (SET_FLAGS_VALUE_A    .get(flag_a)) ap = ap.add(FlagA    );
281             if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
282             if (SET_FLAGS_VALUE_B    .get(flag_a)) ap = ap.add(FlagB    );
283             if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
284             if (SET_FLAGS_VALUE_C    .get(flag_a)) ap = ap.add(FlagC    );
285             if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
286             if (SET_FLAGS_VALUE_A    .get(flag_b)) bp = bp.add(FlagA    );
287             if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
288             if (SET_FLAGS_VALUE_B    .get(flag_b)) bp = bp.add(FlagB    );
289             if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
290             if (SET_FLAGS_VALUE_C    .get(flag_b)) bp = bp.add(FlagC    );
291             if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
292             return new Set(dock, looping, predicate, ap, bp);
293         }
294         if (MOVE.get(inst))
295             return new Move(dock,
296                             looping,
297                             predicate,
298                             !NOT_INTERRUPTIBLE.get(inst),
299                             getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)),
300                             TI.get(inst),
301                             DI.get(inst),
302                             DC.get(inst),
303                             PATH_DATA.get(inst),
304                             DO.get(inst),
305                             TO.get(inst)
306                             );
307         throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
308     }
309
310     // FIXME: should use BitVector here
311     public long writeInstruction(Instruction d, Dock dispatchFrom) {
312         long instr = 0;
313
314         if (d.dock != null) {
315             BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null));
316             BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth);
317             for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
318                 bv2.set(i, bv.get(i));
319             instr = DISPATCH_PATH.setval(instr, bv2);
320         }
321
322         boolean dl = false;
323         Instruction pi = d;
324         if (!pi.looping) instr = OS.set(instr);
325         switch(pi.predicate) {
326             case IgnoreOLC:         instr = P_ALWAYS.set(instr); break;
327             case OLCZero:         instr = P_OLC_ZERO.set(instr); break;
328             case Default: instr = P_OLC_NONZERO.set(instr); break;
329             case FlagA:      instr = P_A.set(instr);      break;
330             case FlagB:      instr = P_B.set(instr);      break;
331             case NotFlagA:  instr = P_NOT_A.set(instr);      break;
332             case NotFlagB:  instr = P_NOT_B.set(instr);      break;
333             default: throw new RuntimeException("error!");
334         }
335
336         if (d instanceof Tail) {
337             instr = TAIL.set(instr);
338
339         } else if (d instanceof Shift) {
340             Shift shift = (Shift)d;
341             instr = SHIFT.set(instr);
342             instr = SHIFT.setval(instr, shift.immediate);
343
344         } else if (d instanceof Flush) {
345             instr = FLUSH.set(instr);
346
347         } else if (d instanceof Set) {
348             Set s = (Set)d;
349             switch(s.dest) {
350                 case InnerLoopCounter:
351                     switch(s.source) {
352                         case DataLatch:
353                             instr = SET_ILC_FROM_DATA_LATCH.set(instr);
354                             break;
355                         case Immediate:
356                             instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
357                             break;
358                         case Infinity:
359                             instr = SET_ILC_FROM_INFINITY.set(instr);
360                             break;
361                     }
362                     break;
363                 case OuterLoopCounter:
364                     switch(s.source) {
365                         case Decrement:
366                             instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
367                             break;
368                         case DataLatch:
369                             instr = SET_OLC_FROM_DATA_LATCH.set(instr);
370                             break;
371                         case Immediate:
372                             instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
373                             break;
374                     }
375                     break;
376                 case Flags: {
377                     instr = SET_FLAGS.set(instr);
378                     instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
379                     instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
380                     break;
381                 }
382                 case DataLatch: {
383                     instr = SET_IMMEDIATE.set(instr);
384                     instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
385                     instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
386                     break;
387                 }
388             }
389
390         } else if (d instanceof Move) {
391             Move inst = (Move)d;
392             instr  = MOVE.set(instr);
393             if (inst.tokenIn)                    instr = TI.set(instr);
394             if (inst.dataIn)                     instr = DI.set(instr);
395             if (inst.latchData)                  instr = DC.set(instr);
396             if (inst.dataOut)                    instr = DO.set(instr);
397             if (inst.tokenOut)                   instr = TO.set(instr);
398             if (!inst.interruptible)             instr = NOT_INTERRUPTIBLE.set(instr);
399
400             if (inst.latchPath)                  instr = PATH_DATA.set(instr);
401             else {
402                 instr  = PATH_IMMEDIATE.set(instr);
403                 if (inst.path != null) {
404                     BitVector bv  = getDestAddr(inst.path);
405                     BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
406                     for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
407                         bv2.set(i, bv.get(i));
408                     instr  = PATH_IMMEDIATE.setval(instr, bv2);
409                 }
410             }
411
412         } else {
413             throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
414
415         }
416         return instr;
417     }
418
419     private long flagFunctionToLong(FlagFunction ff) {
420         long ret = 0;
421         for(Predicate p : ff)
422             switch(p) {
423                 case FlagA    : ret = SET_FLAGS_VALUE_A    .set(ret); break;
424                 case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
425                 case FlagB    : ret = SET_FLAGS_VALUE_B    .set(ret); break;
426                 case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
427                 case FlagC    : ret = SET_FLAGS_VALUE_C    .set(ret); break;
428                 case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
429                 default: throw new RuntimeException();
430             }
431         return ret;
432     }
433
434 }