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 = 12;
23 private static final int EPILOGUE_FIFO_SIZE = 0;
24 private static final int DATA_FIFO_SIZE = 4;
26 private FpgaDestination dataDestination;
27 private FpgaDestination instructionDestination;
29 private Module.InstantiatedModule instance;
31 public Module.InstantiatedModule getInstance() { return instance; }
35 public Destination getDataDestination() { return dataDestination; }
36 public Destination getInstructionDestination() { return instructionDestination; }
37 public int getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
39 FpgaDock(FpgaShip ship, DockDescription 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();
47 instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
49 shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
54 // FabricElement methods //////////////////////////////////////////////////////////////////////////////
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) {
64 instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
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;
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 });
83 out.latchDriver = in.getBits(fpga.PACKET_DATA);
87 public class RequeueModule extends Module {
88 public RequeueModule() {
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;
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);
101 addPreCrap("assign out = "+circulating.isEmpty()+" ? "+fabric_in.getName()+" : "+ondeck_in.getName()+";");
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 */});
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 });
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() });
128 public class DockModule extends Module {
130 public DockModule(boolean inbox) {
131 super(inbox ? "inbox" : "outbox");
133 int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
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);
139 Module.SourcePort instruction = createInputPort("instruction", fpga.WIDTH_PACKET);
140 Module.SourcePort fabric_in = createInputPort("fabric_in", fpga.WIDTH_PACKET);
142 // FIXME: at inboxes, no need for a full set of latches
143 Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET, "");
145 Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
147 fabric_in.hasLatch = false;
148 fabric_in.connect(dfifo.getInputPort("in"));
149 dfifo.getInputPort("in").noDriveLatches = true;
151 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
152 " = { "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+
153 ", "+fpga.PACKET_DATA.verilogVal("fabric_in")+" };\n");
155 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
156 " = "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
159 Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
160 Module.SourcePort ship_out = null;
162 ship_out = createInputPort("ship", fpga.getWordWidth()+1);
163 ship_out.hasLatch = true;
166 Module.SinkPort ship_in = null;
168 ship_in = createOutputPort("ship", fpga.getWordWidth()+1, "");
169 ship_in.hasLatch = true;
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);
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;
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");
188 Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth());
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");
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");
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");
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;
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;");
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();
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())+")";
223 String predicate_met =
226 "!"+fpga.MOVE.verilog(ondeck.getName())+" || ilc!=0"+
229 fpga.P_ALWAYS.verilog(ondeck.getName())+
231 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_z"+
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 "+
243 new Event(new Object[] {
248 fpga.MOVE.verilog(ondeck.getName()),
249 "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
250 torpedo_branch_torpedo
254 torpedo_branch_torpedo,
255 new AssignAction(olc, "0"),
256 new AssignAction(flag_z, "1"),
257 new AssignAction(ilc, "1")
261 new Event(new Object[] { ondeck, "!("+predicate_met+")" },
262 new Action[] { ondeck,
263 new ConditionalAction(fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1"))
266 new Event(new Object[] { ondeck,
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)
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")),
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")),
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)")),
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),
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()))),
332 private String new_flag(String x) {
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" +