break out dataflow nodes into separate classes
authormegacz <adam@megacz.com>
Sun, 15 Mar 2009 01:17:45 +0000 (18:17 -0700)
committermegacz <adam@megacz.com>
Sun, 15 Mar 2009 01:17:45 +0000 (18:17 -0700)
13 files changed:
src/edu/berkeley/fleet/dataflow/AluNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DataFlowGraph.java
src/edu/berkeley/fleet/dataflow/DebugNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DownCounterNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/ForeverNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/MemoryNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/MergeSort.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/Node.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/OnceNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/PunctuatorNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/RepeatNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/SortedMergeNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java [new file with mode: 0644]

diff --git a/src/edu/berkeley/fleet/dataflow/AluNode.java b/src/edu/berkeley/fleet/dataflow/AluNode.java
new file mode 100644 (file)
index 0000000..f6120a3
--- /dev/null
@@ -0,0 +1,12 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class AluNode extends Node {
+    public final Ship    ship = dfg.pool.allocateShip("Alu");
+    public final InPort  in1 = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  in2 = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"));
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+    public AluNode(DataFlowGraph dfg) { super(dfg); }
+}
index 48a8720..6d4a5fd 100644 (file)
@@ -34,6 +34,10 @@ public class DataFlowGraph {
         this.pool  = pool;
     }
 
+    public void addNode(Node node) {
+        this.nodes.add(node);
+    }
+
     public static int reset_count = 0;
     public static HashSet<Dock> torpedoes = new HashSet<Dock>();
 
@@ -50,469 +54,13 @@ public class DataFlowGraph {
             mod.reset(ctx, phase, ackDestination);
     }
 
-    public static class Node {
-
-        void doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, boolean peerUsed) {
-            if (dock.getShip().getType().equals("Debug")) return;
-
-            switch(phase) {
-
-                // Phase 0: torpedo every output dock, put it in
-                // collecting mode.  Cannot combine with phase 1,
-                // because until output docks are in vacuum mode we
-                // cannot be sure that the tokens to the input docks
-                // will eventually succeed.  This may cause the
-                // instructions sent after the tokens to back up into
-                // the switch fabric.
-                case 0: {
-                    if (!dock.isInputDock()) {
-                        torpedoes.add(dock);
-                        LoopFactory lf = new LoopFactory(ctx, dock, 1);
-                        lf.sendToken(ackDestination);
-                        lf = lf.makeNext(0);
-                        lf.abortLoopIfTorpedoPresent();
-                        lf.collectWord();
-                        reset_count++;
-                    }
-                    break;
-                }
-
-                // Phase 1: torpedo every input dock, put it in loopback mode
-                case 1: {
-                    if (dock.isInputDock()) {
-                        torpedoes.add(dock);
-                        LoopFactory lf = new LoopFactory(ctx, dock, 1);
-                        lf.sendToken(ackDestination);
-
-                        // FIXME: this won't work right for ports that
-                        // get "shared" by two senders (for example,
-                        // inAddrRead1/2)
-
-                        if (peerUsed && peer!=null) {
-                            lf = lf.makeNext(0);
-                            lf.abortLoopIfTorpedoPresent();
-                            ((OutPort)peer).recvWord(lf);
-                            ((OutPort)peer).sendToken(lf);
-                        }
-                        reset_count++;
-                    }
-                    break;
-                }
-
-                // Phase 2: torpedo every output dock, have it absorb tokens
-                case 2: {
-                    if (!dock.isInputDock()) {
-                        torpedoes.add(dock);
-                        LoopFactory lf = new LoopFactory(ctx, dock, 1);
-                        if (peer != null)
-                            for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
-                                lf.recvToken();
-                        lf.sendToken(ackDestination);
-                        reset_count++;
-                    }
-                    break;
-                }
-
-                // Phase 3: torpedo every input dock, and we're done
-                case 3: {
-                    if (dock.isInputDock()) {
-                        if (peerUsed && peer!=null) {
-                            torpedoes.add(dock);
-                        }
-                        LoopFactory lf = new LoopFactory(ctx, dock, 1);
-                        lf.sendToken(ackDestination);
-                        reset_count++;
-                    }
-                    break;
-                }
-
-
-            }
-        }
-
-        public final DataFlowGraph dfg;
-        public Node(DataFlowGraph dfg) {
-            this.dfg = dfg;
-            dfg.nodes.add(this);
-        }
-
-        private HashMap<String,Port> ports = new HashMap<String,Port>();
-
-        public InPort  getInPort(String name)  { return (InPort)ports.get(name); }
-        public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
-        
-        public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
-        public void reset(Context ctx, int phase, Destination ackDestination) {
-            for(Port p : ports.values()) p.reset(ctx, phase, ackDestination);
-        }
-
-        public abstract class Port {
-            public final String name;
-            public Port(String name) {
-                this.name = name;
-                if (Node.this.ports.get(name)!=null) throw new RuntimeException();
-                Node.this.ports.put(name,this);
-            }
-            public abstract void build(Context ctx);
-            public abstract void reset(Context ctx, int phase, Destination ackDestination);
-        }
-
-        public abstract class InPort extends Port {
-            OutPort peer;
-            public InPort(String name) { super(name); }
-            public void connect(OutPort peer) {
-                this.setPeer(peer);
-                peer.setPeer(this);
-            }
-            public void setPeer(OutPort peer) {
-                if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
-                this.peer = peer;
-            }
-
-            /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
-            public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
-            /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
-            public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
-
-            public int getTokensToAbsorb() { return 0; }
-        }
-
-        public abstract class OutPort extends Port {
-            InPort peer;
-            public OutPort(String name) { super(name); }
-            public void connect(InPort peer) {
-                this.setPeer(peer);
-                peer.setPeer(this);
-            }
-            public void setPeer(InPort peer) {
-                if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
-                this.peer = peer;
-            }
-
-            /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
-            public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
-            /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
-            public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
-        }
-
-        public final class DockInPort extends InPort {
-            final Dock dock;
-            int count;
-            BitVector[] pattern;
-            public DockInPort(String name, Dock dock) { this(name, dock, 0); }
-            public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
-            public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
-                super(name);
-                this.dock = dock;
-                this.count = count;
-                this.pattern = pattern;
-            }
-            public void recvToken(LoopFactory lf) { lf.recvToken(); }
-            public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
-            public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
-            // number-in-flight is considered a property of the input dock in a pair
-            public int getInflight() { return 4; }
-            //public int getInflight() { return 1; }
-            public int getTokensToAbsorb() { return getInflight(); }
-            private boolean peerUsed() {
-                if (peer==null) return false;
-                for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
-                return false;
-            }
-            public void reset(Context ctx, int phase, Destination ackDestination) {
-                doReset(ctx, phase, dock, peer, ackDestination, peerUsed());
-            }
-            protected void build(Context ctx, LoopFactory lf) {
-                int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
-
-                if (peer!=null)
-                    for(int i=0; i<inflight; i++) peer.sendToken(lf);
-
-                lf = lf.makeNext(count, true);
-                for(int i=0; i<pattern.length; i++) {
-                    if (pattern[i]==null) {
-                        if (peer!=null) {
-                            lf.abortLoopIfTorpedoPresent();
-                            peer.recvWord(lf);
-                            peer.sendToken(lf);
-                            lf.deliver();
-                        } else {
-                            lf.interruptibleNop();
-                        }
-                    } else {
-                        lf.literal(pattern[i]);
-                        lf.abortLoopIfTorpedoPresent();
-                        lf.deliver();
-                    }
-                }
-
-                if (count!=0) {
-                    // "torpedoable nop" to keep the dock in a receptive state
-                    lf.abortLoopIfTorpedoPresent();
-                    lf.recvToken();
-                }
-            }
-            public BitVector getConstant(String constantName) {
-                return dock.getConstant(constantName);
-            }
-        }
-
-        public /*final*/ class DockOutPort extends OutPort {
-            public final Dock dock;
-            public final int count;
-            public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
-            public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
-            public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
-            public void recvWord(LoopFactory lf) { lf.recvWord(); }
-            public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
-            protected void build(Context ctx, LoopFactory lf) {
-                if (peer==null) return;
-                lf = lf.makeNext(count);
-                lf.abortLoopIfTorpedoPresent();
-                peer.recvToken(lf);
-                lf.collectWord();
-                peer.sendWord(lf);
-            }
-            public void reset(Context ctx, int phase, Destination ackDestination) {
-                doReset(ctx, phase, dock, peer, ackDestination, true);
-            }
-        }
-    }
-
-    private BitVector bv(long l) { return new BitVector(fleet.getWordWidth()).set(l); }
-    private BitVector[] bv(long[] l) {
+    BitVector bv(long l) { return new BitVector(fleet.getWordWidth()).set(l); }
+    BitVector[] bv(long[] l) {
         BitVector[] ret = new BitVector[l.length];
         for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);
         return ret;
     }
 
-    /**
-     *  Deliver the constant at out forever.  Flow control in<->out is
-     *  maintained, but out is not flow-controlled, so be sure
-     *  that every datum sent there is consumed synchronously wiht
-     *  data items sent to out.
-     */
-    public static class ForeverNode extends Node {
-        private BitVector bv;
-        public final OutPort out = new OutPort("out") {
-                public void sendToken(LoopFactory lf) { }
-                public void recvWord(LoopFactory lf) { }
-                public void build(Context ctx) { }
-                public void reset(Context ctx, int phase, Destination ackDestination) { }
-                public void setPeer(InPort peer) {
-                    this.peer = peer;
-                    DockInPort pip = ((DockInPort)peer);
-                    for(int i=0; i<pip.pattern.length; i++) {
-                        if (pip.pattern[i]==null)
-                            pip.pattern[i] = bv;
-                    }
-                }
-            };
-        public ForeverNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
-        public ForeverNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
-    }
-
-    public static class OnceNode extends Node {
-        private BitVector bv;
-        public final OutPort out = new OutPort("out") {
-                public void sendToken(LoopFactory lf) { }
-                public void recvWord(LoopFactory lf) { }
-                public void build(Context ctx) { }
-                public void reset(Context ctx, int phase, Destination ackDestination) { }
-                public void setPeer(InPort peer) {
-                    this.peer = peer;
-                    DockInPort pip = ((DockInPort)peer);
-                    BitVector[] pip_pattern = pip.pattern;
-                    BitVector[] temp = new BitVector[pip_pattern.length * 2];
-                    int j = 0;
-                    int i = 0;
-                    boolean done = false;
-                    // FIXME: if peer.count is already 1, this gets simpler and different
-                    for(i=0; i<temp.length; i++) {
-                        if (pip_pattern[j] != null) {
-                            temp[i] = pip_pattern[j];
-                        } else {
-                            if (done) break;
-                            done = true;
-                            temp[i] = bv;
-                        }
-                        j++;
-                        if (j >= pip_pattern.length) j = 0;
-                    }
-                    pip.pattern = new BitVector[i];
-                    System.arraycopy(temp, 0, pip.pattern, 0, i);
-                    pip.count = 1;
-                }
-            };
-        public OnceNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
-        public OnceNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
-    }
-
-    public static class DebugNode extends Node {
-        public final Ship ship = dfg.pool.allocateShip("Debug");
-        public final InPort in = new DockInPort("in", ship.getDock("in"));
-        // NOTE: shutdown needs to treat this specially
-        public DebugNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class UnPunctuatorNode extends Node {
-        private final Ship    ship  = dfg.pool.allocateShip("Counter");
-        public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
-        public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
-        public  final InPort  count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, dfg.bv(1) });
-        public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
-                ship.getDock("inOp").getConstant("PASS_C2_V1"),
-                ship.getDock("inOp").getConstant("DROP_C2_V1") } );
-        public UnPunctuatorNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class PunctuatorNode extends Node {
-        private final long    punc;
-        private final Ship    ship  = dfg.pool.allocateShip("Counter");
-        public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
-        public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
-        public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
-                ship.getDock("inOp").getConstant("PASS_C2_V1"),
-                ship.getDock("inOp").getConstant("PASS_C2_V2") } );
-        public  final InPort  count;
-        public PunctuatorNode(DataFlowGraph dfg, long punc) {
-            super(dfg);
-            this.punc = punc;
-            this.count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, dfg.bv(1), dfg.bv(punc) });
-        }
-    }
-
-    public static class AluNode extends Node {
-        public final Ship    ship = dfg.pool.allocateShip("Alu");
-        public final InPort  in1 = new DockInPort("in1",  ship.getDock("in1"));
-        public final InPort  in2 = new DockInPort("in2",  ship.getDock("in2"));
-        public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"));
-        public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
-        public AluNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class DownCounterNode extends Node {
-        public final Ship    ship  = dfg.pool.allocateShip("Counter");
-        public final InPort  start = new DockInPort("in1",  ship.getDock("in1"));
-        public final InPort  incr  = new DockInPort("in2",  ship.getDock("in2"));
-        public final InPort  inOp  = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
-                ship.getDock("inOp").getConstant("COUNT") });
-        public final OutPort out   = new DockOutPort("out", ship.getDock("out"));
-        public DownCounterNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class RepeatNode extends Node {
-        public final Ship    ship   = dfg.pool.allocateShip("Counter");
-        public final InPort  count  = new DockInPort("in1",  ship.getDock("in1"));
-        public final InPort  val    = new DockInPort("in2",  ship.getDock("in2"));
-        public final InPort  inOP   = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
-                ship.getDock("inOp").getConstant("REPEAT_C1_V2") });
-        public final OutPort out    = new DockOutPort("out", ship.getDock("out"));
-        public RepeatNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class SortedMergeNode extends Node {
-        public final Ship    ship = dfg.pool.allocateShip("Alu");
-        public final InPort  in1  = new DockInPort("in1",  ship.getDock("in1"));
-        public final InPort  in2  = new DockInPort("in2",  ship.getDock("in2"));
-        public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
-                ship.getDock("inOp").getConstant("MAXMERGE") });
-        public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
-        public SortedMergeNode(DataFlowGraph dfg) { super(dfg); }
-    }
-
-    public static class MemoryNode extends Node {
-        public final Ship    ship;
-        public final InPort  inCBD;
-        public final InPort  inAddrRead1;
-        public final InPort  inAddrRead2;
-        public final InPort  inAddrWrite;
-        public final InPort  inDataWrite;
-        public final OutPort outRead1;
-        public final OutPort outRead2;
-        public final OutPort outWrite;
-        public MemoryNode(DataFlowGraph dfg, Ship memoryShip) {
-            super(dfg);
-            this.ship = memoryShip;
-            this.inCBD        = ship.getType().equals("Memory") ? new DockInPort("inCBD", ship.getDock("inCBD")) : null;
-            this.inAddrWrite  = new DockInPort("inAddrWrite", ship.getDock("inAddrWrite"));
-            this.inDataWrite  = new DockInPort("inDataWrite", ship.getDock("inDataWrite"));
-            this.inAddrRead1  = new InPort("inAddrRead1") {
-                    public void recvToken(LoopFactory lf) { lf.recvToken(); }
-                    public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(0)); }
-                    public void build(Context ctx) { }
-                    public int getTokensToAbsorb() { return outRead1.peer.getTokensToAbsorb(); }
-                    public void reset(Context ctx, int phase, Destination ackDestination) {
-                        doReset(ctx, phase, ship.getDock("inAddrRead"), null, ackDestination, false);
-                    }
-                };
-            this.inAddrRead2  = new InPort("inAddrRead2") {
-                    public void recvToken(LoopFactory lf) { lf.recvToken(); }
-                    public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(1)); }
-                    public void build(Context ctx) { }
-                    public int getTokensToAbsorb() { return outRead2.peer.getTokensToAbsorb(); }
-                    public void reset(Context ctx, int phase, Destination ackDestination) { }
-                };
-            this.outRead1 = new OutPort("outRead1") {
-                    public void sendToken(LoopFactory lf) { inAddrRead1.peer.sendToken(lf); }
-                    public void recvWord(LoopFactory lf) { lf.recvWord(); }
-                    public void build(Context ctx) { }
-                    public void reset(Context ctx, int phase, Destination ackDestination) { }
-                };
-            this.outRead2 = new OutPort("outRead2") {
-                    public void sendToken(LoopFactory lf) { inAddrRead2.peer.sendToken(lf); }
-                    public void recvWord(LoopFactory lf) { lf.recvWord(); }
-                    public void build(Context ctx) { }
-                    public void reset(Context ctx, int phase, Destination ackDestination) { }
-                };
-            this.outWrite = new DockOutPort("out", ship.getDock("out")) {
-                    protected void build(Context ctx, LoopFactory lf) {
-                        lf = lf.makeNext(0);
-                        lf.abortLoopIfTorpedoPresent();
-                        lf.collectWord();
-                        
-                        lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO.add(FlagC));
-                        if (this.peer != null) {
-                            lf.setPredicate(Predicate.FlagB);
-                            lf.literal(77);
-                            lf.abortLoopIfTorpedoPresent();
-                            this.peer.recvToken(lf);
-                            this.peer.sendWord(lf);
-                        }
-                        
-                        lf.setPredicate(Predicate.NotFlagB);
-                        lf.abortLoopIfTorpedoPresent();
-                        lf.recvToken();
-                        lf.setFlags(FlagFunction.ZERO.add(NotFlagC).add(FlagB), FlagFunction.ZERO.add(FlagC).add(FlagB));
-                        if (outRead1.peer != null) {
-                            lf.setPredicate(Predicate.NotFlagB);
-                            outRead1.peer.sendWord(lf);
-                        }
-                        if (outRead2.peer != null) {
-                            lf.setPredicate(Predicate.NotFlagA);
-                            outRead2.peer.sendWord(lf);
-                        }
-                        lf.setPredicate(null);
-                    }
-                };
-        }
-        public void build(Context ctx) {
-            super.build(ctx);
-            LoopFactory lf;
-
-            lf = new LoopFactory(ctx, ship.getDock("inAddrRead"), 0);
-            lf.abortLoopIfTorpedoPresent();
-            lf.recvWord();
-            lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
-            lf.setPredicate(Predicate.NotFlagA);
-            lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(0));
-            lf.setPredicate(Predicate.FlagA);
-            lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(1));
-            lf.setPredicate(null);
-            lf.deliver();
-        }
-    }
-
     public static void main(String[] s) throws Exception {
         Fleet fleet = new Fpga();
         //Fleet fleet = new Interpreter(false);
@@ -549,7 +97,7 @@ public class DataFlowGraph {
             if (fp==null) fp = fleet.run(new Instruction[0]);
 
             // do the mergeSort
-            vals = mergeSort(fp, fleet, vals, vals_length, stride, mem1, mem2);
+            vals = MergeSort.mergeSort(fp, fleet, vals, vals_length, stride, mem1, mem2);
 
             // verify the cleanup
             //CleanupUtils.verifyClean(fp);
@@ -568,165 +116,6 @@ public class DataFlowGraph {
     }
 
 
-    public static long[] mergeSort(FleetProcess fp, Fleet fleet,
-                                   long[] vals, int vals_length, int stride_length,
-                                   Ship memoryShip1, Ship memoryShip2) throws Exception {
-
-        if (vals != null) {
-            BitVector[] mem = new BitVector[vals_length];
-            for(int i=0; i<mem.length; i++) mem[i] = new BitVector(fleet.getWordWidth()).set(vals[i]);
-            MemoryUtils.writeMem(fp, memoryShip1, 0, mem);
-        }
-
-        //////////////////////////////////////////////////////////////////////////////
-
-        DataFlowGraph proc = new DataFlowGraph(fleet);
-        DebugNode dm = new DebugNode(proc);
-
-        int end_of_data = vals_length;
-        int num_strides = end_of_data / (stride_length * 2);
-
-        MemoryNode mm  = new MemoryNode(proc, memoryShip1);
-        SortedMergeNode sm = new SortedMergeNode(proc);
-
-        // So far: we have four spare Counter ships; one can be used for resetting
-        for(int i=0; i<2; i++) {
-
-            DownCounterNode c0 = new DownCounterNode(proc);
-            DownCounterNode c1 = new DownCounterNode(proc);
-
-            c0.start.connect(new ForeverNode(proc, stride_length).out);
-            c0.incr.connect(new ForeverNode(proc, 1).out);
-
-            c1.start.connect(new OnceNode(proc, end_of_data + i*stride_length).out);
-            c1.incr.connect(new OnceNode(proc, stride_length*2).out);
-
-            RepeatNode r1 = new RepeatNode(proc);
-            r1.val.connect(c1.out);
-            r1.count.connect(new ForeverNode(proc, stride_length).out);
-
-            AluNode alu = new AluNode(proc);
-            alu.in1.connect(r1.out);
-            alu.in2.connect(c0.out);
-            alu.inOp.connect(new ForeverNode(proc, ((Node.DockInPort)alu.inOp).getConstant("ADD")).out);
-            alu.out.connect(i==0 ? mm.inAddrRead1 : mm.inAddrRead2);
-
-            PunctuatorNode punc = new PunctuatorNode(proc, -1);
-            punc.count.connect(new ForeverNode(proc, stride_length).out);
-            punc.val.connect(i==0 ? mm.outRead1 : mm.outRead2);
-            punc.out.connect(i==0 ? sm.in1 : sm.in2);
-        }
-
-        UnPunctuatorNode unpunc = new UnPunctuatorNode(proc);
-        unpunc.val.connect(sm.out);
-        unpunc.count.connect(new ForeverNode(proc, 2*stride_length).out);
-
-        DownCounterNode cw = new DownCounterNode(proc);
-        cw.start.connect(new OnceNode(proc, end_of_data).out);
-        cw.incr.connect(new OnceNode(proc, 1).out);
-
-        MemoryNode mm2 = new MemoryNode(proc, memoryShip2);
-        mm2.inAddrWrite.connect(cw.out);
-        mm2.inDataWrite.connect(unpunc.out);
-        mm2.outWrite.connect(dm.in);
-
-        //////////////////////////////////////////////////////////////////////////////
-
-        Context ctx = new Context(fp.getFleet());
-        ctx.setAutoflush(true);
-
-        ArrayList<Instruction> ai = new ArrayList<Instruction>();
-        proc.build(ctx);
-        ctx.emit(ai);
-        for(Instruction ins : ai) {
-            //System.out.println(ins);
-            fp.sendInstruction(ins);
-        }
-        fp.flush();
-
-        for(int i=0; i<vals_length; i++) {
-            System.out.print("\rreading back... " + i+"/"+vals_length+"  ");
-            BitVector rec = fp.recvWord();
-            System.out.print(" (prev result: " + rec + " = " + rec.toLong() + ")");
-        }
-        System.out.println("\rdone.                                                                    ");
-
-        //if (true) return ret;
-
-        Context ctx2 = new Context(fp.getFleet());
-        Dock debugIn = fleet.getShip("Debug",0).getDock("in");
-        Dock fred = debugIn;
-        fp.sendToken(debugIn.getInstructionDestination());
-        fp.flush();
-
-        LoopFactory lf = new LoopFactory(ctx2, debugIn, 0);
-        lf.literal(0);
-        lf.abortLoopIfTorpedoPresent();
-        lf.recvToken();
-        lf.deliver();
-
-        ctx2.dispatch(fp);
-        fp.flush();
-
-        int count = 0;
-
-        Ship counter = proc.pool.allocateShip("Counter");
-
-        for(int phase=0; phase<=3; phase++) {
-            System.out.println("== phase "+phase+" ==================================================================");
-            ctx2 = new Context(fp.getFleet());
-
-            Destination ackDestination = counter.getDock("in2").getDataDestination();
-            proc.reset(ctx2, phase, ackDestination);
-
-            Context ctx3 = new Context(fp.getFleet());
-            lf = new LoopFactory(ctx3, counter.getDock("inOp"), 1);
-            lf.literal("DROP_C1_V2");
-            lf.deliver();
-            lf.literal(5);
-            lf.deliver();
-            lf = new LoopFactory(ctx3, counter.getDock("in1"), 1);
-            lf.literal(reset_count-1);
-            lf.deliver();
-            lf.literal(1);
-            lf.deliver();
-            lf = new LoopFactory(ctx3, counter.getDock("in2"), 0);
-            lf.abortLoopIfTorpedoPresent();
-            lf.recvWord();
-            lf.deliver();
-            lf = new LoopFactory(ctx3, counter.getDock("out"), 1);
-            lf.collectWord();
-            lf.sendToken(counter.getDock("in2").getInstructionDestination());  // HACK: we don't check to make sure this hits
-            lf.sendToken(debugIn.getDataDestination());
-            ctx3.dispatch(fp);  // HACK: we don't check to make sure that this is "firmly in place"
-
-            for(Dock dock : torpedoes) fp.sendToken(dock.getInstructionDestination());
-            ctx2.dispatch(fp);
-            fp.flush();
-            System.out.println("flushed");
-
-            fp.recvWord();
-            System.out.println("phase done");
-
-            System.out.println();
-        }
-
-        fp.sendToken(debugIn.getInstructionDestination());
-        fp.flush();
-
-        //System.out.println("verifying cleanup:");
-        //CleanupUtils.verifyClean(fp);
-
-        System.out.println("reading back:");
-        long[] ret = null;
-        if (vals != null) {
-            ret = new long[vals_length];
-            BitVector[] mem = new BitVector[vals_length];
-            MemoryUtils.readMem(fp, memoryShip2, 0, mem);
-            for(int i=0; i<ret.length; i++) ret[i] = mem[i].toLong();
-        }
-        return ret;
-    }
 
     private BitVector[] longsToBitVectors(long[] initialValues) {
         BitVector[] bv = new BitVector[initialValues.length];
diff --git a/src/edu/berkeley/fleet/dataflow/DebugNode.java b/src/edu/berkeley/fleet/dataflow/DebugNode.java
new file mode 100644 (file)
index 0000000..01e2442
--- /dev/null
@@ -0,0 +1,10 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class DebugNode extends Node {
+    public final Ship ship = dfg.pool.allocateShip("Debug");
+    public final InPort in = new DockInPort("in", ship.getDock("in"));
+    // NOTE: shutdown needs to treat this specially
+    public DebugNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/DownCounterNode.java b/src/edu/berkeley/fleet/dataflow/DownCounterNode.java
new file mode 100644 (file)
index 0000000..a183af9
--- /dev/null
@@ -0,0 +1,13 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class DownCounterNode extends Node {
+    public final Ship    ship  = dfg.pool.allocateShip("Counter");
+    public final InPort  start = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  incr  = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  inOp  = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("COUNT") });
+    public final OutPort out   = new DockOutPort("out", ship.getDock("out"));
+    public DownCounterNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/ForeverNode.java b/src/edu/berkeley/fleet/dataflow/ForeverNode.java
new file mode 100644 (file)
index 0000000..3119f39
--- /dev/null
@@ -0,0 +1,29 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ *  Deliver the constant at out forever.  Flow control in<->out is
+ *  maintained, but out is not flow-controlled, so be sure
+ *  that every datum sent there is consumed synchronously wiht
+ *  data items sent to out.
+ */
+public class ForeverNode extends Node {
+    private BitVector bv;
+    public final OutPort out = new OutPort("out") {
+            public void sendToken(LoopFactory lf) { }
+            public void recvWord(LoopFactory lf) { }
+            public void build(Context ctx) { }
+            public void reset(Context ctx, int phase, Destination ackDestination) { }
+            public void setPeer(InPort peer) {
+                this.peer = peer;
+                DockInPort pip = ((DockInPort)peer);
+                for(int i=0; i<pip.pattern.length; i++) {
+                    if (pip.pattern[i]==null)
+                        pip.pattern[i] = bv;
+                }
+            }
+        };
+    public ForeverNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
+    public ForeverNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/MemoryNode.java b/src/edu/berkeley/fleet/dataflow/MemoryNode.java
new file mode 100644 (file)
index 0000000..e606803
--- /dev/null
@@ -0,0 +1,100 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+
+public class MemoryNode extends Node {
+    public final Ship    ship;
+    public final InPort  inCBD;
+    public final InPort  inAddrRead1;
+    public final InPort  inAddrRead2;
+    public final InPort  inAddrWrite;
+    public final InPort  inDataWrite;
+    public final OutPort outRead1;
+    public final OutPort outRead2;
+    public final OutPort outWrite;
+    public MemoryNode(DataFlowGraph dfg, Ship memoryShip) {
+        super(dfg);
+        this.ship = memoryShip;
+        this.inCBD        = ship.getType().equals("Memory") ? new DockInPort("inCBD", ship.getDock("inCBD")) : null;
+        this.inAddrWrite  = new DockInPort("inAddrWrite", ship.getDock("inAddrWrite"));
+        this.inDataWrite  = new DockInPort("inDataWrite", ship.getDock("inDataWrite"));
+        this.inAddrRead1  = new InPort("inAddrRead1") {
+                public void recvToken(LoopFactory lf) { lf.recvToken(); }
+                public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(0)); }
+                public void build(Context ctx) { }
+                public int getTokensToAbsorb() { return outRead1.peer.getTokensToAbsorb(); }
+                public void reset(Context ctx, int phase, Destination ackDestination) {
+                    doReset(ctx, phase, ship.getDock("inAddrRead"), null, ackDestination, false);
+                }
+            };
+        this.inAddrRead2  = new InPort("inAddrRead2") {
+                public void recvToken(LoopFactory lf) { lf.recvToken(); }
+                public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(1)); }
+                public void build(Context ctx) { }
+                public int getTokensToAbsorb() { return outRead2.peer.getTokensToAbsorb(); }
+                public void reset(Context ctx, int phase, Destination ackDestination) { }
+            };
+        this.outRead1 = new OutPort("outRead1") {
+                public void sendToken(LoopFactory lf) { inAddrRead1.peer.sendToken(lf); }
+                public void recvWord(LoopFactory lf) { lf.recvWord(); }
+                public void build(Context ctx) { }
+                public void reset(Context ctx, int phase, Destination ackDestination) { }
+            };
+        this.outRead2 = new OutPort("outRead2") {
+                public void sendToken(LoopFactory lf) { inAddrRead2.peer.sendToken(lf); }
+                public void recvWord(LoopFactory lf) { lf.recvWord(); }
+                public void build(Context ctx) { }
+                public void reset(Context ctx, int phase, Destination ackDestination) { }
+            };
+        this.outWrite = new DockOutPort("out", ship.getDock("out")) {
+                protected void build(Context ctx, LoopFactory lf) {
+                    lf = lf.makeNext(0);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.collectWord();
+                        
+                    lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO.add(FlagC));
+                    if (this.peer != null) {
+                        lf.setPredicate(Predicate.FlagB);
+                        lf.literal(77);
+                        lf.abortLoopIfTorpedoPresent();
+                        this.peer.recvToken(lf);
+                        this.peer.sendWord(lf);
+                    }
+                        
+                    lf.setPredicate(Predicate.NotFlagB);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.recvToken();
+                    lf.setFlags(FlagFunction.ZERO.add(NotFlagC).add(FlagB), FlagFunction.ZERO.add(FlagC).add(FlagB));
+                    if (outRead1.peer != null) {
+                        lf.setPredicate(Predicate.NotFlagB);
+                        outRead1.peer.sendWord(lf);
+                    }
+                    if (outRead2.peer != null) {
+                        lf.setPredicate(Predicate.NotFlagA);
+                        outRead2.peer.sendWord(lf);
+                    }
+                    lf.setPredicate(null);
+                }
+            };
+    }
+    public void build(Context ctx) {
+        super.build(ctx);
+        LoopFactory lf;
+
+        lf = new LoopFactory(ctx, ship.getDock("inAddrRead"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvWord();
+        lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+        lf.setPredicate(Predicate.NotFlagA);
+        lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(0));
+        lf.setPredicate(Predicate.FlagA);
+        lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(1));
+        lf.setPredicate(null);
+        lf.deliver();
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/MergeSort.java b/src/edu/berkeley/fleet/dataflow/MergeSort.java
new file mode 100644 (file)
index 0000000..cdfc8b3
--- /dev/null
@@ -0,0 +1,166 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+
+public class MergeSort {
+    public static long[] mergeSort(FleetProcess fp, Fleet fleet,
+                                   long[] vals, int vals_length, int stride_length,
+                                   Ship memoryShip1, Ship memoryShip2) throws Exception {
+
+        if (vals != null) {
+            BitVector[] mem = new BitVector[vals_length];
+            for(int i=0; i<mem.length; i++) mem[i] = new BitVector(fleet.getWordWidth()).set(vals[i]);
+            MemoryUtils.writeMem(fp, memoryShip1, 0, mem);
+        }
+
+        //////////////////////////////////////////////////////////////////////////////
+
+        DataFlowGraph proc = new DataFlowGraph(fleet);
+        DebugNode dm = new DebugNode(proc);
+
+        int end_of_data = vals_length;
+        int num_strides = end_of_data / (stride_length * 2);
+
+        MemoryNode mm  = new MemoryNode(proc, memoryShip1);
+        SortedMergeNode sm = new SortedMergeNode(proc);
+
+        // So far: we have four spare Counter ships; one can be used for resetting
+        for(int i=0; i<2; i++) {
+
+            DownCounterNode c0 = new DownCounterNode(proc);
+            DownCounterNode c1 = new DownCounterNode(proc);
+
+            c0.start.connect(new ForeverNode(proc, stride_length).out);
+            c0.incr.connect(new ForeverNode(proc, 1).out);
+
+            c1.start.connect(new OnceNode(proc, end_of_data + i*stride_length).out);
+            c1.incr.connect(new OnceNode(proc, stride_length*2).out);
+
+            RepeatNode r1 = new RepeatNode(proc);
+            r1.val.connect(c1.out);
+            r1.count.connect(new ForeverNode(proc, stride_length).out);
+
+            AluNode alu = new AluNode(proc);
+            alu.in1.connect(r1.out);
+            alu.in2.connect(c0.out);
+            alu.inOp.connect(new ForeverNode(proc, ((Node.DockInPort)alu.inOp).getConstant("ADD")).out);
+            alu.out.connect(i==0 ? mm.inAddrRead1 : mm.inAddrRead2);
+
+            PunctuatorNode punc = new PunctuatorNode(proc, -1);
+            punc.count.connect(new ForeverNode(proc, stride_length).out);
+            punc.val.connect(i==0 ? mm.outRead1 : mm.outRead2);
+            punc.out.connect(i==0 ? sm.in1 : sm.in2);
+        }
+
+        UnPunctuatorNode unpunc = new UnPunctuatorNode(proc);
+        unpunc.val.connect(sm.out);
+        unpunc.count.connect(new ForeverNode(proc, 2*stride_length).out);
+
+        DownCounterNode cw = new DownCounterNode(proc);
+        cw.start.connect(new OnceNode(proc, end_of_data).out);
+        cw.incr.connect(new OnceNode(proc, 1).out);
+
+        MemoryNode mm2 = new MemoryNode(proc, memoryShip2);
+        mm2.inAddrWrite.connect(cw.out);
+        mm2.inDataWrite.connect(unpunc.out);
+        mm2.outWrite.connect(dm.in);
+
+        //////////////////////////////////////////////////////////////////////////////
+
+        Context ctx = new Context(fp.getFleet());
+        ctx.setAutoflush(true);
+
+        ArrayList<Instruction> ai = new ArrayList<Instruction>();
+        proc.build(ctx);
+        ctx.emit(ai);
+        for(Instruction ins : ai) {
+            //System.out.println(ins);
+            fp.sendInstruction(ins);
+        }
+        fp.flush();
+
+        for(int i=0; i<vals_length; i++) {
+            System.out.print("\rreading back... " + i+"/"+vals_length+"  ");
+            BitVector rec = fp.recvWord();
+            System.out.print(" (prev result: " + rec + " = " + rec.toLong() + ")");
+        }
+        System.out.println("\rdone.                                                                    ");
+
+        //if (true) return ret;
+
+        Context ctx2 = new Context(fp.getFleet());
+        Dock debugIn = fleet.getShip("Debug",0).getDock("in");
+        Dock fred = debugIn;
+        fp.sendToken(debugIn.getInstructionDestination());
+        fp.flush();
+
+        LoopFactory lf = new LoopFactory(ctx2, debugIn, 0);
+        lf.literal(0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvToken();
+        lf.deliver();
+
+        ctx2.dispatch(fp);
+        fp.flush();
+
+        int count = 0;
+
+        Ship counter = proc.pool.allocateShip("Counter");
+
+        for(int phase=0; phase<=3; phase++) {
+            System.out.println("== phase "+phase+" ==================================================================");
+            ctx2 = new Context(fp.getFleet());
+
+            Destination ackDestination = counter.getDock("in2").getDataDestination();
+            proc.reset(ctx2, phase, ackDestination);
+
+            Context ctx3 = new Context(fp.getFleet());
+            lf = new LoopFactory(ctx3, counter.getDock("inOp"), 1);
+            lf.literal("DROP_C1_V2");
+            lf.deliver();
+            lf.literal(5);
+            lf.deliver();
+            lf = new LoopFactory(ctx3, counter.getDock("in1"), 1);
+            lf.literal(DataFlowGraph.reset_count-1);
+            lf.deliver();
+            lf.literal(1);
+            lf.deliver();
+            lf = new LoopFactory(ctx3, counter.getDock("in2"), 0);
+            lf.abortLoopIfTorpedoPresent();
+            lf.recvWord();
+            lf.deliver();
+            lf = new LoopFactory(ctx3, counter.getDock("out"), 1);
+            lf.collectWord();
+            lf.sendToken(counter.getDock("in2").getInstructionDestination());  // HACK: we don't check to make sure this hits
+            lf.sendToken(debugIn.getDataDestination());
+            ctx3.dispatch(fp);  // HACK: we don't check to make sure that this is "firmly in place"
+
+            for(Dock dock : DataFlowGraph.torpedoes) fp.sendToken(dock.getInstructionDestination());
+            ctx2.dispatch(fp);
+            fp.flush();
+            System.out.println("flushed");
+
+            fp.recvWord();
+            System.out.println("phase done");
+
+            System.out.println();
+        }
+
+        fp.sendToken(debugIn.getInstructionDestination());
+        fp.flush();
+
+        //System.out.println("verifying cleanup:");
+        //CleanupUtils.verifyClean(fp);
+
+        System.out.println("reading back:");
+        long[] ret = null;
+        if (vals != null) {
+            ret = new long[vals_length];
+            BitVector[] mem = new BitVector[vals_length];
+            MemoryUtils.readMem(fp, memoryShip2, 0, mem);
+            for(int i=0; i<ret.length; i++) ret[i] = mem[i].toLong();
+        }
+        return ret;
+    }
+}
\ No newline at end of file
diff --git a/src/edu/berkeley/fleet/dataflow/Node.java b/src/edu/berkeley/fleet/dataflow/Node.java
new file mode 100644 (file)
index 0000000..2b6ad25
--- /dev/null
@@ -0,0 +1,243 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import java.util.concurrent.Semaphore;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+
+public class Node {
+
+    void doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, boolean peerUsed) {
+        if (dock.getShip().getType().equals("Debug")) return;
+
+        switch(phase) {
+
+            // Phase 0: torpedo every output dock, put it in
+            // collecting mode.  Cannot combine with phase 1,
+            // because until output docks are in vacuum mode we
+            // cannot be sure that the tokens to the input docks
+            // will eventually succeed.  This may cause the
+            // instructions sent after the tokens to back up into
+            // the switch fabric.
+            case 0: {
+                if (!dock.isInputDock()) {
+                    DataFlowGraph.torpedoes.add(dock);
+                    LoopFactory lf = new LoopFactory(ctx, dock, 1);
+                    lf.sendToken(ackDestination);
+                    lf = lf.makeNext(0);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.collectWord();
+                    DataFlowGraph.reset_count++;
+                }
+                break;
+            }
+
+                // Phase 1: torpedo every input dock, put it in loopback mode
+            case 1: {
+                if (dock.isInputDock()) {
+                    DataFlowGraph.torpedoes.add(dock);
+                    LoopFactory lf = new LoopFactory(ctx, dock, 1);
+                    lf.sendToken(ackDestination);
+
+                    // FIXME: this won't work right for ports that
+                    // get "shared" by two senders (for example,
+                    // inAddrRead1/2)
+
+                    if (peerUsed && peer!=null) {
+                        lf = lf.makeNext(0);
+                        lf.abortLoopIfTorpedoPresent();
+                        ((OutPort)peer).recvWord(lf);
+                        ((OutPort)peer).sendToken(lf);
+                    }
+                    DataFlowGraph.reset_count++;
+                }
+                break;
+            }
+
+                // Phase 2: torpedo every output dock, have it absorb tokens
+            case 2: {
+                if (!dock.isInputDock()) {
+                    DataFlowGraph.torpedoes.add(dock);
+                    LoopFactory lf = new LoopFactory(ctx, dock, 1);
+                    if (peer != null)
+                        for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
+                            lf.recvToken();
+                    lf.sendToken(ackDestination);
+                    DataFlowGraph.reset_count++;
+                }
+                break;
+            }
+
+                // Phase 3: torpedo every input dock, and we're done
+            case 3: {
+                if (dock.isInputDock()) {
+                    if (peerUsed && peer!=null) {
+                        DataFlowGraph.torpedoes.add(dock);
+                    }
+                    LoopFactory lf = new LoopFactory(ctx, dock, 1);
+                    lf.sendToken(ackDestination);
+                    DataFlowGraph.reset_count++;
+                }
+                break;
+            }
+
+
+        }
+    }
+
+    public final DataFlowGraph dfg;
+    public Node(DataFlowGraph dfg) {
+        this.dfg = dfg;
+        dfg.addNode(this);
+    }
+
+    private HashMap<String,Port> ports = new HashMap<String,Port>();
+
+    public InPort  getInPort(String name)  { return (InPort)ports.get(name); }
+    public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
+        
+    public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
+    public void reset(Context ctx, int phase, Destination ackDestination) {
+        for(Port p : ports.values()) p.reset(ctx, phase, ackDestination);
+    }
+
+    public abstract class Port {
+        public final String name;
+        public Port(String name) {
+            this.name = name;
+            if (Node.this.ports.get(name)!=null) throw new RuntimeException();
+            Node.this.ports.put(name,this);
+        }
+        public abstract void build(Context ctx);
+        public abstract void reset(Context ctx, int phase, Destination ackDestination);
+    }
+
+    public abstract class InPort extends Port {
+        OutPort peer;
+        public InPort(String name) { super(name); }
+        public void connect(OutPort peer) {
+            this.setPeer(peer);
+            peer.setPeer(this);
+        }
+        public void setPeer(OutPort peer) {
+            if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
+            this.peer = peer;
+        }
+
+        /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
+        public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
+        /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
+        public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
+
+        public int getTokensToAbsorb() { return 0; }
+    }
+
+    public abstract class OutPort extends Port {
+        InPort peer;
+        public OutPort(String name) { super(name); }
+        public void connect(InPort peer) {
+            this.setPeer(peer);
+            peer.setPeer(this);
+        }
+        public void setPeer(InPort peer) {
+            if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
+            this.peer = peer;
+        }
+
+        /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
+        public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
+        /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
+        public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
+    }
+
+    public final class DockInPort extends InPort {
+        final Dock dock;
+        int count;
+        BitVector[] pattern;
+        public DockInPort(String name, Dock dock) { this(name, dock, 0); }
+        public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
+        public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
+            super(name);
+            this.dock = dock;
+            this.count = count;
+            this.pattern = pattern;
+        }
+        public void recvToken(LoopFactory lf) { lf.recvToken(); }
+        public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
+        public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
+        // number-in-flight is considered a property of the input dock in a pair
+        public int getInflight() { return 4; }
+        //public int getInflight() { return 1; }
+        public int getTokensToAbsorb() { return getInflight(); }
+        private boolean peerUsed() {
+            if (peer==null) return false;
+            for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
+            return false;
+        }
+        public void reset(Context ctx, int phase, Destination ackDestination) {
+            doReset(ctx, phase, dock, peer, ackDestination, peerUsed());
+        }
+        protected void build(Context ctx, LoopFactory lf) {
+            int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
+
+            if (peer!=null)
+                for(int i=0; i<inflight; i++) peer.sendToken(lf);
+
+            lf = lf.makeNext(count, true);
+            for(int i=0; i<pattern.length; i++) {
+                if (pattern[i]==null) {
+                    if (peer!=null) {
+                        lf.abortLoopIfTorpedoPresent();
+                        peer.recvWord(lf);
+                        peer.sendToken(lf);
+                        lf.deliver();
+                    } else {
+                        lf.interruptibleNop();
+                    }
+                } else {
+                    lf.literal(pattern[i]);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.deliver();
+                }
+            }
+
+            if (count!=0) {
+                // "torpedoable nop" to keep the dock in a receptive state
+                lf.abortLoopIfTorpedoPresent();
+                lf.recvToken();
+            }
+        }
+        public BitVector getConstant(String constantName) {
+            return dock.getConstant(constantName);
+        }
+    }
+
+    public /*final*/ class DockOutPort extends OutPort {
+        public final Dock dock;
+        public final int count;
+        public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
+        public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
+        public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
+        public void recvWord(LoopFactory lf) { lf.recvWord(); }
+        public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
+        protected void build(Context ctx, LoopFactory lf) {
+            if (peer==null) return;
+            lf = lf.makeNext(count);
+            lf.abortLoopIfTorpedoPresent();
+            peer.recvToken(lf);
+            lf.collectWord();
+            peer.sendWord(lf);
+        }
+        public void reset(Context ctx, int phase, Destination ackDestination) {
+            doReset(ctx, phase, dock, peer, ackDestination, true);
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/dataflow/OnceNode.java b/src/edu/berkeley/fleet/dataflow/OnceNode.java
new file mode 100644 (file)
index 0000000..a096095
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class OnceNode extends Node {
+    private BitVector bv;
+    public final OutPort out = new OutPort("out") {
+            public void sendToken(LoopFactory lf) { }
+            public void recvWord(LoopFactory lf) { }
+            public void build(Context ctx) { }
+            public void reset(Context ctx, int phase, Destination ackDestination) { }
+            public void setPeer(InPort peer) {
+                this.peer = peer;
+                DockInPort pip = ((DockInPort)peer);
+                BitVector[] pip_pattern = pip.pattern;
+                BitVector[] temp = new BitVector[pip_pattern.length * 2];
+                int j = 0;
+                int i = 0;
+                boolean done = false;
+                // FIXME: if peer.count is already 1, this gets simpler and different
+                for(i=0; i<temp.length; i++) {
+                    if (pip_pattern[j] != null) {
+                        temp[i] = pip_pattern[j];
+                    } else {
+                        if (done) break;
+                        done = true;
+                        temp[i] = bv;
+                    }
+                    j++;
+                    if (j >= pip_pattern.length) j = 0;
+                }
+                pip.pattern = new BitVector[i];
+                System.arraycopy(temp, 0, pip.pattern, 0, i);
+                pip.count = 1;
+            }
+        };
+    public OnceNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
+    public OnceNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/PunctuatorNode.java b/src/edu/berkeley/fleet/dataflow/PunctuatorNode.java
new file mode 100644 (file)
index 0000000..7fe4577
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class PunctuatorNode extends Node {
+    private final long    punc;
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
+    public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
+    public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("PASS_C2_V1"),
+            ship.getDock("inOp").getConstant("PASS_C2_V2") } );
+    public  final InPort  count;
+    public PunctuatorNode(DataFlowGraph dfg, long punc) {
+        super(dfg);
+        this.punc = punc;
+        this.count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, dfg.bv(1), dfg.bv(punc) });
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/RepeatNode.java b/src/edu/berkeley/fleet/dataflow/RepeatNode.java
new file mode 100644 (file)
index 0000000..7e9ae34
--- /dev/null
@@ -0,0 +1,13 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class RepeatNode extends Node {
+    public final Ship    ship   = dfg.pool.allocateShip("Counter");
+    public final InPort  count  = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  val    = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  inOP   = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("REPEAT_C1_V2") });
+    public final OutPort out    = new DockOutPort("out", ship.getDock("out"));
+    public RepeatNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/SortedMergeNode.java b/src/edu/berkeley/fleet/dataflow/SortedMergeNode.java
new file mode 100644 (file)
index 0000000..4a6bea7
--- /dev/null
@@ -0,0 +1,13 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class SortedMergeNode extends Node {
+    public final Ship    ship = dfg.pool.allocateShip("Alu");
+    public final InPort  in1  = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  in2  = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("MAXMERGE") });
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+    public SortedMergeNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java b/src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java
new file mode 100644 (file)
index 0000000..9607730
--- /dev/null
@@ -0,0 +1,14 @@
+package edu.berkeley.fleet.dataflow;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class UnPunctuatorNode extends Node {
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
+    public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
+    public  final InPort  count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, dfg.bv(1) });
+    public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("PASS_C2_V1"),
+            ship.getDock("inOp").getConstant("DROP_C2_V1") } );
+    public UnPunctuatorNode(DataFlowGraph dfg) { super(dfg); }
+}