b06bc68a0c50adde45e8c655d860ffc0f1f2d06b
[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
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;
27
28     //private static final int DATA_FIFO_SIZE        = 4;
29     static final int DATA_FIFO_SIZE        = 8;
30         
31     private FpgaDestination dataDestination;
32     private FpgaDestination instructionDestination;
33
34     private Module.InstantiatedModule instance;
35
36     public Module.InstantiatedModule getInstance() { return instance; }
37
38     private Fpga fpga;
39
40     public Destination getDataDestination() { return dataDestination; }
41     public Destination getInstructionDestination() { return instructionDestination; }
42     public int         getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
43
44     FpgaDock(FpgaShip ship, DockDescription bbd) {
45         super(ship, 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();            
51         if (isInputDock()) {
52             instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
53         } else {
54             shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
55         }
56     }
57
58
59     // FabricElement methods //////////////////////////////////////////////////////////////////////////////
60
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) {
69         this.upstream = out;
70         instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
71     }
72
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);
80
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 });
87
88             out.connectValue(in.getBits(fpga.PACKET_DATA));
89         }
90     }
91
92     public class RequeueModule extends Module {
93         public RequeueModule() {
94             super("requeue");
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);
99
100             Module.StateWire  circulating   = new StateWire("circulating", false);
101             Module.StateWire  doResetFabric = new StateWire("doResetFabric", false);
102             Module.StateWire  doResetOndeck = new StateWire("doResetOndeck", false);
103
104             out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
105
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 });
111
112             // Updating->Circulating transition
113             new Event(new Object[] { doResetFabric.isEmpty(),
114                                      doResetOndeck.isEmpty(),
115                                      circulating.isEmpty(),
116                                      fabric_in,
117                                      fpga.TAIL.verilog(fabric_in.getName()),
118                                      ondeck_in,
119                                      fpga.HEAD.verilog(ondeck_in.getName()) },
120                       new Action[] { circulating.doFill(),
121                                      fabric_in,
122                                      ondeck_in });
123
124             // Circulating->Updating transition
125             new Event(new Object[] { doResetFabric.isEmpty(),
126                                      doResetOndeck.isEmpty(),
127                                      circulating.isFull(),
128                                      ondeck_in,
129                                      abort.getVerilog() },
130                       new Action[] { circulating.doDrain(),
131                                      ondeck_in });
132
133             // Updating
134             new Event(new Object[] { doResetFabric.isEmpty(),
135                                      doResetOndeck.isEmpty(),
136                                      circulating.isEmpty(),
137                                      fabric_in,
138                                      "!"+fpga.TAIL.verilog(fabric_in.getName()) },
139                       new Action[] { doResetFabric.doFill(),
140                                      out });
141             new Event(new Object[] { doResetFabric.isEmpty(),
142                                      doResetOndeck.isEmpty(),
143                                      circulating.isEmpty(),
144                                      ondeck_in,
145                                      "!"+fpga.HEAD.verilog(ondeck_in.getName()) },
146                       new Action[] { ondeck_in });
147                                      
148             // Circulating
149             new Event(new Object[] { doResetFabric.isEmpty(),
150                                      doResetOndeck.isEmpty(),
151                                      circulating.isFull(),
152                                      ondeck_in,
153                                      "!"+abort.getVerilog() },
154                       new Action[] { doResetOndeck.doFill(),
155                                      out });
156         }
157     }
158
159     public class DockModule extends Module {
160
161         public DockModule(boolean inbox) {
162             super(inbox ? "inbox" : "outbox");
163
164             int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
165
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);
170
171             Module dfifo_m   = new FifoModule(DATA_FIFO_SIZE,        dfifo_width);
172
173             Module.SourcePort instruction   = createInputPort("instruction", fpga.WIDTH_PACKET);
174             Module.SourcePort fabric_in     = createInputPort("fabric_in",   fpga.WIDTH_PACKET);
175
176             // FIXME: at inboxes, no need for a full set of latches
177             Module.SinkPort   fabric_out    = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
178             
179             Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
180
181             fabric_in.connect(dfifo.getInputPort("in"));
182             dfifo.getInputPort("in").connectValue(
183                 !inbox
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)
188                     }));
189         
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;
193
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);
200
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;
205
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");
212
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");
217
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");
222
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");
228
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;
234
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(),
240                                                            (inbox
241                                                             ? new SimpleValue(data_out.getName())
242                                                             : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
243                                                           );
244
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;
247
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);
251
252             Trigger done_executing       = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
253
254             String predicate_met = 
255                 "("+
256                 "("+
257                 "!"+fpga.MOVE.verilog(ondeck.getName())+" || (ilc!=0)"+
258                 ") && ("+
259                 "("+
260                 fpga.P_ALWAYS.verilog(ondeck.getName())+
261                 ") || ("+
262                 fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_d"+
263                 ")"+
264                 ") && ("+
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 "+
269                 ": 1"+
270                 ")"+
271                 ")";
272
273             requeue_abort.connectValue(new SimpleValue("("+predicate_met+") && "+fpga.ABORT.verilog(ondeck.getName())));
274
275             // Torpedo strikes
276             new Event(new Object[] {
277                     ondeck,
278                     data_out,
279                     token_out,
280                     predicate_met,
281                     fpga.MOVE.verilog(ondeck.getName()),
282                     "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
283                     torpedo_branch_torpedo
284                 },
285                 new Object[] {
286                     ondeck,
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)))
291                 });
292
293             // Predicate not met
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))))
298                       });
299
300             new Event(new Object[] { ondeck,
301                                      data_out,
302                                      token_out,
303                                      predicate_met,
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)
307                       },
308                       new Action[] { 
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,
315                                                                                    decremented))),
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"))),
322
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)"))),
329
330                           new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
331                                                 new AssignAction(ilc, new SimpleValue("data_latch_output"))),
332
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,
352                                                                  inbox
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))
357                                                                  )),
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),
361                           inbox
362                           ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"),
363                                              new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
364                           : null,
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)))
378                       }
379                 );
380         }
381
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),
390             };
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]);
394             return ret;
395         }
396     }
397 }
398