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