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("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");
44 // above is the minimal ship set needed to run the regression suite
45 // below are extra bonush ships
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");
59 public Ship createShip(String type, String name) {
61 ShipDescription sd = new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
62 FpgaShip ship = new FpgaShip(this, name, type, sd);
63 ships.put(name, ship);
66 } catch (IOException e) { throw new RuntimeException(e); }
69 public FleetProcess run(final byte[] instructions) {
71 return new Client(bitfile, instructions);
72 } catch (IOException e) { throw new RuntimeException(e); }
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!
79 ArrayList instructionports = new ArrayList<FpgaBenkoBox>();
80 for(FpgaShip ship : shiplist)
81 for(BenkoBox port : ship.getBenkoBoxes())
82 if (!((FpgaBenkoBox)port).special())
83 instructionports.add(port);
84 FabricTree instructions =
85 new FabricTree((FpgaBenkoBox[])instructionports.toArray(new FpgaBenkoBox[0]),
89 ArrayList inputports = new ArrayList<FpgaBenkoBox>();
90 for(FpgaShip ship : shiplist)
91 for(BenkoBox port : ship.getBenkoBoxes())
92 if (!((FpgaBenkoBox)port).special())
95 new FabricTree((FpgaBenkoBox[])inputports.toArray(new FpgaBenkoBox[0]),
99 ArrayList outputports = new ArrayList<FpgaBenkoBox>();
100 for(FpgaShip ship : shiplist)
101 for(BenkoBox port : ship.getBenkoBoxes())
102 if (!((FpgaBenkoBox)port).special() || ((FpgaBenkoBox)port).dhorn())
103 outputports.add(port);
105 new FabricTree((FpgaBenkoBox[])outputports.toArray(new FpgaBenkoBox[0]),
109 ArrayList ihornports = new ArrayList<FpgaBenkoBox>();
110 for(FpgaShip ship : shiplist)
111 for(BenkoBox port : ship.getBenkoBoxes())
112 if (((FpgaBenkoBox)port).ihorn())
113 ihornports.add(port);
115 new FabricTree((FpgaBenkoBox[])ihornports.toArray(new FpgaBenkoBox[0]),
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();
134 System.out.println();
136 instructions.dumpChannels(true);
137 outputs.dumpChannels(true);
138 inputs.dumpChannels(true);
139 ihorns.dumpChannels(true);
140 for(FpgaShip ship : shiplist)
141 for(BenkoBox port : ship.getBenkoBoxes())
142 if (!((FpgaBenkoBox)port).special() || ((FpgaBenkoBox)port).dhorn())
143 System.out.println(" wire [(`PACKET_WIDTH-1):0] data_"
144 +getUniqueName(ship)+"_"+port.getName()+";");
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(FpgaShip 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(", ");
164 String prefix = "data_";
165 if (((FpgaBenkoBox)port).ihorn()) prefix = "ihorn_";
166 if (((FpgaBenkoBox)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(" ");
172 System.out.println(");");
174 for(BenkoBox port : ship.getBenkoBoxes()) {
175 if (((FpgaBenkoBox)port).special()) continue;
176 if (((FpgaBenkoBox)port).inbox) {
177 System.out.print("inbox");
179 System.out.print("outbox");
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();
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);");
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");
214 private static class FabricTree {
218 public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
219 public FabricTree(FpgaBenkoBox[] ports, String component, String prefix) {
220 this.prefix = prefix;
221 root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
223 private Object mkNode(String name, String component, FpgaBenkoBox[] ports,
224 int start, int end, int addr, int bits) {
225 if (end-start == 0) return null;
226 if (end-start == 1) {
227 FpgaBenkoBox p = ports[start];
228 if (prefix.equals("instruction")) {
231 } else if (prefix.equals("dest")) {
235 throw new RuntimeException("too many benkoboxen!");
237 for(Destination d : p.getDestinations()) {
238 if (!(d instanceof FpgaBenkoBox.VirtualPort)) continue;
239 FpgaBenkoBox.VirtualPort vp = (FpgaBenkoBox.VirtualPort)d;
240 vp.addr = p.addr | (count << bits);
250 if (end-start <= 2) {
251 breakpt = (start+end)/2;
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());
258 if (i>start && count2 >= count/2) break;
261 return new Node(name,
263 mkNode(name+"_0", component, ports, start, breakpt, addr, bits+1),
264 mkNode(name+"_1", component, ports, breakpt, end, addr | (1 << bits), bits+1),
268 private String describe(String prefix, Object o) {
269 if (o==null) return null;
270 if (o instanceof FpgaBenkoBox) {
271 FpgaBenkoBox p = (FpgaBenkoBox)o;
272 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
274 if (o instanceof Node) {
275 return ((Node)o).describe(prefix);
286 public Node(String name, String component, Object left, Object right, int addr, int bits) {
290 this.component = component;
294 public void dumpChannels(int indentamount, boolean decl) {
296 for(int i=0; i<indentamount; i++) indent += " ";
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)+";");
302 System.out.println(" "+indent+
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)+
316 dumpChannels(left, indentamount+1, decl);
317 dumpChannels(right, indentamount+1, decl);
319 public void dumpChannels(Object o, int indentamount, boolean decl) {
321 if (o instanceof Node) {
322 ((Node)o).dumpChannels(indentamount, decl);
325 for(int i=0; i<indentamount; i++) indent += " ";
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)+";");
333 public String describe(String prefix) {
338 public static int krunk=0;
340 private static String getUniqueName(Ship ship) {
341 return ship.getType() + ship.getOrdinal();
344 private static int count(Iterable<Destination> it) {
346 for(Destination d : it)
351 public void expand(ShipDescription sd) {
353 if (sd.getSection("fpga")==null) return;
354 String filename = sd.getName().toLowerCase();
355 File outf = new File("build/fpga/"+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);
362 !"debug".equals(filename) &&
363 !"execute".equals(filename) &&
364 !"memory".equals(filename) &&
365 !"fifo".equals(filename);
367 pw.println("`include \"macros.v\"");
369 pw.println("module " + filename + "( clk");
370 for(BenkoBoxDescription bb : sd) {
371 String bb_name = bb.getName();
374 pw.print(", " + bb_name+"_r");
375 pw.print(", " + bb_name+"_a_");
376 pw.print(", " + bb_name+"_d");
378 pw.print(", " + bb_name+"_r_");
379 pw.print(", " + bb_name+"_a");
380 pw.print(", " + bb_name+"_d_");
386 pw.println(" input clk;");
387 for(BenkoBoxDescription bb : sd) {
388 String bb_name = bb.getName();
391 pw.println("`input(" +
395 "[(`PACKET_WIDTH-1):0],"+
399 pw.println("`output(" +
403 "[(`PACKET_WIDTH-1):0],"+
406 pw.println("`defreg(" +
408 "[(`PACKET_WIDTH-1):0],"+
416 pw.println(sd.getSection("fpga"));
419 pw.println("endmodule");
423 } catch (Exception e) { throw new RuntimeException(e); }
426 public int computeOffset(int origin, int target) { return (target - origin)/6; }
427 public int computeTarget(int origin, int offset) { return origin + (offset*6); }
429 private FpgaInstructionEncoder iie = new FpgaInstructionEncoder();
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); }
435 private class FpgaInstructionEncoder extends InstructionEncoder {
436 public long getDestAddr(Destination box) { return ((FpgaBenkoBox.VirtualPort)box).addr; }
437 public long getBoxInstAddr(BenkoBox box) { return ((FpgaBenkoBox)box).instr_addr; }
438 public Destination getDestByAddr(long dest) {
439 for(Ship ship : Fpga.this)
440 for(BenkoBox bb : ship.getBenkoBoxes())
441 for(Destination d : bb.getDestinations())
442 if (getDestAddr(d)==dest)
446 public BenkoBox getBoxByInstAddr(long dest) {
447 for(Ship ship : Fpga.this)
448 for(BenkoBox bb : ship.getBenkoBoxes())
449 if (((FpgaBenkoBox)bb).instr_addr == dest)