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.*;
15 public class Fpga extends Fleet {
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(); }
21 private String bitfile;
23 public static void main(String[] s) throws Exception {
24 new Fpga().dumpFabric(false);
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
34 createShip("Fifo", "fifo1");
35 createShip("Fifo", "fifo2");
36 createShip("Alu2", "alu2a");
37 createShip("BitFifo", "bitfifo");
38 createShip("Rotator", "rotator");
39 // above is the minimal ship set needed to run the regression suite, excluding "ships" tests
40 createShip("Alu1", "alu1");
41 createShip("Lut3", "lut3");
42 createShip("Alu3", "alu3");
45 createShip("Stack", "Stack");
46 createShip("Fifo", "fifo3");
47 createShip("Choice", "Choice");
49 // above is the minimal ship set needed to run the regression suite, including "ships" tests
51 // below are extra bonus ships
53 createShip("Alu2", "alu2b");
54 createShip("Alu2", "alu2c");
55 createShip("Alu2", "alu2d");
56 createShip("Fifo", "fifo4");
57 createShip("Memory", "Memory");
58 createShip("Choice", "Choice");
59 createShip("Choice", "Choice");
60 createShip("Choice", "Choice");
65 public Ship createShip(String type, String name) {
67 ShipDescription sd = new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
68 FpgaShip ship = new FpgaShip(this, name, type, sd);
69 ships.put(name, ship);
72 } catch (IOException e) { throw new RuntimeException(e); }
75 public FleetProcess run(final byte[] instructions) {
77 return new Client(bitfile, instructions);
78 } catch (IOException e) { throw new RuntimeException(e); }
81 public void dumpFabric(boolean quiet) {
82 // FIXME: this is really ugly: the order of port declarations in
83 // the XXXShip.java file must match the order in the .balsa file!
85 ArrayList instructionports = new ArrayList<FpgaPump>();
86 for(FpgaShip ship : shiplist)
87 for(Pump port : ship.getPumps())
88 if (!((FpgaPump)port).special())
89 instructionports.add(port);
90 FabricTree instructions =
91 new FabricTree((FpgaPump[])instructionports.toArray(new FpgaPump[0]),
95 ArrayList inputports = new ArrayList<FpgaPump>();
96 for(FpgaShip ship : shiplist)
97 for(Pump port : ship.getPumps())
98 if (!((FpgaPump)port).special())
101 new FabricTree((FpgaPump[])inputports.toArray(new FpgaPump[0]),
105 ArrayList outputports = new ArrayList<FpgaPump>();
106 for(FpgaShip ship : shiplist)
107 for(Pump port : ship.getPumps())
108 if (!((FpgaPump)port).special() || ((FpgaPump)port).dhorn())
109 outputports.add(port);
111 new FabricTree((FpgaPump[])outputports.toArray(new FpgaPump[0]),
115 ArrayList ihornports = new ArrayList<FpgaPump>();
116 for(FpgaShip ship : shiplist)
117 for(Pump port : ship.getPumps())
118 if (((FpgaPump)port).ihorn())
119 ihornports.add(port);
121 new FabricTree((FpgaPump[])ihornports.toArray(new FpgaPump[0]),
126 System.out.println("`include \"macros.v\"");
127 System.out.println("module fabric(clk, rst, data_Memory0_command_r, data_Memory0_command_a, data_Memory0_command,");
128 System.out.println(" data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
129 System.out.println(" input clk;");
130 System.out.println(" input rst;");
131 System.out.println(" input data_Memory0_command_r;");
132 System.out.println(" output data_Memory0_command_a;");
133 System.out.println(" output data_Debug0_out_r;");
134 System.out.println(" input data_Debug0_out_a;");
135 System.out.println(" output [(`PACKET_WIDTH-1):0] data_Debug0_out;");
136 System.out.println(" input [(`PACKET_WIDTH-1):0] data_Memory0_command;");
137 //System.out.println(" wire [(`INSTRUCTION_WIDTH-1):0] data_Memory0_ihorn;");
138 //System.out.println(" wire [(`PACKET_WIDTH-1):0] data_Memory0_dhorn;");
139 System.out.println();
141 System.out.println();
143 instructions.dumpChannels(true);
144 outputs.dumpChannels(true);
145 inputs.dumpChannels(true);
146 ihorns.dumpChannels(true);
147 for(FpgaShip ship : shiplist)
148 for(Pump port : ship.getPumps())
149 if (!((FpgaPump)port).special() || ((FpgaPump)port).dhorn())
150 System.out.println(" wire [(`PACKET_WIDTH-1):0] data_"
151 +getUniqueName(ship)+"_"+port.getName()+";");
153 System.out.println("wire [(`PACKET_WIDTH-1):0] ihornleft;");
155 System.out.println("");
156 instructions.dumpChannels(false);
157 System.out.println("");
158 outputs.dumpChannels(false);
159 System.out.println("");
160 inputs.dumpChannels(false);
161 System.out.println("");
162 ihorns.dumpChannels(false);
163 System.out.println("");
164 for(FpgaShip ship : shiplist) {
165 System.out.print(ship.getType().toLowerCase());
166 System.out.print(" ");
167 System.out.print("krunk"+(krunk++));
168 System.out.print("(clk, rst, ");
169 boolean first = true;
170 for(Pump port : ship.getPumps()) {
171 if (!first) System.out.print(", ");
173 String prefix = "data_";
174 if (((FpgaPump)port).ihorn()) prefix = "ihorn_";
175 if (((FpgaPump)port).dhorn()) prefix = "source_";
176 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
177 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
178 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName());
179 System.out.print(" ");
181 System.out.println(");");
183 for(Pump port : ship.getPumps()) {
184 if (((FpgaPump)port).special()) continue;
185 if (((FpgaPump)port).inbox) {
186 System.out.print("inbox");
188 System.out.print("outbox");
190 System.out.print(" krunk"+(krunk++)+"(clk, rst, ");
191 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
192 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
193 System.out.print("`packet_data(instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"), ");
194 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
195 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
196 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
197 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
198 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
199 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
200 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
201 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
202 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
203 System.out.print(");");
204 System.out.println();
209 System.out.println("funnel ihornfun(clk, rst, "+
210 " ihornleft_r, ihornleft_a, ihornleft,"+
211 " ihorn_r, ihorn_a, ihorn,"+
212 " source_r, source_a, source);");
213 System.out.println("horn tophorn(clk, rst, "+
214 " ihornleft_r, ihornleft_a, ihornleft,"+
215 " instruction_r, instruction_a, instruction,"+
216 " dest_r, dest_a, dest);");
218 System.out.println("assign instruction_r = ihorn_r;");
219 System.out.println("assign ihorn_a = instruction_a;");
220 System.out.println("assign instruction = ihorn;");
221 System.out.println("assign dest_r = source_r;");
222 System.out.println("assign source_a = dest_a;");
223 System.out.println("assign dest = source;");
225 System.out.println("endmodule");
228 private static class FabricTree {
232 public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
233 public FabricTree(FpgaPump[] ports, String component, String prefix) {
234 this.prefix = prefix;
235 root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
237 private Object mkNode(String name, String component, FpgaPump[] ports,
238 int start, int end, int addr, int bits) {
239 if (end-start == 0) return null;
240 if (end-start == 1) {
241 FpgaPump p = ports[start];
242 if (prefix.equals("instruction")) {
243 p.instr_addr = (addr<<1);
244 p.instr_bits = bits+1;
245 } else if (prefix.equals("dest")) {
246 p.addr = (addr << 1) | 1;
249 throw new RuntimeException("too many pumps!");
251 for(Destination d : p.getDestinations()) {
252 if (!(d instanceof FpgaPump.VirtualPort)) continue;
253 FpgaPump.VirtualPort vp = (FpgaPump.VirtualPort)d;
254 vp.addr = p.addr | (count << bits);
264 if (end-start <= 2) {
265 breakpt = (start+end)/2;
267 for(int i=start; i<end; i++)
268 count += count(ports[i].getDestinations());
269 for(int i=start; i<end-1; i++) {
270 count2 += count(ports[i].getDestinations());
272 if (i>start && count2 >= count/2) break;
275 return new Node(name,
277 mkNode(name+"_0", component, ports, start, breakpt, addr, bits+1),
278 mkNode(name+"_1", component, ports, breakpt, end, addr | (1 << bits), bits+1),
282 private String describe(String prefix, Object o) {
283 if (o==null) return null;
284 if (o instanceof FpgaPump) {
285 FpgaPump p = (FpgaPump)o;
286 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
288 if (o instanceof Node) {
289 return ((Node)o).describe(prefix);
300 public Node(String name, String component, Object left, Object right, int addr, int bits) {
304 this.component = component;
308 public void dumpChannels(int indentamount, boolean decl) {
310 for(int i=0; i<indentamount; i++) indent += " ";
312 String n = describe(prefix).startsWith("instruction")
313 ? "[(`PACKET_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
314 System.out.println(" wire "+n+" "+indent+describe(prefix)+";");
316 System.out.println(" "+indent+
318 "krunk"+(krunk++)+"(clk, rst, "+
319 describe(prefix)+"_r, "+
320 describe(prefix)+"_a, "+
321 describe(prefix)+", "+
322 FabricTree.this.describe(prefix, left)+"_r, "+
323 FabricTree.this.describe(prefix, left)+"_a, "+
324 FabricTree.this.describe(prefix, left)+", "+
325 FabricTree.this.describe(prefix, right)+"_r, "+
326 FabricTree.this.describe(prefix, right)+"_a, "+
327 FabricTree.this.describe(prefix, right)+
330 dumpChannels(left, indentamount+1, decl);
331 dumpChannels(right, indentamount+1, decl);
333 public void dumpChannels(Object o, int indentamount, boolean decl) {
335 if (o instanceof Node) {
336 ((Node)o).dumpChannels(indentamount, decl);
339 for(int i=0; i<indentamount; i++) indent += " ";
341 String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
342 ? "[(`PACKET_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
343 System.out.println(" wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
347 public String describe(String prefix) {
352 public static int krunk=0;
354 private static String getUniqueName(Ship ship) {
355 return ship.getType() + ship.getOrdinal();
358 private static int count(Iterable<Destination> it) {
360 for(Destination d : it)
365 public void expand(ShipDescription sd) {
367 if (sd.getSection("fpga")==null) return;
368 String filename = sd.getName().toLowerCase();
369 File outf = new File("build/fpga/"+filename+".v");
370 new File(outf.getParent()).mkdirs();
371 System.err.println("writing to " + outf);
372 FileOutputStream out = new FileOutputStream(outf);
373 PrintWriter pw = new PrintWriter(out);
376 !"debug".equals(filename) &&
377 !"execute".equals(filename) &&
378 !"memory".equals(filename) &&
379 !"fifo".equals(filename);
382 pw.println("`include \"macros.v\"");
385 pw.print("`define reset ");
386 for(PumpDescription bb : sd) {
387 String bb_name = bb.getName();
389 pw.print(bb_name+"_a <= 1; ");
391 pw.print(bb_name+"_r <= 0; ");
396 pw.println("module " + filename + "( clk, rst ");
397 for(PumpDescription bb : sd) {
398 String bb_name = bb.getName();
401 pw.print(", " + bb_name+"_r");
402 pw.print(", " + bb_name+"_a_");
403 pw.print(", " + bb_name+"_d");
405 pw.print(", " + bb_name+"_r_");
406 pw.print(", " + bb_name+"_a");
407 pw.print(", " + bb_name+"_d_");
413 pw.println(" input clk;");
414 pw.println(" input rst;");
415 for(PumpDescription bb : sd) {
416 String bb_name = bb.getName();
419 pw.println("`input(" +
423 "[(`PACKET_WIDTH-1):0],"+
427 pw.println("`output(" +
431 "[(`PACKET_WIDTH-1):0],"+
434 pw.println("`defreg(" +
436 "[(`PACKET_WIDTH-1):0],"+
444 pw.println(sd.getSection("fpga"));
447 pw.println("endmodule");
451 } catch (Exception e) { throw new RuntimeException(e); }
454 public int computeOffset(int origin, int target) { return (target - origin)/6; }
455 public int computeTarget(int origin, int offset) { return origin + (offset*6); }
457 private FpgaInstructionEncoder iie = new FpgaInstructionEncoder();
458 public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
459 public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
460 public long writeInstruction(Instruction d) { return writeInstruction(d); }
461 public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
463 private class FpgaInstructionEncoder extends InstructionEncoder {
464 public long getDestAddr(Destination box) { return ((FpgaPump.VirtualPort)box).addr; }
465 public long getBoxInstAddr(Pump box) { return ((FpgaPump)box).instr_addr; }
466 public Destination getDestByAddr(long dest) {
467 for(Ship ship : Fpga.this)
468 for(Pump bb : ship.getPumps())
469 for(Destination d : bb.getDestinations())
470 if (getDestAddr(d)==dest)
474 public Pump getBoxByInstAddr(long dest) {
475 for(Ship ship : Fpga.this)
476 for(Pump bb : ship.getPumps())
477 if (((FpgaPump)bb).instr_addr == dest)