major overhaul: update dock to am33
[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 REPEAT_FROM_DATA    = new Mask("...............000001.........0......");
18     public static final Mask REPEAT_FROM_LITERAL = new Mask("...............000001.........1vvvvvv");
19     public static final Mask LOOP_FROM_DATA      = new Mask("...............000010.........0......");
20     public static final Mask LOOP_FROM_LITERAL   = new Mask("...............000010.........1vvvvvv");
21     public static final Mask TAKE_LOOP           = new Mask("...............000011................");
22     public static final Mask KILL                = new Mask("...............000100..........vvvvvv");
23     public static final Mask MASSACRE            = new Mask("...............000101................");
24     public static final Mask CLOG                = new Mask("...............000110................");
25     public static final Mask UNCLOG              = new Mask("...............000111................");
26
27     public static final Mask SK                  = new Mask("...........1.........................");
28     public static final Mask DL                  = new Mask("............1........................");
29     public static final Mask P                   = new Mask(".............vv......................");
30     public static final Mask MOVE                = new Mask("...............001...................");
31     public static final Mask STAND               = new Mask("...................1.................");
32     public static final Mask TI                  = new Mask("....................1................");
33     public static final Mask DI                  = new Mask(".....................1...............");
34     public static final Mask DC                  = new Mask("......................1..............");
35     public static final Mask DO                  = new Mask(".......................1.............");
36     public static final Mask TO                  = new Mask("........................1............");
37     public static final Mask PATH_LITERAL        = new Mask(".........................1vvvvvvvvvvv");
38     public static final Mask PATH_DATA           = new Mask(".........................01..........");
39     public static final Mask PATH_NOCHANGE       = new Mask(".........................00..........");
40
41     public static final Mask LITERAL_LO          = new Mask("...............010vvvvvvvvvvvvvvvvvvv");
42     public static final Mask LITERAL_HI          = new Mask("...............011vvvvvvvvvvvvvvvvvvv");
43     public static final Mask LITERAL             = new Mask("...............1..vvvvvvvvvvvvvvvvvvv");
44     public static final Mask LITERAL_SEL         = new Mask("................vv...................");
45     public static final Mask PUMP_NAME           = new Mask("vvvvvvvvvvv..........................");
46
47
48     /** get the bits describing this box's location on the DESTINATION HORN */
49     protected abstract long getDestAddr(Destination box);
50
51     /** get the bits describing this box's location on the INSTRUCTION HORN */
52     protected abstract long getBoxInstAddr(Pump box);
53
54     /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
55     protected abstract Pump getBoxByInstAddr(long dest);
56     
57     /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
58     protected abstract Destination getDestByAddr(long dest);
59
60     /** read a machine-formatted instruction from a file (into a Java object) */
61     public Instruction readInstruction(DataInputStream is) throws IOException {
62         long inst = 0;
63         try {
64             inst = (inst << 8) | (is.readByte() & 0xff);
65             inst = (inst << 8) | (is.readByte() & 0xff);
66             inst = (inst << 8) | (is.readByte() & 0xff);
67             inst = (inst << 8) | (is.readByte() & 0xff);
68             inst = (inst << 8) | (is.readByte() & 0xff);
69             inst = (inst << 8) | (is.readByte() & 0xff);
70             return readInstruction(inst);
71         } catch (EOFException eof) {
72             return null;
73         }
74     }
75
76     public Instruction readInstruction(long inst) {
77         Pump name           = getBoxByInstAddr(PUMP_NAME.getval(inst));
78
79         if (LOOP_FROM_LITERAL.get(inst))   return new Counter(name, (int)LOOP_FROM_LITERAL.getval(inst),   LOOP_COUNTER);
80         if (REPEAT_FROM_LITERAL.get(inst)) return new Counter(name, (int)REPEAT_FROM_LITERAL.getval(inst), REPEAT_COUNTER);
81         if (LOOP_FROM_DATA.get(inst))      return new Counter(name, DATA_LATCH, LOOP_COUNTER);
82         if (REPEAT_FROM_DATA.get(inst))    return new Counter(name, DATA_LATCH, REPEAT_COUNTER);
83         if (TAKE_LOOP.get(inst))           return new Counter(name, LOOP_COUNTER, DATA_LATCH);
84
85         if (DL.get(inst))                  return new Instruction.DecrLoop(name);
86
87         if (UNCLOG.get(inst))   return new Instruction.UnClog(name);
88         if (CLOG.get(inst))     return new Instruction.Clog(name);
89         if (MASSACRE.get(inst)) return new Instruction.Massacre(name);
90         if (KILL.get(inst))     return new Instruction.Kill(name, (int)(KILL.getval(inst)+1));
91         if (LITERAL_LO.get(inst))  return new Instruction.HalfLiteral(name, LITERAL_LO.getval(inst), 0, false);
92         if (LITERAL_HI.get(inst))  return new Instruction.HalfLiteral(name, LITERAL_HI.getval(inst), 0, true);
93
94         Destination dest    = getDestByAddr(PATH_LITERAL.getval(inst));
95         boolean tokenIn     = TI.get(inst);
96         boolean dataIn      = DI.get(inst);
97         boolean latch       = DC.get(inst);
98         boolean dataOut     = DO.get(inst);
99         boolean tokenOut    = TO.get(inst);
100         boolean standing    = STAND.get(inst);
101         boolean dataOutDest = PATH_DATA.get(inst);
102         return new Instruction.Move(name,
103                                     dest,
104                                     standing?0:1,
105                                     tokenIn,
106                                     dataIn,
107                                     latch,
108                                     dataOutDest,
109                                     dataOut,
110                                     tokenOut,
111                                     false,
112                                     false);
113     }
114
115     public long writeInstruction(Instruction d) {
116         long instr = 0;
117
118         if (d.pump != null)
119             instr = PUMP_NAME.setval(instr, getBoxInstAddr(d.pump));
120
121         if (d instanceof Instruction.CodeBagDescriptor) {
122             Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
123             // MAJOR MAJOR FIXME: upper half here...
124             d = new Instruction.HalfLiteral(lc.pump, ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1, false);
125         }
126
127         if (d instanceof Instruction.UnClog) {
128             instr = UNCLOG.set(instr);
129
130         } else if (d instanceof Instruction.Kill) {
131             Instruction.Kill k = (Instruction.Kill)d;
132             instr = KILL.set(instr);
133             instr = KILL.setval(instr, k.count);
134
135         } else if (d instanceof Instruction.Clog) {
136             instr = CLOG.set(instr);
137
138         } else if (d instanceof Instruction.Massacre) {
139             instr = MASSACRE.set(instr);
140
141         } else if (d instanceof Instruction.HalfLiteral) {
142             Instruction.HalfLiteral inst = (Instruction.HalfLiteral)d;
143             if (inst.pump != null) {
144                 if (inst.high) {
145                     instr = LITERAL_HI.set(instr);
146                     instr = LITERAL_HI.setval(instr, inst.literal);
147                 } else {
148                     instr = LITERAL_LO.set(instr);
149                     instr = LITERAL_LO.setval(instr, inst.literal);
150                 }
151             } else {
152                 instr = inst.literal;
153             }
154
155         } else if (d instanceof Instruction.DecrLoop) {
156             instr = DL.set(instr);
157
158         } else if (d instanceof Instruction.Counter) {
159             Instruction.Counter ic = (Instruction.Counter)d;
160             if      (ic.dest == DATA_LATCH && ic.source == LOOP_COUNTER)   instr = TAKE_LOOP.set(instr);
161             else if (ic.dest == REPEAT_COUNTER && ic.source == DATA_LATCH) instr = REPEAT_FROM_DATA.set(instr);
162             else if (ic.dest == LOOP_COUNTER && ic.source == DATA_LATCH)   instr = LOOP_FROM_DATA.set(instr);
163             else if (ic.dest == REPEAT_COUNTER)                            instr = REPEAT_FROM_LITERAL.setval(REPEAT_FROM_LITERAL.set(instr), ic.source);
164             else if (ic.dest == LOOP_COUNTER)                              instr = LOOP_FROM_LITERAL.setval(LOOP_FROM_LITERAL.set(instr), ic.source);
165             else throw new RuntimeException();
166
167         } else if (d instanceof Instruction.Move) {
168             Instruction.Move inst = (Instruction.Move)d;
169             instr  = MOVE.set(instr);
170             if (inst.tokenIn)                    instr = TI.set(instr);
171             if (inst.dataIn)                     instr = DI.set(instr);
172             if (inst.latch)                      instr = DC.set(instr);
173             if (inst.dataOut)                    instr = DO.set(instr);
174             if (inst.tokenOut)                   instr = TO.set(instr);
175             if (inst.dataOutDest)                instr = PATH_DATA.set(instr);
176             else {
177                 instr  = PATH_LITERAL.set(instr);
178                 instr  = PATH_LITERAL.setval(instr, inst.dest==null?0:getDestAddr(inst.dest));
179             }
180             if (inst.standing)                   instr = STAND.set(instr);
181
182         }
183         return instr;
184     }
185
186     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
187         long instr = writeInstruction(d);
188         for(int i=5; i>=0; i--)
189             os.write(getIntField(i*8+7, i*8, instr));
190    }
191
192 }