added fleet api classes
[fleet.git] / src / edu / berkeley / fleet / interpreter / Interpreter.java
1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.fleet.api.*;
3
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.*;
12 import java.util.*;
13 import java.io.*;
14 import edu.berkeley.fleet.ships.*;
15
16 public class Interpreter extends Fleet implements Iterable<Ship> {
17
18     public InterpreterBenkoBox resolve(edu.berkeley.fleet.api.BenkoBox bb) { return (InterpreterBenkoBox)bb; }
19
20     public void dispatch(Instruction i) {
21
22         if (i instanceof Instruction.Executable) {
23             InterpreterBenkoBox sourceBenkoBox = resolve(((Instruction.Executable)i).benkoBox);
24             if (!(sourceBenkoBox instanceof InstructionPort))
25                 throw new RuntimeException(sourceBenkoBox + " is not an InstructionPort!");
26             ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
27
28         } else if (i instanceof Instruction.Literal.Absolute) {
29             InterpreterBenkoBox destBenkoBox = resolve(((Instruction.Literal.Absolute)i).dest);
30             Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
31             destBenkoBox.addDataFromFabric((int)((Instruction.Literal.Absolute)i).value);
32
33         } else if (i instanceof Instruction.Kill) {
34             InterpreterBenkoBox benkoBox = resolve(((Instruction.Kill)i).benkoBox);
35             if (!(benkoBox instanceof InstructionPort))
36                 throw new RuntimeException(benkoBox + " is not an InstructionPort!");
37             ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
38
39         } else {
40             throw new Error("unsupported!");
41         }
42     }
43
44     /** some "halt ship" can turn this on to stop the interpreter */
45     public boolean halt = false;
46
47     public int[] mem = new int[0];
48     public ArrayList<String> imports = new ArrayList<String>();
49
50     private static String getUniqueName(Ship ship) {
51         return ship.getType() + ship.getOrdinal();
52     }
53
54     public ArrayList<InterpreterShip> shiplist = new ArrayList<InterpreterShip>();
55     public HashMap<String,InterpreterShip> ships = new HashMap<String,InterpreterShip>();
56
57     /** read a machine-formatted instruction from a file (into a Java object) */
58     public Instruction readInstruction(DataInputStream is) throws IOException {
59         // FIXME
60         return null;
61     }
62
63     public void        writeInstruction(DataOutputStream os, Instruction d) throws IOException {
64             if (d instanceof Instruction.Executable) {
65                 Instruction.Executable inst = (Instruction.Executable)d;
66
67                 InterpreterBenkoBox dest = resolve(inst.dest);
68                 long instr = dest==null ? 0 : (dest.addr << 1);
69
70                 instr |= (((long)inst.count) << (11+1));
71                 if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
72                 if (inst.dataOut)  instr |= (1L << (11+1+7+1));
73                 if (inst.latch)    instr |= (1L << (11+1+7+2));
74                 if (inst.dataIn)   instr |= (1L << (11+1+7+3));
75                 if (inst.tokenOut) instr |= (1L << (11+1+7+4));
76                 instr |= ((long)resolve(inst.benkoBox).instr_addr) << (11+5+7+1);
77                 long out = 0;
78                 out |= ((InterpreterBenkoBox)ships.get("command").getBenkoBox("data")).addr;
79                 out |= instr << 11;
80                 dump(os, (out >> (5*8)) & 0xff);
81                 dump(os, (out >> (4*8)) & 0xff);
82                 dump(os, (out >> (3*8)) & 0xff);
83                 dump(os, (out >> (2*8)) & 0xff);
84                 dump(os, (out >> (1*8)) & 0xff);
85                 dump(os, (out >> (0*8)) & 0xff);
86             } else if (d instanceof Instruction.Literal.Absolute) {
87                 Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
88                 long out = 0;
89                 out |= resolve(ld.dest).addr;
90                 out |= ((long)ld.value) << 11;
91                 dump(os, (out >> (5*8)) & 0xff);
92                 dump(os, (out >> (4*8)) & 0xff);
93                 dump(os, (out >> (3*8)) & 0xff);
94                 dump(os, (out >> (2*8)) & 0xff);
95                 dump(os, (out >> (1*8)) & 0xff);
96                 dump(os, (out >> (0*8)) & 0xff);
97             }
98     }
99     public void dump(OutputStream os, long data_) throws IOException {
100         int data = (int)data_;
101         os.write((byte)data);
102         System.out.println(data);
103     }
104
105     public Iterator<Ship> iterator() {
106         return (Iterator<Ship>)(Object)shiplist.iterator();
107     }
108
109     public void go() {
110         while(!halt)
111             for(InterpreterShip ship : ships.values())
112                 for(int j=0; j<10; j++)
113                     ship._service();
114
115         // run the ships a bit longer for good measure
116         for(int i=0; i<100; i++)
117             for(InterpreterShip ship : ships.values())
118                 for(int j=0; j<10; j++)
119                     ship._service();
120
121         // check the state of the ships
122         for(InterpreterShip ship : ships.values())
123             ship.shutdown();
124
125         Log.println(Log.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
126     }
127
128     public void dumpMem() {
129         Log.print(Log.cyan("  MEMORY: "));
130         for(int i=0; i<mem.length; i++) {
131             if ((i%10)==0 && i!=0) Log.print(Log.cyan("          "));
132             Log.print(Log.cyan(mem[i] + " "));
133             if ((i%10)==9 && i!=mem.length-1) Log.println("");
134         }
135         Log.println();
136     }
137
138     public void writeMem(int addr, int data) {
139         if (addr >= mem.length) {
140             int[] mem2 = new int[addr*2+1];
141             System.arraycopy(mem, 0, mem2, 0, mem2.length);
142             mem = mem2;
143         }
144         mem[addr] = data;
145     }
146
147     public InterpreterShip getShip(String name) {
148         InterpreterShip s = ships.get(name);
149         if (s == null) throw new RuntimeException("unknown ship \""+name+"\"");
150         return s;
151     }
152
153     public InterpreterShip tryCreate(String classname, String shipname) {
154         try {
155             Class c = Class.forName(classname);
156             Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
157             InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
158             ships.put(shipname, ret);
159             shiplist.add(ret);
160             return ret;
161         } catch (Exception e) {
162             return null;
163         }
164     }
165
166     public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
167         Log.token(source, dest);
168         dest.addTokenFromFabric();
169     }
170
171     public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
172         Log.data(data+"", source, dest);
173         dest.addDataFromFabric(data);
174     }
175
176     public void dumpFabric(boolean quiet) {
177         // FIXME: this is really ugly: the order of port declarations in
178         //        the XXXShip.java file must match the order in the .balsa file!
179
180         ArrayList instructionports = new ArrayList<InterpreterBenkoBox>();
181         for(InterpreterShip ship : shiplist)
182             for(BenkoBox port : ship.getBenkoBoxes())
183                 if (!((InterpreterBenkoBox)port).special())
184                     instructionports.add(port);
185         FabricTree instructions =
186             new FabricTree((InterpreterBenkoBox[])instructionports.toArray(new InterpreterBenkoBox[0]),
187                            "ihorn",
188                            "instruction");
189
190         ArrayList inputports = new ArrayList<InterpreterBenkoBox>();
191         for(InterpreterShip ship : shiplist)
192             for(BenkoBox port : ship.getBenkoBoxes())
193                 if (!((InterpreterBenkoBox)port).special())
194                     inputports.add(port);
195         FabricTree inputs =
196             new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
197                            "horn",
198                            "dest");
199
200         ArrayList outputports = new ArrayList<InterpreterBenkoBox>();
201         for(InterpreterShip ship : shiplist)
202             for(BenkoBox port : ship.getBenkoBoxes())
203                 if (!((InterpreterBenkoBox)port).special())
204                     outputports.add(port);
205         FabricTree outputs =
206             new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
207                            "funnel",
208                            "source");
209
210         if (quiet) return;
211         System.out.println("`include \"macros.v\"");
212         /*
213         HashSet<Class> added = new HashSet<Class>();
214         for(Ship ship : shiplist)
215             if (!added.contains(ship.getClass())) {
216                 added.add(ship.getClass());
217                 System.out.println("import ["+ship.getBalsaName()+"]");
218             }
219         */
220         System.out.println("module fabric(clk, top_r, top_a, top,");
221         System.out.println("                   data_debug_out_r, data_debug_out_a, data_debug_out);");
222         System.out.println("  input  clk;");
223         System.out.println("  input  top_r;");
224         System.out.println("  output top_a;");
225         System.out.println("  input  [(`PACKET_WIDTH-1):0] top;");
226         System.out.println("  output data_debug_out_r;");
227         System.out.println("  input  data_debug_out_a;");
228         System.out.println("  output [(`PACKET_WIDTH-1):0] data_debug_out;");
229         System.out.println("  wire   [(`INSTRUCTION_WIDTH-1):0] data_command_out;");
230         System.out.println();
231         
232         System.out.println();
233
234         instructions.dumpChannels(true);
235         outputs.dumpChannels(true);
236         inputs.dumpChannels(true);
237         for(InterpreterShip ship : shiplist)
238             for(BenkoBox port : ship.getBenkoBoxes()) {
239                 if (ship instanceof Command && port instanceof Outbox) continue;
240                 System.out.println("  wire [(`PACKET_WIDTH-1):0] data_"+getUniqueName(ship)+"_"+port.getName()+";");
241             }
242
243         System.out.println("");
244         instructions.dumpChannels(false);
245         System.out.println("");
246         outputs.dumpChannels(false);
247         System.out.println("");
248         inputs.dumpChannels(false);
249         System.out.println("");
250         for(InterpreterShip ship : shiplist) {
251             System.out.print(ship.getClass().getSimpleName().toLowerCase());
252             System.out.print(" ");
253             System.out.print("krunk"+(krunk++));
254             System.out.print("(clk, ");
255             boolean first = true;
256             for(BenkoBox port : ship.getBenkoBoxes()) {
257                 if (!first) System.out.print(", ");
258                 first = false;
259                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
260                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
261                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
262                 System.out.print(" ");
263             }
264             System.out.println(");");
265
266             for(BenkoBox port : ship.getBenkoBoxes()) {
267                 if (((InterpreterBenkoBox)port).special()) continue;
268                 if (port instanceof Inbox) {
269                     if (((InterpreterBenkoBox)port).noInbox())
270                         System.out.print("stupidinbox");
271                     else
272                         System.out.print("inbox");
273                 } else {
274                     System.out.print("outbox");
275                 }
276                 System.out.print(" krunk"+(krunk++)+"(clk, ");
277                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
278                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
279                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
280                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
281                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
282                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
283                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
284                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
285                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
286                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
287                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
288                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
289                 System.out.print(");");
290                 System.out.println();
291             }
292
293         }
294         System.out.println("funnel topfun(clk, dest_r, dest_a, dest, source_r, source_a, source, top_r, top_a, top);");
295         System.out.println("");
296         System.out.println("  assign instruction_r      = data_command_out_r;");
297         System.out.println("  assign data_command_out_a = instruction_a;");
298         System.out.println("  assign instruction        = data_command_out;");
299         System.out.println("endmodule");
300     }
301
302     private static class FabricTree {
303         int master_idx = 1;
304         String prefix;
305         Node root;
306         public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
307         public FabricTree(InterpreterBenkoBox[] ports, String component, String prefix) {
308             this.prefix = prefix;
309             root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
310         }
311         private Object mkNode(String name, String component, InterpreterBenkoBox[] ports, int start, int end, int addr, int bits) {
312             if (end-start == 0) return null;
313             if (end-start == 1) {
314                 InterpreterBenkoBox p = ports[start];
315                 if (prefix.equals("instruction")) {
316                     p.instr_addr = addr;
317                     p.instr_bits = bits;
318                 } else {
319                     p.addr = addr;
320                     p.bits = bits;
321                 }
322                 return p;
323             }
324             int len = end-start;
325             return new Node(name,
326                             component,
327                             mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
328                             mkNode(name+"_1", component, ports, start+len/2, end,   addr | (1 << bits), bits+1),
329                             addr,
330                             bits);
331         }
332         private String describe(String prefix, Object o) {
333             if (o==null) return null;
334             if (o instanceof InterpreterBenkoBox) {
335                 InterpreterBenkoBox p = (InterpreterBenkoBox)o;
336                 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
337             }
338             if (o instanceof Node) {
339                 return ((Node)o).describe(prefix);
340             }
341             return null;
342         }
343         private class Node {
344             Object left;
345             Object right;
346             String name;
347             String component;
348         int addr;
349         int bits;
350             public Node(String name, String component, Object left, Object right, int addr, int bits) {
351                 this.left = left;
352                 this.right = right;
353                 this.name = name;
354                 this.component = component;
355                 this.addr = addr;
356                 this.bits = bits;
357             }
358             public void dumpChannels(int indentamount, boolean decl) {
359                 String indent = "";
360                 for(int i=0; i<indentamount; i++) indent += "  ";
361                 if (decl) {
362                     String n = describe(prefix).startsWith("instruction") ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
363                     System.out.println("  wire "+n+" "+indent+describe(prefix)+";");
364                 } else {
365                     System.out.println("     "+indent+
366                                        component+" "+
367                                        "krunk"+(krunk++)+"(clk, "+
368                                        describe(prefix)+"_r, "+
369                                        describe(prefix)+"_a, "+
370                                        describe(prefix)+", "+
371                                        FabricTree.this.describe(prefix, left)+"_r, "+
372                                        FabricTree.this.describe(prefix, left)+"_a, "+
373                                        FabricTree.this.describe(prefix, left)+", "+
374                                        FabricTree.this.describe(prefix, right)+"_r, "+
375                                        FabricTree.this.describe(prefix, right)+"_a, "+
376                                        FabricTree.this.describe(prefix, right)+
377                                        ");");
378                 }
379                 dumpChannels(left, indentamount+1, decl);
380                 dumpChannels(right, indentamount+1, decl);
381             }
382             public void dumpChannels(Object o, int indentamount, boolean decl) {
383                 if (o==null) return;
384                 if (o instanceof Node) {
385                     ((Node)o).dumpChannels(indentamount, decl);
386                 } else {
387                     String indent = "";
388                     for(int i=0; i<indentamount; i++) indent += "  ";
389                     if (decl) {
390                         String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
391                             ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
392                         System.out.println("  wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
393                     }
394                 }
395             }
396             public String describe(String prefix) {
397                 return prefix+name;
398             }
399         }
400     }
401     public static int krunk=0;
402 }