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