remove magic constant 19 from literal encodings
[fleet.git] / src / edu / berkeley / fleet / ies44 / InstructionEncoder.java
1 package edu.berkeley.fleet.ies44;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.*;
4 import edu.berkeley.fleet.util.*;
5 import java.io.*;
6 import static edu.berkeley.fleet.util.BitManipulations.*;
7 import static edu.berkeley.fleet.api.Instruction.*;
8 import static edu.berkeley.fleet.api.Instruction.Counter.*;
9
10 public abstract class InstructionEncoder {
11
12     public static final int WIDTH_WORD             = 37;
13     public static final int WIDTH_ADDR             = 11;
14     public static final int WIDTH_CODEBAG_SIZE     = 6;
15     public static final int WIDTH_COUNTER_LITERAL  = 6;
16
17     public static final Mask FLAGS                = new Mask("...............000000................");
18     public static final Mask FLAGS_A              = new Mask("...............000000vvvvvvvv........");
19     public static final Mask FLAGS_B              = new Mask("...............000000........vvvvvvvv");
20     public static final Mask REPEAT_FROM_DATA     = new Mask("...............000001........00......");
21     public static final Mask REPEAT_FROM_LITERAL  = new Mask("...............000001........10vvvvvv");
22     public static final Mask REPEAT_FROM_STANDING = new Mask("...............000001........11......");
23     public static final Mask LOOP_FROM_DATA       = new Mask("...............000010.........0......");
24     public static final Mask LOOP_FROM_LITERAL    = new Mask("...............000010.........1vvvvvv");
25     public static final Mask TAKE_LOOP            = new Mask("...............000011................");
26     public static final Mask KILL                 = new Mask("...............000100................");
27     public static final Mask MASSACRE             = new Mask("...............000101................");
28     public static final Mask CLOG                 = new Mask("...............000110................");
29     public static final Mask UNCLOG               = new Mask("...............000111................");
30
31     public static final Mask SK                  = new Mask("...........1.........................");
32     public static final Mask DL                  = new Mask("............1........................");
33     public static final Mask P                   = new Mask(".............vv......................");
34     public static final Mask P_A                 = new Mask(".............00......................");
35     public static final Mask P_B                 = new Mask(".............10......................");
36     public static final Mask P_Z                 = new Mask(".............01......................");
37     public static final Mask P_ALWAYS            = new Mask(".............11......................");
38     public static final Mask MOVE                = new Mask("...............001...................");
39     public static final Mask TI                  = new Mask("....................1................");
40     public static final Mask DI                  = new Mask(".....................1...............");
41     public static final Mask DC                  = new Mask("......................1..............");
42     public static final Mask DO                  = new Mask(".......................1.............");
43     public static final Mask TO                  = new Mask("........................1............");
44     public static final Mask PATH_LITERAL        = new Mask(".........................1vvvvvvvvvvv");
45     public static final Mask PATH_DATA           = new Mask(".........................01..........");
46     public static final Mask PATH_NOCHANGE       = new Mask(".........................00..........");
47
48     public static final Mask LITERAL_LO          = new Mask("...............010vvvvvvvvvvvvvvvvvvv");
49     public static final Mask LITERAL_HI          = new Mask("...............011vvvvvvvvvvvvvvvvvvv");
50     public static final Mask LITERAL             = new Mask("...............1..vvvvvvvvvvvvvvvvvvv");
51     public static final Mask LITERAL_SEL         = new Mask("................vv...................");
52     public static final Mask LITERAL_LOW_ZERO    = new Mask("...............100...................");
53     public static final Mask LITERAL_LOW_ONE     = new Mask("...............101...................");
54     public static final Mask LITERAL_HIGH_ZERO   = new Mask("...............110...................");
55     public static final Mask LITERAL_HIGH_ONE    = new Mask("...............111...................");
56     public static final Mask PUMP_NAME           = new Mask("vvvvvvvvvvv..........................");
57
58
59     /** get the bits describing this box's location on the DESTINATION HORN */
60     protected abstract long getDestAddr(Destination box);
61
62     /** get the bits describing this box's location on the INSTRUCTION HORN */
63     protected abstract long getBoxInstAddr(Pump box);
64
65     /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
66     protected abstract Pump getBoxByInstAddr(long dest);
67     
68     /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
69     protected abstract Destination getDestByAddr(long dest);
70
71     /** read a machine-formatted instruction from a file (into a Java object) */
72     public Instruction readInstruction(DataInputStream is) throws IOException {
73         long inst = 0;
74         try {
75             inst = (inst << 8) | (is.readByte() & 0xff);
76             inst = (inst << 8) | (is.readByte() & 0xff);
77             inst = (inst << 8) | (is.readByte() & 0xff);
78             inst = (inst << 8) | (is.readByte() & 0xff);
79             inst = (inst << 8) | (is.readByte() & 0xff);
80             inst = (inst << 8) | (is.readByte() & 0xff);
81             return readInstruction(inst);
82         } catch (EOFException eof) {
83             return null;
84         }
85     }
86
87     public Instruction readInstruction(long inst) {
88         Pump name           = getBoxByInstAddr(PUMP_NAME.getval(inst));
89
90         if (UNCLOG.get(inst))   return new Instruction.UnClog(name);
91         if (CLOG.get(inst))     return new Instruction.Clog(name);
92         if (MASSACRE.get(inst)) return new Instruction.Massacre(name);
93         if (KILL.get(inst))     return new Instruction.Kill(name, (int)(KILL.getval(inst)+1));
94
95         int predicate = 0;
96         if (P_ALWAYS.get(inst)) predicate = Instruction.PredicatedInstruction.P_ALWAYS;
97         if (P_A.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_A;
98         if (P_B.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_B;
99         if (P_Z.get(inst)) predicate = Instruction.PredicatedInstruction.P_IF_Z;
100
101         boolean dl = false;
102         if (DL.get(inst))                   dl = true;
103
104         if (LOOP_FROM_LITERAL.get(inst))    return new Counter(name, dl, predicate, (int)LOOP_FROM_LITERAL.getval(inst),   LOOP_COUNTER);
105         if (REPEAT_FROM_LITERAL.get(inst))  return new Counter(name, dl, predicate, (int)REPEAT_FROM_LITERAL.getval(inst), REPEAT_COUNTER);
106         if (LOOP_FROM_DATA.get(inst))       return new Counter(name, dl, predicate, DATA_LATCH, LOOP_COUNTER);
107         if (REPEAT_FROM_DATA.get(inst))     return new Counter(name, dl, predicate, DATA_LATCH, REPEAT_COUNTER);
108         if (REPEAT_FROM_STANDING.get(inst)) return new Counter(name, dl, predicate, STANDING, REPEAT_COUNTER);
109         if (TAKE_LOOP.get(inst))            return new Counter(name, dl, predicate, LOOP_COUNTER, DATA_LATCH);
110
111         if (LITERAL_LO.get(inst))  return new Instruction.HalfLiteral(name, dl, predicate, LITERAL_LO.getval(inst), 0, false);
112         if (LITERAL_HI.get(inst))  return new Instruction.HalfLiteral(name, dl, predicate, LITERAL_HI.getval(inst), 0, true);
113         if (LITERAL.get(inst)) {
114             long literal = LITERAL.getval(inst);
115             if      (LITERAL_LOW_ZERO.get(inst))  literal = literal << LITERAL_HIGH_ZERO.getWidth();
116             else if (LITERAL_LOW_ONE.get(inst))   literal = (literal << LITERAL_HIGH_ZERO.getWidth()) | ~(-1L << LITERAL_HIGH_ZERO.getWidth());
117             else if (LITERAL_HIGH_ZERO.get(inst)) literal = literal;
118             else if (LITERAL_HIGH_ONE.get(inst))  literal = literal | (-1L << LITERAL_HIGH_ZERO.getWidth());
119             if ((literal & (1L<<(WIDTH_WORD-1))) != 0) literal |= (-1L << WIDTH_WORD);
120             return new Instruction.Literal(name, dl, predicate, literal);
121         }  
122         if (FLAGS.get(inst))       return new Instruction.SetFlags(name, dl, predicate, (int)FLAGS_A.getval(inst), (int)FLAGS_B.getval(inst));
123
124         if (!MOVE.get(inst)) throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
125
126         Destination dest    = getDestByAddr(PATH_LITERAL.getval(inst));
127         boolean tokenIn     = TI.get(inst);
128         boolean dataIn      = DI.get(inst);
129         boolean latch       = DC.get(inst);
130         boolean dataOut     = DO.get(inst);
131         boolean tokenOut    = TO.get(inst);
132         boolean dataOutDest = PATH_DATA.get(inst);
133         return new Instruction.Move(name,
134                                     dl,
135                                     predicate,
136                                     dest,
137                                     tokenIn,
138                                     dataIn,
139                                     latch,
140                                     dataOutDest,
141                                     dataOut,
142                                     tokenOut,
143                                     false,
144                                     false);
145     }
146
147     public long writeInstruction(Instruction d) {
148         long instr = 0;
149
150         if (d.pump != null)
151             instr = PUMP_NAME.setval(instr, getBoxInstAddr(d.pump));
152
153         boolean dl = false;
154         if (d instanceof Instruction.PredicatedInstruction) {
155             Instruction.PredicatedInstruction pi = (Instruction.PredicatedInstruction)d;
156             if (pi.dl) instr = DL.set(instr);
157             switch(pi.predicate) {
158                 case Instruction.PredicatedInstruction.P_ALWAYS: instr = P_ALWAYS.set(instr); break;
159                 case Instruction.PredicatedInstruction.P_IF_A:   instr = P_A.set(instr);      break;
160                 case Instruction.PredicatedInstruction.P_IF_B:   instr = P_B.set(instr);      break;
161                 case Instruction.PredicatedInstruction.P_IF_Z:   instr = P_Z.set(instr);      break;
162             }
163         }
164
165         if (d instanceof Instruction.CodeBagDescriptor) {
166             Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
167             // MAJOR MAJOR FIXME: upper half here...
168             d = new Instruction.HalfLiteral(lc.pump, dl, Instruction.PredicatedInstruction.P_ALWAYS,
169                                             ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1, false);
170         }
171
172         if (d instanceof Instruction.UnClog) {
173             instr = UNCLOG.set(instr);
174
175         } else if (d instanceof Instruction.Kill) {
176             Instruction.Kill k = (Instruction.Kill)d;
177             instr = KILL.set(instr);
178             instr = KILL.setval(instr, k.count);
179
180         } else if (d instanceof Instruction.Clog) {
181             instr = CLOG.set(instr);
182
183         } else if (d instanceof Instruction.Massacre) {
184             instr = MASSACRE.set(instr);
185
186         } else if (d instanceof Instruction.SetFlags) {
187             Instruction.SetFlags sf = (Instruction.SetFlags)d;
188             instr = FLAGS.set(instr);
189             instr = FLAGS_A.setval(instr, sf.flag_a);
190             instr = FLAGS_B.setval(instr, sf.flag_b);
191
192         } else if (d instanceof Instruction.Literal) {
193             long il = ((Instruction.Literal)d).literal;
194             long literal = ((Instruction.Literal)d).literal;
195             long allones = ~(-1L << WIDTH_WORD);
196             il = literal = literal & allones;
197             if      (((il &  (-1L << 19)) & allones) == 0)       instr = LITERAL.setval(LITERAL_HIGH_ZERO.set(instr), il);
198             else if (((il | ~(-1L << 19)) & allones) == allones) instr = LITERAL.setval(LITERAL_HIGH_ONE.set(instr),  il & ~(-1L<<19));
199             else if (((il & ~(-1L << 19)) & allones) == 0)       instr = LITERAL.setval(LITERAL_LOW_ZERO.set(instr), il >> 19);
200             else if (((il |  (-1L << 19)) & allones) == allones) instr = LITERAL.setval(LITERAL_LOW_ONE.set(instr),  (il >> 19));
201             
202         } else if (d instanceof Instruction.HalfLiteral) {
203             Instruction.HalfLiteral inst = (Instruction.HalfLiteral)d;
204             if (inst.pump != null) {
205                 if (inst.high) {
206                     instr = LITERAL_HI.set(instr);
207                     instr = LITERAL_HI.setval(instr, inst.literal);
208                 } else {
209                     instr = LITERAL_LO.set(instr);
210                     instr = LITERAL_LO.setval(instr, inst.literal);
211                 }
212             } else {
213                 instr = inst.literal;
214             }
215
216         } else if (d instanceof Instruction.DecrLoop) {
217             instr = DL.set(instr);
218
219         } else if (d instanceof Instruction.Counter) {
220             Instruction.Counter ic = (Instruction.Counter)d;
221             if      (ic.dest == DATA_LATCH && ic.source == LOOP_COUNTER)   instr = TAKE_LOOP.set(instr);
222             else if (ic.dest == LOOP_COUNTER && ic.source == DATA_LATCH)   instr = LOOP_FROM_DATA.set(instr);
223             else if (ic.dest == REPEAT_COUNTER && ic.source == DATA_LATCH) instr = REPEAT_FROM_DATA.set(instr);
224             else if (ic.dest == REPEAT_COUNTER && ic.source == STANDING)   instr = REPEAT_FROM_STANDING.set(instr);
225             else if (ic.dest == REPEAT_COUNTER)                            instr = REPEAT_FROM_LITERAL.setval(REPEAT_FROM_LITERAL.set(instr), ic.source);
226             else if (ic.dest == LOOP_COUNTER)                              instr = LOOP_FROM_LITERAL.setval(LOOP_FROM_LITERAL.set(instr), ic.source);
227             else throw new RuntimeException();
228
229         } else if (d instanceof Instruction.Move) {
230             Instruction.Move inst = (Instruction.Move)d;
231             instr  = MOVE.set(instr);
232             if (inst.tokenIn)                    instr = TI.set(instr);
233             if (inst.dataIn)                     instr = DI.set(instr);
234             if (inst.latch)                      instr = DC.set(instr);
235             if (inst.dataOut)                    instr = DO.set(instr);
236             if (inst.tokenOut)                   instr = TO.set(instr);
237             if (inst.dataOutDest)                instr = PATH_DATA.set(instr);
238             else {
239                 instr  = PATH_LITERAL.set(instr);
240                 instr  = PATH_LITERAL.setval(instr, inst.dest==null?0:getDestAddr(inst.dest));
241             }
242
243         } else {
244             throw new RuntimeException("unrecognized instruction " + d);
245
246         }
247         return instr;
248     }
249
250     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
251         long instr = writeInstruction(d);
252         for(int i=5; i>=0; i--)
253             os.write(getIntField(i*8+7, i*8, instr));
254    }
255
256 }