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