1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.fleet.*;
6 import java.lang.reflect.*;
7 import edu.berkeley.sbp.chr.*;
8 import edu.berkeley.sbp.misc.*;
9 import edu.berkeley.sbp.meta.*;
10 import edu.berkeley.sbp.bind.*;
11 import edu.berkeley.sbp.util.*;
14 import edu.berkeley.fleet.ships.*;
16 public class Interpreter extends Fleet implements Iterable<Ship> {
18 public InterpreterBenkoBox resolve(edu.berkeley.fleet.api.BenkoBox bb) { return (InterpreterBenkoBox)bb; }
20 public void dumpCode(Instruction[] instructions) throws IOException {
21 DataOutputStream dos = new DataOutputStream(new FileOutputStream("build/fleet.bin"));
22 for(int i=1; i<instructions.length; i++) {
23 Instruction inst = instructions[i];
24 writeInstruction(dos, inst);
30 public void dispatch(Instruction i, long address) {
32 if (i instanceof Instruction.Executable) {
33 InterpreterBenkoBox sourceBenkoBox = resolve(((Instruction.Executable)i).benkoBox);
34 if (!(sourceBenkoBox instanceof InstructionPort))
35 throw new RuntimeException(sourceBenkoBox + " is not an InstructionPort!");
36 ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
38 } else if (i instanceof Instruction.Literal.CodeBagDescriptor) {
40 Instruction.Literal.CodeBagDescriptor cbd = (Instruction.Literal.CodeBagDescriptor)i;
41 dispatchCodeBag(cbd.offset+address, cbd.size);
43 } else if (i instanceof Instruction.Literal.Absolute) {
44 InterpreterBenkoBox destBenkoBox = resolve(((Instruction.Literal.Absolute)i).dest);
45 Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
46 destBenkoBox.addDataFromFabric((int)((Instruction.Literal.Absolute)i).value);
48 } else if (i instanceof Instruction.Kill) {
49 InterpreterBenkoBox benkoBox = resolve(((Instruction.Kill)i).benkoBox);
50 if (!(benkoBox instanceof InstructionPort))
51 throw new RuntimeException(benkoBox + " is not an InstructionPort!");
52 ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
55 throw new Error("unsupported: " + i.getClass().getName());
59 /** some "halt ship" can turn this on to stop the interpreter */
60 public boolean halt = false;
62 public int[] mem = new int[0];
64 public Instruction[] instructions = null;
65 public ArrayList<String> imports = new ArrayList<String>();
67 private static String getUniqueName(Ship ship) {
68 return ship.getType() + ship.getOrdinal();
71 public ArrayList<InterpreterShip> shiplist = new ArrayList<InterpreterShip>();
72 public HashMap<String,InterpreterShip> ships = new HashMap<String,InterpreterShip>();
74 /** read a machine-formatted instruction from a file (into a Java object) */
75 public Instruction readInstruction(DataInputStream is) throws IOException {
80 public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
83 // Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
84 if (d instanceof Instruction.Kill) {
85 Instruction.Kill k = (Instruction.Kill)d;
86 d = new Instruction.Executable(k.benkoBox, null, k.count, false, false, true, false, false, false);
89 if (d instanceof Instruction.Executable) {
90 Instruction.Executable inst = (Instruction.Executable)d;
91 InterpreterBenkoBox dest = resolve(inst.dest);
92 instr = dest==null ? 0 : (dest.addr << 1);
93 if (inst.count >= (1<<8))
94 throw new RuntimeException("count field must be less than 128");
95 instr |= (((long)inst.count) << (11+1));
96 if (inst.tokenIn) instr |= (1L << (11+1+7+0));
97 if (inst.dataIn) instr |= (1L << (11+1+7+1));
98 if (inst.latch) instr |= (1L << (11+1+7+2));
99 if (inst.dataOut) instr |= (1L << (11+1+7+3));
100 if (inst.tokenOut) instr |= (1L << (11+1+7+4));
101 if (inst.recycle) instr |= (1L);
102 instr |= ((long)resolve(inst.benkoBox).instr_addr) << (11+5+7+1);
104 } else if (d instanceof Instruction.Literal.Absolute) {
105 Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
106 instr = (2L << (11+24));
107 instr |= (resolve(ld.dest).addr) << 24;
108 if (ld.value >= (1<<25))
109 throw new RuntimeException("literals must be less than 2^24");
110 instr |= ((long)ld.value);
113 dump(os, (instr >> (5*8)) & 0xff);
114 dump(os, (instr >> (4*8)) & 0xff);
115 dump(os, (instr >> (3*8)) & 0xff);
116 dump(os, (instr >> (2*8)) & 0xff);
117 dump(os, (instr >> (1*8)) & 0xff);
118 dump(os, (instr >> (0*8)) & 0xff);
120 public void dump(OutputStream os, long data_) throws IOException {
121 int data = (int)data_;
122 os.write((byte)data);
123 //System.out.println(data);
126 public Iterator<Ship> iterator() {
127 return (Iterator<Ship>)(Object)shiplist.iterator();
130 public void dispatchCodeBag(long base, long size) {
131 for(long i=base; i<base+size; i++)
132 dispatch(instructions[(int)i], i);
136 Instruction.Literal.CodeBagDescriptor cbl =
137 (Instruction.Literal.CodeBagDescriptor)instructions[0];
138 dispatchCodeBag(cbl.offset+0, cbl.size);
141 for(InterpreterShip ship : ships.values())
142 for(int j=0; j<10; j++)
145 // run the ships a bit longer for good measure
146 for(int i=0; i<100; i++)
147 for(InterpreterShip ship : ships.values())
148 for(int j=0; j<10; j++)
151 // check the state of the ships
152 for(InterpreterShip ship : ships.values())
155 Log.println(Log.yellow(" DONE: ====== FLEET is halted. Have a nice day. ======"));
158 public void dumpMem() {
159 Log.print(Log.cyan(" MEMORY: "));
160 for(int i=0; i<mem.length; i++) {
161 if ((i%10)==0 && i!=0) Log.print(Log.cyan(" "));
162 Log.print(Log.cyan(mem[i] + " "));
163 if ((i%10)==9 && i!=mem.length-1) Log.println("");
168 public int readMem(int addr) {
169 return addr >= mem.length ? 0 : mem[addr];
171 public void writeMem(int addr, int data) {
172 if (addr >= mem.length) {
173 int[] mem2 = new int[addr*2+1];
174 System.arraycopy(mem, 0, mem2, 0, mem2.length);
180 public InterpreterShip getShip(String name) {
181 InterpreterShip s = ships.get(name);
182 if (s == null) throw new RuntimeException("unknown ship \""+name+"\"");
186 public InterpreterShip tryCreate(String classname, String shipname) {
188 Class c = Class.forName(classname);
189 Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
190 InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
191 ships.put(shipname, ret);
194 } catch (Exception e) {
199 public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
200 Log.token(source, dest);
201 dest.addTokenFromFabric();
204 public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
205 Log.data(data+"", source, dest);
206 dest.addDataFromFabric(data);
209 public void dumpFabric(boolean quiet) {
210 // FIXME: this is really ugly: the order of port declarations in
211 // the XXXShip.java file must match the order in the .balsa file!
213 ArrayList instructionports = new ArrayList<InterpreterBenkoBox>();
214 for(InterpreterShip ship : shiplist)
215 for(BenkoBox port : ship.getBenkoBoxes())
216 if (!((InterpreterBenkoBox)port).special())
217 instructionports.add(port);
218 FabricTree instructions =
219 new FabricTree((InterpreterBenkoBox[])instructionports.toArray(new InterpreterBenkoBox[0]),
223 ArrayList inputports = new ArrayList<InterpreterBenkoBox>();
224 for(InterpreterShip ship : shiplist)
225 for(BenkoBox port : ship.getBenkoBoxes())
226 if (!((InterpreterBenkoBox)port).special())
227 inputports.add(port);
229 new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
233 ArrayList outputports = new ArrayList<InterpreterBenkoBox>();
234 for(InterpreterShip ship : shiplist)
235 for(BenkoBox port : ship.getBenkoBoxes())
236 if (!((InterpreterBenkoBox)port).special())
237 outputports.add(port);
239 new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
244 System.out.println("`include \"macros.v\"");
246 HashSet<Class> added = new HashSet<Class>();
247 for(Ship ship : shiplist)
248 if (!added.contains(ship.getClass())) {
249 added.add(ship.getClass());
250 System.out.println("import ["+ship.getBalsaName()+"]");
253 System.out.println("module fabric(clk, data_Execute0_in_r, data_Execute0_in_a, data_Execute0_in,");
254 System.out.println(" data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
255 System.out.println(" input clk;");
256 System.out.println(" input data_Execute0_in_r;");
257 System.out.println(" output data_Execute0_in_a;");
258 System.out.println(" input [(`PACKET_WIDTH-1):0] data_Execute0_in;");
259 System.out.println(" output data_Debug0_out_r;");
260 System.out.println(" input data_Debug0_out_a;");
261 System.out.println(" output [(`PACKET_WIDTH-1):0] data_Debug0_out;");
262 System.out.println(" wire [(`INSTRUCTION_WIDTH-1):0] data_Execute0_ihorn;");
263 System.out.println(" wire [(`PACKET_WIDTH-1):0] data_Execute0_dhorn;");
264 System.out.println();
266 System.out.println();
268 instructions.dumpChannels(true);
269 outputs.dumpChannels(true);
270 inputs.dumpChannels(true);
271 for(InterpreterShip ship : shiplist)
272 for(BenkoBox port : ship.getBenkoBoxes()) {
273 if (ship instanceof Execute && port instanceof Outbox) continue;
274 System.out.println(" wire [(`PACKET_WIDTH-1):0] data_"+getUniqueName(ship)+"_"+port.getName()+";");
277 System.out.println("");
278 instructions.dumpChannels(false);
279 System.out.println("");
280 outputs.dumpChannels(false);
281 System.out.println("");
282 inputs.dumpChannels(false);
283 System.out.println("");
284 for(InterpreterShip ship : shiplist) {
285 System.out.print(ship.getClass().getSimpleName().toLowerCase());
286 System.out.print(" ");
287 System.out.print("krunk"+(krunk++));
288 System.out.print("(clk, ");
289 boolean first = true;
290 for(BenkoBox port : ship.getBenkoBoxes()) {
291 if (!first) System.out.print(", ");
293 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
294 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
295 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
296 System.out.print(" ");
298 System.out.println(");");
300 for(BenkoBox port : ship.getBenkoBoxes()) {
301 if (((InterpreterBenkoBox)port).special()) continue;
302 if (port instanceof Inbox) {
304 if (((InterpreterBenkoBox)port).noInbox())
305 System.out.print("stupidinbox");
308 System.out.print("inbox");
310 System.out.print("outbox");
312 System.out.print(" krunk"+(krunk++)+"(clk, ");
313 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
314 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
315 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
316 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
317 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
318 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
319 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
320 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
321 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
322 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
323 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
324 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
325 System.out.print(");");
326 System.out.println();
330 System.out.println("funnel topfun(clk,"+
331 " dest_r, dest_a, dest,"+
332 " source_r, source_a, source,"+
333 " data_Execute0_dhorn_r, data_Execute0_dhorn_a, data_Execute0_dhorn);");
334 System.out.println("assign instruction_r = data_Execute0_ihorn_r;");
335 System.out.println("assign data_Execute0_ihorn_a = instruction_a;");
336 System.out.println("assign instruction = data_Execute0_ihorn;");
337 System.out.println("endmodule");
340 private static class FabricTree {
344 public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
345 public FabricTree(InterpreterBenkoBox[] ports, String component, String prefix) {
346 this.prefix = prefix;
347 root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
349 private Object mkNode(String name, String component, InterpreterBenkoBox[] ports,
350 int start, int end, int addr, int bits) {
351 if (end-start == 0) return null;
352 if (end-start == 1) {
353 InterpreterBenkoBox p = ports[start];
354 if (prefix.equals("instruction")) {
364 return new Node(name,
366 mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
367 mkNode(name+"_1", component, ports, start+len/2, end, addr | (1 << bits), bits+1),
371 private String describe(String prefix, Object o) {
372 if (o==null) return null;
373 if (o instanceof InterpreterBenkoBox) {
374 InterpreterBenkoBox p = (InterpreterBenkoBox)o;
375 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
377 if (o instanceof Node) {
378 return ((Node)o).describe(prefix);
389 public Node(String name, String component, Object left, Object right, int addr, int bits) {
393 this.component = component;
397 public void dumpChannels(int indentamount, boolean decl) {
399 for(int i=0; i<indentamount; i++) indent += " ";
401 String n = describe(prefix).startsWith("instruction")
402 ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
403 System.out.println(" wire "+n+" "+indent+describe(prefix)+";");
405 System.out.println(" "+indent+
407 "krunk"+(krunk++)+"(clk, "+
408 describe(prefix)+"_r, "+
409 describe(prefix)+"_a, "+
410 describe(prefix)+", "+
411 FabricTree.this.describe(prefix, left)+"_r, "+
412 FabricTree.this.describe(prefix, left)+"_a, "+
413 FabricTree.this.describe(prefix, left)+", "+
414 FabricTree.this.describe(prefix, right)+"_r, "+
415 FabricTree.this.describe(prefix, right)+"_a, "+
416 FabricTree.this.describe(prefix, right)+
419 dumpChannels(left, indentamount+1, decl);
420 dumpChannels(right, indentamount+1, decl);
422 public void dumpChannels(Object o, int indentamount, boolean decl) {
424 if (o instanceof Node) {
425 ((Node)o).dumpChannels(indentamount, decl);
428 for(int i=0; i<indentamount; i++) indent += " ";
430 String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
431 ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
432 System.out.println(" wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
436 public String describe(String prefix) {
441 public static int krunk=0;
443 public int computeOffset(int origin, int target) { return target - origin; }
444 public int computeTarget(int origin, int offset) { return origin + offset; }