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 public class FpgaDock extends FleetTwoDock implements FabricElement {
21 private static final int INSTRUCTION_FIFO_SIZE = 12;
22 private static final int EPILOGUE_FIFO_SIZE = 0;
23 private static final int DATA_FIFO_SIZE = 4;
25 private FpgaDestination dataDestination;
26 private FpgaDestination instructionDestination;
28 private Module.InstantiatedModule instance;
30 public Module.InstantiatedModule getInstance() { return instance; }
34 public Destination getDataDestination() { return dataDestination; }
35 public Destination getInstructionDestination() { return instructionDestination; }
36 public int getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
38 FpgaDock(FpgaShip ship, DockDescription bbd) {
40 this.fpga = (Fpga)ship.getFleet();
41 this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock()));
42 this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false);
43 this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true);
44 Module.InstantiatedModule shipm = ship.getVerilogModule();
46 instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
48 shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
53 // FabricElement methods //////////////////////////////////////////////////////////////////////////////
55 private FabricElement upstream;
56 public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
57 public Module.Port getInputPort() { throw new RuntimeException(); }
58 public Path getPath(Destination dest,BitVector signal) { return getPath((FpgaDestination)dest, signal); }
59 public FpgaPath getPath(FpgaDestination dest,BitVector signal) { return upstream.getPath(dest, signal); }
60 public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
61 public void addOutput(FabricElement out, Module.Port outPort) {
63 instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
66 public class TorpedoBranchModule extends Module {
67 public TorpedoBranchModule() {
68 super("torpedobranch");
69 Module.SourcePort in = createInputPort ("in", fpga.WIDTH_PACKET);
70 Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
71 Module.SinkPort torpedo = createOutputPort("torpedo", 0);
72 Module.StateWire busy = new StateWire("busy", false);
74 new Event(new Object[] { in, busy.isFull(), out },
75 new Action[] { in, busy.doDrain() });
76 new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.testMask(fpga.PACKET_IS_TOKEN) },
77 new Action[] { in, torpedo });
78 new Event(new Object[] { in, busy.isEmpty(), out, in.testMask(fpga.PACKET_IS_TOKEN).invert() },
79 new Action[] { busy.doFill(), out });
81 out.connectValue(in.getBits(fpga.PACKET_DATA));
85 public class RequeueModule extends Module {
86 public RequeueModule() {
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 abort = createInputPort ("abort", 1);
91 Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
93 Module.StateWire circulating = new StateWire("circulating", false);
94 Module.StateWire doResetFabric = new StateWire("doResetFabric", false);
95 Module.StateWire doResetOndeck = new StateWire("doResetOndeck", false);
97 out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
99 // always: discard one-shot instructions
100 new Event(new Object[] { doResetFabric.isFull(), out },
101 new Action[] { doResetFabric.doDrain(), fabric_in });
102 new Event(new Object[] { doResetOndeck.isFull(), out },
103 new Action[] { doResetOndeck.doDrain(), ondeck_in });
105 // Updating->Circulating transition
106 new Event(new Object[] { doResetFabric.isEmpty(),
107 doResetOndeck.isEmpty(),
108 circulating.isEmpty(),
110 fpga.TAIL.verilog(fabric_in.getName()),
112 fpga.HEAD.verilog(ondeck_in.getName()) },
113 new Action[] { circulating.doFill(),
117 // Circulating->Updating transition
118 new Event(new Object[] { doResetFabric.isEmpty(),
119 doResetOndeck.isEmpty(),
120 circulating.isFull(),
122 abort.getVerilog() },
123 new Action[] { circulating.doDrain(),
127 new Event(new Object[] { doResetFabric.isEmpty(),
128 doResetOndeck.isEmpty(),
129 circulating.isEmpty(),
131 "!"+fpga.TAIL.verilog(fabric_in.getName()) },
132 new Action[] { doResetFabric.doFill(),
134 new Event(new Object[] { doResetFabric.isEmpty(),
135 doResetOndeck.isEmpty(),
136 circulating.isEmpty(),
138 "!"+fpga.HEAD.verilog(ondeck_in.getName()) },
139 new Action[] { ondeck_in });
142 new Event(new Object[] { doResetFabric.isEmpty(),
143 doResetOndeck.isEmpty(),
144 circulating.isFull(),
146 "!"+abort.getVerilog() },
147 new Action[] { doResetOndeck.doFill(),
152 public class DockModule extends Module {
154 public DockModule(boolean inbox) {
155 super(inbox ? "inbox" : "outbox");
157 int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
159 // FIXME: assumes fpga.DISPATCH_PATH is at top of word!!!
160 Module ififo_m = new FifoModule(INSTRUCTION_FIFO_SIZE, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
161 Module dfifo_m = new FifoModule(DATA_FIFO_SIZE, dfifo_width);
163 Module.SourcePort instruction = createInputPort("instruction", fpga.WIDTH_PACKET);
164 Module.SourcePort fabric_in = createInputPort("fabric_in", fpga.WIDTH_PACKET);
166 // FIXME: at inboxes, no need for a full set of latches
167 Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
169 Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
171 fabric_in.connect(dfifo.getInputPort("in"));
172 dfifo.getInputPort("in").connectValue(
174 ? fabric_in.getBits(fpga.PACKET_SIGNAL)
175 : new CatValue(new Value[] {
176 fabric_in.getBits(fpga.PACKET_SIGNAL),
177 fabric_in.getBits(fpga.PACKET_DATA)
180 Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
181 Module.SourcePort ship_out = !inbox ? createInputPort("ship", fpga.getWordWidth()+1) : null;
182 Module.SinkPort ship_in = inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null;
184 Module.Latch ilc = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
185 Module.Latch olc = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
186 Module.Latch flag_a = new Latch("flag_a", 1);
187 Module.Latch flag_b = new Latch("flag_b", 1);
188 Module.Latch flag_c = new Latch("flag_c", 1);
189 Module.Latch flag_d = new Latch("flag_d", 1);
190 Module.Latch flag_z = new Latch("flag_z", 1);
192 Module.SinkPort token_out = fabric_out;
193 Module.SourcePort token_in = dfifo_out;
194 Module.SinkPort data_out = inbox ? ship_in : fabric_out;
195 Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
197 Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
198 Module.SinkPort ififo_in = ififo.getInputPort("in");
199 Module.SourcePort ififo_out = ififo.getOutputPort("out");
201 Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
202 instruction.connect(torpedo_branch.getInputPort("in"));
203 Module.SourcePort efifo_out = torpedo_branch.getOutputPort("out");
204 Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
206 Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth));
207 Module.SinkPort fanout_module_in = fanout_module.getInputPort("in");
208 Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
209 Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
211 Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
212 Module.SinkPort requeue_fabric_in = requeue_module.getInputPort("fabric_in");
213 Module.SinkPort requeue_ondeck = requeue_module.getInputPort("ondeck_in");
214 Module.SinkPort requeue_abort = requeue_module.getInputPort("abort");
215 Module.SourcePort requeue_out = requeue_module.getOutputPort("out");
217 efifo_out.connect(requeue_fabric_in);
218 requeue_out.connect(ififo_in);
219 ififo_out.connect(fanout_module_in);
220 fanout_module_out0.connect(requeue_ondeck);
221 Module.SourcePort ondeck = fanout_module_out1;
223 WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width),
224 new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+
225 " ? {1'b0, olc} : ilc)-1"));
226 WireValue data_latch_output_p = new WireValue("data_latch_output",
227 inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(),
229 ? new SimpleValue(data_out.getName())
230 : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
233 Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog());
234 Module.SourcePort data_latch_input = inbox ? data_in : data_in;
236 BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1);
237 bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true);
238 Value magic_standing_value = new ConstantValue(bv);
240 Trigger done_executing = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
242 String predicate_met =
245 "!"+fpga.MOVE.verilog(ondeck.getName())+" || (ilc!=0)"+
248 fpga.P_ALWAYS.verilog(ondeck.getName())+
250 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_d"+
253 " " + fpga.P_A.verilog(ondeck.getName())+" ? flag_a"+
254 ":" + fpga.P_B.verilog(ondeck.getName())+" ? flag_b"+
255 ":" + fpga.P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
256 ":" + fpga.P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
261 requeue_abort.connectValue(new SimpleValue("("+predicate_met+") && "+fpga.ABORT.verilog(ondeck.getName())));
264 new Event(new Object[] {
269 fpga.MOVE.verilog(ondeck.getName()),
270 "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
271 torpedo_branch_torpedo
275 torpedo_branch_torpedo,
276 new AssignAction(olc, new ConstantValue(new BitVector(olc.width).set(0))),
277 new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(1))),
278 new AssignAction(flag_d, new ConstantValue(new BitVector(1).set(1))),
279 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))
283 new Event(new Object[] { ondeck, "!("+predicate_met+")" },
284 new Action[] { ondeck,
285 new ConditionalAction(ondeck.testMask(fpga.MOVE),
286 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))))
289 new Event(new Object[] { ondeck,
293 "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")",
294 new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in),
295 new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in)
298 new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)),
299 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))),
300 new ConditionalAction(done_executing, ondeck),
301 new ConditionalAction(done_executing.invert(),
302 new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value),
303 magic_standing_value,
305 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
306 new AssignAction(olc, new SimpleValue("data_latch_output"))),
307 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
308 new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))),
309 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
310 new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))),
312 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
313 new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
314 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
315 new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
316 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
317 new AssignAction(flag_z, new SimpleValue("(olc==0 || olc==1)"))),
319 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
320 new AssignAction(flag_d, new SimpleValue("data_latch_output==0"))),
321 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
322 new AssignAction(flag_d, new SimpleValue(ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE).getVerilog()+"==0"))),
323 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
324 new AssignAction(flag_d, new SimpleValue("(olc==0 || olc==1)"))),
326 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
327 new AssignAction(ilc, new SimpleValue("data_latch_output"))),
329 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE),
330 new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))),
331 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY),
332 new AssignAction(ilc, magic_standing_value)),
333 new ConditionalAction(ondeck.testMask(fpga.SHIFT),
334 new AssignAction(data_latch,
335 new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
336 ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))),
337 new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE),
338 new AssignAction(data_latch,
339 new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
340 "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+
341 ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))),
342 new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
343 new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))),
344 new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
345 new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))),
346 new ConditionalAction(ondeck.testMask(fpga.MOVE),
347 new AssignAction(flag_c,
349 ? dfifo_out.getBits(dfifo_width-1, dfifo_width-1)
350 : new MuxValue(ondeck.testMask(fpga.DC),
351 ship_out.getBits(fpga.getWordWidth(), fpga.getWordWidth()),
352 dfifo_out.getBits(dfifo_width-1, dfifo_width-1))
354 new ConditionalAction(ondeck.testMask(fpga.DI), data_in),
355 new ConditionalAction(ondeck.testMask(fpga.DO), data_out),
356 new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out),
358 ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"),
359 new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
361 new ConditionalAction(ondeck.testMask(fpga.TI), token_in),
362 new ConditionalAction(ondeck.testMask(fpga.TO), token_out),
363 new ConditionalAction(ondeck.testMask(fpga.DC), new AssignAction(data_latch, data_latch_input)),
364 new AssignAction(token_out.getBits(fpga.PACKET_TOKEN),
365 new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")),
366 new ConditionalAction(ondeck.testMask(fpga.PATH_DATA),
367 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
368 token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
369 data_latch_input.getBits(fpga.DISPATCH_PATH))),
370 new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE),
371 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
372 token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
373 ondeck.getBits(fpga.PATH_IMMEDIATE)))
378 private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) {
379 Value[] vals = new Value[] {
380 new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()),
381 new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c),
382 new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()),
383 new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b),
384 new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()),
385 new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a),
387 Value ret = new ConstantValue(new BitVector(1).set(0));
388 for(int i=0; i<vals.length; i++)
389 ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);