split Fpga.java into two implementations, large and small
[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.api.*;
4 import edu.berkeley.fleet.two.*;
5 import edu.berkeley.fleet.*;
6 import java.lang.reflect.*;
7 import edu.berkeley.sbp.chr.*;
8 import edu.berkeley.sbp.misc.*;
9 import edu.berkeley.sbp.meta.*;
10 import edu.berkeley.sbp.util.*;
11 import java.util.*;
12 import java.io.*;
13 import edu.berkeley.fleet.two.*;
14 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
15 import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
16
17
18 /*
19 => get rid of getInputPort(String) and instead use members
20 => clean up fabricelement methods
21 => get rid of addcrap
22 => automatic width-setting on ports
23 => nuke DATAWIDTH?
24   => serdes and fastclock/slowclock?
25 */
26
27 public class Fpga extends FleetTwoFleet {
28
29     public  Module top;
30     public  FabricElement top_horn;
31     Ship debugShip;
32
33     public LinkedHashMap<String,FpgaShip> ships = new LinkedHashMap<String,FpgaShip>();
34     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
35
36     public Ship getShip(String type, int ordinal) {
37         for(Ship s : this)
38             if (s.getType().equals(type))
39                 if (--ordinal < 0)
40                     return s;
41         return null;
42     }
43
44     public static void main(String[] s) throws Exception { 
45         new Fpga(new Module("root")).top.dump(s[0]);
46     }
47
48     public FleetProcess run(Instruction[] instructions) {
49         try {
50             return new Client(this, "none", instructions);
51         } catch (Exception e) { throw new RuntimeException(e); }
52     }
53
54     // Setup //////////////////////////////////////////////////////////////////////////////
55
56     public Ship createShip(String type, String name) throws IOException {
57         ShipDescription sd = new ShipDescription(type, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
58         FpgaShip ship = new FpgaShip(this, sd);
59         ships.put(name, ship);
60         return ship;
61     }
62
63     public Fpga() throws Exception { this(new Module("root")); }
64     public Fpga(Module top) throws Exception {
65         this.top = top;
66         debugShip = createShip("Debug",     "debug");
67
68         boolean small = false;
69
70         createShip("Memory",      "memory1");
71
72         if (small) {
73             createShip("Fifo", "fifo");
74             createShip("Alu",  "alu");
75         } else {
76             //createShip("Memory",    "memory2");
77             //createShip("Memory",    "memory3");
78
79             for(int i=0; i<5; i++)
80                 createShip("Alu",       "alu"+i);
81
82             for(int i=0; i<2; i++)
83                 createShip("Fifo",      "fifo"+i);
84
85             for(int i=0; i<13; i++)
86                 createShip("Counter",  "counter"+i);
87
88             createShip("CarrySaveAdder",  "csa1");
89             createShip("Rotator",         "rotator");
90             createShip("Lut3",            "lut");
91
92             //createShip("DDR2",    "ddr2");
93         }
94         createShip("DRAM",    "dram");
95         createShip("Video",   "video");
96
97         //Module.SourcePort  debug_in    = top.createWireSourcePort("debug_in", WIDTH_PACKET);
98         Module.SourcePort  debug_out   = null;
99         for(FpgaShip ship : (Iterable<FpgaShip>)(Object)this) {
100             if (ship.getType().toLowerCase().equals("debug"))
101                 debug_out = ship.getVerilogModule().getOutputPort("debug_out");
102         }
103
104         // for FifoShip
105         new Module.InstantiatedModule(top, new FifoModule(8, WIDTH_WORD));
106
107         Module.SourcePort  in          = top.createInputPort("in", 8);
108         Module.SinkPort    out         = top.createOutputPort("out", 8, "");
109         Module.Latch       temp_in     = top.new Latch("temp", WIDTH_PACKET);
110         Module.Latch       count       = top.new Latch("count", 8);
111         Module.Latch       count_out   = top.new Latch("count_out", 8);
112
113         ArrayList inbox_sources = new ArrayList<FabricElement>();
114         ArrayList inbox_dests   = new ArrayList<FabricElement>();
115         ArrayList outbox_sources = new ArrayList<FabricElement>();
116         ArrayList outbox_dests   = new ArrayList<FabricElement>();
117         ArrayList instruction_dests   = new ArrayList<FabricElement>();
118         int numdocks = 0;
119         for(FpgaShip ship : (Iterable<FpgaShip>)(Object)this) {
120             if (ship.getType().toLowerCase().equals("debug"))
121                 debug_out = ship.getVerilogModule().getOutputPort("debug_out");
122             for(Dock port : ship) {
123                 if (port.isInputDock()) {
124                     inbox_sources.add(((FpgaDock)port));
125                     instruction_dests.add(port.getInstructionDestination());
126                     inbox_dests.add(port.getDataDestination());
127                 } else {
128                     outbox_sources.add(((FpgaDock)port));
129                     instruction_dests.add(port.getInstructionDestination());
130                     outbox_dests.add(port.getDataDestination());
131                 }
132                 numdocks++;
133             }
134         }
135         //System.err.println("dock count = " + numdocks);
136         ArrayList dests   = new ArrayList<FabricElement>();
137         ArrayList sources = new ArrayList<FabricElement>();
138         sources.addAll(inbox_sources);
139         sources.addAll(outbox_sources);
140         dests.addAll(inbox_dests);
141         dests.addAll(instruction_dests);
142         dests.addAll(outbox_dests);
143         top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true);
144         FabricElement   source  = mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false);
145         FunnelModule.FunnelInstance top_funnel = new FunnelModule.FunnelInstance(top, null, source.getOutputPort());
146         ((FunnelModule.FunnelInstance)source).out = top_funnel;
147         //top_horn.addInput(top_funnel, top_funnel.getOutputPort());
148         top_funnel.addOutput(top_horn, top_horn.getInputPort());
149
150         //Module.SourcePort  debug_in    = top.createWireSourcePort("debug_in", WIDTH_PACKET);
151         Module.SinkPort debug_in = top_funnel.getInputPort("in1");
152
153         top.new Event(new Object[] { in, "count<=7" },
154                       new Object[] { new SimpleAction(temp_in.getVerilogName()+" <= {" + temp_in.getVerilogName() + "["+(WIDTH_PACKET-(1+8))+":0], in[7:0] };"),
155                                      new SimpleAction("count <= count+1;"),
156                                      in
157                       });
158         top.new Event(new Object[] { debug_in, "count>7" },
159                       new Object[] { new SimpleAction(" count <= 0; "),
160                                      new AssignAction(debug_in, temp_in),
161                                      debug_in
162                       });
163         top.new Event(new Object[] { out, debug_out },
164                       new Object[] { new SimpleAction(out.getVerilogName()+" <= ("+debug_out.getVerilogName()+">> (count_out*8));"),
165                                      new SimpleAction("if (count_out >= 5) begin "+
166                                                           "count_out <= 0; "+debug_out.getVerilogName()+"_a <= 1; end"+
167                                                           " else count_out <= count_out+1; "),
168                                      out });
169
170     }
171
172     public FabricElement mkNode(FabricElement[] ports, boolean is_horn) { return mkNode(ports, is_horn, 0, ports.length); }
173     public FabricElement mkNode(FabricElement[] ports, boolean is_horn, int start, int end) {
174         switch(end-start) {
175             case 0: return null;
176             case 1: return ports[start];
177             default: {
178                 FabricElement leftPort  = mkNode(ports, is_horn,  start,         (end+start)/2);
179                 FabricElement rightPort = mkNode(ports, is_horn,  (end+start)/2, end);
180                 return is_horn
181                     ? new HornModule.HornInstance(top,     leftPort, rightPort)
182                     : new FunnelModule.FunnelInstance(top, leftPort, rightPort);
183             }
184         }
185     }
186
187     public Module getVerilogModule() { return top; }
188
189
190     // Expand //////////////////////////////////////////////////////////////////////////////
191
192     public void expand(ShipDescription sd) {
193         try {
194             if (sd.getSection("fpga")==null) return;
195             String filename = sd.getName().toLowerCase();
196             File outf = new File("build/fpga/"+filename+".v");
197             new File(outf.getParent()).mkdirs();
198             System.err.println("writing to " + outf);
199             FileOutputStream out = new FileOutputStream(outf);
200             PrintWriter pw = new PrintWriter(out);
201
202             boolean debug = "debug".equals(filename);
203
204             pw.println("`include \"bitfields.v\"");
205             pw.println();
206
207             pw.print("`define reset ");
208             for(DockDescription bb : sd) {
209                 String bb_name = bb.getName();
210                 if (bb.isInputDock()) pw.print(bb_name+"_a <= 1; "+bb_name+"_f <= 0; ");
211                 else                  pw.print(bb_name+"_r <= 0; ");
212             }
213             pw.println();
214
215             pw.print("`define flush ");
216             for(DockDescription bb : sd)
217                 if (bb.isInputDock())
218                     pw.print(" if (!"+bb.getName()+"_r_) "+bb.getName()+"_f <= 0; ");
219             pw.print("if (1");
220             for(DockDescription bb : sd)
221                 if (bb.isInputDock())
222                     pw.print(" && "+bb.getName()+"_r_ && !"+bb.getName()+"_a");
223             pw.print(") begin ");
224             if (true) {
225                 pw.print("if (1");
226                 for(DockDescription bb : sd)
227                     if (bb.isInputDock())
228                         pw.print(" && "+bb.getName()+"_d["+WIDTH_WORD+"] ");
229                 pw.print(") begin ");
230                 if (true) {
231                     for(DockDescription bb : sd)
232                         if (bb.isInputDock())
233                             pw.print(bb.getName()+"_f <= 1; ");
234                 }
235                 pw.print(" end else if (0");
236                 for(DockDescription bb : sd)
237                     if (bb.isInputDock())
238                         pw.print(" || "+bb.getName()+"_d["+WIDTH_WORD+"] ");
239                 pw.print(") begin ");
240                 if (true) {
241                     for(DockDescription bb : sd)
242                         if (bb.isInputDock())
243                             pw.print(" if (!"+bb.getName()+"_d["+WIDTH_WORD+"]) "+bb.getName()+"_f <= 1; ");
244                 }
245                 pw.print(" end ");
246             }
247             pw.print(" end ");
248             pw.println();
249             
250             pw.println("module " + filename + "( clk, rst ");
251             for(DockDescription bb : sd) {
252                 String bb_name = bb.getName();
253                 pw.print("        ");
254                 if (bb.isInputDock()) {
255                     pw.print(", " + bb_name+"_r_");
256                     pw.print(", " + bb_name+"_a_");
257                     pw.print(", " + bb_name+"_d");
258                 } else {
259                     pw.print(", " + bb_name+"_r_");
260                     pw.print(", " + bb_name+"_a");
261                     pw.print(", " + bb_name+"_d_");
262                 }
263                 pw.println();
264             }
265             if (filename.equals("debug")) {
266                 pw.println("    , out_r_");
267                 pw.println("    , out_a");
268                 pw.println("    , out_d_");
269             }
270             if (filename.equals("dram")) {
271                 pw.println("    , dram_addr_");
272                 pw.println("    , dram_addr_r_");
273                 pw.println("    , dram_addr_a");
274                 pw.println("    , dram_isread_");
275                 pw.println("    , dram_write_data_");
276                 pw.println("    , dram_write_data_push_");
277                 pw.println("    , dram_write_data_full");
278                 pw.println("    , dram_read_data");
279                 pw.println("    , dram_read_data_pop_");
280                 pw.println("    , dram_read_data_empty");
281                 pw.println("    , dram_read_data_latency");
282             }
283             if (filename.equals("ddr2")) {
284                 pw.println("    , ddr2_addr_");
285                 pw.println("    , ddr2_addr_r_");
286                 pw.println("    , ddr2_addr_a");
287                 pw.println("    , ddr2_isread_");
288                 pw.println("    , ddr2_write_data_");
289                 pw.println("    , ddr2_write_data_push_");
290                 pw.println("    , ddr2_write_data_full");
291                 pw.println("    , ddr2_read_data");
292                 pw.println("    , ddr2_read_data_pop_");
293                 pw.println("    , ddr2_read_data_empty");
294                 pw.println("    , ddr2_read_data_latency");
295             }
296             if (filename.equals("video")) {
297                 pw.println("    , vga_clk");
298                 pw.println("    , vga_psave");
299                 pw.println("    , vga_hsync");
300                 pw.println("    , vga_vsync");
301                 pw.println("    , vga_sync");
302                 pw.println("    , vga_blank");
303                 pw.println("    , vga_r");
304                 pw.println("    , vga_g");
305                 pw.println("    , vga_b");
306                 pw.println("    , vga_clkout");
307             }
308             pw.println("        );");
309             pw.println();
310             pw.println("    input clk;");
311             pw.println("    input rst;");
312             if (filename.equals("debug")) {
313                 pw.println("        output  ["+WIDTH_WORD+":0] out_d_;");
314                 pw.println("        input   out_a;");
315                 pw.println("        output  out_r_;");
316             }
317             if (filename.equals("dram")) {
318                 pw.println("output  [31:0] dram_addr_;");
319                 pw.println("output         dram_addr_r_;");
320                 pw.println("input          dram_addr_a;");
321                 pw.println("output         dram_isread_;");
322                 pw.println("output  [63:0] dram_write_data_;");
323                 pw.println("output         dram_write_data_push_;");
324                 pw.println("input          dram_write_data_full;");
325                 pw.println("input   [63:0] dram_read_data;");
326                 pw.println("output         dram_read_data_pop_;");
327                 pw.println("input          dram_read_data_empty;");
328                 pw.println("input   [1:0]  dram_read_data_latency;");
329             }
330             if (filename.equals("ddr2")) {
331                 pw.println("output  [31:0] ddr2_addr_;");
332                 pw.println("output         ddr2_addr_r_;");
333                 pw.println("input          ddr2_addr_a;");
334                 pw.println("output         ddr2_isread_;");
335                 pw.println("output  [63:0] ddr2_write_data_;");
336                 pw.println("output         ddr2_write_data_push_;");
337                 pw.println("input          ddr2_write_data_full;");
338                 pw.println("input   [63:0] ddr2_read_data;");
339                 pw.println("output         ddr2_read_data_pop_;");
340                 pw.println("input          ddr2_read_data_empty;");
341                 pw.println("input   [1:0]  ddr2_read_data_latency;");
342             }
343             if (filename.equals("video")) {
344                 pw.println("input          vga_clk;");
345                 pw.println("output         vga_psave;");
346                 pw.println("output         vga_hsync;");
347                 pw.println("output         vga_vsync;");
348                 pw.println("output         vga_sync;");
349                 pw.println("output         vga_blank;");
350                 pw.println("output   [7:0] vga_r;");
351                 pw.println("output   [7:0] vga_g;");
352                 pw.println("output   [7:0] vga_b;");
353                 pw.println("output         vga_clkout;");
354             }
355
356             for(DockDescription bb : sd) {
357                 String bb_name = bb.getName();
358                 if (bb.isInputDock()) {
359                     pw.println("        input   ["+WIDTH_WORD+":0] "+bb_name+"_d;");
360                     pw.println("        input   "+bb_name+"_r_;");
361                     pw.println("        wire    "+bb_name+"_r;");
362                     pw.println("        assign  "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+WIDTH_WORD+"];");
363                     pw.println("        output  "+bb_name+"_a_;");
364                     pw.println("        reg     "+bb_name+"_a;");
365                     pw.println("        initial "+bb_name+"_a  = 0;");
366                     pw.println("        reg     "+bb_name+"_f;");
367                     pw.println("        initial "+bb_name+"_f  = 0;");
368                     pw.println("        assign  "+bb_name+"_a_ = "+bb_name+"_a || "+bb_name+"_f;");
369                 } else {
370                     pw.println("        output  ["+WIDTH_WORD+":0] "+bb_name+"_d_;");
371                     pw.println("        input   "+bb_name+"_a;");
372                     pw.println("        output  "+bb_name+"_r_;");
373                     pw.println("        reg     "+bb_name+"_r;");
374                     pw.println("        initial "+bb_name+"_r  = 0;");
375                     pw.println("        assign  "+bb_name+"_r_ = "+bb_name+"_r;");
376                 }
377                 pw.println();
378             }
379
380             pw.println(sd.getSection("fpga"));
381
382             pw.println("endmodule");
383
384             pw.flush();
385             pw.close();
386         } catch (Exception e) { throw new RuntimeException(e); }
387     }
388
389     public long getDestAddr(Path path) {
390         return ((FpgaPath)path).toLong();
391     }
392     public Dock getBoxByInstAddr(long dest) {
393         for(Ship ship : Fpga.this)
394             for(Dock bb : ship)
395                 if (((FpgaDestination)((FpgaDock)bb).getInstructionDestination()).getAddr() == dest)
396                     return bb;
397         return null;
398     }
399
400 }