add commented-out version of UnPunctuatorNode2 to UnPunctuatorNode until I have time...
[fleet.git] / src / edu / berkeley / fleet / dataflow / Node.java
1 package edu.berkeley.fleet.dataflow;
2 import java.util.*;
3 import edu.berkeley.fleet.loops.*;
4 import java.util.concurrent.Semaphore;
5 import java.util.*;
6 import java.net.*;
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.*;
15
16 public class Node {
17
18     public static int CAPACITY = 4;
19
20     public final DataFlowGraph dfg;
21     public Node(DataFlowGraph dfg) {
22         this.dfg = dfg;
23         dfg.addNode(this);
24     }
25
26     private HashMap<String,Port> ports = new HashMap<String,Port>();
27     public void build(CodeBag ctx) { for(Port p : ports.values()) p.build(ctx); }
28     public int reset(CodeBag ctx, int phase, Destination ackDestination) {
29         int ret = 0;
30         for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination);
31         return ret;
32     }
33
34     public abstract class Port {
35         public final String name;
36         public Port(String name) {
37             this.name = name;
38             if (Node.this.ports.get(name)!=null) throw new RuntimeException();
39             Node.this.ports.put(name,this);
40         }
41         public abstract void build(CodeBag ctx);
42         public abstract int  reset(CodeBag ctx, int phase, Destination ackDestination);
43         public String toString() { return Node.this+"."+name; }
44     }
45
46     public abstract class InPort extends Port {
47         OutPort peer;
48         public InPort(String name) { super(name); }
49         public void connect(OutPort peer) {
50             this.setPeer(peer);
51             peer.setPeer(this);
52         }
53
54         public void connectOnce(long val) { connect(new OnceNode(dfg, val).out); }
55         public void connectForever(long val) { connect(new ForeverNode(dfg, val).out); }
56
57         public void setPeer(OutPort peer) {
58             if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
59             this.peer = peer;
60         }
61
62         /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
63         public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
64         /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
65         public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
66
67         public int getTokensToAbsorb() { return 0; }
68         public int getMaxInFlight() { return 0; }
69     }
70
71     public abstract class OutPort extends Port {
72         InPort peer;
73         public OutPort(String name) { super(name); }
74         public void connect(InPort peer) {
75             this.setPeer(peer);
76             peer.setPeer(this);
77         }
78         public void setPeer(InPort peer) {
79             if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
80             this.peer = peer;
81         }
82
83         public int getNumInitialTokens() {
84             return peer.getMaxInFlight();
85         }
86
87         /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
88         public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
89         /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
90         public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
91
92         public int getTokensToAbsorb() {
93             if (peer==null) return 0;
94             return peer.getTokensToAbsorb();
95         }
96     }
97
98     public final class DockInPort extends InPort {
99         final Dock dock;
100         int count;
101         BitVector[] pattern;
102         public boolean sticky = false;
103         public DockInPort(String name, Dock dock) { this(name, dock, 0); }
104         public DockInPort(String name, Dock dock, String constant) {
105             this(name, dock, 0, new BitVector[] { dock.getConstant(constant) }); }
106         public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
107         public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
108             super(name);
109             this.dock = dock;
110             this.count = count;
111             this.pattern = pattern;
112         }
113         public void recvToken(LoopFactory lf) { lf.recvToken(); }
114         public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
115         public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
116
117         // this is the input dock's upper limit on how many data items
118         // may be in flight; the output dock to which it is connected
119         // also has a say
120         public int getMaxInFlight() { return CAPACITY; }
121
122         public int getTokensToAbsorb() { return sticky ? 0 : peer==null ? 0 : peer.getNumInitialTokens(); }
123         private boolean peerUsed() {
124             if (sticky) return false;
125             if (peer==null) return false;
126             for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
127             return false;
128         }
129         public int reset(CodeBag ctx, int phase, Destination ackDestination) {
130             return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, peerUsed());
131         }
132         protected void build(CodeBag ctx, LoopFactory lf) {
133             /*
134             if (sticky) {
135                 if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
136                 lf = lf.makeNext(1, true);
137                 lf.recvWord();
138                 }
139             */
140             if (sticky) {
141                 if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
142                 lf = lf.makeNext(1, true);
143                 lf.setFlags(FlagFunction.ZERO,  FlagFunction.ZERO);
144             }
145
146             if (peer!=null) {
147                 int inflight = (count != 0 && count < peer.getNumInitialTokens()) ? count : peer.getNumInitialTokens();
148                 for(int i=0; i<inflight; i++) peer.sendToken(lf);
149             }
150
151             lf = lf.makeNext(count, true);
152
153             // ugly hack!
154             if (sticky) {
155                 lf.setPredicate(Predicate.NotFlagB);
156                 lf.recvWord();
157                 lf.setPredicate(null);
158                 lf.setFlags(FlagFunction.ZERO,  FlagFunction.ONE);
159             }
160             for(int i=0; i<pattern.length; i++) {
161                 if (pattern[i]==null) {
162                     if (peer!=null) {
163                         lf.abortLoopIfTorpedoPresent();
164                         peer.recvWord(lf);
165                         peer.sendToken(lf);
166                         lf.deliver();
167                     } else {
168                         lf.interruptibleNop();
169                     }
170                 } else {
171                     lf.literal(pattern[i]);
172                     lf.abortLoopIfTorpedoPresent();
173                     lf.deliver();
174                 }
175             }
176
177             if (count!=0) {
178                 // "torpedoable nop" to keep the dock in a receptive state
179                 lf.abortLoopIfTorpedoPresent();
180                 lf.recvToken();
181             }
182         }
183         public BitVector getConstant(String constantName) {
184             return dock.getConstant(constantName);
185         }
186     }
187
188     public /*final*/ class DockOutPort extends OutPort {
189         public final Dock dock;
190         public final int count;
191         public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
192         public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
193         public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
194         public void recvWord(LoopFactory lf) { lf.recvWord(); }
195         public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
196         protected void build(CodeBag ctx, LoopFactory lf) {
197             if (peer==null) return;
198             lf = lf.makeNext(count);
199             lf.abortLoopIfTorpedoPresent();
200             peer.recvToken(lf);
201             lf.collectWord();
202             peer.sendWord(lf);
203         }
204         public int reset(CodeBag ctx, int phase, Destination ackDestination) {
205             return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, true);
206         }
207     }
208
209     BitVector bv(long l) { return new BitVector(dfg.fleet.getWordWidth()).set(l); }
210     BitVector[] bv(long[] l) {
211         BitVector[] ret = new BitVector[l.length];
212         for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);
213         return ret;
214     }
215
216 }