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