add kill*
[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
6 public abstract class InstructionEncoder {
7
8     /** get the bits describing this box's location on the DESTINATION HORN */
9     public abstract long getBoxAddr(BenkoBox box);
10
11     /** get the bits describing this box's location on the INSTRUCTION HORN */
12     public abstract long getBoxInstAddr(BenkoBox box);
13
14     /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
15     public abstract BenkoBox getBoxByAddr(long dest);
16
17     /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
18     public abstract BenkoBox getBoxByInstAddr(long dest);
19
20     /** read a machine-formatted instruction from a file (into a Java object) */
21     public Instruction readInstruction(DataInputStream is) throws IOException {
22         long inst = 0;
23         try {
24             inst = (inst << 8) | (is.readByte() & 0xff);
25             inst = (inst << 8) | (is.readByte() & 0xff);
26             inst = (inst << 8) | (is.readByte() & 0xff);
27             inst = (inst << 8) | (is.readByte() & 0xff);
28             inst = (inst << 8) | (is.readByte() & 0xff);
29             inst = (inst << 8) | (is.readByte() & 0xff);
30             return readInstruction(inst);
31         } catch (EOFException eof) {
32             return null;
33         }
34     }
35
36     public Instruction readInstruction(long instr) {
37         long inst = instr;
38         long head = inst & (0x3L << (24+11));
39         head = head >> (24+11);
40         switch((int)head) {
41             case 0: {
42                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
43                 BenkoBox dest = getBoxByAddr    ((inst >>  1) & 0x7ff);
44                 int count        = ((int)(instr >> 12)) & 0x7f;
45                 boolean tokenIn  = (instr & (1L << (11+1+7+0))) != 0;
46                 boolean dataIn   = ( instr & (1L << (11+1+7+1))) != 0;
47                 boolean latch    = (  instr & (1L << (11+1+7+2))) != 0;
48                 boolean dataOut  = (instr & (1L << (11+1+7+3))) != 0;
49                 boolean tokenOut = (instr & (1L << (11+1+7+4))) != 0;
50                 boolean recycle  = (instr & (1L)) != 0;
51                 if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
52                 return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
53                                                   latch, dataOut, tokenOut, recycle);
54             }
55
56             case 1: {
57                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
58                 int offset = ((int)(instr >> 6)) & ~(0xffffffff << 18);
59                 if ((offset & (1<<17)) != 0) offset |= (0xffffffff << 18);
60                 int size   = ((int)(instr     )) & ~(0xffffffff << 6);
61                 return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
62             }
63
64             case 2: {
65                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
66                 int val   = ((int)(instr     )) & ~(0xffffffff << 24);
67                 return new Instruction.Literal.Absolute(name, val);
68             }
69
70             case 3: {
71                 BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
72                 int val   = ((int)(instr     )) & ~(0xffffffff << 24);
73                 return new Instruction.Literal.Relative(name, val);
74             }
75
76         }
77         return null;
78
79     }
80
81     public long writeInstruction(Instruction d) {
82         long instr = 0;
83
84         // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
85         if (d instanceof Instruction.Kill) {
86             Instruction.Kill k = (Instruction.Kill)d;
87             d = new Instruction.Executable(k.benkoBox, null, k.count, k.killOnlyStandingInstructions,
88                                            false, true, false, false, false);
89         }
90
91         if (d instanceof Instruction.Executable) {
92             Instruction.Executable inst = (Instruction.Executable)d;
93             BenkoBox dest = inst.dest;
94             instr = dest==null ? 0 : (getBoxAddr(dest) << 1);
95             if (inst.count >= (1<<8))
96                 throw new RuntimeException("count field must be less than 128");
97             instr |= (((long)inst.count) << (11+1));
98             if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
99             if (inst.dataIn)   instr |= (1L << (11+1+7+1));
100             if (inst.latch)    instr |= (1L << (11+1+7+2));
101             if (inst.dataOut)  instr |= (1L << (11+1+7+3));
102             if (inst.tokenOut) instr |= (1L << (11+1+7+4));
103             if (inst.recycle)  instr |= (1L);
104             instr |= (getBoxInstAddr(inst.benkoBox) << (11+5+7+1));
105
106         } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
107             Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
108             instr = (1L << (11+24));
109             if (lc.dest != null)
110                 instr |= (getBoxAddr(lc.dest)) << 24;
111             if (lc.size >= (1<<6))
112                 throw new RuntimeException("codebag sizes must be less than 2^6");
113             if (lc.offset >= (1<<17) || lc.offset <= (-1 * (1<<17)))
114                 throw new RuntimeException("codebag offsets must be in the range -(2^17)..2^17");
115             int off = (int)lc.offset;
116             off &= ~(0xffffffff << 18);
117             instr |= (off << 6);
118             instr |= (((long)lc.size));
119
120         } else if (d instanceof Instruction.Literal.Absolute) {
121             Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
122             instr = (2L << (11+24));
123             instr |= (getBoxAddr(ld.dest)) << 24;
124             if (ld.value >= (1<<25))
125                 throw new RuntimeException("literals must be less than 2^24");
126             instr |= ((long)ld.value);
127
128         } else if (d instanceof Instruction.Literal.Relative) {
129             Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
130             instr = (3L << (11+24));
131             instr |= (getBoxAddr(lr.dest)) << 24;
132             if (lr.offset >= (1<<25))
133                 throw new RuntimeException("literals must be less than 2^24");
134             instr |= ((long)lr.offset);
135             
136         }
137         return instr;
138     }
139
140     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
141         long instr = writeInstruction(d);
142         os.write((int)((instr >> (5*8)) & 0xff));
143         os.write((int)((instr >> (4*8)) & 0xff));
144         os.write((int)((instr >> (3*8)) & 0xff));
145         os.write((int)((instr >> (2*8)) & 0xff));
146         os.write((int)((instr >> (1*8)) & 0xff));
147         os.write((int)((instr >> (0*8)) & 0xff));
148    }
149
150 }