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