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 int doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, HashSet<Dock> sendTorpedoesTo, boolean peerUsed) {
20 if (dock.getShip().getType().equals("Debug")) return ret;
24 // Phase 0: torpedo every output dock, put it in
25 // collecting mode. Cannot combine with phase 1,
26 // because until output docks are in vacuum mode we
27 // cannot be sure that the tokens to the input docks
28 // will eventually succeed. This may cause the
29 // instructions sent after the tokens to back up into
32 if (!dock.isInputDock()) {
33 sendTorpedoesTo.add(dock);
34 LoopFactory lf = new LoopFactory(ctx, dock, 1);
35 lf.sendToken(ackDestination);
37 lf.abortLoopIfTorpedoPresent();
44 // Phase 1: torpedo every input dock, put it in loopback mode
46 if (dock.isInputDock()) {
47 sendTorpedoesTo.add(dock);
48 LoopFactory lf = new LoopFactory(ctx, dock, 1);
49 lf.sendToken(ackDestination);
51 // FIXME: this won't work right for ports that
52 // get "shared" by two senders (for example,
55 if (peerUsed && peer!=null) {
57 lf.abortLoopIfTorpedoPresent();
58 ((OutPort)peer).recvWord(lf);
59 ((OutPort)peer).sendToken(lf);
66 // Phase 2: torpedo every output dock, have it absorb tokens
68 if (!dock.isInputDock()) {
69 sendTorpedoesTo.add(dock);
70 LoopFactory lf = new LoopFactory(ctx, dock, 1);
72 for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
74 lf.sendToken(ackDestination);
80 // Phase 3: torpedo every input dock, and we're done
82 if (dock.isInputDock()) {
83 if (peerUsed && peer!=null) {
84 sendTorpedoesTo.add(dock);
86 LoopFactory lf = new LoopFactory(ctx, dock, 1);
87 lf.sendToken(ackDestination);
96 public final DataFlowGraph dfg;
97 public Node(DataFlowGraph dfg) {
102 private HashMap<String,Port> ports = new HashMap<String,Port>();
104 public InPort getInPort(String name) { return (InPort)ports.get(name); }
105 public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
107 public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
108 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
110 for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination, sendTorpedoesTo);
114 public abstract class Port {
115 public final String name;
116 public Port(String name) {
118 if (Node.this.ports.get(name)!=null) throw new RuntimeException();
119 Node.this.ports.put(name,this);
121 public abstract void build(Context ctx);
122 public abstract int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo);
125 public abstract class InPort extends Port {
127 public InPort(String name) { super(name); }
128 public void connect(OutPort peer) {
132 public void setPeer(OutPort peer) {
133 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
137 /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
138 public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
139 /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
140 public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
142 public int getTokensToAbsorb() { return 0; }
145 public abstract class OutPort extends Port {
147 public OutPort(String name) { super(name); }
148 public void connect(InPort peer) {
152 public void setPeer(InPort peer) {
153 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
157 /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
158 public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
159 /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
160 public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
163 public final class DockInPort extends InPort {
167 public DockInPort(String name, Dock dock) { this(name, dock, 0); }
168 public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
169 public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
173 this.pattern = pattern;
175 public void recvToken(LoopFactory lf) { lf.recvToken(); }
176 public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
177 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
178 // number-in-flight is considered a property of the input dock in a pair
179 public int getInflight() { return 4; }
180 //public int getInflight() { return 1; }
181 public int getTokensToAbsorb() { return getInflight(); }
182 private boolean peerUsed() {
183 if (peer==null) return false;
184 for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
187 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
188 return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, peerUsed());
190 protected void build(Context ctx, LoopFactory lf) {
191 int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
194 for(int i=0; i<inflight; i++) peer.sendToken(lf);
196 lf = lf.makeNext(count, true);
197 for(int i=0; i<pattern.length; i++) {
198 if (pattern[i]==null) {
200 lf.abortLoopIfTorpedoPresent();
205 lf.interruptibleNop();
208 lf.literal(pattern[i]);
209 lf.abortLoopIfTorpedoPresent();
215 // "torpedoable nop" to keep the dock in a receptive state
216 lf.abortLoopIfTorpedoPresent();
220 public BitVector getConstant(String constantName) {
221 return dock.getConstant(constantName);
225 public /*final*/ class DockOutPort extends OutPort {
226 public final Dock dock;
227 public final int count;
228 public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
229 public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
230 public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
231 public void recvWord(LoopFactory lf) { lf.recvWord(); }
232 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
233 protected void build(Context ctx, LoopFactory lf) {
234 if (peer==null) return;
235 lf = lf.makeNext(count);
236 lf.abortLoopIfTorpedoPresent();
241 public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
242 return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, true);
246 BitVector bv(long l) { return new BitVector(dfg.fleet.getWordWidth()).set(l); }
247 BitVector[] bv(long[] l) {
248 BitVector[] ret = new BitVector[l.length];
249 for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);