cdad214c97a408d3499eedaad655aeb80b9474dd
[fleet.git] / src / edu / berkeley / fleet / slipway / Slipway.java
1 package edu.berkeley.fleet.slipway;
2 import edu.berkeley.fleet.slipway.*;
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.util.*;
12 import java.util.*;
13 import java.io.*;
14
15 public class Slipway extends Fleet {
16
17     public ArrayList<SlipwayShip> shiplist   = new ArrayList<SlipwayShip>();
18     public HashMap<String,SlipwayShip> ships = new HashMap<String,SlipwayShip>();
19     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)shiplist.iterator(); }
20
21     private String bitfile;
22
23     public static void main(String[] s) throws Exception {
24         new Slipway().dumpFabric(false);
25     }
26
27     public Slipway() { this("gaspified.bit"); }
28     public Slipway(String bitfile) {
29         this.bitfile = bitfile;
30         createShip("Debug",   "debug");
31         createShip("Memory",    "Memory");
32         createShip("Fifo",    "fifo1");
33         createShip("Fifo",    "fifo2");
34         createShip("Fifo",    "fifo3");
35         createShip("Execute", "execute");
36         createShip("Alu1",    "alu1");
37         createShip("Alu2",    "alu2a");
38         createShip("Lut3",      "lut3");
39         createShip("Choice",    "Choice");
40         createShip("Stack",     "Stack");
41         createShip("Alu3",      "alu3");
42         createShip("BitFifo",   "bitfifo");
43
44         // above is the minimal ship set needed to run the regression suite
45         // below are extra bonush ships
46
47         createShip("Alu2",    "alu2b");
48         createShip("Alu2",    "alu2c");
49         createShip("Alu2",    "alu2d");
50         createShip("Fifo",    "fifo4");
51         createShip("Memory",    "Memory");
52         createShip("Choice",    "Choice");
53         createShip("Choice",    "Choice");
54         createShip("Choice",    "Choice");
55         dumpFabric(true);
56     }
57
58     public Ship createShip(String type, String name) {
59         try {
60             ShipDescription sd = new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
61             SlipwayShip ship = new SlipwayShip(this, name, type, sd);
62             ships.put(name, ship);
63             shiplist.add(ship);
64             return ship;
65         } catch (IOException e) { throw new RuntimeException(e); }
66     }
67
68     public FleetProcess run(final byte[] instructions) {
69         try {
70             return new Client(bitfile, instructions);
71         } catch (IOException e) { throw new RuntimeException(e); }
72     }
73
74     public void dumpFabric(boolean quiet) {
75         // FIXME: this is really ugly: the order of port declarations in
76         //        the XXXShip.java file must match the order in the .balsa file!
77
78         ArrayList instructionports = new ArrayList<SlipwayBenkoBox>();
79         for(SlipwayShip ship : shiplist)
80             for(BenkoBox port : ship.getBenkoBoxes())
81                 if (!((SlipwayBenkoBox)port).special())
82                     instructionports.add(port);
83         FabricTree instructions =
84             new FabricTree((SlipwayBenkoBox[])instructionports.toArray(new SlipwayBenkoBox[0]),
85                            "ihorn",
86                            "instruction");
87
88         ArrayList inputports = new ArrayList<SlipwayBenkoBox>();
89         for(SlipwayShip ship : shiplist)
90             for(BenkoBox port : ship.getBenkoBoxes())
91                 if (!((SlipwayBenkoBox)port).special())
92                     inputports.add(port);
93         FabricTree inputs =
94             new FabricTree((SlipwayBenkoBox[])inputports.toArray(new SlipwayBenkoBox[0]),
95                            "horn",
96                            "dest");
97
98         ArrayList outputports = new ArrayList<SlipwayBenkoBox>();
99         for(SlipwayShip ship : shiplist)
100             for(BenkoBox port : ship.getBenkoBoxes())
101                 if (!((SlipwayBenkoBox)port).special() || ((SlipwayBenkoBox)port).dhorn())
102                     outputports.add(port);
103         FabricTree outputs =
104             new FabricTree((SlipwayBenkoBox[])outputports.toArray(new SlipwayBenkoBox[0]),
105                            "funnel",
106                            "source");
107
108         ArrayList ihornports = new ArrayList<SlipwayBenkoBox>();
109         for(SlipwayShip ship : shiplist)
110             for(BenkoBox port : ship.getBenkoBoxes())
111                 if (((SlipwayBenkoBox)port).ihorn())
112                     ihornports.add(port);
113         FabricTree ihorns =
114             new FabricTree((SlipwayBenkoBox[])ihornports.toArray(new SlipwayBenkoBox[0]),
115                            "funnel",
116                            "ihorn");
117         
118         if (quiet) return;
119         System.out.println("`include \"macros.v\"");
120         System.out.println("module fabric(clk, data_Memory0_command_r, data_Memory0_command_a, data_Memory0_command,");
121         System.out.println("                   data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
122         System.out.println("  input  clk;");
123         System.out.println("  input  data_Memory0_command_r;");
124         System.out.println("  output data_Memory0_command_a;");
125         System.out.println("  output data_Debug0_out_r;");
126         System.out.println("  input  data_Debug0_out_a;");
127         System.out.println("  output [(`PACKET_WIDTH-1):0]      data_Debug0_out;");
128         System.out.println("  input  [(`PACKET_WIDTH-1):0]      data_Memory0_command;");
129         //System.out.println("  wire   [(`INSTRUCTION_WIDTH-1):0] data_Memory0_ihorn;");
130         //System.out.println("  wire   [(`PACKET_WIDTH-1):0]      data_Memory0_dhorn;");
131         System.out.println();
132         
133         System.out.println();
134
135         instructions.dumpChannels(true);
136         outputs.dumpChannels(true);
137         inputs.dumpChannels(true);
138         ihorns.dumpChannels(true);
139         for(SlipwayShip ship : shiplist)
140             for(BenkoBox port : ship.getBenkoBoxes())
141                 if (!((SlipwayBenkoBox)port).special() || ((SlipwayBenkoBox)port).dhorn())
142                     System.out.println("  wire [(`PACKET_WIDTH-1):0] data_"
143                                        +getUniqueName(ship)+"_"+port.getName()+";");
144
145         System.out.println("");
146         instructions.dumpChannels(false);
147         System.out.println("");
148         outputs.dumpChannels(false);
149         System.out.println("");
150         inputs.dumpChannels(false);
151         System.out.println("");
152         ihorns.dumpChannels(false);
153         System.out.println("");
154         for(SlipwayShip ship : shiplist) {
155             System.out.print(ship.getType().toLowerCase());
156             System.out.print(" ");
157             System.out.print("krunk"+(krunk++));
158             System.out.print("(clk, ");
159             boolean first = true;
160             for(BenkoBox port : ship.getBenkoBoxes()) {
161                 if (!first) System.out.print(", ");
162                 first = false;
163                 String prefix = "data_";
164                 if (((SlipwayBenkoBox)port).ihorn()) prefix = "ihorn_";
165                 if (((SlipwayBenkoBox)port).dhorn()) prefix = "source_";
166                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
167                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
168                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName());
169                 System.out.print(" ");
170             }
171             System.out.println(");");
172
173             for(BenkoBox port : ship.getBenkoBoxes()) {
174                 if (((SlipwayBenkoBox)port).special()) continue;
175                 if (((SlipwayBenkoBox)port).inbox) {
176                     System.out.print("inbox");
177                 } else {
178                     System.out.print("outbox");
179                 }
180                 System.out.print(" krunk"+(krunk++)+"(clk, ");
181                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
182                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
183                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
184                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
185                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
186                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
187                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
188                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
189                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
190                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
191                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
192                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
193                 System.out.print(");");
194                 System.out.println();
195             }
196
197         }
198         /*
199         System.out.println("funnel topfun(clk,"+
200                            "              dest_r, dest_a, dest,"+
201                            "              source_r, source_a, source,"+
202                            "              data_Memory0_dhorn_r, data_Memory0_dhorn_a, data_Memory0_dhorn);");
203         */
204         System.out.println("assign instruction_r = ihorn_r;");
205         System.out.println("assign ihorn_a = instruction_a;");
206         System.out.println("assign instruction = ihorn;");
207         System.out.println("assign dest_r = source_r;");
208         System.out.println("assign source_a = dest_a;");
209         System.out.println("assign dest = source;");
210         System.out.println("endmodule");
211     }
212
213     private static class FabricTree {
214         int master_idx = 1;
215         String prefix;
216         Node root;
217         public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
218         public FabricTree(SlipwayBenkoBox[] ports, String component, String prefix) {
219             this.prefix = prefix;
220             root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
221         }
222         private Object mkNode(String name, String component, SlipwayBenkoBox[] ports,
223                               int start, int end, int addr, int bits) {
224             if (end-start == 0) return null;
225             if (end-start == 1) {
226                 SlipwayBenkoBox p = ports[start];
227                 if (prefix.equals("instruction")) {
228                     p.instr_addr = addr;
229                     p.instr_bits = bits;
230                 } else if (prefix.equals("dest")) {
231                     p.addr = addr;
232                     p.bits = bits;
233                     if (bits >= 11)
234                         throw new RuntimeException("too many benkoboxen!");
235                     int count = 0;
236                     for(Destination d : p.getDestinations()) {
237                         if (!(d instanceof SlipwayBenkoBox.VirtualPort)) continue;
238                         SlipwayBenkoBox.VirtualPort vp = (SlipwayBenkoBox.VirtualPort)d;
239                         vp.addr = p.addr | (count << bits);
240                         count++;
241                     }
242                 }
243                 return p;
244             }
245             int len = end-start;
246             int count   = 0;
247             int count2  = 0;
248             int breakpt = 0;
249             if (end-start <= 2) {
250                 breakpt = (start+end)/2;
251             } else {
252                 for(int i=start; i<end; i++)
253                     count += count(ports[i].getDestinations());
254                 for(int i=start; i<end-1; i++) {
255                     count2 += count(ports[i].getDestinations());
256                     breakpt = i;
257                     if (i>start && count2 >= count/2) break;
258                 }
259             }
260             return new Node(name,
261                             component,
262                             mkNode(name+"_0", component, ports, start, breakpt, addr,               bits+1),
263                             mkNode(name+"_1", component, ports, breakpt, end,   addr | (1 << bits), bits+1),
264                             addr,
265                             bits);
266         }
267         private String describe(String prefix, Object o) {
268             if (o==null) return null;
269             if (o instanceof SlipwayBenkoBox) {
270                 SlipwayBenkoBox p = (SlipwayBenkoBox)o;
271                 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
272             }
273             if (o instanceof Node) {
274                 return ((Node)o).describe(prefix);
275             }
276             return null;
277         }
278         private class Node {
279             Object left;
280             Object right;
281             String name;
282             String component;
283             int addr;
284             int bits;
285             public Node(String name, String component, Object left, Object right, int addr, int bits) {
286                 this.left = left;
287                 this.right = right;
288                 this.name = name;
289                 this.component = component;
290                 this.addr = addr;
291                 this.bits = bits;
292             }
293             public void dumpChannels(int indentamount, boolean decl) {
294                 String indent = "";
295                 for(int i=0; i<indentamount; i++) indent += "  ";
296                 if (decl) {
297                     String n = describe(prefix).startsWith("instruction")
298                         ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
299                     System.out.println("  wire "+n+" "+indent+describe(prefix)+";");
300                 } else {
301                     System.out.println("     "+indent+
302                                        component+" "+
303                                        "krunk"+(krunk++)+"(clk, "+
304                                        describe(prefix)+"_r, "+
305                                        describe(prefix)+"_a, "+
306                                        describe(prefix)+", "+
307                                        FabricTree.this.describe(prefix, left)+"_r, "+
308                                        FabricTree.this.describe(prefix, left)+"_a, "+
309                                        FabricTree.this.describe(prefix, left)+", "+
310                                        FabricTree.this.describe(prefix, right)+"_r, "+
311                                        FabricTree.this.describe(prefix, right)+"_a, "+
312                                        FabricTree.this.describe(prefix, right)+
313                                        ");");
314                 }
315                 dumpChannels(left, indentamount+1, decl);
316                 dumpChannels(right, indentamount+1, decl);
317             }
318             public void dumpChannels(Object o, int indentamount, boolean decl) {
319                 if (o==null) return;
320                 if (o instanceof Node) {
321                     ((Node)o).dumpChannels(indentamount, decl);
322                 } else {
323                     String indent = "";
324                     for(int i=0; i<indentamount; i++) indent += "  ";
325                     if (decl) {
326                         String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
327                             ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
328                         System.out.println("  wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
329                     }
330                 }
331             }
332             public String describe(String prefix) {
333                 return prefix+name;
334             }
335         }
336     }
337     public static int krunk=0;
338
339     private static String getUniqueName(Ship ship) {
340         return ship.getType() + ship.getOrdinal();
341     }
342
343     private static int count(Iterable<Destination> it) {
344         int ret = 0;
345         for(Destination d : it)
346             ret++;
347         return ret;
348     }
349
350     public void expand(ShipDescription sd) {
351         try {
352             if (sd.getSection("fpga")==null) return;
353             String filename = sd.getName().toLowerCase();
354             File outf = new File("src/edu/berkeley/fleet/slipway/"+filename+".v");
355             new File(outf.getParent()).mkdirs();
356             System.err.println("writing to " + outf);
357             FileOutputStream out = new FileOutputStream(outf);
358             PrintWriter pw = new PrintWriter(out);
359
360             boolean auto =
361                 !"debug".equals(filename) &&
362                 !"execute".equals(filename) &&
363                 !"memory".equals(filename) &&
364                 !"fifo".equals(filename);
365             if (auto) {
366                 pw.println("`include \"macros.v\"");
367                 pw.println();
368                 pw.println("module " + filename + "( clk");
369                 for(BenkoBoxDescription bb : sd) {
370                     String bb_name = bb.getName();
371                     pw.print("        ");
372                     if (bb.isInbox()) {
373                         pw.print(", " + bb_name+"_r");
374                         pw.print(", " + bb_name+"_a_");
375                         pw.print(", " + bb_name+"_d");
376                     } else {
377                         pw.print(", " + bb_name+"_r_");
378                         pw.print(", " + bb_name+"_a");
379                         pw.print(", " + bb_name+"_d_");
380                     }
381                     pw.println();
382                 }
383                 pw.println("        );");
384                 pw.println();
385                 pw.println("    input clk;");
386                 for(BenkoBoxDescription bb : sd) {
387                     String bb_name = bb.getName();
388                     pw.print("        ");
389                     if (bb.isInbox()) {
390                         pw.println("`input(" +
391                                    bb_name+"_r,  "+
392                                    bb_name+"_a,  "+
393                                    bb_name+"_a_, "+
394                                    "[(`PACKET_WIDTH-1):0],"+
395                                    bb_name+"_d)"
396                                    );
397                     } else {
398                         pw.println("`output(" +
399                                    bb_name+"_r,  "+
400                                    bb_name+"_r_, "+
401                                    bb_name+"_a,  "+
402                                    "[(`PACKET_WIDTH-1):0],"+
403                                    bb_name+"_d_)"
404                                    );
405                         pw.println("`defreg(" +
406                                    bb_name+"_d_,  "+
407                                    "[(`PACKET_WIDTH-1):0],"+
408                                    bb_name+"_d)"
409                                    );
410                     }
411                     pw.println();
412                 }
413             }
414
415             pw.println(sd.getSection("fpga"));
416
417             if (auto)
418                 pw.println("endmodule");
419
420             pw.flush();
421             pw.close();
422         } catch (Exception e) { throw new RuntimeException(e); }
423     }
424
425     public int computeOffset(int origin, int target) { return (target - origin)/6; }
426     public int computeTarget(int origin, int offset) { return origin + (offset*6); }
427
428     private SlipwayInstructionEncoder iie = new SlipwayInstructionEncoder();
429     public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
430     public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
431     public long writeInstruction(Instruction d) { return writeInstruction(d); }
432     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
433
434     private class SlipwayInstructionEncoder extends InstructionEncoder {
435         public long getDestAddr(Destination box) { return ((SlipwayBenkoBox.VirtualPort)box).addr; }
436         public long getBoxInstAddr(BenkoBox box) { return ((SlipwayBenkoBox)box).instr_addr; }
437         public Destination getDestByAddr(long dest) {
438             for(Ship ship : Slipway.this)
439                 for(BenkoBox bb : ship.getBenkoBoxes())
440                     for(Destination d : bb.getDestinations())
441                         if (getDestAddr(d)==dest)
442                             return d;
443             return null;
444         }
445         public BenkoBox getBoxByInstAddr(long dest) {
446             for(Ship ship : Slipway.this)
447                 for(BenkoBox bb : ship.getBenkoBoxes())
448                     if (((SlipwayBenkoBox)bb).instr_addr == dest)
449                         return bb;
450             return null;
451         }
452     }
453
454 }