updates to make fpga-code instruction generation work again
[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 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);
25         }
26         dos.flush();
27         dos.close();
28     }
29
30     public void dispatch(Instruction i, long address) {
31
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));
37
38         } else if (i instanceof Instruction.Literal.CodeBagDescriptor) {
39             Log.dispatch(i);
40             Instruction.Literal.CodeBagDescriptor cbd = (Instruction.Literal.CodeBagDescriptor)i;
41             dispatchCodeBag(cbd.offset+address, cbd.size);
42             
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);
47
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);
53
54         } else {
55             throw new Error("unsupported: " + i.getClass().getName());
56         }
57     }
58
59     /** some "halt ship" can turn this on to stop the interpreter */
60     public boolean halt = false;
61
62     public int[] mem = new int[0];
63
64     public Instruction[] instructions = null;
65     public ArrayList<String> imports = new ArrayList<String>();
66
67     private static String getUniqueName(Ship ship) {
68         return ship.getType() + ship.getOrdinal();
69     }
70
71     public ArrayList<InterpreterShip> shiplist = new ArrayList<InterpreterShip>();
72     public HashMap<String,InterpreterShip> ships = new HashMap<String,InterpreterShip>();
73
74     /** read a machine-formatted instruction from a file (into a Java object) */
75     public Instruction readInstruction(DataInputStream is) throws IOException {
76         // FIXME
77         return null;
78     }
79
80     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
81         if (d instanceof Instruction.Executable) {
82             Instruction.Executable inst = (Instruction.Executable)d;
83             
84             InterpreterBenkoBox dest = resolve(inst.dest);
85             long instr = dest==null ? 0 : (dest.addr << 1);
86             
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);
94             long out = 0;
95             out |= ((InterpreterBenkoBox)ships.get("command").getBenkoBox("data")).addr;
96             out |= instr << 11;
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;
105             long out = 0;
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);
114         }
115     }
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);
120     }
121
122     public Iterator<Ship> iterator() {
123         return (Iterator<Ship>)(Object)shiplist.iterator();
124     }
125
126     public void dispatchCodeBag(long base, long size) {
127         for(long i=base; i<base+size; i++)
128             dispatch(instructions[(int)i], i);
129     }
130
131     public void go() {
132         Instruction.Literal.CodeBagDescriptor cbl =
133             (Instruction.Literal.CodeBagDescriptor)instructions[0];
134         dispatchCodeBag(cbl.offset+0, cbl.size);
135
136         while(!halt)
137             for(InterpreterShip ship : ships.values())
138                 for(int j=0; j<10; j++)
139                     ship._service();
140
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++)
145                     ship._service();
146
147         // check the state of the ships
148         for(InterpreterShip ship : ships.values())
149             ship.shutdown();
150
151         Log.println(Log.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
152     }
153
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("");
160         }
161         Log.println();
162     }
163
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);
168             mem = mem2;
169         }
170         mem[addr] = data;
171     }
172
173     public InterpreterShip getShip(String name) {
174         InterpreterShip s = ships.get(name);
175         if (s == null) throw new RuntimeException("unknown ship \""+name+"\"");
176         return s;
177     }
178
179     public InterpreterShip tryCreate(String classname, String shipname) {
180         try {
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);
185             shiplist.add(ret);
186             return ret;
187         } catch (Exception e) {
188             return null;
189         }
190     }
191
192     public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
193         Log.token(source, dest);
194         dest.addTokenFromFabric();
195     }
196
197     public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
198         Log.data(data+"", source, dest);
199         dest.addDataFromFabric(data);
200     }
201
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!
205
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]),
213                            "ihorn",
214                            "instruction");
215
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);
221         FabricTree inputs =
222             new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
223                            "horn",
224                            "dest");
225
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);
231         FabricTree outputs =
232             new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
233                            "funnel",
234                            "source");
235
236         if (quiet) return;
237         System.out.println("`include \"macros.v\"");
238         /*
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()+"]");
244           }
245         */
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();
257         
258         System.out.println();
259
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()+";");
267             }
268
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(", ");
284                 first = false;
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(" ");
289             }
290             System.out.println(");");
291
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");
297                     else
298                         System.out.print("inbox");
299                 } else {
300                     System.out.print("outbox");
301                 }
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();
317             }
318
319         }
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");
326     }
327
328     private static class FabricTree {
329         int master_idx = 1;
330         String prefix;
331         Node root;
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);
336         }
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")) {
343                     p.instr_addr = addr;
344                     p.instr_bits = bits;
345                 } else {
346                     p.addr = addr;
347                     p.bits = bits;
348                 }
349                 return p;
350             }
351             int len = end-start;
352             return new Node(name,
353                             component,
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),
356                             addr,
357                             bits);
358         }
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();
364             }
365             if (o instanceof Node) {
366                 return ((Node)o).describe(prefix);
367             }
368             return null;
369         }
370         private class Node {
371             Object left;
372             Object right;
373             String name;
374             String component;
375             int addr;
376             int bits;
377             public Node(String name, String component, Object left, Object right, int addr, int bits) {
378                 this.left = left;
379                 this.right = right;
380                 this.name = name;
381                 this.component = component;
382                 this.addr = addr;
383                 this.bits = bits;
384             }
385             public void dumpChannels(int indentamount, boolean decl) {
386                 String indent = "";
387                 for(int i=0; i<indentamount; i++) indent += "  ";
388                 if (decl) {
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)+";");
392                 } else {
393                     System.out.println("     "+indent+
394                                        component+" "+
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)+
405                                        ");");
406                 }
407                 dumpChannels(left, indentamount+1, decl);
408                 dumpChannels(right, indentamount+1, decl);
409             }
410             public void dumpChannels(Object o, int indentamount, boolean decl) {
411                 if (o==null) return;
412                 if (o instanceof Node) {
413                     ((Node)o).dumpChannels(indentamount, decl);
414                 } else {
415                     String indent = "";
416                     for(int i=0; i<indentamount; i++) indent += "  ";
417                     if (decl) {
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)+";");
421                     }
422                 }
423             }
424             public String describe(String prefix) {
425                 return prefix+name;
426             }
427         }
428     }
429     public static int krunk=0;
430
431     public int computeOffset(int origin, int target) { return target - origin; }
432     public int computeTarget(int origin, int offset) { return origin + offset; }
433 }