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