massive overhaul of fpga code
[fleet.git] / src / edu / berkeley / fleet / fpga / FpgaDock.java
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.*;
10 import java.util.*;
11 import java.io.*;
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.*;
17 import java.util.*;
18
19 public class FpgaDock extends FleetTwoDock implements FabricElement {
20
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;
24         
25     private FpgaDestination dataDestination;
26     private FpgaDestination instructionDestination;
27
28     private Module.InstantiatedModule instance;
29
30     public Module.InstantiatedModule getInstance() { return instance; }
31
32     private Fpga fpga;
33
34     public Destination getDataDestination() { return dataDestination; }
35     public Destination getInstructionDestination() { return instructionDestination; }
36     public int         getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
37
38     FpgaDock(FpgaShip ship, DockDescription bbd) {
39         super(ship, 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();            
45         if (isInputDock()) {
46             instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
47         } else {
48             shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
49         }
50     }
51
52
53     // FabricElement methods //////////////////////////////////////////////////////////////////////////////
54
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) {
62         this.upstream = out;
63         instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
64     }
65
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);
73
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 });
80
81             out.connectValue(in.getBits(fpga.PACKET_DATA));
82         }
83     }
84
85     public class RequeueModule extends Module {
86         public RequeueModule() {
87             super("requeue");
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 flag_z    = createInputPort ("flag_z",     1);
91             Module.SinkPort   out       = createOutputPort("out",        fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
92
93             Module.StateWire  using         = new StateWire("using", false);
94             Module.StateWire  circulating   = new StateWire("circulating", false);
95             Module.StateWire  doResetFabric = new StateWire("doResetFabric", false);
96             Module.StateWire  doResetOndeck = new StateWire("doResetOndeck", false);
97
98             out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
99
100             // always: discard one-shot instructions
101             new Event(new Object[] { ondeck_in, fpga.OS.verilog(ondeck_in.getName()) },
102                       new Action[] { ondeck_in, });
103
104             new Event(new Object[] { doResetFabric.isFull(),  out },
105                       new Action[] { doResetFabric.doDrain(), fabric_in });
106             new Event(new Object[] { doResetOndeck.isFull(),  out },
107                       new Action[] { doResetOndeck.doDrain(), ondeck_in });
108
109             new Event(new Object[] { circulating.isEmpty(),                  fabric_in, fpga.TAIL.verilog(fabric_in.getName()) },
110                       new Action[] { circulating.doFill(),                   fabric_in });
111             new Event(new Object[] { circulating.isEmpty(),                  fabric_in, "!("+fpga.TAIL.verilog(fabric_in.getName())+")", doResetFabric.isEmpty() },
112                       new Action[] {                                         out, doResetFabric.doFill() });
113             new Event(new Object[] { using.isEmpty(),                        ondeck_in, "!("+fpga.OS.verilog(ondeck_in.getName())+")", "flag_z" },
114                       new Action[] {                                         ondeck_in, });
115             new Event(new Object[] { using.isEmpty(),                        ondeck_in, "!("+fpga.OS.verilog(ondeck_in.getName())+")", "!flag_z" },
116                       new Action[] { using.doFill() });
117             new Event(new Object[] { circulating.isFull(),  using.isFull(),  ondeck_in, "!("+fpga.OS.verilog(ondeck_in.getName())+")", "flag_z" },
118                       new Action[] { circulating.doDrain(), using.doDrain(), ondeck_in, });
119             new Event(new Object[] { circulating.isFull(),  using.isFull(),  ondeck_in, "!("+fpga.OS.verilog(ondeck_in.getName())+")", "!flag_z", doResetOndeck.isEmpty() },
120                       new Action[] {                                         out, doResetOndeck.doFill() });
121
122         }
123     }
124
125     public class DockModule extends Module {
126
127         public DockModule(boolean inbox) {
128             super(inbox ? "inbox" : "outbox");
129
130             int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
131
132             // FIXME: assumes fpga.DISPATCH_PATH is at top of word!!!
133             Module ififo_m   = new FifoModule(INSTRUCTION_FIFO_SIZE, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
134             Module dfifo_m   = new FifoModule(DATA_FIFO_SIZE,        dfifo_width);
135
136             Module.SourcePort instruction   = createInputPort("instruction", fpga.WIDTH_PACKET);
137             Module.SourcePort fabric_in     = createInputPort("fabric_in",   fpga.WIDTH_PACKET);
138
139             // FIXME: at inboxes, no need for a full set of latches
140             Module.SinkPort   fabric_out    = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
141             
142             Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
143
144             fabric_in.connect(dfifo.getInputPort("in"));
145             dfifo.getInputPort("in").connectValue(
146                 !inbox
147                 ? fabric_in.getBits(fpga.PACKET_SIGNAL)
148                 : new CatValue(new Value[] {
149                         fabric_in.getBits(fpga.PACKET_SIGNAL),
150                         fabric_in.getBits(fpga.PACKET_DATA)
151                     }));
152         
153             Module.SourcePort dfifo_out     = dfifo.getOutputPort("out");
154             Module.SourcePort ship_out      = !inbox ? createInputPort("ship",  fpga.getWordWidth()+1) : null;
155             Module.SinkPort   ship_in       =  inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null;
156
157             Module.Latch     ilc            = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
158             Module.Latch     olc            = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
159             Module.Latch     flag_a         = new Latch("flag_a", 1);
160             Module.Latch     flag_b         = new Latch("flag_b", 1);
161             Module.Latch     flag_c         = new Latch("flag_c", 1);
162             Module.Latch     flag_z         = new Latch("flag_z", 1);
163
164             Module.SinkPort   token_out     = fabric_out;
165             Module.SourcePort token_in      = dfifo_out;
166             Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
167             Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
168
169             Module.InstantiatedModule ififo = new Module.InstantiatedModule(this, ififo_m);
170             Module.SinkPort   ififo_in      = ififo.getInputPort("in");
171             Module.SourcePort ififo_out     = ififo.getOutputPort("out");
172
173             Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
174             instruction.connect(torpedo_branch.getInputPort("in"));
175             Module.SourcePort efifo_out              = torpedo_branch.getOutputPort("out");
176             Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
177
178             Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth));
179             Module.SinkPort   fanout_module_in   = fanout_module.getInputPort("in");
180             Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
181             Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
182
183             Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
184             Module.SinkPort   requeue_fabric_in = requeue_module.getInputPort("fabric_in");
185             Module.SinkPort   requeue_ondeck    = requeue_module.getInputPort("ondeck_in");
186             Module.SinkPort   requeue_flag_z    = requeue_module.getInputPort("flag_z");
187             Module.SourcePort requeue_out       = requeue_module.getOutputPort("out");
188
189             efifo_out.connect(requeue_fabric_in);
190             requeue_out.connect(ififo_in);
191             ififo_out.connect(fanout_module_in);
192             fanout_module_out0.connect(requeue_ondeck);
193             Module.SourcePort ondeck = fanout_module_out1;
194
195             WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width),
196                                                   new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+
197                                                                   " ? {1'b0, olc} : ilc)-1"));
198             WireValue data_latch_output_p = new WireValue("data_latch_output",
199                                                            inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(),
200                                                            (inbox
201                                                             ? new SimpleValue(data_out.getName())
202                                                             : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
203                                                           );
204             requeue_flag_z.connectValue(new SimpleValue("(olc==0)"));
205
206             Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog());
207             Module.SourcePort  data_latch_input = inbox ? data_in : data_in;
208
209             BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1);
210             bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true);
211             Value magic_standing_value = new ConstantValue(bv);
212
213             Trigger done_executing       = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
214
215             String predicate_met = 
216                 "("+
217                 "("+
218                 "!"+fpga.MOVE.verilog(ondeck.getName())+" || (ilc!=0)"+
219                 ") && ("+
220                 "("+
221                 fpga.P_ALWAYS.verilog(ondeck.getName())+
222                 ") || ("+
223                 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_z"+
224                 ")"+
225                 ") && ("+
226                 " " + fpga.P_A.verilog(ondeck.getName())+" ? flag_a"+
227                 ":" + fpga.P_B.verilog(ondeck.getName())+" ? flag_b"+
228                 ":" + fpga.P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
229                 ":" + fpga.P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
230                 ": 1"+
231                 ")"+
232                 ")";
233
234             // Torpedo strikes
235             new Event(new Object[] {
236                     ondeck,
237                     data_out,
238                     token_out,
239                     predicate_met,
240                     fpga.MOVE.verilog(ondeck.getName()),
241                     "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
242                     torpedo_branch_torpedo
243                 },
244                 new Object[] {
245                     ondeck,
246                     torpedo_branch_torpedo,
247                     new AssignAction(olc,    new ConstantValue(new BitVector(olc.width).set(0))),
248                     new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0))),
249                     new AssignAction(ilc,    new ConstantValue(new BitVector(ilc.width).set(1)))
250                 });
251
252             // Predicate not met
253             new Event(new Object[] { ondeck, "!("+predicate_met+")" },
254                       new Action[] { ondeck,
255                                      new ConditionalAction(ondeck.testMask(fpga.MOVE),
256                                                            new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))))
257                       });
258
259             new Event(new Object[] { ondeck,
260                                      data_out,
261                                      token_out,
262                                      predicate_met,
263                                      "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")",
264                                      new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in),
265                                      new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in)
266                       },
267                       new Action[] { 
268                           new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)),
269                                                 new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))),
270                           new ConditionalAction(done_executing, ondeck),
271                           new ConditionalAction(done_executing.invert(),
272                                                 new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value),
273                                                                                    magic_standing_value,
274                                                                                    decremented))),
275                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
276                                                 new AssignAction(olc, new SimpleValue("data_latch_output"))),
277                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
278                                                 new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))),
279                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
280                                                 new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))),
281
282                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
283                                                 new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
284                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
285                                                 new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
286                           new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
287                                                 new AssignAction(flag_z, new SimpleValue("(olc==0 || olc==1)"))),
288
289                           new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
290                                                 new AssignAction(ilc, new SimpleValue("data_latch_output"))),
291
292                           new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE),
293                                                 new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))),
294                           new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY),
295                                                 new AssignAction(ilc, magic_standing_value)),
296                           new ConditionalAction(ondeck.testMask(fpga.SHIFT),
297                                                 new AssignAction(data_latch,
298                                                                  new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
299                                                                                  ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))),
300                           new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE),
301                                                 new AssignAction(data_latch,
302                                                                  new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
303                                                                                  "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+
304                                                                                  ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))),
305                           new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
306                                                 new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))),
307                           new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
308                                                 new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))),
309                           new ConditionalAction(inbox
310                                                 ? new OrTrigger(ondeck.testMask(fpga.DI), ondeck.testMask(fpga.TI))
311                                                 : new AndTrigger(ondeck.testMask(fpga.DI).invert(), ondeck.testMask(fpga.TI)),
312                                                 new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))),
313                           new ConditionalAction(ondeck.testMask(fpga.DI),    data_in),
314                           new ConditionalAction(ondeck.testMask(fpga.DO),    data_out),
315                           new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out),
316                           inbox
317                           ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
318                           : new ConditionalAction(ondeck.testMask(fpga.DI),   new AssignAction(flag_c, new SimpleValue(data_latch_input.getVerilog()+"["+fpga.getWordWidth()+"]"))),
319                           new ConditionalAction(ondeck.testMask(fpga.TI),    token_in),
320                           new ConditionalAction(ondeck.testMask(fpga.TO),    token_out),
321                           new ConditionalAction(ondeck.testMask(fpga.DC),   new AssignAction(data_latch, data_latch_input)),
322                           new AssignAction(token_out.getBits(fpga.PACKET_TOKEN),
323                                            new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")),
324                           new ConditionalAction(ondeck.testMask(fpga.PATH_DATA),
325                                                 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
326                                                                                       token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
327                                                                  data_latch_input.getBits(fpga.DISPATCH_PATH))),
328                           new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE),
329                                                 new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
330                                                                                       token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
331                                                                  ondeck.getBits(fpga.PATH_IMMEDIATE)))
332                       }
333                 );
334         }
335
336         private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) {
337             Value[] vals = new Value[] {
338                 new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()),
339                 new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c),
340                 new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()),
341                 new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b),
342                 new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()),
343                 new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a),
344             };
345             Value ret = new ConstantValue(new BitVector(1).set(0));
346             for(int i=0; i<vals.length; i++)
347                 ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);
348             return ret;
349         }
350     }
351 }
352