c89b1396c35e86a4a3b3332394a2ba521395cc3a
[fleet.git] / src / edu / berkeley / fleet / slipway / Slipway.java
1 package edu.berkeley.fleet.slipway;
2 import edu.berkeley.fleet.interpreter.*;
3 import edu.berkeley.fleet.doc.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.fleet.ies44.*;
6 import edu.berkeley.fleet.*;
7 import java.lang.reflect.*;
8 import edu.berkeley.sbp.chr.*;
9 import edu.berkeley.sbp.misc.*;
10 import edu.berkeley.sbp.meta.*;
11 import edu.berkeley.sbp.bind.*;
12 import edu.berkeley.sbp.util.*;
13 import java.util.*;
14 import java.io.*;
15 import edu.berkeley.fleet.interpreter.ships.*;
16
17 public class Slipway extends Interpreter {
18
19     private String bitfile;
20
21     public Slipway() { this("superbowl2.bit"); }
22     public Slipway(String bitfile) {
23         this.bitfile = bitfile;
24         createShip("Debug",   "debug");
25         createShip("Fifo",    "fifo1");
26         createShip("Alu2",    "alu2a");
27         createShip("Alu2",    "alu2b");
28         createShip("Alu2",    "alu2c");
29         createShip("Alu2",    "alu2d");
30         createShip("Execute", "execute");
31         createShip("Fifo",    "fifo1");
32         createShip("Fifo",    "fifo2");
33         createShip("Fifo",    "fifo3");
34         createShip("Fifo",    "fifo4");
35         // FIXME cant have less than two feeding the instruction horn or BUG
36         createShip("Iscratch",  "iscratch1");
37         createShip("Iscratch",  "iscratch2");
38         createShip("Dscratch",  "dscratch1");
39         createShip("Dscratch",  "dscratch2");
40         createShip("Lut3",      "lut3");
41         createShip("Alu1",      "alu1");
42         dumpFabric(true);
43     }
44
45     public Ship createShip(String type, String name) {
46         InterpreterShip ship = (InterpreterShip)super.createShip(type, name);
47         if        (ship.getClass().getSimpleName().equals("Debug")) {
48             new DataOutbox(ship, "out", true);
49             
50         } else if (ship.getClass().getSimpleName().equals("Execute")) {
51             new DataOutbox(ship, "ihorn", true, true, false);
52             new DataOutbox(ship, "dhorn", true, false, true);
53             
54         } else if (ship.getClass().getSimpleName().equals("Iscratch")) {
55             new DataInbox(ship,  "command", true);
56             new DataOutbox(ship, "ihorn",   true, true, false);
57             new DataOutbox(ship, "dhorn",   true, false, true);
58         }
59         return ship;
60     }
61
62     public FleetProcess run(final byte[] instructions) {
63         try {
64             return new Client(bitfile, instructions);
65         } catch (IOException e) { throw new RuntimeException(e); }
66     }
67
68     public void dumpFabric(boolean quiet) {
69         // FIXME: this is really ugly: the order of port declarations in
70         //        the XXXShip.java file must match the order in the .balsa file!
71
72         ArrayList instructionports = new ArrayList<InterpreterBenkoBox>();
73         for(InterpreterShip ship : shiplist)
74             for(BenkoBox port : ship.getBenkoBoxes())
75                 if (!((InterpreterBenkoBox)port).special())
76                     instructionports.add(port);
77         FabricTree instructions =
78             new FabricTree((InterpreterBenkoBox[])instructionports.toArray(new InterpreterBenkoBox[0]),
79                            "ihorn",
80                            "instruction");
81
82         ArrayList inputports = new ArrayList<InterpreterBenkoBox>();
83         for(InterpreterShip ship : shiplist)
84             for(BenkoBox port : ship.getBenkoBoxes())
85                 if (!((InterpreterBenkoBox)port).special())
86                     inputports.add(port);
87         FabricTree inputs =
88             new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
89                            "horn",
90                            "dest");
91
92         ArrayList outputports = new ArrayList<InterpreterBenkoBox>();
93         for(InterpreterShip ship : shiplist)
94             for(BenkoBox port : ship.getBenkoBoxes())
95                 if (!((InterpreterBenkoBox)port).special() || ((InterpreterBenkoBox)port).dhorn())
96                     outputports.add(port);
97         FabricTree outputs =
98             new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
99                            "funnel",
100                            "source");
101
102         ArrayList ihornports = new ArrayList<InterpreterBenkoBox>();
103         for(InterpreterShip ship : shiplist)
104             for(BenkoBox port : ship.getBenkoBoxes())
105                 if (((InterpreterBenkoBox)port).ihorn())
106                     ihornports.add(port);
107         FabricTree ihorns =
108             new FabricTree((InterpreterBenkoBox[])ihornports.toArray(new InterpreterBenkoBox[0]),
109                            "funnel",
110                            "ihorn");
111         
112         if (quiet) return;
113         System.out.println("`include \"macros.v\"");
114         System.out.println("module fabric(clk, data_Iscratch0_command_r, data_Iscratch0_command_a, data_Iscratch0_command,");
115         System.out.println("                   data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
116         System.out.println("  input  clk;");
117         System.out.println("  input  data_Iscratch0_command_r;");
118         System.out.println("  output data_Iscratch0_command_a;");
119         System.out.println("  output data_Debug0_out_r;");
120         System.out.println("  input  data_Debug0_out_a;");
121         System.out.println("  output [(`PACKET_WIDTH-1):0]      data_Debug0_out;");
122         System.out.println("  input  [(`PACKET_WIDTH-1):0]      data_Iscratch0_command;");
123         //System.out.println("  wire   [(`INSTRUCTION_WIDTH-1):0] data_Iscratch0_ihorn;");
124         //System.out.println("  wire   [(`PACKET_WIDTH-1):0]      data_Iscratch0_dhorn;");
125         System.out.println();
126         
127         System.out.println();
128
129         instructions.dumpChannels(true);
130         outputs.dumpChannels(true);
131         inputs.dumpChannels(true);
132         ihorns.dumpChannels(true);
133         for(InterpreterShip ship : shiplist)
134             for(BenkoBox port : ship.getBenkoBoxes())
135                 if (!((InterpreterBenkoBox)port).special() || ((InterpreterBenkoBox)port).dhorn())
136                     System.out.println("  wire [(`PACKET_WIDTH-1):0] data_"
137                                        +getUniqueName(ship)+"_"+port.getName()+";");
138
139         System.out.println("");
140         instructions.dumpChannels(false);
141         System.out.println("");
142         outputs.dumpChannels(false);
143         System.out.println("");
144         inputs.dumpChannels(false);
145         System.out.println("");
146         ihorns.dumpChannels(false);
147         System.out.println("");
148         for(InterpreterShip ship : shiplist) {
149             System.out.print(ship.getClass().getSimpleName().toLowerCase());
150             System.out.print(" ");
151             System.out.print("krunk"+(krunk++));
152             System.out.print("(clk, ");
153             boolean first = true;
154             for(BenkoBox port : ship.getBenkoBoxes()) {
155                 if (!first) System.out.print(", ");
156                 first = false;
157                 String prefix = "data_";
158                 if (((InterpreterBenkoBox)port).ihorn()) prefix = "ihorn_";
159                 if (((InterpreterBenkoBox)port).dhorn()) prefix = "source_";
160                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
161                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
162                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName());
163                 System.out.print(" ");
164             }
165             System.out.println(");");
166
167             for(BenkoBox port : ship.getBenkoBoxes()) {
168                 if (((InterpreterBenkoBox)port).special()) continue;
169                 if (port instanceof Inbox) {
170                     System.out.print("inbox");
171                 } else {
172                     System.out.print("outbox");
173                 }
174                 System.out.print(" krunk"+(krunk++)+"(clk, ");
175                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
176                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
177                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
178                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
179                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
180                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
181                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
182                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
183                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
184                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
185                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
186                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
187                 System.out.print(");");
188                 System.out.println();
189             }
190
191         }
192         /*
193         System.out.println("funnel topfun(clk,"+
194                            "              dest_r, dest_a, dest,"+
195                            "              source_r, source_a, source,"+
196                            "              data_Iscratch0_dhorn_r, data_Iscratch0_dhorn_a, data_Iscratch0_dhorn);");
197         */
198         System.out.println("assign instruction_r = ihorn_r;");
199         System.out.println("assign ihorn_a = instruction_a;");
200         System.out.println("assign instruction = ihorn;");
201         System.out.println("assign dest_r = source_r;");
202         System.out.println("assign source_a = dest_a;");
203         System.out.println("assign dest = source;");
204         System.out.println("endmodule");
205     }
206
207     private static class FabricTree {
208         int master_idx = 1;
209         String prefix;
210         Node root;
211         public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
212         public FabricTree(InterpreterBenkoBox[] ports, String component, String prefix) {
213             this.prefix = prefix;
214             root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
215         }
216         private Object mkNode(String name, String component, InterpreterBenkoBox[] ports,
217                               int start, int end, int addr, int bits) {
218             if (end-start == 0) return null;
219             if (end-start == 1) {
220                 InterpreterBenkoBox p = ports[start];
221                 if (prefix.equals("instruction")) {
222                     p.instr_addr = addr;
223                     p.instr_bits = bits;
224                 } else if (prefix.equals("dest")) {
225                     p.addr = addr;
226                     p.bits = bits;
227                 }
228                 return p;
229             }
230             int len = end-start;
231             return new Node(name,
232                             component,
233                             mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
234                             mkNode(name+"_1", component, ports, start+len/2, end,   addr | (1 << bits), bits+1),
235                             addr,
236                             bits);
237         }
238         private String describe(String prefix, Object o) {
239             if (o==null) return null;
240             if (o instanceof InterpreterBenkoBox) {
241                 InterpreterBenkoBox p = (InterpreterBenkoBox)o;
242                 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
243             }
244             if (o instanceof Node) {
245                 return ((Node)o).describe(prefix);
246             }
247             return null;
248         }
249         private class Node {
250             Object left;
251             Object right;
252             String name;
253             String component;
254             int addr;
255             int bits;
256             public Node(String name, String component, Object left, Object right, int addr, int bits) {
257                 this.left = left;
258                 this.right = right;
259                 this.name = name;
260                 this.component = component;
261                 this.addr = addr;
262                 this.bits = bits;
263             }
264             public void dumpChannels(int indentamount, boolean decl) {
265                 String indent = "";
266                 for(int i=0; i<indentamount; i++) indent += "  ";
267                 if (decl) {
268                     String n = describe(prefix).startsWith("instruction")
269                         ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
270                     System.out.println("  wire "+n+" "+indent+describe(prefix)+";");
271                 } else {
272                     System.out.println("     "+indent+
273                                        component+" "+
274                                        "krunk"+(krunk++)+"(clk, "+
275                                        describe(prefix)+"_r, "+
276                                        describe(prefix)+"_a, "+
277                                        describe(prefix)+", "+
278                                        FabricTree.this.describe(prefix, left)+"_r, "+
279                                        FabricTree.this.describe(prefix, left)+"_a, "+
280                                        FabricTree.this.describe(prefix, left)+", "+
281                                        FabricTree.this.describe(prefix, right)+"_r, "+
282                                        FabricTree.this.describe(prefix, right)+"_a, "+
283                                        FabricTree.this.describe(prefix, right)+
284                                        ");");
285                 }
286                 dumpChannels(left, indentamount+1, decl);
287                 dumpChannels(right, indentamount+1, decl);
288             }
289             public void dumpChannels(Object o, int indentamount, boolean decl) {
290                 if (o==null) return;
291                 if (o instanceof Node) {
292                     ((Node)o).dumpChannels(indentamount, decl);
293                 } else {
294                     String indent = "";
295                     for(int i=0; i<indentamount; i++) indent += "  ";
296                     if (decl) {
297                         String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
298                             ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
299                         System.out.println("  wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
300                     }
301                 }
302             }
303             public String describe(String prefix) {
304                 return prefix+name;
305             }
306         }
307     }
308     public static int krunk=0;
309
310     private static String getUniqueName(Ship ship) {
311         return ship.getType() + ship.getOrdinal();
312     }
313
314     public void expand(ShipDescription sd) {
315         try {
316             String filename = sd.name.toLowerCase();
317             File outf = new File("src/edu/berkeley/fleet/slipway/"+filename+".v");
318             new File(outf.getParent()).mkdirs();
319             System.err.println("writing to " + outf);
320             FileOutputStream out = new FileOutputStream(outf);
321             PrintWriter pw = new PrintWriter(out);
322
323             boolean auto = filename.equals("alu2") || filename.equals("alu1") || filename.equals("lut3");
324             if (auto) {
325                 pw.println("`include \"macros.v\"");
326                 pw.println();
327                 pw.println("module " + filename + "( clk");
328                 for(ShipDescription.BenkoBox bb : sd.benkoBoxes) {
329                     if (bb.ports.length > 1) throw new RuntimeException("gah");
330                     String bb_name = bb.ports[0];
331                     pw.print("        ");
332                     if (bb.inbox) {
333                         pw.print(", " + bb_name+"_r");
334                         pw.print(", " + bb_name+"_a_");
335                         pw.print(", " + bb_name+"_d");
336                     } else {
337                         pw.print(", " + bb_name+"_r_");
338                         pw.print(", " + bb_name+"_a");
339                         pw.print(", " + bb_name+"_d_");
340                     }
341                     pw.println();
342                 }
343                 pw.println("        );");
344                 pw.println();
345                 pw.println("    input clk;");
346                 for(ShipDescription.BenkoBox bb : sd.benkoBoxes) {
347                     if (bb.ports.length > 1) throw new RuntimeException("gah");
348                     String bb_name = bb.ports[0];
349                     pw.print("        ");
350                     if (bb.inbox) {
351                         pw.println("`input(" +
352                                    bb_name+"_r,  "+
353                                    bb_name+"_a,  "+
354                                    bb_name+"_a_, "+
355                                    "[(`DATAWIDTH-1):0],"+
356                                    bb_name+"_d)"
357                                    );
358                     } else {
359                         pw.println("`output(" +
360                                    bb_name+"_r,  "+
361                                    bb_name+"_r_, "+
362                                    bb_name+"_a,  "+
363                                    "[(`DATAWIDTH-1):0],"+
364                                    bb_name+"_d_)"
365                                    );
366                         pw.println("`defreg(" +
367                                    bb_name+"_d_,  "+
368                                    "[(`DATAWIDTH-1):0],"+
369                                    bb_name+"_d)"
370                                    );
371                     }
372                     pw.println();
373                 }
374             }
375
376             pw.println(sd.sections.get("fpga"));
377
378             if (auto)
379                 pw.println("endmodule");
380
381             pw.flush();
382             pw.close();
383         } catch (Exception e) { throw new RuntimeException(e); }
384     }
385
386 }