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