fixed bug in InstructionEncoder
[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 java.io.*;
5 import static edu.berkeley.fleet.ies44.BitManipulations.*;
6
7 public abstract class InstructionEncoder {
8
9     public static final int WIDTH_WORD          = 37;   /* word width */
10     public static final int WIDTH_CODEBAG_SIZE  = 6;
11     public static final int WIDTH_PUMP_ADDR     = 11;
12     public static final int WIDTH_DEST_ADDR     = 11;
13     public static final int WIDTH_COUNT         = 7;
14
15     public static final int OFFSET_RQ           = 0;
16     public static final int OFFSET_DEST         = 1;
17     public static final int OFFSET_COUNT        = OFFSET_DEST+WIDTH_DEST_ADDR;
18     public static final int OFFSET_CONTROL      = OFFSET_COUNT+WIDTH_COUNT;
19     public static final int OFFSET_TI           = OFFSET_CONTROL+0;
20     public static final int OFFSET_DI           = OFFSET_CONTROL+1;
21     public static final int OFFSET_DL           = OFFSET_CONTROL+2;
22     public static final int OFFSET_DO           = OFFSET_CONTROL+3;
23     public static final int OFFSET_TO           = OFFSET_CONTROL+4;
24     public static final int OFFSET_PUMP_ADDR    = 24;
25
26     /** get the bits describing this box's location on the DESTINATION HORN */
27     protected abstract long getDestAddr(Destination box);
28
29     /** get the bits describing this box's location on the INSTRUCTION HORN */
30     protected abstract long getBoxInstAddr(BenkoBox box);
31
32     /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
33     protected abstract BenkoBox getBoxByInstAddr(long dest);
34     
35     /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
36     protected abstract Destination getDestByAddr(long dest);
37
38     /** read a machine-formatted instruction from a file (into a Java object) */
39     public Instruction readInstruction(DataInputStream is) throws IOException {
40         long inst = 0;
41         try {
42             inst = (inst << 8) | (is.readByte() & 0xff);
43             inst = (inst << 8) | (is.readByte() & 0xff);
44             inst = (inst << 8) | (is.readByte() & 0xff);
45             inst = (inst << 8) | (is.readByte() & 0xff);
46             inst = (inst << 8) | (is.readByte() & 0xff);
47             inst = (inst << 8) | (is.readByte() & 0xff);
48             return readInstruction(inst);
49         } catch (EOFException eof) {
50             return null;
51         }
52     }
53
54     public Instruction readInstruction(long instr) {
55         long inst = instr;
56         switch((int)getField(WIDTH_WORD-1, WIDTH_WORD-2, inst)) {
57             case 0: {
58                 BenkoBox name    = getBoxByInstAddr(getIntField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, inst));
59                 Destination dest = getDestByAddr   (getIntField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,      inst));
60                 int count        = getIntField(                 OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,     inst);
61                 boolean tokenIn  = getBit(OFFSET_TI, instr);
62                 boolean dataIn   = getBit(OFFSET_DI, instr);
63                 boolean latch    = getBit(OFFSET_DL, instr);
64                 boolean dataOut  = getBit(OFFSET_DO, instr);
65                 boolean tokenOut = getBit(OFFSET_TO, instr);
66                 boolean recycle  = getBit(OFFSET_RQ, instr);
67                 if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
68                 return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
69                                                   latch, dataOut, tokenOut, recycle);
70             }
71
72             case 1: {
73                 Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, inst));
74                 long offset = getSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, WIDTH_CODEBAG_SIZE, instr);
75                 long size   = getSignedField(WIDTH_CODEBAG_SIZE-1,        0,                 instr);
76                 return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
77             }
78
79             case 2: {
80                 Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_PUMP_ADDR+1, inst));
81                 return new Instruction.Literal.Absolute(name, getSignedField(WIDTH_WORD-3-WIDTH_PUMP_ADDR, 0, instr));
82             }
83
84             case 3: {
85                 Destination name = getDestByAddr(getField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_PUMP_ADDR+1, inst));
86                 return new Instruction.Literal.Relative(name, getSignedField(WIDTH_WORD-3-WIDTH_PUMP_ADDR, 0, instr));
87             }
88
89         }
90         return null;
91
92     }
93
94     public long writeInstruction(Instruction d) {
95         long instr = 0;
96
97         // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
98         if (d instanceof Instruction.Kill) {
99             Instruction.Kill k = (Instruction.Kill)d;
100             d = new Instruction.Executable(k.benkoBox, null, k.count, k.killOnlyStandingInstructions,
101                                            false, true, false, false, false);
102         }
103
104         if (d instanceof Instruction.Executable) {
105             Instruction.Executable inst = (Instruction.Executable)d;
106             instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR,   getBoxInstAddr(inst.benkoBox));
107             instr |= putField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,        inst.dest==null?0:getDestAddr(inst.dest));
108             instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,       inst.count);
109             instr |= putField(OFFSET_TI,                          OFFSET_TI,          inst.tokenIn?1:0);
110             instr |= putField(OFFSET_DI,                          OFFSET_DI,          inst.dataIn?1:0);
111             instr |= putField(OFFSET_DL,                          OFFSET_DL,          inst.latch?1:0);
112             instr |= putField(OFFSET_DO,                          OFFSET_DO,          inst.dataOut?1:0);
113             instr |= putField(OFFSET_TO,                          OFFSET_TO,          inst.tokenOut?1:0);
114             instr |= putField(OFFSET_RQ,                          OFFSET_RQ,          inst.recycle?1:0);
115
116         } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
117             Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
118             instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 1);
119             if (lc.dest != null) instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(lc.dest));
120             instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, WIDTH_CODEBAG_SIZE, lc.offset);
121             instr |= putField(WIDTH_CODEBAG_SIZE-1,        0,                 lc.size);
122
123         } else if (d instanceof Instruction.Literal.Absolute) {
124             Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
125             instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 2);
126             instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(ld.dest));
127             instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, 0, ld.value);
128
129         } else if (d instanceof Instruction.Literal.Relative) {
130             Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
131             instr = putField(WIDTH_WORD-1, WIDTH_WORD-2, 3);
132             instr |= putField(WIDTH_WORD-3, WIDTH_WORD-3-WIDTH_DEST_ADDR+1, getDestAddr(lr.dest));
133             instr |= putSignedField(WIDTH_WORD-3-WIDTH_DEST_ADDR, 0, lr.offset);
134             
135         }
136         return instr;
137     }
138
139     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
140         long instr = writeInstruction(d);
141         for(int i=5; i>=0; i--)
142             os.write(getIntField(i*8+7, i*8, instr));
143    }
144
145 }