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