add ir.Counter
authoradam <adam@megacz.com>
Mon, 3 Nov 2008 10:19:00 +0000 (11:19 +0100)
committeradam <adam@megacz.com>
Mon, 3 Nov 2008 10:19:00 +0000 (11:19 +0100)
src/edu/berkeley/fleet/ir/Counter.java [new file with mode: 0644]

diff --git a/src/edu/berkeley/fleet/ir/Counter.java b/src/edu/berkeley/fleet/ir/Counter.java
new file mode 100644 (file)
index 0000000..e6ea2ab
--- /dev/null
@@ -0,0 +1,329 @@
+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