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 = 12;
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 DockModule extends Module {
66 public DockModule(boolean inbox) {
67 super(inbox ? "inbox" : "outbox");
70 Module horn = new HornModule();
71 Module funnel = new FunnelModule();
72 Module.SourcePort instruction = createInputPort("instruction", WIDTH_PACKET);
73 Module.SourcePort fabric_in = createInputPort("fabric_in", WIDTH_PACKET);
74 Module.SinkPort fabric_out = createOutputPort("fabric_out", WIDTH_PACKET, "");
76 FunnelModule.FunnelInstance f0 = new FunnelModule.FunnelInstance(this, instruction, fabric_in);
77 Module.SourcePort ship_out = createInputPort("ship", WIDTH_WORD);
78 FunnelModule.FunnelInstance f1 = new FunnelModule.FunnelInstance(this, f0.getOutputPort(), ship_out);
79 f1.addOutput(f0, fabric_out);
81 Module.SinkPort ship_in = createOutputPort("ship", WIDTH_PACKET, "");
82 instruction.connect(fabric_out);
83 fabric_in.connect(ship_in);
87 int dfifo_width = inbox ? WIDTH_WORD+1 : 1;
89 // FIXME: assumes DISPATCH_PATH is at top of word!!!
90 Module ififo_m = new FifoModule(INSTRUCTION_FIFO_SIZE, WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
91 Module efifo_m = new FifoModule(EPILOGUE_FIFO_SIZE, WIDTH_WORD-DISPATCH_PATH.valmaskwidth);
92 Module dfifo_m = new FifoModule(DATA_FIFO_SIZE, dfifo_width);
93 Module.SourcePort instruction = createInputPort("instruction", WIDTH_PACKET);
94 instruction.hasLatch = true;
96 Module.SourcePort fabric_in = createInputPort("fabric_in", WIDTH_PACKET);
98 // FIXME: at inboxes, no need for a full set of latches
99 Module.SinkPort fabric_out = createOutputPort("fabric_out", WIDTH_PACKET, "");
101 Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
103 fabric_in.hasLatch = false;
104 addPreCrap("assign "+dfifo.getInputPort("in").getName()+"_r = fabric_in_r;\n");
105 addPreCrap("assign fabric_in_a = "+dfifo.getInputPort("in").getName()+"_a;\n");
107 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
108 " = { "+PACKET_SIGNAL.verilogVal("fabric_in")+
109 ", "+PACKET_DATA.verilogVal("fabric_in")+" };\n");
111 addPreCrap("assign "+dfifo.getInputPort("in").getName()+
112 " = "+PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
115 Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
116 Module.SourcePort ship_out = null;
118 ship_out = createInputPort("ship", WIDTH_WORD+1);
119 ship_out.hasLatch = true;
122 Module.SinkPort ship_in = null;
124 ship_in = createOutputPort("ship", WIDTH_WORD, "");
125 ship_in.hasLatch = true;
128 Module.Latch repeat_counter = new Latch("repeat_counter", SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
129 Module.Latch loop_counter = new Latch("loop_counter", SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
130 Module.Latch flag_a = new Latch("flag_a", 1);
131 Module.Latch flag_b = new Latch("flag_b", 1);
132 Module.Latch flag_c = new Latch("flag_c", 1);
134 Module.StateWire isHatchOpen = new StateWire("hatch", true);
135 Module.StateWire proceed = new StateWire("proceed", false);
137 Module.SinkPort token_out = fabric_out;
138 Module.SourcePort token_in = dfifo_out;
139 Module.SinkPort data_out = inbox ? ship_in : fabric_out;
140 Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
142 Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
143 Module.SinkPort ififo_in = ififo.getInputPort("in");
144 ififo_in.hasLatch = false;
145 ififo_in.forceNoLatch = true;
147 Module.SourcePort ififo_out = ififo.getOutputPort("out");
149 Module.InstantiatedModule efifo = new Module.InstantiatedModule(this, efifo_m);
150 Module.SinkPort efifo_in = efifo.getInputPort("in");
151 Module.SourcePort efifo_out = efifo.getOutputPort("out");
152 efifo_in.hasLatch = false;
153 efifo_in.forceNoLatch = true;
155 Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", WIDTH_WORD);
156 Module.SinkPort data_latch_input_p = createWirePort("data_latch_input", inbox ? WIDTH_WORD : WIDTH_WORD+1);
159 addPreCrap("wire ["+(ififo_out.width-1)+":0] ondeck;");
160 addPreCrap("wire ["+(Math.max(repeat_counter.width,loop_counter.width)-1)+":0] decremented;");
161 addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";");
162 addPreCrap("assign data_latch_input = " + (inbox ? data_in.getName() : data_in.getName())+";");
163 addPreCrap("assign "+efifo_in.getName()+" = `packet_data("+instruction.getName()+");");
164 addPreCrap("assign "+ififo_in.getName()+" = hatch ? "+efifo_out.getName()+" : ondeck;");
165 addPreCrap("assign ondeck = "+ififo_out.getName()+";");
166 addPreCrap("assign decremented = (`instruction_is_decr_loop(ondeck) ? {1'b0, loop_counter} : repeat_counter)-1;");
168 Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
169 String data_latch_input = "data_latch_input";
172 new Event(new Object[] { "loop_counter==0" },
173 new Action[] { isHatchOpen.doFill() });
176 new Event(new Object[] { instruction,
177 PACKET_TOKEN.verilogVal("instruction"),
182 new Action[] { instruction,
184 new AssignAction(loop_counter, "0"),
185 new AssignAction(repeat_counter, "1"),
186 isHatchOpen.doFill(),
188 // Non-Torpedo Arrival
189 new Event(new Object[] { instruction,
191 "!("+PACKET_TOKEN.verilogVal("instruction")+")"
196 new Event(new Object[] { efifo_in.getName()+"_a" },
197 new Action[] { new SimpleAction(instruction.getName()+"_a <= 1;") });
200 new Event(new Object[] { efifo_out, TAIL.verilog(efifo_out.getName()) },
201 new Action[] { efifo_out, isHatchOpen.doDrain() } );
203 new Event(new Object[] { efifo_out,
205 "!("+TAIL.verilog(efifo_out.getName())+")",
206 isHatchOpen.isFull() },
207 new Action[] { efifo_out,
213 new Event(new Object[] { ififo_out, ififo_in, proceed.isFull() },
214 new Action[] { ififo_out, proceed.doDrain() });
216 new Object[] { ififo_out,
221 "(!`predicate_met(ondeck) || "+OS.verilog("ondeck")+" || !hatch)",
222 new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_datain(ondeck))", data_in),
223 new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck))", token_in)
226 new ConditionalAction("`done_executing(ondeck) && `instruction_is_normal(ondeck)",
227 new AssignAction(repeat_counter, "1")),
228 new ConditionalAction("!`should_requeue(ondeck) && `done_executing(ondeck)", ififo_out),
229 new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", ififo_in),
230 new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", proceed.doFill()),
231 new ConditionalAction("!`done_executing(ondeck)",
232 new AssignAction(repeat_counter,
233 "repeat_counter==`magic_standing_value?`magic_standing_value:decremented")),
234 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_loop(ondeck)",
235 new AssignAction(loop_counter, "data_latch_output")),
236 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_loop(ondeck)",
237 new AssignAction(loop_counter, "`instruction_loop_count_immediate(ondeck)")),
238 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_decr_loop(ondeck)",
239 new AssignAction(loop_counter, "loop_counter==0 ? 0 : decremented")),
240 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_repeat(ondeck)",
241 new AssignAction(repeat_counter, "data_latch_output")),
242 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_repeat(ondeck)",
243 new AssignAction(repeat_counter, "`instruction_repeat_count_immediate(ondeck)")),
244 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_standing_to_repeat(ondeck)",
245 new AssignAction(repeat_counter, "`magic_standing_value")),
246 new ConditionalAction("`predicate_met(ondeck) &&"+SHIFT.verilog("ondeck"),
247 new AssignAction(data_latch,
248 "{ data_latch_output["+(WIDTH_WORD-1-SHIFT.valmaskwidth)+":0], "+
249 SHIFT.verilogVal("ondeck")+"}")),
250 new ConditionalAction("`predicate_met(ondeck) && "+SET_IMMEDIATE.verilog("ondeck"),
251 new AssignAction(data_latch,
252 "{ {"+(WIDTH_WORD-FleetTwoFleet.DataLatch_WIDTH)+
253 "{"+SET_IMMEDIATE_EXTEND.verilogVal("ondeck")+"}}, "+
254 SET_IMMEDIATE.verilogVal("ondeck")+" }")),
255 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)",
256 new AssignAction(flag_a, "`new_flag_a(ondeck)")),
257 new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)",
258 new AssignAction(flag_b, "`new_flag_b(ondeck)")),
260 ? new ConditionalAction("`predicate_met(ondeck) && "+
261 "(`instruction_bit_datain(ondeck) || `instruction_bit_tokenin(ondeck))",
262 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1)))
263 : new ConditionalAction("`predicate_met(ondeck) && "+
264 "(!`instruction_bit_datain(ondeck) && `instruction_bit_tokenin(ondeck))",
265 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1)))
268 new ConditionalAction("`predicate_met(ondeck) && "+
269 "(`instruction_bit_datain(ondeck))",
270 new AssignAction(flag_c, "data_latch_input["+WIDTH_WORD+"]")),
271 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_datain(ondeck)", data_in),
272 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_dataout(ondeck)", data_out),
273 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck)", token_in),
274 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)", token_out),
275 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)",
276 new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"),
278 new ConditionalAction("`predicate_met(ondeck) && !`instruction_bit_tokenout(ondeck)",
279 new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"),
281 new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_latch(ondeck)",
282 new AssignAction(data_latch, data_latch_input)),
283 new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_data(ondeck)",
284 new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
285 DISPATCH_PATH.verilogVal(data_latch_input))),
286 new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_immediate(ondeck)",
287 new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
288 "`instruction_path_immediate(ondeck)")),
294 public void dump(PrintWriter pw, boolean fix) {
296 pw.println("`define packet_signal_and_dest(p) { "+PACKET_SIGNAL.verilogVal("p")+", "+PACKET_DEST.verilogVal("p")+" }");
297 pw.println("`define instruction_is_load_data_to_repeat(i) "+SET_ILC_FROM_DATA_LATCH.verilog("i"));
298 pw.println("`define instruction_is_load_data_to_loop(i) "+SET_OLC_FROM_DATA_LATCH.verilog("i"));
299 pw.println("`define instruction_is_load_immediate_to_repeat(i) "+SET_ILC_FROM_IMMEDIATE.verilog("i"));
300 pw.println("`define instruction_is_load_immediate_to_loop(i) "+SET_OLC_FROM_IMMEDIATE.verilog("i"));
301 pw.println("`define instruction_is_load_standing_to_repeat(i) "+SET_ILC_FROM_INFINITY.verilog("i"));
302 pw.println("`define instruction_repeat_count_immediate(i) "+SET_ILC_FROM_IMMEDIATE.verilogVal("i"));
303 pw.println("`define instruction_loop_count_immediate(i) "+SET_OLC_FROM_IMMEDIATE.verilogVal("i"));
305 pw.println("`define instruction_path_immediate(i) "+PATH_IMMEDIATE.verilogVal("i"));
306 pw.println("`define instruction_path_from_immediate(i) "+PATH_IMMEDIATE.verilog("i"));
307 pw.println("`define instruction_path_from_data(i) "+PATH_DATA.verilog("i"));
309 pw.println("`define instruction_is_tail(i) "+TAIL.verilog("i"));
310 pw.println("`define instruction_is_normal(i) "+MOVE.verilog("i"));
311 pw.println("`define instruction_is_setflags(i) "+SET_FLAGS.verilog("i"));
313 pw.println("`define instruction_is_decr_loop(i) "+SET_OLC_FROM_OLC_MINUS_ONE.verilog("i"));
315 pw.println("`define instruction_bit_tokenout(i) (`instruction_is_normal(i) && "+TO.verilog("i")+")");
316 pw.println("`define instruction_bit_dataout(i) (`instruction_is_normal(i) && "+DO.verilog("i")+")");
317 pw.println("`define instruction_bit_latch(i) (`instruction_is_normal(i) && "+DC.verilog("i")+")");
318 pw.println("`define instruction_bit_datain(i) (`instruction_is_normal(i) && "+DI.verilog("i")+")");
319 pw.println("`define instruction_bit_tokenin(i) (`instruction_is_normal(i) && "+TI.verilog("i")+")");
320 pw.println("`define should_requeue(i) (loop_counter!=0 && !("+OS.verilog("i")+"))");
321 pw.println("`define predicate_met(i) ("+
323 "!`instruction_is_normal(i) || repeat_counter!=0"+
325 P_OLC_ZERO.verilog("i")+"==(loop_counter==0)"+
327 " " + P_A.verilog("i")+" ? flag_a"+
328 ":" + P_B.verilog("i")+" ? flag_b"+
329 ":" + P_NOT_A.verilog("i")+" ? !flag_a"+
330 ":" + P_NOT_B.verilog("i")+" ? !flag_b "+
334 pw.println("`define new_flag(x) ("+
335 "( ((x >> 0) & 1) & !flag_c) |" +
336 "( ((x >> 1) & 1) & flag_c) |" +
337 "( ((x >> 2) & 1) & !flag_b) |" +
338 "( ((x >> 3) & 1) & flag_b) |" +
339 "( ((x >> 4) & 1) & !flag_a) |" +
340 "( ((x >> 5) & 1) & flag_a) | 0" +
342 pw.println("`define new_flag_a(i) `new_flag("+SET_FLAGS_A.verilogVal("i")+")");
343 pw.println("`define new_flag_b(i) `new_flag("+SET_FLAGS_B.verilogVal("i")+")");
344 pw.println("`define done_executing(i) (repeat_counter==0 || repeat_counter==1 || !`instruction_is_normal(i))");
346 pw.println("`define magic_standing_value (1<<"+SET_ILC_FROM_IMMEDIATE.valmaskwidth+")");