1 package edu.berkeley.fleet.dataflow;
2 import edu.berkeley.fleet.loops.*;
3 import java.util.concurrent.Semaphore;
6 import edu.berkeley.fleet.two.*;
7 import edu.berkeley.fleet.api.*;
8 import edu.berkeley.fleet.fpga.*;
9 import edu.berkeley.fleet.api.Instruction.*;
10 import edu.berkeley.fleet.api.Instruction.Set;
11 import edu.berkeley.fleet.api.Instruction.Set.*;
12 import static edu.berkeley.fleet.api.Predicate.*;
13 import static edu.berkeley.fleet.util.BitManipulations.*;
17 void doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, boolean peerUsed) {
18 if (dock.getShip().getType().equals("Debug")) return;
22 // Phase 0: torpedo every output dock, put it in
23 // collecting mode. Cannot combine with phase 1,
24 // because until output docks are in vacuum mode we
25 // cannot be sure that the tokens to the input docks
26 // will eventually succeed. This may cause the
27 // instructions sent after the tokens to back up into
30 if (!dock.isInputDock()) {
31 DataFlowGraph.torpedoes.add(dock);
32 LoopFactory lf = new LoopFactory(ctx, dock, 1);
33 lf.sendToken(ackDestination);
35 lf.abortLoopIfTorpedoPresent();
37 DataFlowGraph.reset_count++;
42 // Phase 1: torpedo every input dock, put it in loopback mode
44 if (dock.isInputDock()) {
45 DataFlowGraph.torpedoes.add(dock);
46 LoopFactory lf = new LoopFactory(ctx, dock, 1);
47 lf.sendToken(ackDestination);
49 // FIXME: this won't work right for ports that
50 // get "shared" by two senders (for example,
53 if (peerUsed && peer!=null) {
55 lf.abortLoopIfTorpedoPresent();
56 ((OutPort)peer).recvWord(lf);
57 ((OutPort)peer).sendToken(lf);
59 DataFlowGraph.reset_count++;
64 // Phase 2: torpedo every output dock, have it absorb tokens
66 if (!dock.isInputDock()) {
67 DataFlowGraph.torpedoes.add(dock);
68 LoopFactory lf = new LoopFactory(ctx, dock, 1);
70 for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
72 lf.sendToken(ackDestination);
73 DataFlowGraph.reset_count++;
78 // Phase 3: torpedo every input dock, and we're done
80 if (dock.isInputDock()) {
81 if (peerUsed && peer!=null) {
82 DataFlowGraph.torpedoes.add(dock);
84 LoopFactory lf = new LoopFactory(ctx, dock, 1);
85 lf.sendToken(ackDestination);
86 DataFlowGraph.reset_count++;
95 public final DataFlowGraph dfg;
96 public Node(DataFlowGraph dfg) {
101 private HashMap<String,Port> ports = new HashMap<String,Port>();
103 public InPort getInPort(String name) { return (InPort)ports.get(name); }
104 public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
106 public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
107 public void reset(Context ctx, int phase, Destination ackDestination) {
108 for(Port p : ports.values()) p.reset(ctx, phase, ackDestination);
111 public abstract class Port {
112 public final String name;
113 public Port(String name) {
115 if (Node.this.ports.get(name)!=null) throw new RuntimeException();
116 Node.this.ports.put(name,this);
118 public abstract void build(Context ctx);
119 public abstract void reset(Context ctx, int phase, Destination ackDestination);
122 public abstract class InPort extends Port {
124 public InPort(String name) { super(name); }
125 public void connect(OutPort peer) {
129 public void setPeer(OutPort peer) {
130 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
134 /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
135 public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
136 /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
137 public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
139 public int getTokensToAbsorb() { return 0; }
142 public abstract class OutPort extends Port {
144 public OutPort(String name) { super(name); }
145 public void connect(InPort peer) {
149 public void setPeer(InPort peer) {
150 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
154 /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
155 public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
156 /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
157 public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
160 public final class DockInPort extends InPort {
164 public DockInPort(String name, Dock dock) { this(name, dock, 0); }
165 public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
166 public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
170 this.pattern = pattern;
172 public void recvToken(LoopFactory lf) { lf.recvToken(); }
173 public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
174 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
175 // number-in-flight is considered a property of the input dock in a pair
176 public int getInflight() { return 4; }
177 //public int getInflight() { return 1; }
178 public int getTokensToAbsorb() { return getInflight(); }
179 private boolean peerUsed() {
180 if (peer==null) return false;
181 for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
184 public void reset(Context ctx, int phase, Destination ackDestination) {
185 doReset(ctx, phase, dock, peer, ackDestination, peerUsed());
187 protected void build(Context ctx, LoopFactory lf) {
188 int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
191 for(int i=0; i<inflight; i++) peer.sendToken(lf);
193 lf = lf.makeNext(count, true);
194 for(int i=0; i<pattern.length; i++) {
195 if (pattern[i]==null) {
197 lf.abortLoopIfTorpedoPresent();
202 lf.interruptibleNop();
205 lf.literal(pattern[i]);
206 lf.abortLoopIfTorpedoPresent();
212 // "torpedoable nop" to keep the dock in a receptive state
213 lf.abortLoopIfTorpedoPresent();
217 public BitVector getConstant(String constantName) {
218 return dock.getConstant(constantName);
222 public /*final*/ class DockOutPort extends OutPort {
223 public final Dock dock;
224 public final int count;
225 public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
226 public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
227 public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
228 public void recvWord(LoopFactory lf) { lf.recvWord(); }
229 public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
230 protected void build(Context ctx, LoopFactory lf) {
231 if (peer==null) return;
232 lf = lf.makeNext(count);
233 lf.abortLoopIfTorpedoPresent();
238 public void reset(Context ctx, int phase, Destination ackDestination) {
239 doReset(ctx, phase, dock, peer, ackDestination, true);
243 BitVector bv(long l) { return new BitVector(dfg.fleet.getWordWidth()).set(l); }
244 BitVector[] bv(long[] l) {
245 BitVector[] ret = new BitVector[l.length];
246 for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);