massive overhaul of fpga code
[fleet.git] / src / edu / berkeley / fleet / fpga / FpgaDock.java
1 package edu.berkeley.fleet.fpga;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.*;
5 import java.lang.reflect.*;
6 import edu.berkeley.sbp.chr.*;
7 import edu.berkeley.sbp.misc.*;
8 import edu.berkeley.sbp.meta.*;
9 import edu.berkeley.sbp.util.*;
10 import java.util.*;
11 import java.io.*;
12 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
13 import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
14 import edu.berkeley.fleet.api.*;
15 import edu.berkeley.fleet.api.Dock;
16 import edu.berkeley.fleet.two.*;
17 import java.util.*;
18
19 /** the pump itself is a */
20 public class FpgaDock extends FleetTwoDock implements FabricElement {
21
22     private static final int INSTRUCTION_FIFO_SIZE = 12;
23     private static final int EPILOGUE_FIFO_SIZE    = 0;
24     private static final int DATA_FIFO_SIZE        = 12;
25         
26     private FpgaDestination dataDestination;
27     private FpgaDestination instructionDestination;
28
29     private Module.InstantiatedModule instance;
30
31     public Module.InstantiatedModule getInstance() { return instance; }
32
33     public Destination getDataDestination() { return dataDestination; }
34     public Destination getInstructionDestination() { return instructionDestination; }
35     public int         getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
36
37     FpgaDock(FpgaShip ship, DockDescription bbd) {
38         super(ship, bbd);
39         this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock()));
40         this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false);
41         this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true);
42         Module.InstantiatedModule shipm = ship.getVerilogModule();            
43         if (isInputDock()) {
44             instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
45         } else {
46             shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
47         }
48     }
49
50
51     // FabricElement methods //////////////////////////////////////////////////////////////////////////////
52
53     private FabricElement upstream;
54     public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
55     public Module.Port getInputPort()  { throw new RuntimeException(); }
56     public FpgaPath getPath(FabricElement dest, BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
57     public FpgaPath getPath(Destination dest,BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
58     public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
59     public void addOutput(FabricElement out, Module.Port outPort) {
60         this.upstream = out;
61         instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
62     }
63
64     public static class DockModule extends Module {
65
66         public DockModule(boolean inbox) {
67             super(inbox ? "inbox" : "outbox");
68
69             /*
70             Module horn      = new HornModule();
71             Module funnel    = new FunnelModule();
72             Module.SourcePort instruction   = createInputPort("instruction",       WIDTH_PACKET);
73             Module.SourcePort fabric_in     = createInputPort("fabric_in",   WIDTH_PACKET);
74             Module.SinkPort   fabric_out    = createOutputPort("fabric_out", WIDTH_PACKET, "");
75             if (!inbox) {
76                 FunnelModule.FunnelInstance f0 = new FunnelModule.FunnelInstance(this, instruction, fabric_in);
77                 Module.SourcePort ship_out = createInputPort("ship",        WIDTH_WORD);
78                 FunnelModule.FunnelInstance f1 = new FunnelModule.FunnelInstance(this, f0.getOutputPort(), ship_out);
79                 f1.addOutput(f0, fabric_out);
80             } else {
81                 Module.SinkPort ship_in = createOutputPort("ship",        WIDTH_PACKET, "");
82                 instruction.connect(fabric_out);
83                 fabric_in.connect(ship_in);
84             }
85             */
86
87             int dfifo_width = inbox ? WIDTH_WORD+1 : 1;
88
89             // FIXME: assumes DISPATCH_PATH is at top of word!!!
90             Module ififo_m   = new FifoModule(INSTRUCTION_FIFO_SIZE, WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
91             Module efifo_m   = new FifoModule(EPILOGUE_FIFO_SIZE,    WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
92             Module dfifo_m   = new FifoModule(DATA_FIFO_SIZE,        dfifo_width);
93             Module.SourcePort instruction   = createInputPort("instruction", WIDTH_PACKET);
94             instruction.hasLatch = true;
95
96             Module.SourcePort fabric_in     = createInputPort("fabric_in",   WIDTH_PACKET);
97
98             // FIXME: at inboxes, no need for a full set of latches
99             Module.SinkPort   fabric_out    = createOutputPort("fabric_out", WIDTH_PACKET, "");
100             
101             Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
102
103             fabric_in.hasLatch = false;
104             addPreCrap("assign "+dfifo.getInputPort("in").getName()+"_r = fabric_in_r;\n");
105             addPreCrap("assign fabric_in_a = "+dfifo.getInputPort("in").getName()+"_a;\n");
106             if (inbox)
107                 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
108                            " = { "+PACKET_SIGNAL.verilogVal("fabric_in")+
109                            ",    "+PACKET_DATA.verilogVal("fabric_in")+" };\n");
110             else
111                 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
112                            " = "+PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
113
114         
115             Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
116             Module.SourcePort   ship_out    = null;
117             if (!inbox) {
118                 ship_out = createInputPort("ship",        WIDTH_WORD+1);
119                 ship_out.hasLatch = true;
120             }
121
122             Module.SinkPort   ship_in     = null;
123             if (inbox) {
124                 ship_in = createOutputPort("ship",        WIDTH_WORD, "");
125                 ship_in.hasLatch = true;
126             }
127
128             Module.Latch     repeat_counter = new Latch("repeat_counter", SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
129             Module.Latch     loop_counter   = new Latch("loop_counter", SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
130             Module.Latch     flag_a         = new Latch("flag_a", 1);
131             Module.Latch     flag_b         = new Latch("flag_b", 1);
132             Module.Latch     flag_c         = new Latch("flag_c", 1);
133
134             Module.StateWire  isHatchOpen   = new StateWire("hatch", true);
135             Module.StateWire  proceed       = new StateWire("proceed", false);
136         
137             Module.SinkPort   token_out     = fabric_out;
138             Module.SourcePort token_in      = dfifo_out;
139             Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
140             Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
141
142             Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
143             Module.SinkPort   ififo_in      = ififo.getInputPort("in");
144             ififo_in.hasLatch = false;
145             ififo_in.forceNoLatch = true;
146
147             Module.SourcePort ififo_out     = ififo.getOutputPort("out");
148
149             Module.InstantiatedModule efifo = new Module.InstantiatedModule(this, efifo_m);
150             Module.SinkPort   efifo_in      = efifo.getInputPort("in");
151             Module.SourcePort efifo_out     = efifo.getOutputPort("out");
152             efifo_in.hasLatch = false;
153             efifo_in.forceNoLatch = true;
154
155             Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", WIDTH_WORD);
156             Module.SinkPort data_latch_input_p  = createWirePort("data_latch_input", inbox ? WIDTH_WORD : WIDTH_WORD+1);
157
158             // FIXME
159             addPreCrap("wire ["+(ififo_out.width-1)+":0] ondeck;");
160             addPreCrap("wire ["+(Math.max(repeat_counter.width,loop_counter.width)-1)+":0] decremented;");
161             addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";");
162             addPreCrap("assign data_latch_input = " + (inbox ? data_in.getName() : data_in.getName())+";");
163             addPreCrap("assign "+efifo_in.getName()+" = `packet_data("+instruction.getName()+");");
164             addPreCrap("assign "+ififo_in.getName()+" = hatch ? "+efifo_out.getName()+" : ondeck;");
165             addPreCrap("assign ondeck = "+ififo_out.getName()+";");
166             addPreCrap("assign decremented = (`instruction_is_decr_loop(ondeck) ? {1'b0, loop_counter} : repeat_counter)-1;");
167
168             Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
169             String data_latch_input  = "data_latch_input";
170
171             // Open the Hatch
172             new Event(new Object[] { "loop_counter==0" },
173                       new Action[] { isHatchOpen.doFill() });
174
175             // Torpedo Arrival
176             new Event(new Object[] { instruction,
177                                      PACKET_TOKEN.verilogVal("instruction"),
178                                      ififo_out,
179                                      token_out,
180                                      I.verilog("ondeck"),
181                 },
182                 new Action[] { instruction,
183                                ififo_out,
184                                new AssignAction(loop_counter, "0"),
185                                new AssignAction(repeat_counter, "1"),
186                                isHatchOpen.doFill(),
187                 });
188             // Non-Torpedo Arrival
189             new Event(new Object[] { instruction,
190                                      efifo_in,
191                                      "!("+PACKET_TOKEN.verilogVal("instruction")+")"
192                 },
193                 new Action[] {
194                     efifo_in,
195                 });
196             new Event(new Object[] { efifo_in.getName()+"_a" },
197                       new Action[] { new SimpleAction(instruction.getName()+"_a <= 1;") });
198
199             // Tail
200             new Event(new Object[] { efifo_out, TAIL.verilog(efifo_out.getName()) },
201                       new Action[] { efifo_out, isHatchOpen.doDrain() } );
202             // Enqueue
203             new Event(new Object[] { efifo_out,
204                                      ififo_in,
205                                      "!("+TAIL.verilog(efifo_out.getName())+")",
206                                      isHatchOpen.isFull() },
207                 new Action[] { efifo_out,
208                                ififo_in,
209                 }
210                 );
211
212             // Execute                                     
213             new Event(new Object[] { ififo_out, ififo_in, proceed.isFull() },
214                       new Action[] { ififo_out,           proceed.doDrain() });
215             new Event(
216                       new Object[] { ififo_out,
217                                      data_out,
218                                      token_out,
219                                      ififo_in,
220                                      proceed.isEmpty(),
221                                      "(!`predicate_met(ondeck) || "+OS.verilog("ondeck")+" || !hatch)",
222                                      new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_datain(ondeck))", data_in),
223                                      new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck))", token_in)
224                       },
225                       new Action[] { 
226                                      new ConditionalAction("`done_executing(ondeck) && `instruction_is_normal(ondeck)",
227                                                            new AssignAction(repeat_counter, "1")),
228                                      new ConditionalAction("!`should_requeue(ondeck) && `done_executing(ondeck)", ififo_out),
229                                      new ConditionalAction("`should_requeue(ondeck)  && `done_executing(ondeck)", ififo_in),
230                                      new ConditionalAction("`should_requeue(ondeck)  && `done_executing(ondeck)", proceed.doFill()),
231                                      new ConditionalAction("!`done_executing(ondeck)",
232                                                            new AssignAction(repeat_counter,
233                                                                             "repeat_counter==`magic_standing_value?`magic_standing_value:decremented")),
234                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_loop(ondeck)",
235                                                            new AssignAction(loop_counter, "data_latch_output")),
236                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_loop(ondeck)",
237                                                            new AssignAction(loop_counter, "`instruction_loop_count_immediate(ondeck)")),
238                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_decr_loop(ondeck)",
239                                                            new AssignAction(loop_counter, "loop_counter==0 ? 0 : decremented")),
240                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_repeat(ondeck)",
241                                                            new AssignAction(repeat_counter, "data_latch_output")),
242                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_repeat(ondeck)",
243                                                            new AssignAction(repeat_counter, "`instruction_repeat_count_immediate(ondeck)")),
244                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_standing_to_repeat(ondeck)",
245                                                            new AssignAction(repeat_counter, "`magic_standing_value")),
246                                      new ConditionalAction("`predicate_met(ondeck) &&"+SHIFT.verilog("ondeck"),
247                                                            new AssignAction(data_latch,
248                                                                             "{ data_latch_output["+(WIDTH_WORD-1-SHIFT.valmaskwidth)+":0], "+
249                                                                             SHIFT.verilogVal("ondeck")+"}")),
250                                      new ConditionalAction("`predicate_met(ondeck) && "+SET_IMMEDIATE.verilog("ondeck"),
251                                                            new AssignAction(data_latch,
252                                                                             "{ {"+(WIDTH_WORD-FleetTwoFleet.DataLatch_WIDTH)+
253                                                                             "{"+SET_IMMEDIATE_EXTEND.verilogVal("ondeck")+"}}, "+
254                                                                             SET_IMMEDIATE.verilogVal("ondeck")+" }")),
255                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)",
256                                                            new AssignAction(flag_a, "`new_flag_a(ondeck)")),
257                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)",
258                                                            new AssignAction(flag_b, "`new_flag_b(ondeck)")),
259                                      (inbox
260                                       ? new ConditionalAction("`predicate_met(ondeck) && "+
261                                                               "(`instruction_bit_datain(ondeck) || `instruction_bit_tokenin(ondeck))",
262                                                               new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1)))
263                                       : new ConditionalAction("`predicate_met(ondeck) && "+
264                                                               "(!`instruction_bit_datain(ondeck) && `instruction_bit_tokenin(ondeck))",
265                                                               new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1)))
266                                       ),
267                                      inbox ? null :
268                                      new ConditionalAction("`predicate_met(ondeck) && "+
269                                                            "(`instruction_bit_datain(ondeck))",
270                                                            new AssignAction(flag_c, "data_latch_input["+WIDTH_WORD+"]")),
271                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_datain(ondeck)",   data_in),
272                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_dataout(ondeck)",  data_out),
273                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck)",  token_in),
274                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)", token_out),
275                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)",
276                                                            new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"),
277                                                                             "1")),
278                                      new ConditionalAction("`predicate_met(ondeck) && !`instruction_bit_tokenout(ondeck)",
279                                                            new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"),
280                                                                             "0")),
281                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_latch(ondeck)",
282                                                            new AssignAction(data_latch, data_latch_input)),
283                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_data(ondeck)",
284                                                            new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
285                                                                             DISPATCH_PATH.verilogVal(data_latch_input))),
286                                      new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_immediate(ondeck)",
287                                                            new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
288                                                                             "`instruction_path_immediate(ondeck)")),
289                       }
290                       );
291
292         }
293
294         public void dump(PrintWriter pw, boolean fix) {
295
296             pw.println("`define packet_signal_and_dest(p)                 { "+PACKET_SIGNAL.verilogVal("p")+", "+PACKET_DEST.verilogVal("p")+" }");
297             pw.println("`define instruction_is_load_data_to_repeat(i)     "+SET_ILC_FROM_DATA_LATCH.verilog("i"));
298             pw.println("`define instruction_is_load_data_to_loop(i)       "+SET_OLC_FROM_DATA_LATCH.verilog("i"));
299             pw.println("`define instruction_is_load_immediate_to_repeat(i)  "+SET_ILC_FROM_IMMEDIATE.verilog("i"));
300             pw.println("`define instruction_is_load_immediate_to_loop(i)    "+SET_OLC_FROM_IMMEDIATE.verilog("i"));
301             pw.println("`define instruction_is_load_standing_to_repeat(i) "+SET_ILC_FROM_INFINITY.verilog("i"));
302             pw.println("`define instruction_repeat_count_immediate(i)       "+SET_ILC_FROM_IMMEDIATE.verilogVal("i"));
303             pw.println("`define instruction_loop_count_immediate(i)         "+SET_OLC_FROM_IMMEDIATE.verilogVal("i"));
304
305             pw.println("`define instruction_path_immediate(i)              "+PATH_IMMEDIATE.verilogVal("i"));
306             pw.println("`define instruction_path_from_immediate(i)         "+PATH_IMMEDIATE.verilog("i"));
307             pw.println("`define instruction_path_from_data(i)            "+PATH_DATA.verilog("i"));
308
309             pw.println("`define instruction_is_tail(i)                   "+TAIL.verilog("i"));
310             pw.println("`define instruction_is_normal(i)                 "+MOVE.verilog("i"));
311             pw.println("`define instruction_is_setflags(i)               "+SET_FLAGS.verilog("i"));
312
313             pw.println("`define instruction_is_decr_loop(i)              "+SET_OLC_FROM_OLC_MINUS_ONE.verilog("i"));
314
315             pw.println("`define instruction_bit_tokenout(i)     (`instruction_is_normal(i) && "+TO.verilog("i")+")");
316             pw.println("`define instruction_bit_dataout(i)      (`instruction_is_normal(i) && "+DO.verilog("i")+")");
317             pw.println("`define instruction_bit_latch(i)        (`instruction_is_normal(i) && "+DC.verilog("i")+")");
318             pw.println("`define instruction_bit_datain(i)       (`instruction_is_normal(i) && "+DI.verilog("i")+")");
319             pw.println("`define instruction_bit_tokenin(i)      (`instruction_is_normal(i) && "+TI.verilog("i")+")");
320             pw.println("`define should_requeue(i)               (loop_counter!=0 && !("+OS.verilog("i")+"))");
321             pw.println("`define predicate_met(i)  ("+
322                        "("+
323                        "!`instruction_is_normal(i) || repeat_counter!=0"+
324                        ") && ("+
325                        P_OLC_ZERO.verilog("i")+"==(loop_counter==0)"+
326                        ") && ("+
327                        " " + P_A.verilog("i")+" ? flag_a"+
328                        ":" + P_B.verilog("i")+" ? flag_b"+
329                        ":" + P_NOT_A.verilog("i")+" ? !flag_a"+
330                        ":" + P_NOT_B.verilog("i")+" ? !flag_b "+
331                        ": 1"+
332                        ")"+
333                        ")");
334             pw.println("`define new_flag(x)         ("+
335                        "( ((x >> 0) & 1) & !flag_c) |" +
336                        "( ((x >> 1) & 1) &  flag_c) |" +
337                        "( ((x >> 2) & 1) & !flag_b) |" +
338                        "( ((x >> 3) & 1) &  flag_b) |" +
339                        "( ((x >> 4) & 1) & !flag_a) |" +
340                        "( ((x >> 5) & 1) &  flag_a) | 0" +
341                        ")");
342             pw.println("`define new_flag_a(i)                   `new_flag("+SET_FLAGS_A.verilogVal("i")+")");
343             pw.println("`define new_flag_b(i)                   `new_flag("+SET_FLAGS_B.verilogVal("i")+")");
344             pw.println("`define done_executing(i)               (repeat_counter==0 || repeat_counter==1 || !`instruction_is_normal(i))");
345
346             pw.println("`define magic_standing_value            (1<<"+SET_ILC_FROM_IMMEDIATE.valmaskwidth+")");
347
348             super.dump(pw,fix);
349         }
350     }
351 }