5684e84db2e36ef7a77cef3856f137ccc5e3c148
[fleet.git] / src / edu / berkeley / fleet / dataflow / Node.java
1 package edu.berkeley.fleet.dataflow;
2 import edu.berkeley.fleet.loops.*;
3 import java.util.concurrent.Semaphore;
4 import java.util.*;
5 import java.net.*;
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.*;
14
15 public class Node {
16
17     void doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, boolean peerUsed) {
18         if (dock.getShip().getType().equals("Debug")) return;
19
20         switch(phase) {
21
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
28             // the switch fabric.
29             case 0: {
30                 if (!dock.isInputDock()) {
31                     DataFlowGraph.torpedoes.add(dock);
32                     LoopFactory lf = new LoopFactory(ctx, dock, 1);
33                     lf.sendToken(ackDestination);
34                     lf = lf.makeNext(0);
35                     lf.abortLoopIfTorpedoPresent();
36                     lf.collectWord();
37                     DataFlowGraph.reset_count++;
38                 }
39                 break;
40             }
41
42                 // Phase 1: torpedo every input dock, put it in loopback mode
43             case 1: {
44                 if (dock.isInputDock()) {
45                     DataFlowGraph.torpedoes.add(dock);
46                     LoopFactory lf = new LoopFactory(ctx, dock, 1);
47                     lf.sendToken(ackDestination);
48
49                     // FIXME: this won't work right for ports that
50                     // get "shared" by two senders (for example,
51                     // inAddrRead1/2)
52
53                     if (peerUsed && peer!=null) {
54                         lf = lf.makeNext(0);
55                         lf.abortLoopIfTorpedoPresent();
56                         ((OutPort)peer).recvWord(lf);
57                         ((OutPort)peer).sendToken(lf);
58                     }
59                     DataFlowGraph.reset_count++;
60                 }
61                 break;
62             }
63
64                 // Phase 2: torpedo every output dock, have it absorb tokens
65             case 2: {
66                 if (!dock.isInputDock()) {
67                     DataFlowGraph.torpedoes.add(dock);
68                     LoopFactory lf = new LoopFactory(ctx, dock, 1);
69                     if (peer != null)
70                         for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
71                             lf.recvToken();
72                     lf.sendToken(ackDestination);
73                     DataFlowGraph.reset_count++;
74                 }
75                 break;
76             }
77
78                 // Phase 3: torpedo every input dock, and we're done
79             case 3: {
80                 if (dock.isInputDock()) {
81                     if (peerUsed && peer!=null) {
82                         DataFlowGraph.torpedoes.add(dock);
83                     }
84                     LoopFactory lf = new LoopFactory(ctx, dock, 1);
85                     lf.sendToken(ackDestination);
86                     DataFlowGraph.reset_count++;
87                 }
88                 break;
89             }
90
91
92         }
93     }
94
95     public final DataFlowGraph dfg;
96     public Node(DataFlowGraph dfg) {
97         this.dfg = dfg;
98         dfg.addNode(this);
99     }
100
101     private HashMap<String,Port> ports = new HashMap<String,Port>();
102
103     public InPort  getInPort(String name)  { return (InPort)ports.get(name); }
104     public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
105         
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);
109     }
110
111     public abstract class Port {
112         public final String name;
113         public Port(String name) {
114             this.name = name;
115             if (Node.this.ports.get(name)!=null) throw new RuntimeException();
116             Node.this.ports.put(name,this);
117         }
118         public abstract void build(Context ctx);
119         public abstract void reset(Context ctx, int phase, Destination ackDestination);
120     }
121
122     public abstract class InPort extends Port {
123         OutPort peer;
124         public InPort(String name) { super(name); }
125         public void connect(OutPort peer) {
126             this.setPeer(peer);
127             peer.setPeer(this);
128         }
129         public void setPeer(OutPort peer) {
130             if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
131             this.peer = peer;
132         }
133
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);
138
139         public int getTokensToAbsorb() { return 0; }
140     }
141
142     public abstract class OutPort extends Port {
143         InPort peer;
144         public OutPort(String name) { super(name); }
145         public void connect(InPort peer) {
146             this.setPeer(peer);
147             peer.setPeer(this);
148         }
149         public void setPeer(InPort peer) {
150             if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
151             this.peer = peer;
152         }
153
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);
158     }
159
160     public final class DockInPort extends InPort {
161         final Dock dock;
162         int count;
163         BitVector[] pattern;
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) {
167             super(name);
168             this.dock = dock;
169             this.count = count;
170             this.pattern = pattern;
171         }
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;
182             return false;
183         }
184         public void reset(Context ctx, int phase, Destination ackDestination) {
185             doReset(ctx, phase, dock, peer, ackDestination, peerUsed());
186         }
187         protected void build(Context ctx, LoopFactory lf) {
188             int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
189
190             if (peer!=null)
191                 for(int i=0; i<inflight; i++) peer.sendToken(lf);
192
193             lf = lf.makeNext(count, true);
194             for(int i=0; i<pattern.length; i++) {
195                 if (pattern[i]==null) {
196                     if (peer!=null) {
197                         lf.abortLoopIfTorpedoPresent();
198                         peer.recvWord(lf);
199                         peer.sendToken(lf);
200                         lf.deliver();
201                     } else {
202                         lf.interruptibleNop();
203                     }
204                 } else {
205                     lf.literal(pattern[i]);
206                     lf.abortLoopIfTorpedoPresent();
207                     lf.deliver();
208                 }
209             }
210
211             if (count!=0) {
212                 // "torpedoable nop" to keep the dock in a receptive state
213                 lf.abortLoopIfTorpedoPresent();
214                 lf.recvToken();
215             }
216         }
217         public BitVector getConstant(String constantName) {
218             return dock.getConstant(constantName);
219         }
220     }
221
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();
234             peer.recvToken(lf);
235             lf.collectWord();
236             peer.sendWord(lf);
237         }
238         public void reset(Context ctx, int phase, Destination ackDestination) {
239             doReset(ctx, phase, dock, peer, ackDestination, true);
240         }
241     }
242
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]);
247         return ret;
248     }
249 }