change readInstruction/writeInstruction to encodeInstruction/decodeInstruction
[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 static final Mask PACKET_TOKEN               = new Mask("v.................................................");
14     public static final Mask PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
15     public static final Mask PACKET_SIGNAL              = new Mask("......................................v...........");
16     public static final Mask PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
17
18     public static final Mask CBD_SIZE                   = new Mask("...............................vvvvvv");
19     public static final Mask CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
20
21     public static final int  WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
22     public static final int  WIDTH_PACKET               = PACKET_TOKEN.width;
23
24     public static final Mask WHOLE_WORD                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
25     public static final Mask DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
26     public static final Mask DISPATCH_INSTR             = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
27     public static final Mask I                          = new Mask("...........1.........................");
28     public static final Mask OS                         = new Mask("............1........................");
29     public static final Mask P                          = new Mask(".............vvv.....................");
30     public static final Mask P_NOT_A                    = new Mask(".............000.....................");
31     public static final Mask P_A                        = new Mask(".............001.....................");
32     public static final Mask P_NOT_B                    = new Mask(".............010.....................");
33     public static final Mask P_B                        = new Mask(".............011.....................");
34     public static final Mask P_UNUSED                   = new Mask(".............100.....................");
35     public static final Mask P_OLC_ZERO                 = new Mask(".............101.....................");
36     public static final Mask P_OLC_NONZERO              = new Mask(".............110.....................");
37     public static final Mask P_ALWAYS                   = new Mask(".............111.....................");
38
39     public static final Mask SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
40
41     public static final Mask TAIL                       = new Mask("................11...................");
42
43     public static final Mask MOVE                       = new Mask("................01...................");
44     public static final Mask TI                         = new Mask("................011..................");
45     public static final Mask DI                         = new Mask("................01.1.................");
46     public static final Mask FLUSH                      = new Mask("................01.01................");
47     public static final Mask DC                         = new Mask("................01.11................");
48     public static final Mask DO                         = new Mask("................01...1...............");
49     public static final Mask TO                         = new Mask("................01....1..............");
50     public static final Mask PATH_IMMEDIATE             = new Mask("................01.....1vvvvvvvvvvvvv");
51     public static final Mask PATH_DATA                  = new Mask("................01.....01............");
52     public static final Mask PATH_NOCHANGE              = new Mask("................01.....00............");
53
54     public static final Mask SET_OLC_FROM_IMMEDIATE     = new Mask("................101000100......vvvvvv");
55     public static final Mask SET_OLC_FROM_DATA_LATCH    = new Mask("................101000010............");
56     public static final Mask SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
57
58     public static final Mask SET_ILC_FROM_IMMEDIATE     = new Mask("................10010010......0vvvvvv");
59     public static final Mask SET_ILC_FROM_INFINITY      = new Mask("................10010010......1......");
60     public static final Mask SET_ILC_FROM_DATA_LATCH    = new Mask("................10010001.............");
61
62     public static final Mask SET_IMMEDIATE              = new Mask("................100010.vvvvvvvvvvvvvv");
63     public static final Mask SET_IMMEDIATE_EXTEND       = new Mask("................100010v..............");
64
65     public static final Mask SET_FLAGS                  = new Mask("................100001...............");
66     public static final Mask SET_FLAGS_A                = new Mask("................100001...vvvvvv......");
67     public static final Mask SET_FLAGS_B                = new Mask("................100001.........vvvvvv");
68     public static final Mask SET_FLAGS_VALUE_A          = new Mask("1.....");
69     public static final Mask SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
70     public static final Mask SET_FLAGS_VALUE_B          = new Mask("..1...");
71     public static final Mask SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
72     public static final Mask SET_FLAGS_VALUE_C          = new Mask("....1.");
73     public static final Mask SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
74
75     // Misc //////////////////////////////////////////////////////////////////////////////
76
77     public static final long DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
78     private static final long mask  = ~(-1L << DataLatch_WIDTH);
79     public static boolean isSmallEnoughToFit(long immediate) {
80         if ((immediate & ~mask) == 0)   return true;
81         if ((immediate |  mask) == -1L) return true;
82         return false;
83     }
84
85     public int getWordWidth() { return 37; }
86
87     //////////////////////////////////////////////////////////////////////////////
88
89     /** get the bits describing this box's location on the DESTINATION HORN */
90     protected abstract BitVector getDestAddr(Path box);
91
92     private static final BitVector SIGNAL_ZERO = new BitVector(1);
93     private static final BitVector SIGNAL_ONE  = new BitVector(1).set(0,true);
94
95     /** decode a path, given the starting point and the bits that comprise it */
96     public Path getPathByAddr(Dock source, BitVector dest) {
97         for(Ship ship : this)
98             for(Dock bb : ship) {
99                 for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) {
100                     for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) {
101                         Path p = (Path)source.getPath(d, signal);
102                         if (getDestAddr(p).equals(dest)) return p;
103                     }
104                 }
105             }
106         return null;
107     }
108
109     public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) {
110         return readInstruction(instruction.toLong(), dispatchFrom);
111     }
112
113     public BitVector   encodeInstruction(Instruction instr, Dock dispatchFrom) {
114         return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom));
115     }
116
117     public int getShiftWidth() { return SHIFT.valmaskwidth; }
118     public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; }
119
120     // FIXME: should use BitVector here
121     public Instruction readInstruction(long inst, Dock dispatchFrom) {
122         Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock();
123
124         if (TAIL.get(inst))   return new Tail(dock);
125
126         Predicate predicate = Default;
127         if (P_ALWAYS.get(inst)) predicate = IgnoreOLC;
128         if (P_OLC_NONZERO.get(inst))    predicate = Default;
129         if (P_OLC_ZERO.get(inst))    predicate = OLCZero;
130         if (P_A.get(inst))      predicate = FlagA;
131         if (P_B.get(inst))      predicate = FlagB;
132         if (P_NOT_A.get(inst))  predicate = NotFlagA;
133         if (P_NOT_B.get(inst))  predicate = NotFlagB;
134
135         boolean looping = !OS.get(inst);
136         if (FLUSH.get(inst))
137             return new Flush(dock, looping, predicate);
138         if (SHIFT.get(inst))                return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst)));
139         if (SET_IMMEDIATE.get(inst)) {
140             boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
141             long immediate = SET_IMMEDIATE.getval(inst);
142             if (extend) immediate |= (-1L << DataLatch_WIDTH);
143             return new Set(dock, looping, predicate, SetDest.DataLatch, (immediate));
144         }
145
146         if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
147             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
148         if (SET_OLC_FROM_IMMEDIATE.get(inst))
149             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
150         if (SET_ILC_FROM_IMMEDIATE.get(inst))
151             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
152         if (SET_OLC_FROM_DATA_LATCH.get(inst))
153             return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
154         if (SET_ILC_FROM_DATA_LATCH.get(inst))
155             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
156         if (SET_ILC_FROM_INFINITY.get(inst))
157             return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
158         if (SET_FLAGS.get(inst)) {
159             long flag_a = SET_FLAGS_A.getval(inst);
160             long flag_b = SET_FLAGS_B.getval(inst);
161             FlagFunction ap = FlagFunction.ZERO;
162             FlagFunction bp = FlagFunction.ZERO;
163             if (SET_FLAGS_VALUE_A    .get(flag_a)) ap = ap.add(FlagA    );
164             if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
165             if (SET_FLAGS_VALUE_B    .get(flag_a)) ap = ap.add(FlagB    );
166             if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
167             if (SET_FLAGS_VALUE_C    .get(flag_a)) ap = ap.add(FlagC    );
168             if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
169             if (SET_FLAGS_VALUE_A    .get(flag_b)) bp = bp.add(FlagA    );
170             if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
171             if (SET_FLAGS_VALUE_B    .get(flag_b)) bp = bp.add(FlagB    );
172             if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
173             if (SET_FLAGS_VALUE_C    .get(flag_b)) bp = bp.add(FlagC    );
174             if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
175             return new Set(dock, looping, predicate, ap, bp);
176         }
177         if (MOVE.get(inst))
178             return new Move(dock,
179                             looping,
180                             predicate,
181                             I.get(inst),
182                             getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)),
183                             TI.get(inst),
184                             DI.get(inst),
185                             DC.get(inst),
186                             PATH_DATA.get(inst),
187                             DO.get(inst),
188                             TO.get(inst)
189                             );
190         throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
191     }
192
193     public long writeInstruction(Instruction d, Dock dispatchFrom) {
194         long instr = 0;
195
196         if (d.dock != null) {
197             BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null));
198             BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth);
199             for(int i=0; i<bv2.length(); i++)
200                 bv2.set(i, bv.get(i));
201             instr = DISPATCH_PATH.setval(instr, bv2);
202         }
203
204         boolean dl = false;
205         Instruction pi = d;
206         if (!pi.looping) instr = OS.set(instr);
207         switch(pi.predicate) {
208             case IgnoreOLC:         instr = P_ALWAYS.set(instr); break;
209             case OLCZero:         instr = P_OLC_ZERO.set(instr); break;
210             case Default: instr = P_OLC_NONZERO.set(instr); break;
211             case FlagA:      instr = P_A.set(instr);      break;
212             case FlagB:      instr = P_B.set(instr);      break;
213             case NotFlagA:  instr = P_NOT_A.set(instr);      break;
214             case NotFlagB:  instr = P_NOT_B.set(instr);      break;
215             default: throw new RuntimeException("error!");
216         }
217
218         if (d instanceof Tail) {
219             instr = TAIL.set(instr);
220
221         } else if (d instanceof Shift) {
222             Shift shift = (Shift)d;
223             instr = SHIFT.set(instr);
224             instr = SHIFT.setval(instr, shift.immediate);
225
226         } else if (d instanceof Flush) {
227             instr = FLUSH.set(instr);
228
229         } else if (d instanceof Set) {
230             Set s = (Set)d;
231             switch(s.dest) {
232                 case InnerLoopCounter:
233                     switch(s.source) {
234                         case DataLatch:
235                             instr = SET_ILC_FROM_DATA_LATCH.set(instr);
236                             break;
237                         case Immediate:
238                             instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
239                             break;
240                         case Infinity:
241                             instr = SET_ILC_FROM_INFINITY.set(instr);
242                             break;
243                     }
244                     break;
245                 case OuterLoopCounter:
246                     switch(s.source) {
247                         case Decrement:
248                             instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
249                             break;
250                         case DataLatch:
251                             instr = SET_OLC_FROM_DATA_LATCH.set(instr);
252                             break;
253                         case Immediate:
254                             instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
255                             break;
256                     }
257                     break;
258                 case Flags: {
259                     instr = SET_FLAGS.set(instr);
260                     instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
261                     instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
262                     break;
263                 }
264                 case DataLatch: {
265                     instr = SET_IMMEDIATE.set(instr);
266                     instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
267                     instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
268                     break;
269                 }
270             }
271
272         } else if (d instanceof Move) {
273             Move inst = (Move)d;
274             instr  = MOVE.set(instr);
275             if (inst.tokenIn)                    instr = TI.set(instr);
276             if (inst.dataIn)                     instr = DI.set(instr);
277             if (inst.latchData)                  instr = DC.set(instr);
278             if (inst.dataOut)                    instr = DO.set(instr);
279             if (inst.tokenOut)                   instr = TO.set(instr);
280             if (inst.interruptible)              instr = I.set(instr);
281
282             if (inst.latchPath)                  instr = PATH_DATA.set(instr);
283             else {
284                 instr  = PATH_IMMEDIATE.set(instr);
285                 if (inst.path != null) {
286                     BitVector bv  = getDestAddr(inst.path);
287                     BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
288                     for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
289                         bv2.set(i, bv.get(i));
290                     instr  = PATH_IMMEDIATE.setval(instr, bv2);
291                 }
292             }
293
294         } else {
295             throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
296
297         }
298         return instr;
299     }
300
301     private long flagFunctionToLong(FlagFunction ff) {
302         long ret = 0;
303         for(Predicate p : ff)
304             switch(p) {
305                 case FlagA    : ret = SET_FLAGS_VALUE_A    .set(ret); break;
306                 case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
307                 case FlagB    : ret = SET_FLAGS_VALUE_B    .set(ret); break;
308                 case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
309                 case FlagC    : ret = SET_FLAGS_VALUE_C    .set(ret); break;
310                 case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
311                 default: throw new RuntimeException();
312             }
313         return ret;
314     }
315
316 }