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