1 package edu.berkeley.fleet.dataflow;
3 import edu.berkeley.fleet.loops.*;
4 import java.util.concurrent.Semaphore;
7 import edu.berkeley.fleet.two.*;
8 import edu.berkeley.fleet.api.*;
9 import edu.berkeley.fleet.fpga.*;
10 import edu.berkeley.fleet.api.Instruction.*;
11 import edu.berkeley.fleet.api.Instruction.Set;
12 import edu.berkeley.fleet.api.Instruction.Set.*;
13 import static edu.berkeley.fleet.api.Predicate.*;
14 import static edu.berkeley.fleet.util.BitManipulations.*;
18 public final DataFlowGraph dfg;
19 public Node(DataFlowGraph dfg) {
24 private HashMap<String,Port> ports = new HashMap<String,Port>();
25 public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
26 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
28 for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination, sendTorpedoesTo);
32 public abstract class Port {
33 public final String name;
34 public Port(String name) {
36 if (Node.this.ports.get(name)!=null) throw new RuntimeException();
37 Node.this.ports.put(name,this);
39 public abstract void build(Context ctx);
40 public abstract int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo);
41 public String toString() { return Node.this+"."+name; }
44 public abstract class InPort extends Port {
46 public InPort(String name) { super(name); }
47 public void connect(OutPort peer) {
51 public void setPeer(OutPort peer) {
52 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
56 /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
57 public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
58 /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
59 public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
61 public int getTokensToAbsorb() { return 0; }
64 public abstract class OutPort extends Port {
66 public OutPort(String name) { super(name); }
67 public void connect(InPort peer) {
71 public void setPeer(InPort peer) {
72 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
76 /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
77 public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
78 /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
79 public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
82 public final class DockInPort extends InPort {
86 public DockInPort(String name, Dock dock) { this(name, dock, 0); }
87 public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
88 public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
92 this.pattern = pattern;
94 public void recvToken(LoopFactory lf) { lf.recvToken(); }
95 public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
96 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
97 // number-in-flight is considered a property of the input dock in a pair
98 public int getInflight() { return 4; }
99 //public int getInflight() { return 1; }
100 public int getTokensToAbsorb() { return getInflight(); }
101 private boolean peerUsed() {
102 if (peer==null) return false;
103 for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
106 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
107 return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, peerUsed());
109 protected void build(Context ctx, LoopFactory lf) {
110 int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
113 for(int i=0; i<inflight; i++) peer.sendToken(lf);
115 lf = lf.makeNext(count, true);
116 for(int i=0; i<pattern.length; i++) {
117 if (pattern[i]==null) {
119 lf.abortLoopIfTorpedoPresent();
124 lf.interruptibleNop();
127 lf.literal(pattern[i]);
128 lf.abortLoopIfTorpedoPresent();
134 // "torpedoable nop" to keep the dock in a receptive state
135 lf.abortLoopIfTorpedoPresent();
139 public BitVector getConstant(String constantName) {
140 return dock.getConstant(constantName);
144 public /*final*/ class DockOutPort extends OutPort {
145 public final Dock dock;
146 public final int count;
147 public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
148 public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
149 public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
150 public void recvWord(LoopFactory lf) { lf.recvWord(); }
151 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
152 protected void build(Context ctx, LoopFactory lf) {
153 if (peer==null) return;
154 lf = lf.makeNext(count);
155 lf.abortLoopIfTorpedoPresent();
160 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
161 return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, true);
165 BitVector bv(long l) { return new BitVector(dfg.fleet.getWordWidth()).set(l); }
166 BitVector[] bv(long[] l) {
167 BitVector[] ret = new BitVector[l.length];
168 for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);
172 // Reset //////////////////////////////////////////////////////////////////////////////
174 int doReset(Context ctx,
178 Destination ackDestination,
179 HashSet<Dock> sendTorpedoesTo,
182 if (dock.getShip().getType().equals("Debug")) return ret;
186 // Phase 0: torpedo every output dock, put it in
187 // collecting mode. Cannot combine with phase 1,
188 // because until output docks are in vacuum mode we
189 // cannot be sure that the tokens to the input docks
190 // will eventually succeed. This may cause the
191 // instructions sent after the tokens to back up into
192 // the switch fabric.
194 if (!dock.isInputDock()) {
195 sendTorpedoesTo.add(dock);
196 LoopFactory lf = new LoopFactory(ctx, dock, 1);
197 lf.sendToken(ackDestination);
199 lf.abortLoopIfTorpedoPresent();
206 // [wait for all output docks to confirm that they've been torpedoed]
207 // Phase 1: torpedo every input dock (causing them to flush), put it in loopback mode
209 if (dock.isInputDock()) {
210 sendTorpedoesTo.add(dock);
211 LoopFactory lf = new LoopFactory(ctx, dock, 1);
212 lf.sendToken(ackDestination);
214 // FIXME: this won't work right for ports that
215 // get "shared" by two senders (for example,
218 if (peerUsed && peer!=null) {
220 lf.abortLoopIfTorpedoPresent();
221 ((OutPort)peer).recvWord(lf);
222 ((OutPort)peer).sendToken(lf);
229 // [wait for all input docks to confirm that they've been torpedoed and have flushed]
230 // Phase 2: torpedo every output dock, have it absorb tokens
232 if (!dock.isInputDock()) {
233 sendTorpedoesTo.add(dock);
234 LoopFactory lf = new LoopFactory(ctx, dock, 1);
236 for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
238 lf.sendToken(ackDestination);
244 // [wait for all output docks to confirm that they've absorbed enough tokens]
245 // Phase 3: torpedo every input dock, await confirmation, and we're done
247 if (dock.isInputDock()) {
248 if (peerUsed && peer!=null) {
249 sendTorpedoesTo.add(dock);
251 LoopFactory lf = new LoopFactory(ctx, dock, 1);
252 lf.sendToken(ackDestination);