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.*;
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.*;
19 /** the pump itself is a */
20 public class FpgaDock extends FleetTwoDock implements FabricElement {
22 private static final int INSTRUCTION_FIFO_SIZE = 16;
23 private static final int EPILOGUE_FIFO_SIZE = 0;
24 private static final int DATA_FIFO_SIZE = 16;
26 private FpgaDestination dataDestination;
27 private FpgaDestination instructionDestination;
29 private Module.InstantiatedModule instance;
31 public Module.InstantiatedModule getInstance() { return instance; }
33 public Destination getDataDestination() { return dataDestination; }
34 public Destination getInstructionDestination() { return instructionDestination; }
35 public int getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
37 FpgaDock(FpgaShip ship, DockDescription 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();
44 instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
46 shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
51 // FabricElement methods //////////////////////////////////////////////////////////////////////////////
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) {
61 instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
64 public static class TorpedoBranchModule extends Module {
65 public TorpedoBranchModule() {
66 super("torpedobranch");
67 Module.SourcePort in = createInputPort ("in", WIDTH_PACKET);
68 // FIXME: assumes DISPATCH_PATH is at top of word!!!
69 Module.SinkPort out = createOutputPort("out", WIDTH_WORD-DISPATCH_PATH.valmaskwidth, "");
70 Module.SinkPort torpedo = createOutputPort("torpedo", 0, "");
73 torpedo.hasLatch = false;
75 addPreCrap("assign out = `packet_data(in);");
76 addPreCrap("assign out_r = in_r && !("+PACKET_TOKEN.verilogVal("in")+");");
77 addPreCrap("assign torpedo_r = in_r && "+PACKET_TOKEN.verilogVal("in")+";");
78 addPreCrap("assign in_a = out_a || torpedo_a;");
82 public static class FanoutModule extends Module {
83 public FanoutModule(int width) {
84 super("fanout"+width);
85 Module.SourcePort in = createInputPort ("in", width);
86 Module.SinkPort out0 = createOutputPort("out0", width, "");
87 Module.SinkPort out1 = createOutputPort("out1", width, "");
89 out0.hasLatch = false;
90 out1.hasLatch = false;
91 addPreCrap("assign out0 = in;");
92 addPreCrap("assign out1 = in;");
93 addPreCrap("assign out0_r = in_r;");
94 addPreCrap("assign out1_r = in_r;");
95 addPreCrap("reg in_a__;");
96 addPreCrap("assign in_a = in_a__;");
97 addPreCrap("always @(posedge clk) begin if (out0_a && out1_a) in_a__ <= 1; if (!out0_a && !out1_a) in_a__ <= 0; end");
101 public static class RequeueModule extends Module {
102 public RequeueModule() {
104 Module.SourcePort fabric_in = createInputPort ("fabric_in", WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
105 Module.SourcePort ondeck_in = createInputPort ("ondeck_in", WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
106 Module.SourcePort olc_in = createInputPort ("olc_in", SET_OLC_FROM_IMMEDIATE.valmaskwidth);
107 Module.SinkPort out = createOutputPort("out", WIDTH_WORD-DISPATCH_PATH.valmaskwidth, "");
110 Module.StateWire using = new StateWire("using", false);
111 Module.StateWire circulating = new StateWire("circulating", false);
113 // always: discard one-shot instructions
114 new Event(new Object[] { ondeck_in, /*olc_in,*/ OS.verilog(ondeck_in.getName()) },
115 new Action[] { ondeck_in, /*olc_in */});
117 new Event(new Object[] { circulating.isEmpty(), fabric_in, TAIL.verilog(fabric_in.getName()) },
118 new Action[] { circulating.doFill(), fabric_in });
119 new Event(new Object[] { circulating.isEmpty(), fabric_in, "!("+TAIL.verilog(fabric_in.getName())+")" },
120 new Action[] { fabric_in, out, new AssignAction(out, fabric_in) });
121 new Event(new Object[] { using.isEmpty(), ondeck_in, /*olc_in,*/ "!("+OS.verilog(ondeck_in.getName())+")", "olc_in==0" },
122 new Action[] { ondeck_in, /*olc_in */ });
123 new Event(new Object[] { using.isEmpty(), ondeck_in, /*olc_in,*/ "!("+OS.verilog(ondeck_in.getName())+")", "olc_in!=0" },
124 new Action[] { using.doFill() });
125 new Event(new Object[] { circulating.isFull(), using.isFull(), ondeck_in, /*olc_in,*/ "!("+OS.verilog(ondeck_in.getName())+")", "olc_in==0" },
126 new Action[] { circulating.doDrain(), using.doDrain(), ondeck_in, /*olc_in */});
127 new Event(new Object[] { circulating.isFull(), using.isFull(), ondeck_in, /*olc_in,*/ "!("+OS.verilog(ondeck_in.getName())+")", "olc_in!=0" },
128 new Action[] { ondeck_in, out, /*olc_in,*/ new AssignAction(out, ondeck_in) });
133 public static class DockModule extends Module {
135 public DockModule(boolean inbox) {
136 super(inbox ? "inbox" : "outbox");
138 int dfifo_width = inbox ? WIDTH_WORD+1 : 1;
140 // FIXME: assumes DISPATCH_PATH is at top of word!!!
141 Module ififo_m = new FifoModule(INSTRUCTION_FIFO_SIZE, WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
142 Module dfifo_m = new FifoModule(DATA_FIFO_SIZE, dfifo_width);
144 Module.SourcePort instruction = createInputPort("instruction", WIDTH_PACKET);
145 Module.SourcePort fabric_in = createInputPort("fabric_in", WIDTH_PACKET);
147 // FIXME: at inboxes, no need for a full set of latches
148 Module.SinkPort fabric_out = createOutputPort("fabric_out", WIDTH_PACKET, "");
150 Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
152 fabric_in.hasLatch = false;
153 addPreCrap("assign "+dfifo.getInputPort("in").getName()+"_r = fabric_in_r;\n");
154 addPreCrap("assign fabric_in_a = "+dfifo.getInputPort("in").getName()+"_a;\n");
156 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
157 " = { "+PACKET_SIGNAL.verilogVal("fabric_in")+
158 ", "+PACKET_DATA.verilogVal("fabric_in")+" };\n");
160 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
161 " = "+PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
164 Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
165 Module.SourcePort ship_out = null;
167 ship_out = createInputPort("ship", WIDTH_WORD+1);
168 ship_out.hasLatch = true;
171 Module.SinkPort ship_in = null;
173 ship_in = createOutputPort("ship", WIDTH_WORD+1, "");
174 ship_in.hasLatch = true;
177 Module.Latch repeat_counter = new Latch("repeat_counter", SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
178 Module.Latch loop_counter = new Latch("loop_counter", SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
179 Module.Latch flag_a = new Latch("flag_a", 1);
180 Module.Latch flag_b = new Latch("flag_b", 1);
181 Module.Latch flag_c = new Latch("flag_c", 1);
183 Module.StateWire torpedoWaiting = new StateWire("torpedoWaiting", false);
185 Module.SinkPort token_out = fabric_out;
186 Module.SourcePort token_in = dfifo_out;
187 Module.SinkPort data_out = inbox ? ship_in : fabric_out;
188 Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
190 Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
191 Module.SinkPort ififo_in = ififo.getInputPort("in");
192 Module.SourcePort ififo_out = ififo.getOutputPort("out");
194 Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", inbox ? WIDTH_WORD+1 : WIDTH_WORD);
196 Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
197 instruction.connect(torpedo_branch.getInputPort("in"));
198 Module.SourcePort efifo_out = torpedo_branch.getOutputPort("out");
199 Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
201 Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(WIDTH_WORD-DISPATCH_PATH.valmaskwidth));
202 Module.SinkPort fanout_module_in = fanout_module.getInputPort("in");
203 Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
204 Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
206 Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
207 Module.SinkPort requeue_fabric_in = requeue_module.getInputPort("fabric_in");
208 Module.SinkPort requeue_ondeck = requeue_module.getInputPort("ondeck_in");
209 Module.SinkPort requeue_olc_in = requeue_module.getInputPort("olc_in");
210 Module.SourcePort requeue_out = requeue_module.getOutputPort("out");
212 efifo_out.connect(requeue_fabric_in);
213 requeue_out.connect(ififo_in);
214 ififo_out.connect(fanout_module_in);
215 fanout_module_out0.connect(requeue_ondeck);
216 Module.SourcePort ondeck = fanout_module_out1;
218 addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";");
219 addPreCrap("wire ["+(Math.max(repeat_counter.width,loop_counter.width)-1)+":0] decremented;");
220 addPreCrap("assign decremented = ("+SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName())+" ? {1'b0, loop_counter} : repeat_counter)-1;");
221 addPreCrap("assign "+requeue_olc_in.getName()+" = loop_counter;");
223 Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
224 String data_latch_input = inbox ? data_in.getName() : data_in.getName();
226 String magic_standing_value = "(1<<"+SET_ILC_FROM_IMMEDIATE.valmaskwidth+")";
227 String done_executing = "(repeat_counter==0 || repeat_counter==1 || !"+MOVE.verilog(ondeck.getName())+")";
230 new Event(new Object[] { torpedo_branch_torpedo, torpedoWaiting.isEmpty() },
231 new Action[] { torpedo_branch_torpedo, torpedoWaiting.doFill() });
233 String predicate_met =
236 "!"+MOVE.verilog(ondeck.getName())+" || repeat_counter!=0"+
239 P_ALWAYS.verilog(ondeck.getName())+
241 P_OLC_ZERO.verilog(ondeck.getName())+"==(loop_counter==0)"+
244 " " + P_A.verilog(ondeck.getName())+" ? flag_a"+
245 ":" + P_B.verilog(ondeck.getName())+" ? flag_b"+
246 ":" + P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
247 ":" + P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
253 new Event(new Object[] {
258 MOVE.verilog(ondeck.getName()),
259 I.verilog(ondeck.getName()),
260 torpedoWaiting.isFull()
264 torpedoWaiting.doDrain(),
265 new AssignAction(loop_counter, "0"),
266 new AssignAction(repeat_counter, "1")
270 new Event(new Object[] { ondeck, "!("+predicate_met+")" },
271 new Action[] { ondeck });
273 new Event(new Object[] { ondeck,
277 "(!"+MOVE.verilog(ondeck.getName())+" || !"+I.verilog(ondeck.getName())+" || !"+torpedoWaiting.isFull()+")",
278 new ConditionalTrigger(DI.verilog(ondeck.getName()), data_in),
279 new ConditionalTrigger(TI.verilog(ondeck.getName()), token_in)
282 new ConditionalAction(done_executing+" && "+MOVE.verilog(ondeck.getName()), new AssignAction(repeat_counter, "1")),
283 new ConditionalAction(done_executing, ondeck),
284 new ConditionalAction("!"+done_executing,
285 new AssignAction(repeat_counter,
286 "repeat_counter=="+magic_standing_value+"?"+magic_standing_value+":decremented")),
288 new ConditionalAction(SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(loop_counter, "data_latch_output")),
289 new ConditionalAction(SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()),
290 new AssignAction(loop_counter, SET_OLC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
291 new ConditionalAction(SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()),
292 new AssignAction(loop_counter, "loop_counter==0 ? 0 : decremented")),
293 new ConditionalAction(SET_ILC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(repeat_counter, "data_latch_output")),
294 new ConditionalAction(SET_ILC_FROM_IMMEDIATE.verilog(ondeck.getName()),
295 new AssignAction(repeat_counter, SET_ILC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
296 new ConditionalAction(SET_ILC_FROM_INFINITY.verilog(ondeck.getName()), new AssignAction(repeat_counter, magic_standing_value)),
297 new ConditionalAction(SHIFT.verilog(ondeck.getName()),
298 new AssignAction(data_latch,
299 "{ data_latch_output["+(WIDTH_WORD-1-SHIFT.valmaskwidth)+":0], "+
300 SHIFT.verilogVal(ondeck.getName())+"}")),
301 new ConditionalAction(SET_IMMEDIATE.verilog(ondeck.getName()),
302 new AssignAction(data_latch,
303 "{ {"+(WIDTH_WORD-FleetTwoFleet.DataLatch_WIDTH)+
304 "{"+SET_IMMEDIATE_EXTEND.verilogVal(ondeck.getName())+"}}, "+
305 SET_IMMEDIATE.verilogVal(ondeck.getName())+" }")),
306 new ConditionalAction(SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_a, "`new_flag_a("+ondeck.getName()+")")),
307 new ConditionalAction(SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_b, "`new_flag_b("+ondeck.getName()+")")),
308 new ConditionalAction(inbox
309 ? "("+DI.verilog(ondeck.getName())+" || "+TI.verilog(ondeck.getName())+")"
310 : "(!"+DI.verilog(ondeck.getName())+" && "+TI.verilog(ondeck.getName())+")",
311 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))),
312 new ConditionalAction(DI.verilog(ondeck.getName()), data_in),
313 new ConditionalAction(DO.verilog(ondeck.getName()), data_out),
314 new ConditionalAction(FLUSH.verilog(ondeck.getName()), data_out),
316 ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+WIDTH_WORD+"]"), FLUSH.verilog(ondeck.getName())+"?1:0")
317 : new ConditionalAction(DI.verilog(ondeck.getName()), new AssignAction(flag_c, data_latch_input+"["+WIDTH_WORD+"]")),
318 new ConditionalAction(TI.verilog(ondeck.getName()), token_in),
319 new ConditionalAction(TO.verilog(ondeck.getName()), token_out),
320 new ConditionalAction(DC.verilog(ondeck.getName()), new AssignAction(data_latch, data_latch_input)),
321 new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"), "("+TO.verilog(ondeck.getName())+")?1:0"),
322 new ConditionalAction(PATH_DATA.verilog(ondeck.getName()),
323 new AssignAction(new SimpleAssignable("{ "+PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
324 PACKET_DEST.verilogVal(token_out.getName())+" }"),
325 DISPATCH_PATH.verilogVal(data_latch_input))),
326 new ConditionalAction(PATH_IMMEDIATE.verilog(ondeck.getName()),
327 new AssignAction(new SimpleAssignable("{ "+PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
328 PACKET_DEST.verilogVal(token_out.getName())+" }"),
329 PATH_IMMEDIATE.verilogVal(ondeck.getName()))),
334 public void dump(PrintWriter pw, boolean fix) {
335 pw.println("`define new_flag(x) ("+
336 "( ((x >> 0) & 1) & !flag_c) |" +
337 "( ((x >> 1) & 1) & flag_c) |" +
338 "( ((x >> 2) & 1) & !flag_b) |" +
339 "( ((x >> 3) & 1) & flag_b) |" +
340 "( ((x >> 4) & 1) & !flag_a) |" +
341 "( ((x >> 5) & 1) & flag_a) | 0" +
343 pw.println("`define new_flag_a(i) `new_flag("+SET_FLAGS_A.verilogVal("i")+")");
344 pw.println("`define new_flag_b(i) `new_flag("+SET_FLAGS_B.verilogVal("i")+")");