--- /dev/null
+package edu.berkeley.fleet.ir;
+import java.util.concurrent.Semaphore;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.fpga.*;
+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 edu.berkeley.fleet.ir.Context.LoopFactory;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.SetDest;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+import static edu.berkeley.fleet.api.Predicate.*;
+import edu.berkeley.fleet.ir.Context.LoopFactory;
+
+public class Counter {
+
+
+ /**
+ * Merge two sorted streams; it will issue tokens to provoke inputs
+ */
+ public static Dock merger(Context ctx,
+ Ship alu,
+ Destination in1_ack,
+ int inflight_in1,
+ Destination in2_ack,
+ int inflight_in2,
+ Destination d) {
+
+ Dock out = alu.getDock("out");
+ Dock inOp = alu.getDock("inOp");
+ Dock in1 = alu.getDock("in1");
+ Dock in2 = alu.getDock("in2");
+
+ LoopFactory lf_in1 = ctx.new LoopFactory(in1, 1);
+ LoopFactory lf_in2 = ctx.new LoopFactory(in2, 1);
+ LoopFactory lf_inOp = ctx.new LoopFactory(inOp, 1);
+
+ for(int i=0; i<inflight_in1; i++) lf_in1.sendToken(in1_ack);
+ for(int i=0; i<inflight_in2; i++) lf_in2.sendToken(in2_ack);
+
+ lf_inOp.literal(4); // MAX
+
+ lf_in1 = lf_in1.makeNext(0);
+ lf_in2 = lf_in2.makeNext(0);
+ lf_inOp = lf_inOp.makeNext(0);
+
+ lf_in1.recvWord();
+ lf_in1.deliver();
+ lf_in1.sendToken(in1_ack);
+
+ lf_in2.recvWord();
+ lf_in2.deliver();
+ lf_in2.sendToken(in2_ack);
+
+ lf_inOp.deliver();
+
+ LoopFactory lf_out = ctx.new LoopFactory(out, 0);
+ lf_out.recvToken();
+ lf_out.collectWord();
+ lf_out.sendWord(d);
+
+ return out;
+ }
+
+
+ // FEATURE: optimize for short runs (use ILC counter, perhaps ILC+OLC combo)
+ // FEATURE: stop-at-zero when counting downward
+ /**
+ * A downward counter; returns the output dock that produces
+ * the values.
+ *
+ * For each token sent to the output dock, a value will be sent
+ * to dest.
+ */
+ public static Dock counter(Context ctx,
+ Ship alu,
+ long start,
+ long incr,
+ int inflight,
+ Destination dest,
+ BitVector signal) {
+
+ if (inflight < 1) throw new RuntimeException();
+
+ boolean incr_is_positive = false;
+ boolean compile_time_start = true;
+ boolean compile_time_incr = true;
+
+ Dock out = alu.getDock("out");
+ Dock inOp = alu.getDock("inOp");
+ Dock in1 = alu.getDock("in1");
+ Dock in2 = alu.getDock("in2");
+ LoopFactory lf;
+
+ //
+ // FIXME: make sure we cope properly with getting torpedoed
+ // before inflight-many tokens have arrived
+ //
+
+ // FIXME: update Alu to "take-one" behavior, then fix stuff below
+
+ LoopFactory lf_in1 = ctx.new LoopFactory(in1, 1);
+ LoopFactory lf_in2 = ctx.new LoopFactory(in2, 1);
+ LoopFactory lf_inOp = ctx.new LoopFactory(inOp, 1);
+ LoopFactory lf_out = ctx.new LoopFactory(out, 1);
+
+ // Phase 1 //////////////////////////////////////////////////////////////////////////////
+
+ if (compile_time_incr) lf_in1.literal(incr); else lf_in1.recvWord();
+ if (compile_time_start) lf_in2.literal(start); else lf_in2.recvWord();
+ for(int i=0; i<inflight; i++) {
+ lf_in1.deliver();
+ lf_inOp.literal(0 /*IN1*/);
+ lf_inOp.deliver();
+ lf_out.collectWord();
+ lf_out.sendWord(in1.getDataDestination());
+
+ lf_in2.deliver();
+ lf_inOp.literal(1 /*IN2*/);
+ lf_inOp.deliver();
+ lf_out.collectWord();
+ lf_out.sendWord(in1.getDataDestination());
+ }
+
+ // Phase 2 //////////////////////////////////////////////////////////////////////////////
+
+ // FIXME: tokens for flow control here
+ lf_inOp.literal(incr_is_positive ? 3/*SUB*/ : 2/*ADD*/);
+ lf_inOp = lf_inOp.makeNext(0);
+ lf_inOp.deliver();
+
+ lf_in2.literal(0);
+ for(int i=0; i<inflight; i++) {
+ lf_in1.recvWord();
+ lf_in1.deliver();
+ lf_in2.deliver();
+ lf_out.collectWord();
+ lf_out.sendWord(in2.getDataDestination());
+
+ lf_in1.recvWord();
+ lf_in1.deliver();
+ lf_in2.deliver();
+
+ lf_out.collectWord();
+ lf_out.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+ lf_out.setPredicate(Predicate.FlagA);
+ lf_out.abort();
+ lf_out.setPredicate(null);
+ lf_out.sendWord(in1.getDataDestination());
+ lf_out.recvToken();
+ lf_out.sendWord(dest, signal);
+
+ lf_in2.recvWord();
+ }
+
+ // Phase 3 //////////////////////////////////////////////////////////////////////////////
+
+ lf_in1 = lf_in1.makeNext(0);
+ lf_in1.recvWord();
+ lf_in1.deliver();
+
+ // FIXME: tokens for flow control here
+ lf_in2 = lf_in2.makeNext(0);
+ lf_in2.deliver();
+
+ lf_out = lf_out.makeNext(0);
+ lf_out.collectWord();
+ lf_out.sendWord(in1.getDataDestination());
+ lf_out.recvToken();
+ lf_out.sendWord(dest, signal);
+
+ // FIXME: ensure that if torpedoes arrive in phase1 or phase2 we deal with them properly
+
+ return out;
+ }
+
+ /**
+ * A memory read with two address inputs.
+ *
+ * Returns the address input dock of the memory ship. Assumes
+ * that addresses will be sent to this dock from two distinct
+ * sources (in0 and in1), distinguished by the signal bit.
+ * Values read from memory will be routed to out0 or out1
+ * depending on which input source the address came from.
+ *
+ * This widget does not send acknowledgement tokens; the
+ * recipients at out0 and out1 should send their tokens to in0
+ * and in1.
+ */
+ public static Dock memReadTwo(Context ctx,
+ Ship mem,
+ Destination out0,
+ Destination out1) {
+
+ Dock inAddrRead = mem.getDock("inAddrRead");
+ Dock out = mem.getDock("out");
+
+ LoopFactory lf_inAddrRead = ctx.new LoopFactory(inAddrRead, 0);
+ LoopFactory lf_out = ctx.new LoopFactory(out, 0);
+
+ lf_inAddrRead.recvWord();
+ lf_inAddrRead.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+ lf_inAddrRead.setPredicate(Predicate.FlagA);
+ lf_inAddrRead.sendToken(out.getDataDestination(), new BitVector(1).set(1));
+ lf_inAddrRead.setPredicate(Predicate.NotFlagA);
+ lf_inAddrRead.sendToken(out.getDataDestination(), new BitVector(1).set(0));
+ lf_inAddrRead.setPredicate(null);
+ lf_inAddrRead.deliver();
+
+ lf_out.recvToken();
+ lf_out.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+ lf_out.collectWord();
+ lf_out.setPredicate(Predicate.FlagA);
+ lf_out.sendWord(out1);
+ lf_out.setPredicate(Predicate.NotFlagA);
+ lf_out.sendWord(out0);
+ lf_out.setPredicate(null);
+
+ return inAddrRead;
+ }
+
+ public static void fillMemRandom(Fleet fleet, Ship memory, FleetProcess fp) {
+ Random random = new Random(System.currentTimeMillis());
+
+ int SIZE = 256;
+
+ int[] ints = new int[SIZE/2];
+ int[] intsbig = new int[SIZE];
+ BitVector[] vals = new BitVector[SIZE];
+ BitVector[] vals2 = new BitVector[SIZE];
+
+ for(int j=0; j<2; j++) {
+ for(int i=0; i<ints.length; i++) {
+ ints[i] = Math.abs(random.nextInt());
+ }
+ ints[ints.length-1] = Integer.MAX_VALUE;
+ Arrays.sort(ints);
+ for(int i=0; i<ints.length; i++) {
+ vals[i+j*ints.length] = new BitVector(fleet.getWordWidth()).set(ints[i]);
+ intsbig[i+j*ints.length] = ints[i];
+ }
+ }
+ Arrays.sort(intsbig);
+
+ Gadgets.writeMem(fp, memory, 0, vals);
+ }
+
+ public static void main(String[] s) throws Exception {
+ Random random = new Random(System.currentTimeMillis());
+ Fleet fleet = new Fpga();
+ FleetProcess fp = fleet.run(new Instruction[0]);
+
+ int SIZE = 128;
+
+ Ship memory = fleet.getShip("DRAM",0);
+ int[] ints = new int[SIZE/2];
+ int[] intsbig = new int[SIZE];
+ BitVector[] vals = new BitVector[SIZE];
+ BitVector[] vals2 = new BitVector[SIZE];
+
+ for(int j=0; j<2; j++) {
+ for(int i=0; i<ints.length; i++) {
+ ints[i] = Math.abs(random.nextInt());
+ }
+ ints[ints.length-1] = Integer.MAX_VALUE;
+ Arrays.sort(ints);
+ for(int i=0; i<ints.length; i++) {
+ vals[i+j*ints.length] = new BitVector(fleet.getWordWidth()).set(ints[i]);
+ intsbig[i+j*ints.length] = ints[i];
+ }
+ }
+ Arrays.sort(intsbig);
+
+ Gadgets.writeMem(fp, memory, 0, vals);
+ Gadgets.readMem(fp, memory, 0, vals2);
+ for(int i=0; i<vals.length; i++)
+ if (!vals[i].equals(vals2[i]))
+ System.out.println("disagreement! on index " + i + "\n "+vals[i]+"\n "+vals2[i]);
+ System.out.println("done reading and verifying!");
+ System.out.println();
+ System.out.println();
+
+ Context ctx = new Context(fp.getFleet());
+ Ship debug = fleet.getShip("Debug", 0);
+
+ Ship merger_alu = ctx.allocateShip("Alu");
+
+ Dock mem_in = memReadTwo(ctx, memory,
+ merger_alu.getDock("in1").getDataDestination(),
+ merger_alu.getDock("in2").getDataDestination());
+
+ Dock counter_0_ack = counter(ctx, ctx.allocateShip("Alu"), SIZE/2-1, -1, 1, mem_in.getDataDestination(), new BitVector(1).set(0));
+
+ Dock counter_1_ack = counter(ctx, ctx.allocateShip("Alu"), SIZE-1, -1, 1, mem_in.getDataDestination(), new BitVector(1).set(1));
+
+ Dock d3 = merger(ctx, merger_alu,
+ counter_0_ack.getDataDestination(), 1,
+ counter_1_ack.getDataDestination(), 1,
+ debug.getDock("in").getDataDestination());
+
+
+ LoopFactory lf;
+ lf = ctx.new LoopFactory(debug.getDock("in"), 0);
+ lf.sendToken(d3.getDataDestination());
+ lf.recvWord();
+ lf.deliver();
+
+ ArrayList<Instruction> ai = new ArrayList<Instruction>();
+ ctx.emit(ai);
+ for(Instruction ins : ai)
+ fp.sendInstruction(ins);
+ fp.flush();
+
+ System.out.println("reading sorted words...");
+ for(int i=intsbig.length-1; i>=0; i--) {
+ BitVector bv = fp.recvWord();
+ int x = (int)bv.toLong();
+ if (x==intsbig[i]) System.out.println("agree " + x);
+ else System.out.println("DISAGREE " + x + " " + intsbig[i]);
+ }
+ System.out.println("done.");
+ }
+
+}
\ No newline at end of file