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;
23 // Marina has 12 latches in the ring, 9 of which are wagged (plus
24 // M1, OD, RQ), so max capacity is 11 instructions
25 static final int INSTRUCTION_FIFO_SIZE = 11;
26 static final int INSTRUCTION_WAGGED_STAGES = 8;
28 //private static final int DATA_FIFO_SIZE = 4;
29 static final int DATA_FIFO_SIZE = 8;
31 private FpgaDestination dataDestination;
32 private FpgaDestination instructionDestination;
34 private Module.InstantiatedModule instance;
36 public Module.InstantiatedModule getInstance() { return instance; }
40 public Destination getDataDestination() { return dataDestination; }
41 public Destination getInstructionDestination() { return instructionDestination; }
42 public int getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
44 FpgaDock(FpgaShip ship, DockDescription bbd) {
46 this.fpga = (Fpga)ship.getFleet();
47 this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock()));
48 this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false);
49 this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true);
50 Module.InstantiatedModule shipm = ship.getVerilogModule();
52 instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
54 shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
59 // FabricElement methods //////////////////////////////////////////////////////////////////////////////
61 private FabricElement upstream;
62 public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
63 public Module.Port getInputPort() { throw new RuntimeException(); }
64 public Path getPath(Destination dest,BitVector signal) { return getPath((FpgaDestination)dest, signal); }
65 public FpgaPath getPath(FpgaDestination dest,BitVector signal) { return upstream.getPath(dest, signal); }
66 public int getPathLength(FpgaDestination dest) { return upstream.getPathLength(dest)-1; }
67 public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
68 public void addOutput(FabricElement out, Module.Port outPort) {
70 instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
73 public class TorpedoBranchModule extends Module {
74 public TorpedoBranchModule() {
75 super("torpedobranch");
76 Module.SourcePort in = createInputPort ("in", fpga.WIDTH_PACKET);
77 Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
78 Module.SinkPort torpedo = createOutputPort("torpedo", 0);
79 Module.StateWire busy = new StateWire("busy", false);
81 new Event(new Object[] { in, busy.isFull(), out },
82 new Action[] { in, busy.doDrain() });
83 new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.testMask(fpga.PACKET_IS_TOKEN) },
84 new Action[] { in, torpedo });
85 new Event(new Object[] { in, busy.isEmpty(), out, in.testMask(fpga.PACKET_IS_TOKEN).invert() },
86 new Action[] { busy.doFill(), out });
88 out.connectValue(in.getBits(fpga.PACKET_DATA));
92 public class RequeueModule extends Module {
93 public RequeueModule() {
95 Module.SourcePort fabric_in = createInputPort ("fabric_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
96 Module.SourcePort ondeck_in = createInputPort ("ondeck_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
97 Module.SourcePort abort = createInputPort ("abort", 1);
98 Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
100 Module.StateWire circulating = new StateWire("circulating", false);
101 Module.StateWire doResetFabric = new StateWire("doResetFabric", false);
102 Module.StateWire doResetOndeck = new StateWire("doResetOndeck", false);
104 out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
106 // always: discard one-shot instructions
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 // Updating->Circulating transition
113 new Event(new Object[] { doResetFabric.isEmpty(),
114 doResetOndeck.isEmpty(),
115 circulating.isEmpty(),
117 fpga.TAIL.verilog(fabric_in.getName()),
119 fpga.HEAD.verilog(ondeck_in.getName()) },
120 new Action[] { circulating.doFill(),
124 // Circulating->Updating transition
125 new Event(new Object[] { doResetFabric.isEmpty(),
126 doResetOndeck.isEmpty(),
127 circulating.isFull(),
129 abort.getVerilog() },
130 new Action[] { circulating.doDrain(),
134 new Event(new Object[] { doResetFabric.isEmpty(),
135 doResetOndeck.isEmpty(),
136 circulating.isEmpty(),
138 "!"+fpga.TAIL.verilog(fabric_in.getName()) },
139 new Action[] { doResetFabric.doFill(),
141 new Event(new Object[] { doResetFabric.isEmpty(),
142 doResetOndeck.isEmpty(),
143 circulating.isEmpty(),
145 "!"+fpga.HEAD.verilog(ondeck_in.getName()) },
146 new Action[] { ondeck_in });
149 new Event(new Object[] { doResetFabric.isEmpty(),
150 doResetOndeck.isEmpty(),
151 circulating.isFull(),
153 "!"+abort.getVerilog() },
154 new Action[] { doResetOndeck.doFill(),
159 public class DockModule extends Module {
161 public DockModule(boolean inbox) {
162 super(inbox ? "inbox" : "outbox");
164 int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
166 // FIXME: assumes fpga.DISPATCH_PATH is at top of word!!!
167 Module ififo_m_1 = new FifoModule(INSTRUCTION_FIFO_SIZE, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
168 //Module ififo_m_1 = new FifoModule(INSTRUCTION_FIFO_SIZE-INSTRUCTION_WAGGED_STAGES, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
169 //Module ififo_m_2 = new FifoModule(INSTRUCTION_WAGGED_STAGES, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, true);
171 Module dfifo_m = new FifoModule(DATA_FIFO_SIZE, dfifo_width);
173 Module.SourcePort instruction = createInputPort("instruction", fpga.WIDTH_PACKET);
174 Module.SourcePort fabric_in = createInputPort("fabric_in", fpga.WIDTH_PACKET);
176 // FIXME: at inboxes, no need for a full set of latches
177 Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
179 Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
181 fabric_in.connect(dfifo.getInputPort("in"));
182 dfifo.getInputPort("in").connectValue(
184 ? fabric_in.getBits(fpga.PACKET_SIGNAL)
185 : new CatValue(new Value[] {
186 fabric_in.getBits(fpga.PACKET_SIGNAL),
187 fabric_in.getBits(fpga.PACKET_DATA)
190 Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
191 Module.SourcePort ship_out = !inbox ? createInputPort("ship", fpga.getWordWidth()+1) : null;
192 Module.SinkPort ship_in = inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null;
194 Module.Latch ilc = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
195 Module.Latch olc = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
196 Module.Latch flag_a = new Latch("flag_a", 1);
197 Module.Latch flag_b = new Latch("flag_b", 1);
198 Module.Latch flag_c = new Latch("flag_c", 1);
199 Module.Latch flag_d = new Latch("flag_d", 1);
201 Module.SinkPort token_out = fabric_out;
202 Module.SourcePort token_in = dfifo_out;
203 Module.SinkPort data_out = inbox ? ship_in : fabric_out;
204 Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
206 Module.InstantiatedModule ififo_1 = new Module.InstantiatedModule(this, ififo_m_1);
207 //Module.InstantiatedModule ififo_2 = new Module.InstantiatedModule(this, ififo_m_2);
208 //ififo_1.getOutputPort("out").connect(ififo_2.getInputPort("in"));
209 Module.SinkPort ififo_in = ififo_1.getInputPort("in");
210 //Module.SourcePort ififo_out = ififo_2.getOutputPort("out");
211 Module.SourcePort ififo_out = ififo_1.getOutputPort("out");
213 Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
214 instruction.connect(torpedo_branch.getInputPort("in"));
215 Module.SourcePort efifo_out = torpedo_branch.getOutputPort("out");
216 Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
218 Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth));
219 Module.SinkPort fanout_module_in = fanout_module.getInputPort("in");
220 Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
221 Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
223 Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
224 Module.SinkPort requeue_fabric_in = requeue_module.getInputPort("fabric_in");
225 Module.SinkPort requeue_ondeck = requeue_module.getInputPort("ondeck_in");
226 Module.SinkPort requeue_abort = requeue_module.getInputPort("abort");
227 Module.SourcePort requeue_out = requeue_module.getOutputPort("out");
229 efifo_out.connect(requeue_fabric_in);
230 requeue_out.connect(ififo_in);
231 ififo_out.connect(fanout_module_in);
232 fanout_module_out0.connect(requeue_ondeck);
233 Module.SourcePort ondeck = fanout_module_out1;
235 WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width),
236 new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+
237 " ? {1'b0, olc} : ilc)-1"));
238 WireValue data_latch_output_p = new WireValue("data_latch_output",
239 inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(),
241 ? new SimpleValue(data_out.getName())
242 : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
245 Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog());
246 Module.SourcePort data_latch_input = inbox ? data_in : data_in;
248 BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1);
249 bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true);
250 Value magic_standing_value = new ConstantValue(bv);
252 Trigger done_executing = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
254 String predicate_met =
257 "!"+fpga.MOVE.verilog(ondeck.getName())+" || (ilc!=0)"+
260 fpga.P_ALWAYS.verilog(ondeck.getName())+
262 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_d"+
265 " " + fpga.P_A.verilog(ondeck.getName())+" ? flag_a"+
266 ":" + fpga.P_B.verilog(ondeck.getName())+" ? flag_b"+
267 ":" + fpga.P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
268 ":" + fpga.P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
273 requeue_abort.connectValue(new SimpleValue("("+predicate_met+") && "+fpga.ABORT.verilog(ondeck.getName())));
276 new Event(new Object[] {
281 fpga.MOVE.verilog(ondeck.getName()),
282 "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
283 torpedo_branch_torpedo
287 torpedo_branch_torpedo,
288 new AssignAction(olc, new ConstantValue(new BitVector(olc.width).set(0))),
289 new AssignAction(flag_d, new ConstantValue(new BitVector(1).set(1))),
290 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))
294 new Event(new Object[] { ondeck, "!("+predicate_met+")" },
295 new Action[] { ondeck,
296 new ConditionalAction(ondeck.testMask(fpga.MOVE),
297 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))))
300 new Event(new Object[] { ondeck,
304 "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")",
305 new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in),
306 new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in)
309 new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)),
310 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))),
311 new ConditionalAction(done_executing, ondeck),
312 new ConditionalAction(done_executing.invert(),
313 new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value),
314 magic_standing_value,
316 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
317 new AssignAction(olc, new SimpleValue("data_latch_output"))),
318 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
319 new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))),
320 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
321 new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))),
323 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
324 new AssignAction(flag_d, new SimpleValue("data_latch_output==0"))),
325 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
326 new AssignAction(flag_d, new SimpleValue(ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE).getVerilog()+"==0"))),
327 new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
328 new AssignAction(flag_d, new SimpleValue("(olc==0 || olc==1)"))),
330 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
331 new AssignAction(ilc, new SimpleValue("data_latch_output"))),
333 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE),
334 new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))),
335 new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY),
336 new AssignAction(ilc, magic_standing_value)),
337 new ConditionalAction(ondeck.testMask(fpga.SHIFT),
338 new AssignAction(data_latch,
339 new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
340 ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))),
341 new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE),
342 new AssignAction(data_latch,
343 new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
344 "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+
345 ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))),
346 new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
347 new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))),
348 new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
349 new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))),
350 new ConditionalAction(ondeck.testMask(fpga.MOVE),
351 new AssignAction(flag_c,
353 ? dfifo_out.getBits(dfifo_width-1, dfifo_width-1)
354 : new MuxValue(ondeck.testMask(fpga.DC),
355 ship_out.getBits(fpga.getWordWidth(), fpga.getWordWidth()),
356 dfifo_out.getBits(dfifo_width-1, dfifo_width-1))
358 new ConditionalAction(ondeck.testMask(fpga.DI), data_in),
359 new ConditionalAction(ondeck.testMask(fpga.DO), data_out),
360 new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out),
362 ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"),
363 new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
365 new ConditionalAction(ondeck.testMask(fpga.TI), token_in),
366 new ConditionalAction(ondeck.testMask(fpga.TO), token_out),
367 new ConditionalAction(ondeck.testMask(fpga.DC), new AssignAction(data_latch, data_latch_input)),
368 new AssignAction(token_out.getBits(fpga.PACKET_TOKEN),
369 new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")),
370 new ConditionalAction(ondeck.testMask(fpga.PATH_DATA),
371 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
372 token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
373 data_latch_input.getBits(fpga.DISPATCH_PATH))),
374 new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE),
375 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
376 token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
377 ondeck.getBits(fpga.PATH_IMMEDIATE)))
382 private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) {
383 Value[] vals = new Value[] {
384 new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()),
385 new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c),
386 new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()),
387 new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b),
388 new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()),
389 new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a),
391 Value ret = new ConstantValue(new BitVector(1).set(0));
392 for(int i=0; i<vals.length; i++)
393 ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);