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