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