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