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 = ("+SET_OLC_FROM_OLC_MINUS_ONE.verilog("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"),
179 I.verilog("ondeck") },
180 new Action[] { instruction,
182 new AssignAction(loop_counter, "0"),
183 new AssignAction(repeat_counter, "1"),
184 isHatchOpen.doFill() });
185 // Non-Torpedo Arrival
186 new Event(new Object[] { instruction, efifo_in, "!("+PACKET_TOKEN.verilogVal("instruction")+")" },
187 new Action[] { efifo_in });
188 new Event(new Object[] { efifo_in.getName()+"_a" },
189 new Action[] { new SimpleAction(instruction.getName()+"_a <= 1;") });
192 new Event(new Object[] { efifo_out, ififo_in, isHatchOpen.isFull(), TAIL.verilog(efifo_out.getName()) },
193 new Action[] { efifo_out, isHatchOpen.doDrain() } );
195 new Event(new Object[] { efifo_out, ififo_in, isHatchOpen.isFull(), "!("+TAIL.verilog(efifo_out.getName())+")" },
196 new Action[] { efifo_out, ififo_in } );
199 new Event(new Object[] { ififo_out, ififo_in, proceed.isFull() },
200 new Action[] { ififo_out, proceed.doDrain() });
202 new Object[] { ififo_out,
207 "(!`predicate_met(ondeck) || "+OS.verilog("ondeck")+" || !hatch)",
208 new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_datain(ondeck))", data_in),
209 new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck))", token_in)
212 new ConditionalAction(" `done_executing(ondeck) && "+MOVE.verilog("ondeck"), new AssignAction(repeat_counter, "1")),
213 new ConditionalAction("!`should_requeue(ondeck) && `done_executing(ondeck)", ififo_out),
214 new ConditionalAction(" `should_requeue(ondeck) && `done_executing(ondeck)", ififo_in),
215 new ConditionalAction(" `should_requeue(ondeck) && `done_executing(ondeck)", proceed.doFill()),
216 new ConditionalAction("!`done_executing(ondeck)",
217 new AssignAction(repeat_counter,
218 "repeat_counter==`magic_standing_value?`magic_standing_value:decremented"))
221 new Object[] { ififo_out,
226 "`predicate_met(ondeck)",
227 "("+OS.verilog("ondeck")+" || !hatch)",
228 new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in),
229 new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in)
232 new ConditionalAction(SET_OLC_FROM_DATA_LATCH.verilog("ondeck"), new AssignAction(loop_counter, "data_latch_output")),
233 new ConditionalAction(SET_OLC_FROM_IMMEDIATE.verilog("ondeck"),
234 new AssignAction(loop_counter, SET_OLC_FROM_IMMEDIATE.verilogVal("ondeck"))),
235 new ConditionalAction(SET_OLC_FROM_OLC_MINUS_ONE.verilog("ondeck"),
236 new AssignAction(loop_counter, "loop_counter==0 ? 0 : decremented")),
237 new ConditionalAction(SET_ILC_FROM_DATA_LATCH.verilog("ondeck"), new AssignAction(repeat_counter, "data_latch_output")),
238 new ConditionalAction(SET_ILC_FROM_IMMEDIATE.verilog("ondeck"),
239 new AssignAction(repeat_counter, SET_ILC_FROM_IMMEDIATE.verilogVal("ondeck"))),
240 new ConditionalAction(SET_ILC_FROM_INFINITY.verilog("ondeck"), new AssignAction(repeat_counter, "`magic_standing_value")),
241 new ConditionalAction(SHIFT.verilog("ondeck"),
242 new AssignAction(data_latch,
243 "{ data_latch_output["+(WIDTH_WORD-1-SHIFT.valmaskwidth)+":0], "+
244 SHIFT.verilogVal("ondeck")+"}")),
245 new ConditionalAction(SET_IMMEDIATE.verilog("ondeck"),
246 new AssignAction(data_latch,
247 "{ {"+(WIDTH_WORD-FleetTwoFleet.DataLatch_WIDTH)+
248 "{"+SET_IMMEDIATE_EXTEND.verilogVal("ondeck")+"}}, "+
249 SET_IMMEDIATE.verilogVal("ondeck")+" }")),
250 new ConditionalAction(SET_FLAGS.verilog("ondeck"), new AssignAction(flag_a, "`new_flag_a(ondeck)")),
251 new ConditionalAction(SET_FLAGS.verilog("ondeck"), new AssignAction(flag_b, "`new_flag_b(ondeck)")),
252 new ConditionalAction(inbox
253 ? "(`instruction_bit_datain(ondeck) || `instruction_bit_tokenin(ondeck))"
254 : "(!`instruction_bit_datain(ondeck) && `instruction_bit_tokenin(ondeck))",
255 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))),
256 inbox?null:new ConditionalAction("`instruction_bit_datain(ondeck)", new AssignAction(flag_c, "data_latch_input["+WIDTH_WORD+"]")),
257 new ConditionalAction("`instruction_bit_datain(ondeck)", data_in),
258 new ConditionalAction("`instruction_bit_dataout(ondeck)", data_out),
259 new ConditionalAction("`instruction_bit_tokenin(ondeck)", token_in),
260 new ConditionalAction("`instruction_bit_tokenout(ondeck)", token_out),
261 new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)),
262 new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"), "`instruction_bit_tokenout(ondeck)?1:0"),
263 new ConditionalAction("`instruction_path_from_data(ondeck)",
264 new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
265 DISPATCH_PATH.verilogVal(data_latch_input))),
266 new ConditionalAction("`instruction_path_from_immediate(ondeck)",
267 new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"),
268 "`instruction_path_immediate(ondeck)")),
274 public void dump(PrintWriter pw, boolean fix) {
276 pw.println("`define packet_signal_and_dest(p) { "+PACKET_SIGNAL.verilogVal("p")+", "+PACKET_DEST.verilogVal("p")+" }");
277 pw.println("`define instruction_repeat_count_immediate(i) "+SET_ILC_FROM_IMMEDIATE.verilogVal("i"));
278 pw.println("`define instruction_loop_count_immediate(i) "+SET_OLC_FROM_IMMEDIATE.verilogVal("i"));
280 pw.println("`define instruction_path_immediate(i) "+PATH_IMMEDIATE.verilogVal("i"));
281 pw.println("`define instruction_path_from_immediate(i) "+PATH_IMMEDIATE.verilog("i"));
282 pw.println("`define instruction_path_from_data(i) "+PATH_DATA.verilog("i"));
284 pw.println("`define instruction_bit_tokenout(i) ("+MOVE.verilog("i")+" && "+TO.verilog("i")+")");
285 pw.println("`define instruction_bit_dataout(i) ("+MOVE.verilog("i")+" && "+DO.verilog("i")+")");
286 pw.println("`define instruction_bit_latch(i) ("+MOVE.verilog("i")+" && "+DC.verilog("i")+")");
287 pw.println("`define instruction_bit_datain(i) ("+MOVE.verilog("i")+" && "+DI.verilog("i")+")");
288 pw.println("`define instruction_bit_tokenin(i) ("+MOVE.verilog("i")+" && "+TI.verilog("i")+")");
289 pw.println("`define should_requeue(i) (loop_counter!=0 && !("+OS.verilog("i")+"))");
290 pw.println("`define predicate_met(i) ("+
292 "!"+MOVE.verilog("i")+" || repeat_counter!=0"+
295 P_ALWAYS.verilog("i")+
297 P_OLC_ZERO.verilog("i")+"==(loop_counter==0)"+
300 " " + P_A.verilog("i")+" ? flag_a"+
301 ":" + P_B.verilog("i")+" ? flag_b"+
302 ":" + P_NOT_A.verilog("i")+" ? !flag_a"+
303 ":" + P_NOT_B.verilog("i")+" ? !flag_b "+
307 pw.println("`define new_flag(x) ("+
308 "( ((x >> 0) & 1) & !flag_c) |" +
309 "( ((x >> 1) & 1) & flag_c) |" +
310 "( ((x >> 2) & 1) & !flag_b) |" +
311 "( ((x >> 3) & 1) & flag_b) |" +
312 "( ((x >> 4) & 1) & !flag_a) |" +
313 "( ((x >> 5) & 1) & flag_a) | 0" +
315 pw.println("`define new_flag_a(i) `new_flag("+SET_FLAGS_A.verilogVal("i")+")");
316 pw.println("`define new_flag_b(i) `new_flag("+SET_FLAGS_B.verilogVal("i")+")");
317 pw.println("`define done_executing(i) (repeat_counter==0 || repeat_counter==1 || !"+MOVE.verilog("i")+")");
319 pw.println("`define magic_standing_value (1<<"+SET_ILC_FROM_IMMEDIATE.valmaskwidth+")");