change polarity of I-bit
[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        = 4;
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     private Fpga fpga;
34
35     public Destination getDataDestination() { return dataDestination; }
36     public Destination getInstructionDestination() { return instructionDestination; }
37     public int         getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
38
39     FpgaDock(FpgaShip ship, DockDescription bbd) {
40         super(ship, bbd);
41         this.fpga = (Fpga)ship.getFleet();
42         this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock()));
43         this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false);
44         this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true);
45         Module.InstantiatedModule shipm = ship.getVerilogModule();            
46         if (isInputDock()) {
47             instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
48         } else {
49             shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
50         }
51     }
52
53
54     // FabricElement methods //////////////////////////////////////////////////////////////////////////////
55
56     private FabricElement upstream;
57     public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
58     public Module.Port getInputPort()  { throw new RuntimeException(); }
59     public FpgaPath getPath(FabricElement dest, BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
60     public FpgaPath getPath(Destination dest,BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
61     public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
62     public void addOutput(FabricElement out, Module.Port outPort) {
63         this.upstream = out;
64         instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
65     }
66
67     public class TorpedoBranchModule extends Module {
68         public TorpedoBranchModule() {
69             super("torpedobranch");
70             Module.SourcePort in      = createInputPort ("in",  fpga.WIDTH_PACKET);
71             // FIXME: assumes DISPATCH_PATH is at top of word!!!
72             Module.SinkPort   out     = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, "");
73             Module.SinkPort   torpedo = createOutputPort("torpedo", 0, "");
74             in.hasLatch = false;
75             out.hasLatch = false;
76             torpedo.hasLatch = false;
77
78             addPreCrap("assign out        = "+fpga.PACKET_DATA.verilogVal("in")+";");
79             addPreCrap("assign out_r      = in_r && !("+fpga.PACKET_TOKEN.verilogVal("in")+");");
80             addPreCrap("assign torpedo_r  = in_r &&   "+fpga.PACKET_TOKEN.verilogVal("in")+";");
81             addPreCrap("assign in_a       = out_a || torpedo_a;");
82         }
83     }
84
85     public class RequeueModule extends Module {
86         public RequeueModule() {
87             super("requeue");
88             Module.SourcePort fabric_in = createInputPort ("fabric_in",  fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
89             Module.SourcePort ondeck_in = createInputPort ("ondeck_in",  fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
90             Module.SourcePort olc_in    = createInputPort ("olc_in",     fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth);
91             Module.SinkPort   out       = createOutputPort("out",        fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, "");
92             out.forceNoLatch = true;
93
94             Module.StateWire  using         = new StateWire("using", false);
95             Module.StateWire  circulating   = new StateWire("circulating", false);
96             Module.StateWire  doResetFabric = new StateWire("doResetFabric", false);
97             Module.StateWire  doResetOndeck = new StateWire("doResetOndeck", false);
98
99             addPreCrap("assign out = "+circulating.isEmpty()+" ? "+fabric_in.getName()+" : "+ondeck_in.getName()+";");
100
101             // always: discard one-shot instructions
102             new Event(new Object[] { ondeck_in, /*olc_in,*/ fpga.OS.verilog(ondeck_in.getName()) },
103                       new Action[] { ondeck_in, /*olc_in */});
104
105             new Event(new Object[] { doResetFabric.isFull(),  out },
106                       new Action[] { doResetFabric.doDrain(), fabric_in });
107             new Event(new Object[] { doResetOndeck.isFull(),  out },
108                       new Action[] { doResetOndeck.doDrain(), ondeck_in });
109
110             new Event(new Object[] { circulating.isEmpty(),                  fabric_in, fpga.TAIL.verilog(fabric_in.getName()) },
111                       new Action[] { circulating.doFill(),                   fabric_in });
112             new Event(new Object[] { circulating.isEmpty(),                  fabric_in, "!("+fpga.TAIL.verilog(fabric_in.getName())+")", doResetFabric.isEmpty() },
113                       new Action[] {                                         out, doResetFabric.doFill() });
114             new Event(new Object[] { using.isEmpty(),                        ondeck_in, /*olc_in,*/   "!("+fpga.OS.verilog(ondeck_in.getName())+")", "olc_in==0" },
115                       new Action[] {                                         ondeck_in, /*olc_in */ });
116             new Event(new Object[] { using.isEmpty(),                        ondeck_in, /*olc_in,*/   "!("+fpga.OS.verilog(ondeck_in.getName())+")", "olc_in!=0" },
117                       new Action[] { using.doFill() });
118             new Event(new Object[] { circulating.isFull(),  using.isFull(),  ondeck_in, /*olc_in,*/   "!("+fpga.OS.verilog(ondeck_in.getName())+")", "olc_in==0" },
119                       new Action[] { circulating.doDrain(), using.doDrain(), ondeck_in, /*olc_in */});
120             new Event(new Object[] { circulating.isFull(),  using.isFull(),  ondeck_in, /*olc_in,*/   "!("+fpga.OS.verilog(ondeck_in.getName())+")", "olc_in!=0", doResetOndeck.isEmpty() },
121                       new Action[] {                                         out, /*olc_in,*/ doResetOndeck.doFill() });
122
123         }
124     }
125
126     public class DockModule extends Module {
127
128         public DockModule(boolean inbox) {
129             super(inbox ? "inbox" : "outbox");
130
131             int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
132
133             // FIXME: assumes fpga.DISPATCH_PATH is at top of word!!!
134             Module ififo_m   = new FifoModule(INSTRUCTION_FIFO_SIZE, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
135             Module dfifo_m   = new FifoModule(DATA_FIFO_SIZE,        dfifo_width);
136
137             Module.SourcePort instruction   = createInputPort("instruction", fpga.WIDTH_PACKET);
138             Module.SourcePort fabric_in     = createInputPort("fabric_in",   fpga.WIDTH_PACKET);
139
140             // FIXME: at inboxes, no need for a full set of latches
141             Module.SinkPort   fabric_out    = createOutputPort("fabric_out", fpga.WIDTH_PACKET, "");
142             
143             Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
144
145             fabric_in.hasLatch = false;
146             addPreCrap("assign "+dfifo.getInputPort("in").getName()+"_r = fabric_in_r;\n");
147             addPreCrap("assign fabric_in_a = "+dfifo.getInputPort("in").getName()+"_a;\n");
148             if (inbox)
149                 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
150                            " = { "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+
151                            ",    "+fpga.PACKET_DATA.verilogVal("fabric_in")+" };\n");
152             else
153                 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
154                            " = "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
155
156         
157             Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
158             Module.SourcePort   ship_out    = null;
159             if (!inbox) {
160                 ship_out = createInputPort("ship",        fpga.getWordWidth()+1);
161                 ship_out.hasLatch = true;
162             }
163
164             Module.SinkPort   ship_in     = null;
165             if (inbox) {
166                 ship_in = createOutputPort("ship",        fpga.getWordWidth()+1, "");
167                 ship_in.hasLatch = true;
168             }
169
170             Module.Latch     ilc = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
171             Module.Latch     olc   = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
172             Module.Latch     flag_a         = new Latch("flag_a", 1);
173             Module.Latch     flag_b         = new Latch("flag_b", 1);
174             Module.Latch     flag_c         = new Latch("flag_c", 1);
175
176             Module.StateWire  torpedoWaiting = new StateWire("torpedoWaiting", false);
177         
178             Module.SinkPort   token_out     = fabric_out;
179             Module.SourcePort token_in      = dfifo_out;
180             Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
181             Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
182
183             Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
184             Module.SinkPort   ififo_in      = ififo.getInputPort("in");
185             Module.SourcePort ififo_out     = ififo.getOutputPort("out");
186
187             Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth());
188
189             Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
190             instruction.connect(torpedo_branch.getInputPort("in"));
191             Module.SourcePort efifo_out              = torpedo_branch.getOutputPort("out");
192             Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
193
194             Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth));
195             Module.SinkPort   fanout_module_in   = fanout_module.getInputPort("in");
196             Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
197             Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
198
199             Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
200             Module.SinkPort   requeue_fabric_in = requeue_module.getInputPort("fabric_in");
201             Module.SinkPort   requeue_ondeck    = requeue_module.getInputPort("ondeck_in");
202             Module.SinkPort   requeue_olc_in    = requeue_module.getInputPort("olc_in");
203             Module.SourcePort requeue_out       = requeue_module.getOutputPort("out");
204
205             efifo_out.connect(requeue_fabric_in);
206             requeue_out.connect(ififo_in);
207             ififo_out.connect(fanout_module_in);
208             fanout_module_out0.connect(requeue_ondeck);
209             Module.SourcePort ondeck = fanout_module_out1;
210
211             addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName()))+";");
212             addPreCrap("wire ["+(Math.max(ilc.width,olc.width)-1)+":0] decremented;");
213             addPreCrap("assign decremented = ("+fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName())+" ? {1'b0, olc} : ilc)-1;");
214             addPreCrap("assign "+requeue_olc_in.getName()+" = olc;");
215
216             Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName()));
217             String data_latch_input  = inbox ? data_in.getName() : data_in.getName();
218
219             String magic_standing_value = "(1<<"+fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+")";
220             String done_executing       = "(ilc==0 || ilc==1 || !"+fpga.MOVE.verilog(ondeck.getName())+")";
221
222             // Torpedo Arrival
223             new Event(new Object[] { torpedo_branch_torpedo, torpedoWaiting.isEmpty() },
224                       new Action[] { torpedo_branch_torpedo, torpedoWaiting.doFill() });
225
226             String predicate_met = 
227                 "("+
228                 "("+
229                 "!"+fpga.MOVE.verilog(ondeck.getName())+" || ilc!=0"+
230                 ") && ("+
231                 "("+
232                 fpga.P_ALWAYS.verilog(ondeck.getName())+
233                 ") || ("+
234                 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==(olc==0)"+
235                 ")"+
236                 ") && ("+
237                 " " + fpga.P_A.verilog(ondeck.getName())+" ? flag_a"+
238                 ":" + fpga.P_B.verilog(ondeck.getName())+" ? flag_b"+
239                 ":" + fpga.P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
240                 ":" + fpga.P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
241                 ": 1"+
242                 ")"+
243                 ")";
244
245             // Torpedo strikes
246             new Event(new Object[] {
247                     ondeck,
248                     data_out,
249                     token_out,
250                     predicate_met,
251                     fpga.MOVE.verilog(ondeck.getName()),
252                     "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
253                     torpedoWaiting.isFull()
254                 },
255                 new Object[] {
256                     ondeck,
257                     torpedoWaiting.doDrain(),
258                     new AssignAction(olc, "0"),
259                     new AssignAction(ilc, "1")
260                 });
261
262             // Predicate not met
263             new Event(new Object[] { ondeck, "!("+predicate_met+")" },
264                       new Action[] { ondeck,
265                                      new ConditionalAction(fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1"))
266                       });
267
268             new Event(new Object[] { ondeck,
269                                      data_out,
270                                      token_out,
271                                      predicate_met,
272                                      "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedoWaiting.isFull()+")",
273                                      new ConditionalTrigger(fpga.DI.verilog(ondeck.getName()), data_in),
274                                      new ConditionalTrigger(fpga.TI.verilog(ondeck.getName()), token_in)
275                       },
276                       new Action[] { 
277                           new ConditionalAction(done_executing+" && "+fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1")),
278                           new ConditionalAction(done_executing, ondeck),
279                           new ConditionalAction("!"+done_executing,
280                                                 new AssignAction(ilc,
281                                                                  "ilc=="+magic_standing_value+"?"+magic_standing_value+":decremented")),
282
283                           new ConditionalAction(fpga.SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(olc, "data_latch_output")),
284                           new ConditionalAction(fpga.SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()),
285                                                 new AssignAction(olc, fpga.SET_OLC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
286                           new ConditionalAction(fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()),
287                                                 new AssignAction(olc, "olc==0 ? 0 : decremented")),
288                           new ConditionalAction(fpga.SET_ILC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(ilc, "data_latch_output")),
289                           new ConditionalAction(fpga.SET_ILC_FROM_IMMEDIATE.verilog(ondeck.getName()),
290                                                 new AssignAction(ilc, fpga.SET_ILC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
291                           new ConditionalAction(fpga.SET_ILC_FROM_INFINITY.verilog(ondeck.getName()), new AssignAction(ilc, magic_standing_value)),
292                           new ConditionalAction(fpga.SHIFT.verilog(ondeck.getName()),
293                                                 new AssignAction(data_latch,
294                                                                  "{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
295                                                                  fpga.SHIFT.verilogVal(ondeck.getName())+"}")),
296                           new ConditionalAction(fpga.SET_IMMEDIATE.verilog(ondeck.getName()),
297                                                 new AssignAction(data_latch,
298                                                                  "{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
299                                                                  "{"+fpga.SET_IMMEDIATE_EXTEND.verilogVal(ondeck.getName())+"}}, "+
300                                                                  fpga.SET_IMMEDIATE.verilogVal(ondeck.getName())+" }")),
301                           new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_a, new_flag(fpga.SET_FLAGS_A.verilogVal(ondeck.getName())))),
302                           new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_b, new_flag(fpga.SET_FLAGS_B.verilogVal(ondeck.getName())))),
303                           new ConditionalAction(inbox
304                                                 ? "("+fpga.DI.verilog(ondeck.getName())+" || "+fpga.TI.verilog(ondeck.getName())+")"
305                                                 : "(!"+fpga.DI.verilog(ondeck.getName())+" && "+fpga.TI.verilog(ondeck.getName())+")",
306                                                 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))),
307                           new ConditionalAction(fpga.DI.verilog(ondeck.getName()),    data_in),
308                           new ConditionalAction(fpga.DO.verilog(ondeck.getName()),    data_out),
309                           new ConditionalAction(fpga.FLUSH.verilog(ondeck.getName()), data_out),
310                           inbox
311                           ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), fpga.FLUSH.verilog(ondeck.getName())+"?1:0")
312                           : new ConditionalAction(fpga.DI.verilog(ondeck.getName()),   new AssignAction(flag_c, data_latch_input+"["+fpga.getWordWidth()+"]")),
313                           new ConditionalAction(fpga.TI.verilog(ondeck.getName()),    token_in),
314                           new ConditionalAction(fpga.TO.verilog(ondeck.getName()),    token_out),
315                           new ConditionalAction(fpga.DC.verilog(ondeck.getName()),   new AssignAction(data_latch, data_latch_input)),
316                           new AssignAction(new SimpleAssignable(fpga.PACKET_TOKEN.verilogVal(token_out.getName())), "("+fpga.TO.verilog(ondeck.getName())+")?1:0"),
317                           new ConditionalAction(fpga.PATH_DATA.verilog(ondeck.getName()),
318                                                 new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
319                                                                                       fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"),
320                                                                  fpga.DISPATCH_PATH.verilogVal(data_latch_input))),
321                           new ConditionalAction(fpga.PATH_IMMEDIATE.verilog(ondeck.getName()),
322                                                 new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
323                                                                                       fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"),
324                                                                  fpga.PATH_IMMEDIATE.verilogVal(ondeck.getName()))),
325                       }
326                       );
327         }
328
329         private String new_flag(String x) {
330             return "("+
331                 "( (("+x+" >> 0) & 1) & !flag_c) |" +
332                 "( (("+x+" >> 1) & 1) &  flag_c) |" +
333                 "( (("+x+" >> 2) & 1) & !flag_b) |" +
334                 "( (("+x+" >> 3) & 1) &  flag_b) |" +
335                 "( (("+x+" >> 4) & 1) & !flag_a) |" +
336                 "( (("+x+" >> 5) & 1) &  flag_a) | 0" +
337                 ")";
338         }
339     }
340 }
341