public final OutPort out = new DockOutPort("out", ship.getDock("out"));
public AluNode(DataFlowGraph dfg) { super(dfg); }
+ public AluNode(DataFlowGraph dfg, String opcode) {
+ super(dfg);
+ inOp.connect(new ForeverNode(dfg, ((Node.DockInPort)inOp).getConstant(opcode)).out);
+ }
}
import java.util.*;
import java.net.*;
-public class DataFlowGraph {
+/**
+ * A dataflow graph.
+ */
+public class DataFlowGraph implements Iterable<Node> {
public final Fleet fleet;
public final ShipPool pool;
- private HashSet<Node> nodes = new HashSet<Node>();
- public DataFlowGraph(Fleet fleet) { this(fleet, new ShipPool(fleet)); }
+ /**
+ * Use LinkedHashSet to get a predictable/repeatable iteration
+ * order, which leads to predictable/repeatable code
+ */
+ private LinkedHashSet<Node> nodes = new LinkedHashSet<Node>();
+
public DataFlowGraph(Fleet fleet, ShipPool pool) {
this.fleet = fleet;
this.pool = pool;
}
+ public Iterator<Node> iterator() { return nodes.iterator(); }
public void addNode(Node node) { this.nodes.add(node); }
- public void build(Context ctx) {
- for(Node mod : nodes)
- mod.build(ctx);
- }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
- int ret = 0;
- for(Node mod : nodes)
- ret += mod.reset(ctx, phase, ackDestination, sendTorpedoesTo);
- return ret;
+ public CodeBag build(CodeBag cb) {
+ boolean oldAutoflush = cb.getAutoflush();
+ cb.setAutoflush(true);
+ for(Node mod : nodes) mod.build(cb);
+ // this breaks stuff, but it shouldn't!
+ //cb.setAutoflush(oldAutoflush);
+ return cb;
}
}
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
+/** Items supplied to the "in" port will appear at the debug output of the Fleet */
public class DebugNode extends Node {
private final Ship ship = dfg.pool.allocateShip("Debug");
public final InPort in = new DockInPort("in", ship.getDock("in"));
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+public class DiscardNode extends Node {
+
+ private final Ship ship = dfg.pool.allocateShip("Counter");
+ private final InPort op = new DockInPort("op", ship.getDock("inOp"), "PASS_C2_V1");
+ public final InPort in = new DockInPort("val", ship.getDock("in1"));
+ public final InPort count = new DockInPort("count", ship.getDock("in2"));
+
+ public final OutPort out = new DockOutPort("out", ship.getDock("out")) {
+ protected void build(CodeBag ctx, LoopFactory lf) {
+
+ lf = lf.makeNext(0);
+
+ lf.abortLoopIfTorpedoPresent();
+ lf.collectWord();
+ lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+
+ lf.setPredicate(Predicate.FlagA);
+ lf.abortLoopIfTorpedoPresent();
+ peer.recvToken(lf);
+ peer.sendWord(lf);
+ lf.setPredicate(null);
+
+ }
+ };
+
+ public DiscardNode(DataFlowGraph dfg) {
+ super(dfg);
+ }
+
+}
+
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+/**
+ * This class contains all of the shutdown and cleanup logic.
+ */
+public class DoneNode extends Node {
+
+ private final Ship counter = dfg.pool.allocateShip("Counter");
+ private final Program program;
+ private CodeBag shutdownCodeBag = null;
+
+ public final InPort in = new InPort("in") {
+ private Dock dock = counter.getDock("out");
+ public void recvToken(LoopFactory lf) { }
+ public void sendWord(LoopFactory lf) { lf.sendToken(dock); }
+ public int getInflight() { return 1; }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+ public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+ protected void build(CodeBag ctx, LoopFactory lf) {
+ lf.recvToken();
+ lf.literal(getShutdownCodeBag());
+ lf.sendWord(program.getCBDDestination());
+ }
+ };
+
+ public DoneNode(DataFlowGraph dfg, Program program) {
+ super(dfg);
+ this.program = program;
+ }
+
+ public Destination getDestinationToSendNextCodeBagDescriptorTo() {
+ return counter.getDock("in1").getDataDestination();
+ }
+
+ private static final int PHASES = 4;
+
+ private CodeBag getShutdownCodeBag() {
+ if (shutdownCodeBag!=null) return shutdownCodeBag;
+
+ CodeBag[] cb = new CodeBag[PHASES];
+ for(int phase=0; phase<PHASES; phase++)
+ cb[phase] = new CodeBag(dfg.fleet, program);
+
+ for(int phase=0; phase<PHASES; phase++) {
+ // ctx_counter sets up the counter ship which will tally
+ // the acknowledgement tokens coming back from the
+ // torpedoed docks.
+ CodeBag ctx_counter = cb[phase];
+
+ // ctx_reset is the context holding the reset code (not including torpedoes) for this phase
+ CodeBag ctx_reset = new CodeBag(dfg.fleet, program);
+
+ int expected_tokens = 0;
+ for(Node node : dfg)
+ expected_tokens += node.reset(ctx_reset, phase, counter.getDock("in2").getDataDestination());
+ if (expected_tokens==0) throw new RuntimeException("should not happen");
+
+ // The loops below use a count of zero and an
+ // unconditional abort instead of a count of 1. This is
+ // to ensure that the loop will not start executing until
+ // all instructions are safely in the instruction ring.
+ // That in turn ensures that the "ready" tokens are not
+ // sent until the counter is truly prepared to consume a
+ // deluge of tokens.
+
+ LoopFactory lf;
+ lf = ctx_counter.loopFactory(counter.getDock("inOp"), 0);
+ lf.sendToken(counter.getDock("out")); // ready->
+ lf.literal("DROP_C1_V2");
+ lf.deliver();
+ lf.literal("PASS_C1_V1");
+ lf.deliver();
+ lf.abort();
+
+ lf = ctx_counter.loopFactory(counter.getDock("in1"), 0);
+ lf.sendToken(counter.getDock("out")); // ready->
+ lf.literal(expected_tokens);
+ lf.deliver();
+ lf.literal(1);
+ lf.deliver();
+ if (phase<PHASES-1) lf.literal(cb[phase+1]);
+ else lf.recvWord();
+ lf.deliver();
+ lf.abort();
+
+ lf = ctx_counter.loopFactory(counter.getDock("in2"), 1);
+ lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO);
+ lf = lf.makeNext(0);
+ lf.setPredicate(Predicate.FlagD);
+ lf.sendToken(counter.getDock("out"));
+ lf.setPredicate(null);
+ lf.setPredicate(Predicate.NotFlagA);
+ lf.sendToken(counter.getDock("out")); // ready->
+ lf.setPredicate(null);
+ lf.setFlags(FlagFunction.ONE, FlagFunction.ZERO);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+
+ lf = ctx_counter.loopFactory(counter.getDock("out"), 1);
+ lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO);
+ lf.literal(ctx_reset);
+ lf = lf.makeNext(0);
+ lf.setPredicate(Predicate.NotFlagA);
+ lf.recvToken();
+ lf.recvToken();
+ lf.recvToken();
+ lf.sendWord(program.getCBDDestination());
+ lf.setFlags(FlagFunction.ONE, FlagFunction.ZERO);
+ lf.setPredicate(null);
+ lf.collectWord();
+ lf.sendTorpedo(counter.getDock("in2"));
+ lf.recvToken();
+ lf.sendWord(program.getCBDDestination());
+ lf.abort();
+
+ cb[phase].seal();
+ ctx_reset.seal();
+ }
+ return (shutdownCodeBag = cb[0]);
+ }
+
+ // Reset //////////////////////////////////////////////////////////////////////////////
+
+ static int doReset(CodeBag ctx,
+ int phase,
+ Dock dock,
+ Port self,
+ Port peer,
+ Destination ackDestination,
+ boolean peerUsed) {
+ int ret = 0;
+
+ 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()) {
+ ctx.sendTorpedo(dock);
+ LoopFactory lf = ctx.loopFactory(dock, 1);
+ lf.sendToken(ackDestination);
+ lf = lf.makeNext(0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.collectWord();
+ ret++;
+ }
+ break;
+ }
+
+ // [wait for all output docks to confirm that they've been torpedoed]
+ // Phase 1: torpedo every input dock (causing them to flush), put it in loopback mode
+ case 1: {
+ if (dock.isInputDock()) {
+ ctx.sendTorpedo(dock);
+ LoopFactory lf = ctx.loopFactory(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);
+ }
+ ret++;
+ }
+ break;
+ }
+
+ // [wait for all input docks to confirm that they've been torpedoed and have flushed]
+ // Phase 2: torpedo every output dock, have it absorb tokens
+ case 2: {
+ if (!dock.isInputDock()) {
+ ctx.sendTorpedo(dock);
+ LoopFactory lf = ctx.loopFactory(dock, 1);
+ for(int i=0; i<((OutPort)self).getTokensToAbsorb(); i++)
+ lf.recvToken();
+ lf.sendToken(ackDestination);
+ ret++;
+ }
+ break;
+ }
+
+ // [wait for all output docks to confirm that they've absorbed enough tokens]
+ // Phase 3: torpedo every input dock, await confirmation, and we're done
+ case 3: {
+ if (dock.isInputDock()) {
+ if (peerUsed && peer!=null) {
+ ctx.sendTorpedo(dock);
+ }
+ LoopFactory lf = ctx.loopFactory(dock, 1);
+ lf.sendToken(ackDestination);
+ ret++;
+ }
+ break;
+ }
+ }
+ return ret;
+ }
+}
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
+/**
+ * Takes a starting value at "start" and a (positive) decrement
+ * amount at "incr" and counts down; the first value emitted will be
+ * (start-incr).
+ */
public class DownCounterNode extends Node {
private final Ship ship = dfg.pool.allocateShip("Counter");
- private final InPort inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
- ship.getDock("inOp").getConstant("COUNT") });
-
+ private final InPort inOp = new DockInPort("inOp", ship.getDock("inOp"), "COUNT");
public final InPort start = new DockInPort("start", ship.getDock("in1"));
public final InPort incr = new DockInPort("incr", ship.getDock("in2"));
public final OutPort out = new DockOutPort("out", ship.getDock("out"));
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ * Discards all items provided; does not require any ships.
+ */
+public class DropNode extends Node {
+
+ public final InPort in = new InPort("in") {
+ // FIXME: I'm still not sure if this screws up the protocol somewhere
+ public void recvToken(LoopFactory loopfactory_at_output_dock) { }
+ public void sendWord(LoopFactory loopfactory_at_output_dock) { }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+ public void build(CodeBag ctx) { }
+ };
+
+ public DropNode(DataFlowGraph dfg) {
+ super(dfg);
+ }
+
+}
+
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/** A simple FIFO */
+public class FifoNode extends Node {
+ private final Ship ship = dfg.pool.allocateShip("Fifo");
+
+ public final InPort in = new DockInPort("in", ship.getDock("in"));
+ public final OutPort out = new DockOutPort("out", ship.getDock("out"));
+
+ public FifoNode(DataFlowGraph dfg) { super(dfg); }
+}
public final OutPort out = new OutPort("out") {
public void sendToken(LoopFactory lf) { }
public void recvWord(LoopFactory lf) { }
- public void build(Context ctx) { }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) { return 0; }
+ public void build(CodeBag ctx) { }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
public void setPeer(InPort peer) {
this.peer = peer;
DockInPort pip = ((DockInPort)peer);
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class Lut3Node extends Node {
+ private final Ship ship = dfg.pool.allocateShip("Lut3");
+
+ public final InPort in1 = new DockInPort("in1", ship.getDock("in1"));
+ public final InPort in2 = new DockInPort("in2", ship.getDock("in2"));
+ public final InPort in3 = new DockInPort("in3", ship.getDock("in3"));
+ public final InPort inLut = new DockInPort("inLut", ship.getDock("inLut"));
+ public final OutPort out = new DockOutPort("out", ship.getDock("out"));
+
+ public Lut3Node(DataFlowGraph dfg) { super(dfg); }
+}
import java.util.*;
import edu.berkeley.fleet.loops.*;
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.*;
public MemoryNode(DataFlowGraph dfg, Ship memoryShip) {
super(dfg);
this.ship = memoryShip;
+
+ // ugly hack
+ if (ship.getType().equals("Dvi")) {
+ new DockInPort("inPixelX", ship.getDock("inPixelX"), 0, new BitVector[] { null });
+ new DockInPort("inPixelY", ship.getDock("inPixelY"), 0, new BitVector[] { null });
+ new DockInPort("inPixelValue", ship.getDock("inPixelValue"), 0, new BitVector[] { null });
+ }
+
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.inAddrWrite = new InPort("inAddrWrite") {
+ public void recvToken(LoopFactory lf) { lf.recvToken(); }
+ public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrWrite").getDataDestination()); }
+ public void build(CodeBag ctx) {
+ LoopFactory lf = ctx.loopFactory(ship.getDock("inAddrWrite"), 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+ }
+ public int getTokensToAbsorb() { return outWrite.peer.getTokensToAbsorb(); }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+ return DoneNode.doReset(ctx, phase, ship.getDock("inAddrWrite"), this, null, ackDestination, false);
+ }
+ };
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 void build(CodeBag ctx) { }
public int getTokensToAbsorb() { return outRead1.peer.getTokensToAbsorb(); }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
- return doReset(ctx, phase, ship.getDock("inAddrRead"), null, ackDestination, sendTorpedoesTo, false);
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+ return DoneNode.doReset(ctx, phase, ship.getDock("inAddrRead"), this, 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 void build(CodeBag ctx) { }
public int getTokensToAbsorb() { return outRead2.peer.getTokensToAbsorb(); }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) { return 0; }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
};
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 int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) { return 0; }
+ public int getNumInitialTokens() { return Math.max(1,Node.CAPACITY/2); }
+ public void build(CodeBag ctx) { }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
};
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 int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) { return 0; }
+ public int getNumInitialTokens() { return Math.max(1,Node.CAPACITY/2); }
+ public void build(CodeBag ctx) { }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
};
this.outWrite = new DockOutPort("out", ship.getDock("out")) {
- protected void build(Context ctx, LoopFactory lf) {
+ public void sendToken(LoopFactory lf) { inAddrWrite.peer.sendToken(lf); }
+ public void recvWord(LoopFactory lf) { lf.recvWord(); }
+ public int getTokensToAbsorb() { return 0; }
+ protected void build(CodeBag ctx, LoopFactory lf) {
lf = lf.makeNext(0);
lf.abortLoopIfTorpedoPresent();
lf.collectWord();
- lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO.add(FlagC));
+ lf.setFlags(FlagFunction.ONE, 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);
}
}
};
}
- public void build(Context ctx) {
+ public void build(CodeBag ctx) {
super.build(ctx);
LoopFactory lf;
- lf = new LoopFactory(ctx, ship.getDock("inAddrRead"), 0);
+ lf = ctx.loopFactory(ship.getDock("inAddrRead"), 0);
lf.abortLoopIfTorpedoPresent();
lf.recvWord();
lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
lf.setPredicate(null);
lf.deliver();
}
+
+
+
+ public static void clearMem(FleetProcess fp,
+ Ship memory,
+ ShipPool pool,
+ long offset,
+ long count) throws RuntimeException {
+
+ DataFlowGraph dfg = new DataFlowGraph(fp.getFleet(), pool);
+
+ MemoryNode mem = new MemoryNode(dfg, memory);
+ UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+ discard.count.connect(new OnceNode(dfg, (int)(count)).out);
+ DebugNode debug = new DebugNode(dfg);
+ DownCounterNode c1 = new DownCounterNode(dfg);
+ c1.start.connect(new OnceNode(dfg, count).out);
+ c1.incr.connect(new OnceNode(dfg, 1).out);
+ mem.inAddrWrite.connect(c1.out);
+ mem.inDataWrite.connect(new ForeverNode(dfg, 0).out);
+ mem.outWrite.connect(discard.val);
+ discard.out.connect(debug.in);
+
+ CodeBag ctx = new CodeBag(fp.getFleet());
+ dfg.build(ctx);
+ ctx.dispatch(fp, true);
+ System.out.println("waiting...");
+ fp.recvWord();
+ System.out.println("... done");
+
+ // FIXME: cleanup?
+ }
+
+ public static void main(String[] s) throws Exception {
+ Fleet fleet = new Fpga();
+ FleetProcess fp;
+ ShipPool pool = new ShipPool(fleet);
+ Ship mem1 = pool.allocateShip("Memory");
+ Ship mem2 = pool.allocateShip("Memory");
+ Ship mem3 = pool.allocateShip("Memory");
+
+ fp = fleet.run(new Instruction[0]);
+ clearMem(fp, mem1, new ShipPool(fleet), 0, 16 * 1024);
+ fp.terminate();
+
+ fp = fleet.run(new Instruction[0]);
+ clearMem(fp, mem2, new ShipPool(fleet), 0, 16 * 1024);
+ fp.terminate();
+
+ fp = fleet.run(new Instruction[0]);
+ clearMem(fp, mem3, new ShipPool(fleet), 0, 16 * 1024);
+ fp.terminate();
+ }
+
+
}
package edu.berkeley.fleet.dataflow;
import java.util.*;
+import java.io.*;
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
import edu.berkeley.fleet.fpga.*;
-import java.util.*;
+//import org.ibex.graphics.*;
public class MergeSort {
- public static long[] mergeSort(FleetProcess fp, Fleet fleet, ShipPool pool,
- 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);
- }
- //////////////////////////////////////////////////////////////////////////////
+ private final Fleet fleet;
+ private final Ship mem1;
+ private final Ship mem2;
+ private final int arity;
+ private final ShipPool pool;
+ private final Program program;
+ private final DataFlowGraph dfg;
+
+ private ParameterNode[] pn0;
+ private ParameterNode[] pn1;
+ private ParameterNode[] pn2;
+ private ParameterNode[] pn3;
+ private ParameterNode[] pn4;
+ private ParameterNode[] pn_base1;
+ private ParameterNode pn_base2;
+ private ParameterNode pn5;
+ private ParameterNode pn6;
+ private ParameterNode pn_end;
+
+ CodeBag cb2 = null;
+ Destination next_dest = null;
+
+ public MergeSort(Fleet fleet, Program program, ShipPool pool, int arity, Ship mem1, Ship mem2) {
+ this.fleet = fleet;
+ this.mem1 = mem1;
+ this.mem2 = mem2;
+ this.arity = arity;
+ this.pool = pool;
+ this.program = program;
+ this.dfg = new DataFlowGraph(fleet, pool);
+ /*
+ pool.allocateShip(mem1);
+ if (mem2 != mem1) pool.allocateShip(mem2);
+ */
+ next_dest = makeDfgCodeBag(dfg);
+ cb2 = dfg.build(new CodeBag(dfg.fleet, program));
+ cb2.seal();
+ }
- DataFlowGraph proc = new DataFlowGraph(fleet, pool);
- DebugNode dm = new DebugNode(proc);
+ public Destination makeDfgCodeBag(DataFlowGraph dfg) {
- int end_of_data = vals_length;
- int num_strides = end_of_data / (stride_length * 2);
+ MemoryNode mem_read = new MemoryNode(dfg, mem1);
+ MemoryNode mem_write = (mem1==mem2) ? mem_read : new MemoryNode(dfg, mem2);
- MemoryNode mm = new MemoryNode(proc, memoryShip1);
- SortedMergeNode sm = new SortedMergeNode(proc);
+ AluNode sm = new AluNode(dfg, "MAXMERGE");
- // So far: we have four spare Counter ships; one can be used for resetting
- for(int i=0; i<2; i++) {
+ pn0 = new ParameterNode[arity];
+ pn1 = new ParameterNode[arity];
+ pn2 = new ParameterNode[arity];
+ pn3 = new ParameterNode[arity];
+ pn4 = new ParameterNode[arity];
+ pn_base1 = new ParameterNode[arity];
+ pn_base2 = new ParameterNode(dfg, true);
+ pn_end = new ParameterNode(dfg);
+ pn5 = new ParameterNode(dfg);
+ pn6 = new ParameterNode(dfg, true);
- DownCounterNode c0 = new DownCounterNode(proc);
- DownCounterNode c1 = new DownCounterNode(proc);
+ // So far: we have four spare Counter ships; one can be used for resetting
+ for(int i=0; i<arity; i++) {
- c0.start.connect(new ForeverNode(proc, stride_length).out);
- c0.incr.connect(new ForeverNode(proc, 1).out);
+ DownCounterNode c0 = new DownCounterNode(dfg);
+ DownCounterNode c1 = new DownCounterNode(dfg);
- c1.start.connect(new OnceNode(proc, end_of_data + i*stride_length).out);
- c1.incr.connect(new OnceNode(proc, stride_length*2).out);
+ c0.start.connect((pn0[i] = new ParameterNode(dfg, true)).out);
+ c0.incr.connect(new ForeverNode(dfg, 1).out);
+ c1.start.connect((pn1[i] = new ParameterNode(dfg)).out);
+ c1.incr.connect((pn2[i] = new ParameterNode(dfg)).out);
- RepeatNode r1 = new RepeatNode(proc);
+ RepeatNode r1 = new RepeatNode(dfg);
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);
+ r1.count.connect((pn3[i] = new ParameterNode(dfg, true)).out);
+
+ AluNode alu1 = new AluNode(dfg, "ADD");
+ AluNode alu2 = new AluNode(dfg, "ADD");
+ alu1.in1.connect(r1.out);
+ alu1.in2.connect(c0.out);
+ alu1.out.connect(alu2.in2);
+ alu2.in1.connect((pn_base1[i] = new ParameterNode(dfg, true)).out);
+ alu2.out.connect(i==0 ? mem_read.inAddrRead1 : mem_read.inAddrRead2);
+
+ PunctuatorNode punc = new PunctuatorNode(dfg, -1);
+ punc.count.connect((pn4[i] = new ParameterNode(dfg, true)).out);
+ punc.val.connect(i==0 ? mem_read.outRead1 : mem_read.outRead2);
punc.out.connect(i==0 ? sm.in1 : sm.in2);
}
- UnPunctuatorNode unpunc = new UnPunctuatorNode(proc);
+ UnPunctuatorNode unpunc = new UnPunctuatorNode(dfg);
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);
+ unpunc.count.connect(pn6.out);
- MemoryNode mm2 = new MemoryNode(proc, memoryShip2);
- mm2.inAddrWrite.connect(cw.out);
- mm2.inDataWrite.connect(unpunc.out);
- mm2.outWrite.connect(dm.in);
+ DownCounterNode cw = new DownCounterNode(dfg);
+ cw.start.connect(pn5.out);
+ cw.incr.connect(new OnceNode(dfg, 1).out);
- //////////////////////////////////////////////////////////////////////////////
+ AluNode alu = new AluNode(dfg, "ADD");
+ alu.in1.connect(pn_base2.out);
+ cw.out.connect(alu.in2);
+ mem_write.inAddrWrite.connect(alu.out);
+ mem_write.inDataWrite.connect(unpunc.out);
- Ship codeMemoryShip = proc.pool.allocateShip("Memory");
+ UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+ discard.count.connect(pn_end.out);
+ mem_write.outWrite.connect(discard.val);
+ DoneNode done = new DoneNode(dfg, program);
+ discard.out.connect(done.in);
- Context ctx = new Context(fp.getFleet());
- ctx.setAutoflush(true);
- proc.build(ctx);
- ctx.dispatch(fp, true);
+ return done.getDestinationToSendNextCodeBagDescriptorTo();
+ }
- 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. ");
-
- Dock debugIn = fleet.getShip("Debug",0).getDock("in");
- fp.sendToken(debugIn.getInstructionDestination());
- fp.flush();
-
- int count = 0;
- Ship counter = proc.pool.allocateShip("Counter");
-
- for(int phase=0; phase<=3; phase++) {
- System.out.println("== phase "+phase+" ==================================================================");
-
- LoopFactory lf;
-
- Destination ackDestination = counter.getDock("in2").getDataDestination();
- HashSet<Dock> sendTorpedoesTo = new HashSet<Dock>();
- Context ctx_reset = new Context(fp.getFleet());
- int expected_tokens = proc.reset(ctx_reset, phase, ackDestination, sendTorpedoesTo);
-
- Context ctx_debug = new Context(fp.getFleet());
- lf = new LoopFactory(ctx_debug, debugIn, 0);
- lf.literal(0);
- lf.abortLoopIfTorpedoPresent();
- lf.recvToken();
- lf.deliver();
-
- Context ctx_count = new Context(fp.getFleet());
- lf = new LoopFactory(ctx_count, counter.getDock("inOp"), 1);
- lf.literal("DROP_C1_V2");
- lf.deliver();
- lf.literal(5);
- lf.deliver();
- lf = new LoopFactory(ctx_count, counter.getDock("in1"), 1);
- lf.literal(expected_tokens-1);
- lf.deliver();
- lf.literal(1);
- lf.deliver();
- lf = new LoopFactory(ctx_count, counter.getDock("in2"), 0);
- lf.abortLoopIfTorpedoPresent();
- lf.recvWord();
- lf.deliver();
- lf = new LoopFactory(ctx_count, 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());
-
- Program program = new Program(codeMemoryShip);
- CodeBag cb = program.makeCodeBag(ctx_count);
- program.install(fp);
- MemoryUtils.putMemoryShipInDispatchMode(fp, codeMemoryShip);
- program.run(fp, cb);
- fp.flush();
-
- ctx_debug.dispatch(fp, true);
- //ctx_count.dispatch(fp, true); // HACK: we don't check to make sure that this is "firmly in place"
- for(Dock dock : sendTorpedoesTo) fp.sendToken(dock.getInstructionDestination());
- ctx_reset.dispatch(fp, true);
- System.out.println("flushed");
-
- fp.recvWord();
- fp.sendToken(debugIn.getInstructionDestination());
- System.out.println("phase done");
-
- MemoryUtils.removeMemoryShipFromDispatchMode(fp, codeMemoryShip);
- System.out.println();
+ public CodeBag build(DataFlowGraph dfg,
+ CodeBag ctx,
+ int vals_length, int stride_length,
+ long base1,
+ long base2,
+ CodeBag next) throws Exception {
+
+ for(int i=0; i<arity; i++) {
+ if (pn0[i]!=null) pn0[i].set(ctx, stride_length);
+ if (pn1[i]!=null) pn1[i].set(ctx, vals_length + i*stride_length);
+ if (pn2[i]!=null) pn2[i].set(ctx, 2*stride_length);
+ if (pn3[i]!=null) pn3[i].set(ctx, stride_length);
+ if (pn4[i]!=null) pn4[i].set(ctx, stride_length);
+ if (pn_base1[i]!=null) pn_base1[i].set(ctx, base1);
}
+ pn5.set(ctx, vals_length);
+ pn6.set(ctx, 2*stride_length+1);
+ pn_base2.set(ctx, base2);
+ pn_end.set(ctx, vals_length);
+ ctx.sendWord(cb2.getDescriptor(), program.getCBDDestination());
+ ctx.sendWord(next.getDescriptor(), next_dest);
+ ctx.seal();
+
+ return ctx;
+ }
- fp.flush();
-
- //System.out.println("verifying cleanup:");
- //CleanupUtils.verifyClean(fp);
+ public static void main(String[] s) throws Exception {
+ //mergeSort(1024*64, 4, "Dvi",
+ mergeSort(1024*128, 4, "Dvi",
+ 4194304
+ );
+ //548*478);
+ }
- 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();
+ /** demo */
+ public static void main0(String[] s) throws Exception {
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("stats.txt")));
+ //int inflight = 1;
+ for(int inflight=1; inflight <= 8; inflight++)
+ for(int count = 32; count < 2097152; count *= 2) {
+ System.out.println("==============================================================================");
+ System.out.println("count="+count);
+ System.out.println("inflight="+inflight);
+ //long time = timeit(count, inflight);
+ long time = mergeSort(count, inflight, "DDR2", 0);
+ pw.println(inflight + ", " + count + ", " + time);
+ pw.flush();
}
- return ret;
}
- /** demo */
- public static void main(String[] s) throws Exception {
+ public static long timeit(int count, int inflight) throws Exception {
Fleet fleet = new Fpga();
- //Fleet fleet = new Interpreter(false);
+ FleetProcess fp = fleet.run(new Instruction[0]);
+ ShipPool pool = new ShipPool(fleet);
+ //Program program = new Program(pool.allocateShip("Memory"));
+ CodeBag cb = new CodeBag(fleet);
- Random random = new Random(System.currentTimeMillis());
- long[] vals = new long[256];
- for(int i=0; i<vals.length; i++) {
- vals[i] = Math.abs(random.nextInt());
- }
+ Ship counter1 = pool.allocateShip("Counter");
+ Ship counter2 = pool.allocateShip("Counter");
- Ship mem1 = fleet.getShip("Memory", 0);
- Ship mem2 = fleet.getShip("Memory", 1);
- //Ship mem2 = fleet.getShip("DDR2", 0);
+ Ship timer = pool.allocateShip("Timer");
+ Ship debug = pool.allocateShip("Debug");
- FleetProcess fp;
- int stride = 1;
- fp = null;
+ LoopFactory lf;
- fp = fleet.run(new Instruction[0]);
- MemoryUtils.writeMem(fp, mem1, 0, vals);
- int vals_length = vals.length;
+ lf = cb.loopFactory(debug.getDock("in"), 2);
+ lf.recvWord();
+ lf.deliver();
- // Disable readback/writeback inside the loop
- vals = null;
- while(stride < vals_length) {
-
- // reset the FleetProcess
- //fp.terminate(); fp = null;
+ // First counter //////////////////////////////////////////////////////////////////////////////
- System.out.println("stride " + stride);
+ lf = cb.loopFactory(counter1.getDock("in1"), 1);
+ lf.recvToken();
+ lf.literal(count);
+ lf.deliver();
- // if we reset the FleetProcess, restart it
- if (fp==null) fp = fleet.run(new Instruction[0]);
+ lf = cb.loopFactory(counter1.getDock("in2"), 1);
+ lf.literal(1);
+ lf.deliver();
- ShipPool pool = new ShipPool(fleet);
- pool.allocateShip(mem1);
- pool.allocateShip(mem2);
+ lf = cb.loopFactory(counter1.getDock("inOp"), 1);
+ lf.literal("COUNT");
+ lf.deliver();
- // do the mergeSort
- vals = MergeSort.mergeSort(fp, fleet, pool, vals, vals_length, stride, mem1, mem2);
+ lf = cb.loopFactory(counter1.getDock("out"), 0);
+ lf.recvToken();
+ lf.collectWord();
+ lf.sendWord(counter2.getDock("in2"));
- // verify the cleanup
- //CleanupUtils.verifyClean(fp);
- Ship mem = mem1; mem1=mem2; mem2=mem;
+ // Second counter //////////////////////////////////////////////////////////////////////////////
- stride = stride * 2;
- System.out.println();
- }
+ lf = cb.loopFactory(counter2.getDock("in1"), 1);
+ lf.literal(count);
+ lf.deliver();
+ lf.literal(1);
+ lf.deliver();
+ lf.literal(1);
+ lf.deliver();
+
+ lf = cb.loopFactory(counter2.getDock("in2"), 1);
+ for(int i=0; i<inflight; i++)
+ lf.sendToken(counter1.getDock("out"));
+ lf = lf.makeNext(0);
+ lf.recvWord();
+ lf.sendToken(counter1.getDock("out"));
+ lf.deliver();
+
+ lf = cb.loopFactory(counter2.getDock("inOp"), 1);
+ lf.literal("DROP_C1_V2");
+ lf.deliver();
+ lf.literal("PASS_C1_V1");
+ lf.deliver();
+
+ lf = cb.loopFactory(counter2.getDock("out"), 1);
+ lf.collectWord();
+ lf.sendToken(timer.getDock("out"));
+
+
+ // Timer //////////////////////////////////////////////////////////////////////////////
+
+ lf = cb.loopFactory(timer.getDock("out"), 1);
+ lf.collectWord();
+ lf.sendToken(counter1.getDock("in1"));
+ lf.sendWord(debug.getDock("in"));
+ lf.recvToken();
+ lf.collectWord();
+ lf.sendWord(debug.getDock("in"));
+
+ FpgaDock out = (FpgaDock)counter1.getDock("out");
+ FpgaDock in = (FpgaDock)counter2.getDock("in2");
+ System.out.println("distance is " + out.getPathLength((FpgaDestination)in.getDataDestination()));
+ System.out.println("reverse distance is " + in.getPathLength((FpgaDestination)out.getDataDestination()));
+
+ for(Instruction i : cb.emit()) System.out.println(i);
+ cb.dispatch(fp, true);
+ long time1 = fp.recvWord().toLong();
+ System.out.println("got " + time1);
+ long time2 = fp.recvWord().toLong();
+ System.out.println("got " + time2);
+ System.out.println("diff=" + (time2-time1));
+
+ fp.terminate();
+
+ return (time2-time1);
+ }
+
+ public static long mergeSort(int vals_length, int inflight, String shipType, int clearAmount) throws Exception {
+ Node.CAPACITY = inflight;
+
+ Fleet fleet = new Fpga();
+ FleetProcess fp = fleet.run(new Instruction[0]);
+ ShipPool pool = new ShipPool(fleet);
+ Ship mem1 = pool.allocateShip(shipType);
+
+
+ if (clearAmount > 0)
+ randomizeMemory(fp, pool, mem1, 0, clearAmount, false);
+
+ //randomizeMemory(fp, pool, mem1, 0, vals_length, true);
BitVector[] bvs = new BitVector[vals_length];
- MemoryUtils.readMem(fp, mem1, 0, bvs);
+
+ long index = 0;
+ /*
+ Picture p = new Picture(new FileInputStream("campus.png"));
+ for(int y=0; y<(478/2); y++)
+ for(int x=0; x<544; x++) {
+ if (index >= vals_length) break;
+ int pixel = (x>=p.width) ? 0 : p.data[p.width*y+x];
+ long r = (pixel>>0) & 0xff;
+ long g = (pixel>>8) & 0xff;
+ long b = (pixel>>16) & 0xff;
+ r >>= 2;
+ g >>= 2;
+ b >>= 2;
+ //r = ~(-1L<<6);
+ //g = ~(-1L<<6);
+ //b = ~(-1L<<6);
+ bvs[(int)index] = new BitVector(fleet.getWordWidth()).set( r | (g<<6) | (b<<12) | (index<<18) );
+ index++;
+ }
+ */
+ for(; index<vals_length; index++) {
+ long tag = index<<18;
+ bvs[(int)index] = new BitVector(fleet.getWordWidth()).set( tag );
+ }
+
+ System.out.println("final index " + index);
+
+ Random random = new Random(System.currentTimeMillis());
+ for(int i=0; i<bvs.length*10; i++) {
+ int from = Math.abs(random.nextInt()) % bvs.length;
+ int to = Math.abs(random.nextInt()) % bvs.length;
+ BitVector bv = bvs[from];
+ bvs[from] = bvs[to];
+ bvs[to] = bv;
+ }
+
+ MemoryUtils.writeMem(fp, pool, mem1, offset, bvs);
+
+ Program program = new Program(pool.allocateShip("Memory"));
+ long ret = new MergeSort(fleet, program, pool, 2, mem1, mem1).main(fp, vals_length);
+
+ //long ret = 0;
+ // verify the cleanup?
+ //CleanupUtils.verifyClean(fp);
+ //MemoryUtils.readMem(fp, new ShipPool(fp.getFleet()), mem1, 0, bvs);
+
+ BitVector[] bvx = new BitVector[1024];
+ MemoryUtils.readMem(fp, new ShipPool(fp.getFleet()), mem1, 0, bvx);
+ for(int i=0; i<bvx.length; i++)
+ System.out.println(bvx[i]);
+ /*
System.out.println("results:");
- for(int i=0; i<vals_length; i++)
- System.out.println(bvs[i].toLong());
+ for(int i=0; i<vals_length-1; i++)
+ if ( (bvs[i].toLong() & ~(-1L<<18)) != ~(-1L<<18))
+ System.out.println(bvs[i]);
+ */
+ /*
+ for(int i=0; i<vals_length-1; i++) {
+ if (bvs[i].toLong() > bvs[i+1].toLong())
+ System.out.println("sort failure at "+i+":\n "+bvs[i]+"\n "+bvs[i+1]);
+ }
+ */
+ fp.terminate();
+ return ret;
}
+ static int offset = 40;
+
+ //static int offset = 32;
+ //static int offset = 544*2;
+ //static int offset = 544;
+
+ public long main(FleetProcess fp, int vals_length) throws Exception {
+
+ long base_read = offset;
+ //long base_write = offset+((vals_length/544)+1)*544;
+ //long base_write = offset;
+ long base_write = vals_length + offset;
+
+ int stride = 1;
+ ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+ codeBags.add(new CodeBag(dfg.fleet, program));
+ for(; ;) {
+ CodeBag cb = codeBags.get(codeBags.size()-1);
+ //System.out.println("cb="+i+", stride="+stride);
+ boolean last = /*(base_write==offset) && */ (stride*2 >= vals_length);
+ CodeBag next;
+ if (last) {
+ next = program.getEndProgramCodeBag();
+ } else {
+ next = new CodeBag(dfg.fleet, program);
+ codeBags.add(codeBags.size(), next);
+ }
+ build(dfg, cb, vals_length, stride, base_read, base_write, next);
+ cb.seal();
+ long base = base_read; base_read=base_write; base_write=base;
+ //i++;
+ if (last) break;
+ if ((stride*2) < vals_length) stride *= 2;
+ }
+ System.out.println("done building codebags; installing...");
+ System.out.println("cb.length=="+codeBags.size());
+
+ Ship button = pool.allocateShip("Button");
+ CodeBag cb = new CodeBag(dfg.fleet, program);
+ LoopFactory lf = cb.loopFactory(button.getDock("out"), 1);
+ lf.collectWord();
+ lf.literal(codeBags.get(0).getDescriptor());
+ lf.sendWord(program.getCBDDestination());
+ cb.seal();
+
+ // FIXME
+ return program.run(fp, cb, new ShipPool(fp.getFleet()));
+ }
+
+ public static void randomizeMemory(FleetProcess fp, ShipPool pool_, Ship memory, long start, long length, boolean randomize) {
+ ShipPool pool = new ShipPool(pool_);
+ Ship mem = pool.allocateShip("Memory");
+ Program prog = new Program(mem);
+
+ DataFlowGraph dfg = new DataFlowGraph(fp.getFleet(), pool);
+ DownCounterNode dcn = new DownCounterNode(dfg);
+ dcn.start.connectOnce(length);
+ dcn.incr.connectOnce(1);
+
+ AluNode alu = new AluNode(dfg, "ADD");
+ alu.in1.connectForever(start);
+ alu.in2.connect(dcn.out);
+
+ MemoryNode mn = new MemoryNode(dfg, memory);
+ mn.inAddrWrite.connect(alu.out);
+
+ AluNode aluAnd = new AluNode(dfg, "AND");
+ if (randomize) {
+ aluAnd.in1.connect(new RandomNode(dfg).out);
+ } else {
+ //aluAnd.in1.connectForever( ~(-1L<<36) );
+ aluAnd.in1.connectForever( 0 );
+ }
+ aluAnd.in2.connectForever( ~(-1<<18) );
+ mn.inDataWrite.connect(aluAnd.out);
+
+ UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+ discard.count.connectOnce(length);
+ discard.val.connect(mn.outWrite);
+ DoneNode done = new DoneNode(dfg, prog);
+ discard.out.connect(done.in);
+
+ CodeBag cb = new CodeBag(fp.getFleet(), prog);
+ dfg.build(cb);
+ cb.seal();
+
+ CodeBag cb2 = new CodeBag(fp.getFleet(), prog);
+ Ship button = fp.getFleet().getShip("Button",0);
+
+ LoopFactory lf = cb2.loopFactory(button.getDock("out"), 1);
+ //lf.collectWord();
+ lf.literal(prog.getEndProgramCodeBag().getDescriptor());
+ lf.sendWord(done.getDestinationToSendNextCodeBagDescriptorTo());
+ lf.literal(cb.getDescriptor());
+ lf.sendWord(prog.getCBDDestination());
+ cb2.seal();
+
+ System.out.println("dispatching randomization codebag...");
+ prog.run(fp, cb2, pool);
+ System.out.println(" randomization done.");
+ pool.releaseAll();
+ }
}
public class Node {
+ public static int CAPACITY = 4;
+
public final DataFlowGraph dfg;
public Node(DataFlowGraph dfg) {
this.dfg = dfg;
}
private HashMap<String,Port> ports = new HashMap<String,Port>();
- public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
+ public void build(CodeBag ctx) { for(Port p : ports.values()) p.build(ctx); }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) {
int ret = 0;
- for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination, sendTorpedoesTo);
+ for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination);
return ret;
}
if (Node.this.ports.get(name)!=null) throw new RuntimeException();
Node.this.ports.put(name,this);
}
- public abstract void build(Context ctx);
- public abstract int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo);
+ public abstract void build(CodeBag ctx);
+ public abstract int reset(CodeBag ctx, int phase, Destination ackDestination);
public String toString() { return Node.this+"."+name; }
}
this.setPeer(peer);
peer.setPeer(this);
}
+
+ public void connectOnce(long val) { connect(new OnceNode(dfg, val).out); }
+ public void connectForever(long val) { connect(new ForeverNode(dfg, val).out); }
+
public void setPeer(OutPort peer) {
if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
this.peer = peer;
public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
public int getTokensToAbsorb() { return 0; }
+ public int getMaxInFlight() { return 0; }
}
public abstract class OutPort extends Port {
this.peer = peer;
}
+ public int getNumInitialTokens() {
+ return peer.getMaxInFlight();
+ }
+
/** 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 int getTokensToAbsorb() {
+ if (peer==null) return 0;
+ return peer.getTokensToAbsorb();
+ }
}
public final class DockInPort extends InPort {
final Dock dock;
int count;
BitVector[] pattern;
+ public boolean sticky = false;
public DockInPort(String name, Dock dock) { this(name, dock, 0); }
+ public DockInPort(String name, Dock dock, String constant) {
+ this(name, dock, 0, new BitVector[] { dock.getConstant(constant) }); }
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);
}
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(); }
+ public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+
+ // this is the input dock's upper limit on how many data items
+ // may be in flight; the output dock to which it is connected
+ // also has a say
+ public int getMaxInFlight() { return CAPACITY; }
+
+ public int getTokensToAbsorb() { return sticky ? 0 : peer==null ? 0 : peer.getNumInitialTokens(); }
private boolean peerUsed() {
+ if (sticky) return false;
if (peer==null) return false;
for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
return false;
}
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
- return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, peerUsed());
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+ return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, peerUsed());
}
- protected void build(Context ctx, LoopFactory lf) {
- int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
+ protected void build(CodeBag ctx, LoopFactory lf) {
+ /*
+ if (sticky) {
+ if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
+ lf = lf.makeNext(1, true);
+ lf.recvWord();
+ }
+ */
+ if (sticky) {
+ if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
+ lf = lf.makeNext(1, true);
+ lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO);
+ }
- if (peer!=null)
+ if (peer!=null) {
+ int inflight = (count != 0 && count < peer.getNumInitialTokens()) ? count : peer.getNumInitialTokens();
for(int i=0; i<inflight; i++) peer.sendToken(lf);
+ }
lf = lf.makeNext(count, true);
+
+ // ugly hack!
+ if (sticky) {
+ lf.setPredicate(Predicate.NotFlagB);
+ lf.recvWord();
+ lf.setPredicate(null);
+ lf.setFlags(FlagFunction.ZERO, FlagFunction.ONE);
+ }
for(int i=0; i<pattern.length; i++) {
if (pattern[i]==null) {
if (peer!=null) {
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) {
+ public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+ protected void build(CodeBag ctx, LoopFactory lf) {
if (peer==null) return;
lf = lf.makeNext(count);
lf.abortLoopIfTorpedoPresent();
lf.collectWord();
peer.sendWord(lf);
}
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) {
- return doReset(ctx, phase, dock, peer, ackDestination, sendTorpedoesTo, true);
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+ return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, true);
}
}
return ret;
}
- // Reset //////////////////////////////////////////////////////////////////////////////
-
- int doReset(Context ctx,
- int phase,
- Dock dock,
- Port peer,
- Destination ackDestination,
- HashSet<Dock> sendTorpedoesTo,
- boolean peerUsed) {
- int ret = 0;
- if (dock.getShip().getType().equals("Debug")) return ret;
-
- 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()) {
- sendTorpedoesTo.add(dock);
- LoopFactory lf = new LoopFactory(ctx, dock, 1);
- lf.sendToken(ackDestination);
- lf = lf.makeNext(0);
- lf.abortLoopIfTorpedoPresent();
- lf.collectWord();
- ret++;
- }
- break;
- }
-
- // [wait for all output docks to confirm that they've been torpedoed]
- // Phase 1: torpedo every input dock (causing them to flush), put it in loopback mode
- case 1: {
- if (dock.isInputDock()) {
- sendTorpedoesTo.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);
- }
- ret++;
- }
- break;
- }
-
- // [wait for all input docks to confirm that they've been torpedoed and have flushed]
- // Phase 2: torpedo every output dock, have it absorb tokens
- case 2: {
- if (!dock.isInputDock()) {
- sendTorpedoesTo.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);
- ret++;
- }
- break;
- }
-
- // [wait for all output docks to confirm that they've absorbed enough tokens]
- // Phase 3: torpedo every input dock, await confirmation, and we're done
- case 3: {
- if (dock.isInputDock()) {
- if (peerUsed && peer!=null) {
- sendTorpedoesTo.add(dock);
- }
- LoopFactory lf = new LoopFactory(ctx, dock, 1);
- lf.sendToken(ackDestination);
- ret++;
- }
- break;
- }
- }
- return ret;
- }
-
}
public final OutPort out = new OutPort("out") {
public void sendToken(LoopFactory lf) { }
public void recvWord(LoopFactory lf) { }
- public void build(Context ctx) { }
- public int reset(Context ctx, int phase, Destination ackDestination, HashSet<Dock> sendTorpedoesTo) { return 0; }
+ public void build(CodeBag ctx) { }
+ public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
public void setPeer(InPort peer) {
this.peer = peer;
DockInPort pip = ((DockInPort)peer);
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+// derived from OnceNode
+public class ParameterNode extends Node {
+
+ private boolean forever;
+
+ public void set(CodeBag ctx, long l) {
+ set(ctx, new BitVector(ctx.fleet.getWordWidth()).set(l));
+ }
+ public void set(CodeBag ctx, BitVector bv) {
+ ctx.sendWord(bv, ((DockInPort)out.peer).dock.getDataDestination());
+ }
+
+ public final OutPort out = new OutPort("out") {
+ public void sendToken(LoopFactory lf) { }
+ public void recvWord(LoopFactory lf) { if (!forever) lf.recvWord(); }
+ public void build(CodeBag ctx) { }
+ public int reset(CodeBag ctx, int phase,
+ Destination ackDestination) {
+ return 0; }
+ public void setPeer(InPort peer) {
+ this.peer = peer;
+ DockInPort pip = ((DockInPort)peer);
+ BitVector[] pip_pattern = pip.pattern;
+
+ if (forever) {
+ pip.sticky = true;
+ return;
+ }
+
+ 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 ParameterNode(DataFlowGraph dfg) { this(dfg, false); }
+ public ParameterNode(DataFlowGraph dfg, boolean forever) { super(dfg); this.forever = forever; }
+}
import java.util.*;
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+/**
+ * Takes an item from "count", passes that many items from "val" to
+ * "out", and then supplies one instance of "punc" at "out".
+ */
public class PunctuatorNode extends Node {
private final long punc;
- private final Ship ship = dfg.pool.allocateShip("Counter");
- private 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 final OutPort out = new DockOutPort("out", ship.getDock("out"));
+ private final Ship ship = dfg.pool.allocateShip("Counter");
+ private final InPort op = new DockInPort("inOp", ship.getDock("inOp"), "PASS_C2_V1");
public final InPort val = new DockInPort("val", ship.getDock("in1"));
+ public final OutPort out = new DockOutPort("out", ship.getDock("out")) {
+ protected void build(CodeBag ctx, LoopFactory lf) {
+ lf = lf.makeNext(0);
+ lf.abortLoopIfTorpedoPresent();
+ peer.recvToken(lf);
+ lf.collectWord();
+ peer.sendWord(lf);
+
+ lf.literal(punc);
+ lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+ lf.setPredicate(Predicate.FlagA);
+ peer.recvToken(lf);
+ peer.sendWord(lf);
+ lf.setPredicate(null);
+ }
+ };
public PunctuatorNode(DataFlowGraph dfg, long punc) {
super(dfg);
this.punc = punc;
- this.count = new DockInPort("in2", ship.getDock("in2"), 0, new BitVector[] { null, bv(1), bv(punc) });
+ this.count = new DockInPort("in2", ship.getDock("in2"));
}
}
--- /dev/null
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class RandomNode extends Node {
+ private final Ship ship = dfg.pool.allocateShip("Random");
+ public final OutPort out = new DockOutPort("out", ship.getDock("out"));
+ public RandomNode(DataFlowGraph dfg) { super(dfg); }
+}
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
+/**
+ * Takes a count from "count" and an item from "val" and emits
+ * count-many copies of val at "out".
+ */
public class RepeatNode extends Node {
private final Ship ship = dfg.pool.allocateShip("Counter");
- private final InPort inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
- ship.getDock("inOp").getConstant("REPEAT_C1_V2") });
-
- public final InPort count = new DockInPort("count", ship.getDock("in1"));
- public final InPort val = new DockInPort("val", ship.getDock("in2"));
- public final OutPort out = new DockOutPort("out", ship.getDock("out"));
+ private final InPort inOp = new DockInPort("inOp", ship.getDock("inOp"), "REPEAT_C1_V2");
+ public final InPort count = new DockInPort("count", ship.getDock("in1"));
+ public final InPort val = new DockInPort("val", ship.getDock("in2"));
+ public final OutPort out = new DockOutPort("out", ship.getDock("out"));
public RepeatNode(DataFlowGraph dfg) { super(dfg); }
}
import java.util.*;
import edu.berkeley.fleet.loops.*;
import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+/**
+ * Takes an item from the "count" port, then passes/drops through count-1
+ * items from "val" to "out" and drops/passes the count-th item.
+ */
public class UnPunctuatorNode extends Node {
private final Ship ship = dfg.pool.allocateShip("Counter");
- private final InPort op = new DockInPort("op", ship.getDock("inOp"), 0, new BitVector[] {
- ship.getDock("inOp").getConstant("PASS_C2_V1"),
- ship.getDock("inOp").getConstant("DROP_C2_V1") } );
-
- public final OutPort out = new DockOutPort("out", ship.getDock("out"));
+ private final InPort op = new DockInPort("op", ship.getDock("inOp"), "PASS_C2_V1");
public final InPort val = new DockInPort("val", ship.getDock("in1"));
- public final InPort count = new DockInPort("count", ship.getDock("in2"), 0, new BitVector[] { null, bv(1) });
+ public final InPort count = new DockInPort("count", ship.getDock("in2"));
+ public final OutPort out = new DockOutPort("out", ship.getDock("out")) {
+ protected void build(CodeBag ctx, LoopFactory lf) {
+ lf = lf.makeNext(0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.collectWord();
+ lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+ lf.setPredicate(passPunctuationInsteadOfValues ? Predicate.FlagA : Predicate.NotFlagA);
+ lf.abortLoopIfTorpedoPresent();
+ peer.recvToken(lf);
+ peer.sendWord(lf);
+ lf.setPredicate(null);
+ }
+ };
- public UnPunctuatorNode(DataFlowGraph dfg) { super(dfg); }
+ private boolean passPunctuationInsteadOfValues;
+ public UnPunctuatorNode(DataFlowGraph dfg) { this(dfg, false); }
+ public UnPunctuatorNode(DataFlowGraph dfg, boolean passPunctuationInsteadOfValues) {
+ super(dfg);
+ this.passPunctuationInsteadOfValues = passPunctuationInsteadOfValues;
+ }
}