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