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 {
81 if (d instanceof Instruction.Executable) {
82 Instruction.Executable inst = (Instruction.Executable)d;
84 InterpreterBenkoBox dest = resolve(inst.dest);
85 long instr = dest==null ? 0 : (dest.addr << 1);
87 instr |= (((long)inst.count) << (11+1));
88 if (inst.tokenIn) instr |= (1L << (11+1+7+0));
89 if (inst.dataOut) instr |= (1L << (11+1+7+1));
90 if (inst.latch) instr |= (1L << (11+1+7+2));
91 if (inst.dataIn) instr |= (1L << (11+1+7+3));
92 if (inst.tokenOut) instr |= (1L << (11+1+7+4));
93 instr |= ((long)resolve(inst.benkoBox).instr_addr) << (11+5+7+1);
95 out |= ((InterpreterBenkoBox)ships.get("command").getBenkoBox("data")).addr;
97 dump(os, (out >> (5*8)) & 0xff);
98 dump(os, (out >> (4*8)) & 0xff);
99 dump(os, (out >> (3*8)) & 0xff);
100 dump(os, (out >> (2*8)) & 0xff);
101 dump(os, (out >> (1*8)) & 0xff);
102 dump(os, (out >> (0*8)) & 0xff);
103 } else if (d instanceof Instruction.Literal.Absolute) {
104 Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
106 out |= resolve(ld.dest).addr;
107 out |= ((long)ld.value) << 11;
108 dump(os, (out >> (5*8)) & 0xff);
109 dump(os, (out >> (4*8)) & 0xff);
110 dump(os, (out >> (3*8)) & 0xff);
111 dump(os, (out >> (2*8)) & 0xff);
112 dump(os, (out >> (1*8)) & 0xff);
113 dump(os, (out >> (0*8)) & 0xff);
116 public void dump(OutputStream os, long data_) throws IOException {
117 int data = (int)data_;
118 os.write((byte)data);
119 System.out.println(data);
122 public Iterator<Ship> iterator() {
123 return (Iterator<Ship>)(Object)shiplist.iterator();
126 public void dispatchCodeBag(long base, long size) {
127 for(long i=base; i<base+size; i++)
128 dispatch(instructions[(int)i], i);
132 Instruction.Literal.CodeBagDescriptor cbl =
133 (Instruction.Literal.CodeBagDescriptor)instructions[0];
134 dispatchCodeBag(cbl.offset+0, cbl.size);
137 for(InterpreterShip ship : ships.values())
138 for(int j=0; j<10; j++)
141 // run the ships a bit longer for good measure
142 for(int i=0; i<100; i++)
143 for(InterpreterShip ship : ships.values())
144 for(int j=0; j<10; j++)
147 // check the state of the ships
148 for(InterpreterShip ship : ships.values())
151 Log.println(Log.yellow(" DONE: ====== FLEET is halted. Have a nice day. ======"));
154 public void dumpMem() {
155 Log.print(Log.cyan(" MEMORY: "));
156 for(int i=0; i<mem.length; i++) {
157 if ((i%10)==0 && i!=0) Log.print(Log.cyan(" "));
158 Log.print(Log.cyan(mem[i] + " "));
159 if ((i%10)==9 && i!=mem.length-1) Log.println("");
164 public void writeMem(int addr, int data) {
165 if (addr >= mem.length) {
166 int[] mem2 = new int[addr*2+1];
167 System.arraycopy(mem, 0, mem2, 0, mem2.length);
173 public InterpreterShip getShip(String name) {
174 InterpreterShip s = ships.get(name);
175 if (s == null) throw new RuntimeException("unknown ship \""+name+"\"");
179 public InterpreterShip tryCreate(String classname, String shipname) {
181 Class c = Class.forName(classname);
182 Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
183 InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
184 ships.put(shipname, ret);
187 } catch (Exception e) {
192 public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
193 Log.token(source, dest);
194 dest.addTokenFromFabric();
197 public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
198 Log.data(data+"", source, dest);
199 dest.addDataFromFabric(data);
202 public void dumpFabric(boolean quiet) {
203 // FIXME: this is really ugly: the order of port declarations in
204 // the XXXShip.java file must match the order in the .balsa file!
206 ArrayList instructionports = new ArrayList<InterpreterBenkoBox>();
207 for(InterpreterShip ship : shiplist)
208 for(BenkoBox port : ship.getBenkoBoxes())
209 if (!((InterpreterBenkoBox)port).special())
210 instructionports.add(port);
211 FabricTree instructions =
212 new FabricTree((InterpreterBenkoBox[])instructionports.toArray(new InterpreterBenkoBox[0]),
216 ArrayList inputports = new ArrayList<InterpreterBenkoBox>();
217 for(InterpreterShip ship : shiplist)
218 for(BenkoBox port : ship.getBenkoBoxes())
219 if (!((InterpreterBenkoBox)port).special())
220 inputports.add(port);
222 new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
226 ArrayList outputports = new ArrayList<InterpreterBenkoBox>();
227 for(InterpreterShip ship : shiplist)
228 for(BenkoBox port : ship.getBenkoBoxes())
229 if (!((InterpreterBenkoBox)port).special())
230 outputports.add(port);
232 new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
237 System.out.println("`include \"macros.v\"");
239 HashSet<Class> added = new HashSet<Class>();
240 for(Ship ship : shiplist)
241 if (!added.contains(ship.getClass())) {
242 added.add(ship.getClass());
243 System.out.println("import ["+ship.getBalsaName()+"]");
246 System.out.println("module fabric(clk, top_r, top_a, top,");
247 System.out.println(" data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
248 System.out.println(" input clk;");
249 System.out.println(" input top_r;");
250 System.out.println(" output top_a;");
251 System.out.println(" input [(`PACKET_WIDTH-1):0] top;");
252 System.out.println(" output data_Debug0_out_r;");
253 System.out.println(" input data_Debug0_out_a;");
254 System.out.println(" output [(`PACKET_WIDTH-1):0] data_Debug0_out;");
255 System.out.println(" wire [(`INSTRUCTION_WIDTH-1):0] data_Command0_out;");
256 System.out.println();
258 System.out.println();
260 instructions.dumpChannels(true);
261 outputs.dumpChannels(true);
262 inputs.dumpChannels(true);
263 for(InterpreterShip ship : shiplist)
264 for(BenkoBox port : ship.getBenkoBoxes()) {
265 if (ship instanceof Command && port instanceof Outbox) continue;
266 System.out.println(" wire [(`PACKET_WIDTH-1):0] data_"+getUniqueName(ship)+"_"+port.getName()+";");
269 System.out.println("");
270 instructions.dumpChannels(false);
271 System.out.println("");
272 outputs.dumpChannels(false);
273 System.out.println("");
274 inputs.dumpChannels(false);
275 System.out.println("");
276 for(InterpreterShip ship : shiplist) {
277 System.out.print(ship.getClass().getSimpleName().toLowerCase());
278 System.out.print(" ");
279 System.out.print("krunk"+(krunk++));
280 System.out.print("(clk, ");
281 boolean first = true;
282 for(BenkoBox port : ship.getBenkoBoxes()) {
283 if (!first) System.out.print(", ");
285 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
286 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
287 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
288 System.out.print(" ");
290 System.out.println(");");
292 for(BenkoBox port : ship.getBenkoBoxes()) {
293 if (((InterpreterBenkoBox)port).special()) continue;
294 if (port instanceof Inbox) {
295 if (((InterpreterBenkoBox)port).noInbox())
296 System.out.print("stupidinbox");
298 System.out.print("inbox");
300 System.out.print("outbox");
302 System.out.print(" krunk"+(krunk++)+"(clk, ");
303 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
304 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
305 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
306 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
307 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
308 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
309 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
310 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
311 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
312 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
313 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
314 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
315 System.out.print(");");
316 System.out.println();
320 System.out.println("funnel topfun(clk, dest_r, dest_a, dest, source_r, source_a, source, top_r, top_a, top);");
321 System.out.println("");
322 System.out.println(" assign instruction_r = data_Command0_out_r;");
323 System.out.println(" assign data_Command0_out_a = instruction_a;");
324 System.out.println(" assign instruction = data_Command0_out;");
325 System.out.println("endmodule");
328 private static class FabricTree {
332 public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
333 public FabricTree(InterpreterBenkoBox[] ports, String component, String prefix) {
334 this.prefix = prefix;
335 root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
337 private Object mkNode(String name, String component, InterpreterBenkoBox[] ports,
338 int start, int end, int addr, int bits) {
339 if (end-start == 0) return null;
340 if (end-start == 1) {
341 InterpreterBenkoBox p = ports[start];
342 if (prefix.equals("instruction")) {
352 return new Node(name,
354 mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
355 mkNode(name+"_1", component, ports, start+len/2, end, addr | (1 << bits), bits+1),
359 private String describe(String prefix, Object o) {
360 if (o==null) return null;
361 if (o instanceof InterpreterBenkoBox) {
362 InterpreterBenkoBox p = (InterpreterBenkoBox)o;
363 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
365 if (o instanceof Node) {
366 return ((Node)o).describe(prefix);
377 public Node(String name, String component, Object left, Object right, int addr, int bits) {
381 this.component = component;
385 public void dumpChannels(int indentamount, boolean decl) {
387 for(int i=0; i<indentamount; i++) indent += " ";
389 String n = describe(prefix).startsWith("instruction")
390 ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
391 System.out.println(" wire "+n+" "+indent+describe(prefix)+";");
393 System.out.println(" "+indent+
395 "krunk"+(krunk++)+"(clk, "+
396 describe(prefix)+"_r, "+
397 describe(prefix)+"_a, "+
398 describe(prefix)+", "+
399 FabricTree.this.describe(prefix, left)+"_r, "+
400 FabricTree.this.describe(prefix, left)+"_a, "+
401 FabricTree.this.describe(prefix, left)+", "+
402 FabricTree.this.describe(prefix, right)+"_r, "+
403 FabricTree.this.describe(prefix, right)+"_a, "+
404 FabricTree.this.describe(prefix, right)+
407 dumpChannels(left, indentamount+1, decl);
408 dumpChannels(right, indentamount+1, decl);
410 public void dumpChannels(Object o, int indentamount, boolean decl) {
412 if (o instanceof Node) {
413 ((Node)o).dumpChannels(indentamount, decl);
416 for(int i=0; i<indentamount; i++) indent += " ";
418 String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
419 ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
420 System.out.println(" wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
424 public String describe(String prefix) {
429 public static int krunk=0;
431 public int computeOffset(int origin, int target) { return target - origin; }
432 public int computeTarget(int origin, int offset) { return origin + offset; }