--- /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;
+
+/*
+ - Change Alu behavior to "drain one"
+ - DROP1, DROP2
+ - secondary DDR chip
+ - facility for launching and Concluding a context
+ - implement the merge operation and test it
+ - test case for DRAM ship
+ - hideously ugly hacks in Verilog.java!
+ - dispatch ALWAYS needs to go via memory first, unless transmissions to
+ debugIn are flow-controlled properly
+ - current write-to-mem transformation screws up -- it can clog
+ */
+
+public class Gadgets {
+
+ public static void readMem(FleetProcess fp, Ship memory, long offset, BitVector[] vals) throws RuntimeException {
+ doMem(true, fp, memory, offset, vals);
+ }
+ public static void writeMem(FleetProcess fp, Ship memory, long offset, BitVector[] vals) throws RuntimeException {
+ doMem(false, fp, memory, offset, vals);
+ }
+ public static void doMem(final boolean read, final FleetProcess fp, final Ship memory, final long offset, final BitVector[] vals) throws RuntimeException {
+ if (fp.getFleet() != memory.getFleet())
+ throw new RuntimeException("Fleet mismatch");
+
+ final Dock inAddrWrite = memory.getDock("inAddrWrite");
+ final Dock inDataWrite = memory.getDock("inDataWrite");
+ final Dock inAddrRead = memory.getDock("inAddrRead");
+ final Dock out = memory.getDock("out");
+ final Dock debugIn = fp.getDebugInputDock();
+
+ final Semaphore sem = new Semaphore(12 /* FIXME */);
+
+ Context ctx = new Context(fp.getFleet());
+ LoopFactory lf;
+ if (read) {
+ lf = ctx.new LoopFactory(inAddrRead, 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+ } else {
+ lf = ctx.new LoopFactory(inAddrWrite, 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+ lf = ctx.new LoopFactory(inDataWrite, 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+ }
+
+ lf = ctx.new LoopFactory(out, 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.collectWord();
+ lf.sendWord(debugIn.getDataDestination());
+
+ lf = ctx.new LoopFactory(debugIn, 0);
+ lf.abortLoopIfTorpedoPresent();
+ lf.recvWord();
+ lf.deliver();
+
+ ArrayList<Instruction> ai = new ArrayList<Instruction>();
+ ctx.emit(ai);
+ for(Instruction ins : ai)
+ fp.sendInstruction(ins);
+
+ new Thread() {
+ public void run() { try {
+ for(int i=0; i<vals.length; i++) {
+ if (!sem.tryAcquire()) {
+ fp.flush();
+ sem.acquire();
+ }
+ if (read) {
+ fp.sendWord(inAddrRead.getDataDestination(), new BitVector(fp.getFleet().getWordWidth()).set(i+offset));
+ } else {
+ fp.sendWord(inAddrWrite.getDataDestination(), new BitVector(fp.getFleet().getWordWidth()).set(i+offset));
+ fp.sendWord(inDataWrite.getDataDestination(), vals[i]);
+ }
+ }
+ fp.flush();
+ } catch (Exception e) { throw new RuntimeException(e); }
+ }
+ }.start();
+
+ for(int i=0; i<vals.length; i++) {
+ BitVector outv = fp.recvWord();
+ if (read) vals[i] = outv;
+ if (read) System.out.print("\rread from address: " + i + ", got " + vals[i] + " = " + vals[i].toLong()+" ");
+ else System.out.print("\rwrote to address: " + i+" ");
+ sem.release();
+ }
+
+ if (read) {
+ fp.sendToken(inAddrRead.getInstructionDestination());
+ } else {
+ fp.sendToken(inAddrWrite.getInstructionDestination());
+ fp.sendToken(inDataWrite.getInstructionDestination());
+ }
+ fp.sendToken(out.getInstructionDestination());
+ fp.sendToken(debugIn.getInstructionDestination());
+ System.out.println();
+ }
+
+ /** returns the output Dock at which the merged values may be collected */
+ public static Dock mergeSort(FleetProcess fp,
+ Context ctx,
+ Ship sourceMem,
+ Ship destMem,
+ long read_start,
+ long write_start,
+ int stride_length, /* per arity */
+ int num_strides,
+ int arity
+ )
+ throws RuntimeException {
+
+ if (arity != 2) throw new RuntimeException();
+ if (num_strides != 1) throw new RuntimeException();
+ LoopFactory lf;
+
+ Dock mem_inAddrData = sourceMem.getDock("inAddrData");
+ Dock mem_out = sourceMem.getDock("out");
+
+ Ship merger = ctx.allocateShip("Alu");
+ Dock[] merger_inputs = new Dock[] { merger.getDock("in1"), merger.getDock("in2") };
+ Dock merger_inOp = merger.getDock("inOp");
+
+ // Address Generators (arity-many) /////////////////////////////////////////////////////////////////////
+
+ Ship[] address_generators = new Ship[arity];
+ for(int i=0; i<address_generators.length; i++) {
+ address_generators[i] = ctx.allocateShip("Alu");
+ long start = read_start + i*stride_length;
+ int count = stride_length;
+
+ Dock ag_out = address_generators[i].getDock("out");
+ Dock ag_op = address_generators[i].getDock("inOp");
+ Dock ag_in1 = address_generators[i].getDock("in1");
+ Dock ag_in2 = address_generators[i].getDock("in2");
+ BitVector signal = new BitVector(1/*FIXME*/).set(i/*FIXME*/);
+
+ lf = ctx.new LoopFactory(ag_in1, 0);
+ lf.literal(1);
+ lf = lf.makeNext(count);
+
+
+ lf = ctx.new LoopFactory(ag_out, 1);
+ lf.literal(start);
+ lf = lf.makeNext(0);
+ lf.recvToken();
+ lf.sendWord(mem_inAddrData.getDataDestination(), signal);
+ //lf.sendWord(ag_in1);
+ // FIXME ...
+ }
+
+ // Memory Read ////////////////////////////////////////////////////////////////////////////////////////
+
+ lf = ctx.new LoopFactory(mem_inAddrData, 0);
+ lf.recvWord();
+ lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+ lf.setPredicate(Predicate.NotFlagA);
+ lf.sendToken(mem_out.getDataDestination(), new BitVector(1/*FIXME*/).set(0)); // note: arity-many tokens may pile up at mem_out...
+ lf.setPredicate(Predicate.FlagA);
+ lf.sendToken(mem_out.getDataDestination(), new BitVector(1/*FIXME*/).set(1));
+ lf.setPredicate(null);
+ lf.deliver();
+
+ lf = ctx.new LoopFactory(mem_out, 0);
+ lf.collectWord();
+ lf.recvToken();
+ lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+ lf.setPredicate(Predicate.NotFlagA);
+ lf.sendWord(merger_inputs[0].getDataDestination());
+ lf.setPredicate(Predicate.FlagA);
+ lf.sendWord(merger_inputs[1].getDataDestination());
+ lf.setPredicate(null);
+
+ // Merger /////////////////////////////////////////////////////////////////////////////////////////////
+
+ for(int i=0; i<merger_inputs.length; i++) {
+ lf = ctx.new LoopFactory(merger_inputs[i], stride_length);
+ lf.sendToken(address_generators[i].getDock("out").getDataDestination());
+ lf.recvWord();
+ lf.deliver();
+
+ lf = lf.makeNext(1);
+ lf.literal(-1);
+ lf.deliver();
+ }
+
+ lf = ctx.new LoopFactory(merger_inOp, 1);
+ lf.literal(5); // MIN
+ lf = lf.makeNext(stride_length * arity);
+ lf.deliver();
+ lf = lf.makeNext(1);
+ lf.literal(7); // DROP1
+ lf.deliver();
+ lf.literal(8); // DROP2
+ lf.deliver();
+
+ return merger.getDock("out");
+ }
+
+ 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]);
+ Ship memory = fleet.getShip("DRAM",0);
+ //Ship memory = fleet.getShip("Memory",0);
+ BitVector[] vals = new BitVector[2 * 1024];
+ BitVector[] vals2 = new BitVector[2 * 1024];
+ for(int i=0; i<vals.length; i++)
+ vals[i] = new BitVector(fleet.getWordWidth()).set(random.nextLong());
+ writeMem(fp, memory, 0, vals);
+ 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!");
+ }
+}