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