--- /dev/null
+package edu.berkeley.fleet;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+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.util.BitManipulations.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.SHIFT;
+
+// EXPERIMENTAL. Do not use.
+
+// FEATURE: official definition of what a nonblocking instruction is
+
+/**
+ *
+ * A helper class for building loops of instructions.
+ *
+ * This class abstracts away:
+ * - The maximum size of a loop
+ * - The maximum length of a "one shot" instruction sequence
+ * - The looping/oneshot bit
+ * - The outer loop counter
+ * - The inner loop counter (opportunities to use it are auto-detected)
+ *
+ * It also performs various optimizations and provides a more
+ * convenient way of managing the predicate/interruptible fields.
+ *
+ * To get the most compact coding, the components of a Move should be
+ * performed in this order when possible, with no intervening commands:
+ *
+ * 1. recvToken()
+ * 2. recv()/collect()
+ * 3. sendToken()
+ * 4. deliver()/send()
+ *
+ */
+public class Loops {
+
+ public static abstract class Loop {
+ private final Dock dock;
+ private final String friendlyName;
+ private final int count;
+ private Predicate predicate = Predicate.Default;
+ private Loop next = null;
+ private ArrayList<Instruction> instructions = new ArrayList<Instruction>();
+
+ /**
+ * Creates a new loop.
+ * @dock the dock at which to execute the instructions
+ * @friendlyName a descriptive string for debugging the compiler
+ * @prev a loop for which this is the successor loop (if any)
+ * @count the number of times to execute this loop; <tt>0</tt> means continue until torpedoed
+ */
+ public Loop(Dock dock, int count, String friendlyName, Loop prev) {
+ this.dock = dock;
+ this.count = count;
+ this.friendlyName = friendlyName;
+ if (prev.getNext() != null) throw new RuntimeException();
+ prev.setNext(this);
+ }
+
+ public Loop getNext() { return next; }
+ public void setNext(Loop next) { this.next = next; }
+
+
+ // Building Loops //////////////////////////////////////////////////////////////////////////////
+
+ boolean pending_interruptible = false;
+ boolean pending_recvToken = false;
+ boolean pending_recvOrCollect = false;
+ boolean pending_latchData = false;
+ boolean pending_latchPath = false;
+ boolean pending_sendToken = false;
+ Destination pending_dest = null;
+
+ void flush_pending() { flush_pending(false); }
+ void flush_pending(boolean pending_dataOut) {
+ if (!pending_recvToken &&
+ !pending_recvOrCollect &&
+ !pending_sendToken &&
+ !pending_dataOut) {
+ if (pending_interruptible)
+ throw new RuntimeException("abortLoopIfTorpedoPresent() must be followed immediately by a Move");
+ } else {
+ instructions.add(new Move(dock,
+ count!=1,
+ predicate,
+ pending_interruptible,
+ pending_dest==null ? null : dock.getPath(pending_dest,null),
+ pending_recvToken,
+ pending_recvOrCollect,
+ pending_latchData,
+ pending_latchPath,
+ pending_dataOut,
+ pending_sendToken));
+ }
+ pending_interruptible = false;
+ pending_recvToken = false;
+ pending_recvOrCollect = false;
+ pending_latchData = false;
+ pending_latchPath = false;
+ pending_sendToken = false;
+ pending_dest = null;
+ }
+
+ /** sets the predicate which will be applied to subsequent instructions, or null for the default predicate */
+ public void setPredicate(Predicate p) {
+ if (p==null) p = Predicate.Default;
+ if (predicate==p) return;
+ flush_pending();
+ predicate = p;
+ }
+
+ /** must be followed immediately by a move-based instruction */
+ public void abortLoopIfTorpedoPresent() {
+ flush_pending();
+ if (count!=0) throw new RuntimeException("currently, only forever-loops may be sensitive to torpedoes");
+ pending_interruptible = true;
+ }
+
+ /** [either] */
+ public void recvToken() {
+ if (pending_recvToken || pending_recvOrCollect || pending_sendToken) flush_pending();
+ pending_recvToken = true;
+ }
+
+ /** [inboxes only] */
+ public void recv(boolean latchData, boolean latchPath) {
+ if (!dock.isInputDock()) throw new RuntimeException("recv() may only be used at input docks");
+ if (pending_recvOrCollect || pending_sendToken) flush_pending();
+ pending_recvOrCollect = true;
+ pending_latchData = latchData;
+ pending_latchPath = latchPath;
+ }
+
+ /** [outboxes only], will fuse with previous instruction if it was a recvToken() */
+ public void collect(boolean latchData, boolean latchPath) {
+ if (!dock.isOutputDock()) throw new RuntimeException("collect() may only be used at output docks");
+ if (pending_recvOrCollect || pending_sendToken) flush_pending();
+ pending_recvOrCollect = true;
+ pending_latchData = latchData;
+ pending_latchPath = latchPath;
+ }
+
+ /** [either], will fuse with previous instruction if it was a recvToken(), recv(), or collect() */
+ public void sendToken(Destination dest) {
+ if (pending_sendToken) flush_pending();
+ pending_dest = dest;
+ pending_sendToken = true;
+ }
+
+ /** [inboxes only], will fuse with previous instruction if it was a sendToken() */
+ public void deliver() {
+ if (!dock.isInputDock()) throw new RuntimeException("deliver() may only be used at input docks");
+ flush_pending(true);
+ }
+
+ /** [outboxes only], will fuse with previous instruction if it was a sendToken() */
+ public void send(Destination dest) {
+ if (!dock.isOutputDock()) throw new RuntimeException("send() may only be used at output docks");
+ if (pending_sendToken) flush_pending();
+ pending_dest = dest;
+ flush_pending(true);
+ }
+
+ /** sets the data latch to a literal value */
+ public void literal(long literal) {
+ flush_pending();
+ if (FleetTwoFleet.isSmallEnoughToFit(literal)) {
+ instructions.add(new Instruction.Set(dock, count!=1, predicate, SetDest.DataLatch, literal));
+ } else {
+ int counter = 0;
+ while(counter < dock.getShip().getFleet().getWordWidth()) counter += SHIFT.valmaskwidth;
+ warn("literal " + literal + " requires " + counter + " instructions");
+ while(counter > 0) {
+ instructions.add(new Shift(dock, count!=1, predicate,
+ new BitVector(dock.getShip().getFleet().getWordWidth())
+ .set(getField(counter-1, counter-SHIFT.valmaskwidth, literal))));
+ counter -= SHIFT.valmaskwidth;
+ }
+ }
+ }
+
+ /** sets the flags */
+ public void setFlags(Instruction.Set.FlagFunction newFlagA, Instruction.Set.FlagFunction newFlagB) {
+ flush_pending();
+ instructions.add(new Instruction.Set(dock,
+ count!=1,
+ predicate,
+ newFlagA,
+ newFlagB));
+ }
+
+
+ // Emitting Code //////////////////////////////////////////////////////////////////////////////
+
+ void optimize() {
+ flush_pending();
+ // FEATURE: find sequences of >2 adjacent identical instructions, replace with use of ILC
+ // FEATURE: after optimizing, find single-instruction loops, replace with use of ILC
+ // FEATURE: consider doing loop unrolling if two copies of the loop fit in the instruction buffer...
+ // FEATURE: clever instruction re-oredering?
+ }
+
+ /**
+ * The code emitted by this method makes the following assumptions:
+ *
+ * - The instructions emitted are dispatched in order
+ * - At the time of dispatch:
+ * - all instructions which remain in the target dock's instruction fifo are nonblocking instructions
+ * - either the target docks' OLC=0 or all instructions which remain in its instruction fifo are one-shot instructions
+ * - after executing these remaining instructions, the target dock's hatch is open
+ *
+ * A Move instruction is a blocking instruction if either its
+ * tokenIn or dataIn bits are set. All other instructions
+ * are non-blocking.
+ */
+ public void emit(ArrayList<Instruction> ic) {
+ flush_pending();
+ optimize();
+
+ // FIXME: if this loop is a count==1 loop, we can emit the successor loop along with it...
+
+ // the number of instructions after and including the first blocking instruction
+ int numInstructionsNotIncludingNonblockingPrefix = 0;
+ int loopSize = 0;
+ boolean blockingInstructionEncountered = false;
+
+ // Set the OLC (it might previously have been zero)
+ ic.add(new Set(dock, false, Predicate.IgnoreOLC, SetDest.OuterLoopCounter, count==0 ? 1 : count));
+
+ for(Instruction i : instructions) {
+ if (i instanceof Move && (((Move)i).tokenIn || ((Move)i).dataIn))
+ blockingInstructionEncountered = true;
+ if (blockingInstructionEncountered)
+ numInstructionsNotIncludingNonblockingPrefix++;
+ loopSize++;
+ ic.add(i);
+ }
+
+ if (count!=1) {
+ ic.add(new Instruction.Tail(dock));
+ if (loopSize > dock.getInstructionFifoSize())
+ throw new RuntimeException("instruction loop is too long for instruction fifo");
+ } else {
+ if (numInstructionsNotIncludingNonblockingPrefix > dock.getInstructionFifoSize())
+ throw new RuntimeException("instruction sequence is too long for instruction fifo");
+ }
+
+ if (next != null)
+ throw new RuntimeException("no support for successor loops yet");
+ }
+
+ void warn(String warning) {
+ System.err.println("warning: " + warning);
+ }
+
+ // Helpers //////////////////////////////////////////////////////////////////////////////
+
+ public void recvData() { recv(true, false); }
+ public void recvPacket() { recv(true, true); }
+ public void collectData() { collect(true, false); }
+ public void collectPacket() { collect(true, true); }
+
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet.ir;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.interpreter.*;
+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 java.io.*;
+import java.util.*;
+import java.net.*;
+
+// ScanRows+Fix: HARD!
+/**
+ * How do we know when a stream is done? In the case of Equalize?
+ */
+
+// Video-Out
+// Loopback (fixpoint of a bundle)
+
+public class New {
+
+ public final Fleet fleet;
+ public New(Fleet fleet) { this.fleet = fleet; }
+
+ private HashSet<Segment> segments = new HashSet<Segment>();
+
+ private HashSet<Ship> allocated = new HashSet<Ship>();
+ Ship allocate(String shipType) {
+ for(Ship ship : fleet)
+ if (shipType.equals(ship.getType()) && !allocated.contains(ship)) {
+ allocated.add(ship);
+ return ship;
+ }
+ throw new RuntimeException("no more ships of type " + shipType);
+ }
+
+ public void emit(ArrayList<Instruction> al) {
+ for(Segment s : segments) s.emitPrologue(al);
+ for(Segment s : segments) s.emitInstructions(al);
+ for(Segment s : segments) s.emitEpilogue(al);
+ }
+
+ public abstract class Segment {
+
+ public final int inputWidth;
+ public final int outputWidth;
+ protected Dock[] inputs;
+
+ public Segment(int inputWidth, int outputWidth) {
+ this.inputWidth = inputWidth;
+ this.outputWidth = outputWidth;
+ segments.add(this);
+ }
+
+ /** sets input docks, returns output docks */
+ public final Dock[] setInputs(Dock[] inputs) {
+ if (inputs.length != inputWidth) throw new RuntimeException();
+ this.inputs = inputs;
+ Dock[] ret = _setInputs();
+ if (ret.length != outputWidth) throw new RuntimeException();
+ return ret;
+ }
+
+ public abstract Dock[] _setInputs();
+ public void emitPrologue(ArrayList<Instruction> il) { }
+ public abstract void emitInstructions(ArrayList<Instruction> il);
+ public void emitEpilogue(ArrayList<Instruction> il) { }
+ }
+
+ public class Debug extends Segment {
+ Ship debugShip;
+ public Debug() {
+ super(1, 0);
+ debugShip = allocate("Debug");
+ }
+ public Dock[] _setInputs() { return new Dock[0]; }
+ public void emitPrologue(ArrayList<Instruction> il) { }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ il.add(Util.sendto(inputs[0], true, debugShip.getDock("in")));
+ il.add(Util.wait(inputs[0], true));
+
+ il.add(Util.setILCInfinity(debugShip.getDock("in")));
+ il.add(Util.recvDeliverAck(debugShip.getDock("in"), inputs[0]));
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) { }
+ }
+
+ public class Constant extends Segment {
+ Ship fifoShip = null;
+ public final long constant;
+ public Constant(long constant) {
+ super(0, 1);
+ this.constant = constant;
+ }
+ public Dock[] _setInputs() {
+ if (fifoShip == null) fifoShip = allocate("Fifo");
+ return new Dock[] { fifoShip.getDock("out") };
+ }
+ public void emitPrologue(ArrayList<Instruction> il) {
+ il.add(Util.setOLC(fifoShip.getDock("out"), 1));
+ il.add(Util.collect(fifoShip.getDock("out"), true));
+ }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ Dock fifoIn = fifoShip.getDock("in");
+ Util.literal(fifoIn, constant, il);
+ il.add(Util.setILCInfinity(fifoIn));
+ il.add(Util.deliver(fifoIn));
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) {
+ il.add(Util.tail(fifoShip.getDock("out")));
+ }
+ }
+
+ public class Alu extends Segment {
+ Ship alu = null;
+ public final int opcode;
+ public Alu(int opcode) {
+ super((opcode==-1) ? 3 : 2, 1);
+ this.opcode = opcode;
+ }
+ public Dock[] _setInputs() {
+ if (alu == null) alu = allocate("Alu2");
+ return new Dock[] { alu.getDock("out") };
+ }
+ public void emitPrologue(ArrayList<Instruction> il) {
+ il.add(Util.setOLC(alu.getDock("out"), 1));
+ il.add(Util.collect(alu.getDock("out"), true));
+ }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ Dock inOp = alu.getDock("inOp");
+
+ if (opcode==-1) {
+ il.add(Util.setILCInfinity(alu.getDock("inOp")));
+ il.add(Util.recvDeliverAck(alu.getDock("inOp"), inputs[2]));
+ il.add(Util.sendto(inputs[2], true, alu.getDock("inOp")));
+ il.add(Util.wait(inputs[2], true));
+ } else {
+ Util.literal(alu.getDock("inOp"), opcode, il);
+ il.add(Util.setILCInfinity(alu.getDock("inOp")));
+ il.add(Util.deliver(alu.getDock("inOp")));
+ }
+
+ il.add(Util.setILCInfinity(alu.getDock("in1")));
+ il.add(Util.recvDeliverAck(alu.getDock("in1"), inputs[0]));
+ il.add(Util.sendto(inputs[0], true, alu.getDock("in1")));
+ il.add(Util.wait(inputs[0], true));
+
+ il.add(Util.setILCInfinity(alu.getDock("in2")));
+ il.add(Util.recvDeliverAck(alu.getDock("in2"), inputs[1]));
+ il.add(Util.sendto(inputs[1], true, alu.getDock("in2")));
+ il.add(Util.wait(inputs[1], true));
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) {
+ il.add(Util.tail(alu.getDock("out")));
+ }
+ }
+
+ public class Counter extends Segment {
+ Ship alu = null;
+ public final long start;
+ public final long incr;
+ public Counter(long start, long incr) {
+ super(0, 1);
+ this.start = start;
+ this.incr = incr;
+ }
+ public Dock[] _setInputs() {
+ if (alu == null) alu = allocate("Alu2");
+ return new Dock[] { alu.getDock("out") };
+ }
+ public void emitPrologue(ArrayList<Instruction> il) {
+ Util.literal(alu.getDock("out"), start, il);
+ il.add(Util.setOLC(alu.getDock("out"), 1));
+ }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ Dock inOp = alu.getDock("inOp");
+ Util.literal(inOp, 2, il);
+ il.add(Util.setILCInfinity(inOp));
+ il.add(Util.deliver(inOp));
+
+ il.add(Util.setILCInfinity(alu.getDock("in1")));
+ il.add(Util.recvDeliver(alu.getDock("in1")));
+
+ Util.infiniteLiteral(alu.getDock("in2"), incr, il);
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) {
+ il.add(Util.sendto(alu.getDock("out"), true, alu.getDock("in1")));
+ il.add(Util.collect(alu.getDock("out"), true));
+ il.add(Util.tail(alu.getDock("out")));
+ }
+ }
+
+ public class Between extends Segment {
+ Ship alu = null;
+ public final long min;
+ public final long max;
+ public Between(long min, long max) {
+ super(1, 1);
+ this.min = min;
+ this.max = max;
+ }
+ public Dock[] _setInputs() {
+ if (alu == null) alu = allocate("Alu2");
+ return new Dock[] { alu.getDock("out") };
+ }
+ public void emitPrologue(ArrayList<Instruction> il) {
+ il.add(Util.setOLC(alu.getDock("out"), 1));
+ il.add(Util.setOLC(alu.getDock("inOp"), 1));
+ il.add(Util.setOLC(alu.getDock("in1"), 1));
+ il.add(Util.setOLC(alu.getDock("in2"), 1));
+
+ il.add(Util.collect(alu.getDock("out"), true));
+ il.add(new Set(alu.getDock("out"), true, Predicate.Default, FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO));
+ il.add(Util.collect(alu.getDock("out"), true));
+ il.add(new Set(alu.getDock("out"), true, Predicate.Default, FlagFunction.ZERO.add(FlagC).add(FlagA), FlagFunction.ZERO));
+ il.add(new Set(alu.getDock("out"), true, Predicate.NotFlagA, SetDest.DataLatch, 1));
+ il.add(new Set(alu.getDock("out"), true, Predicate.FlagA, SetDest.DataLatch, 0));
+ }
+
+ public void emitInstructions(ArrayList<Instruction> il) {
+ Util.literal(alu.getDock("inOp"), 4, il, true); // MAX
+ il.add(Util.deliver(alu.getDock("inOp"), true));
+ Util.literal(alu.getDock("in1"), max, il, true);
+ il.add(Util.deliver(alu.getDock("in1"), true));
+ il.add(Util.recvDeliverAck(alu.getDock("in2"), inputs[0], true));
+
+ Util.literal(alu.getDock("inOp"), 4, il, true); // MIN
+ il.add(Util.deliver(alu.getDock("inOp"), true));
+ Util.literal(alu.getDock("in2"), min, il, true);
+ il.add(Util.deliver(alu.getDock("in2"), true));
+ il.add(Util.recvDeliverAck(alu.getDock("in1"), inputs[0], true));
+
+ il.add(Util.sendto(inputs[0], true, alu.getDock("in2")));
+ il.add(Util.sendto(inputs[0], true, alu.getDock("in1")));
+ il.add(Util.wait(inputs[0], true));
+ il.add(Util.wait(inputs[0], true));
+ }
+
+ public void emitEpilogue(ArrayList<Instruction> il) {
+ il.add(Util.tail(alu.getDock("in1")));
+ il.add(Util.tail(alu.getDock("in2")));
+ il.add(Util.tail(alu.getDock("inOp")));
+ il.add(Util.tail(alu.getDock("out")));
+ }
+ }
+
+
+ public class FifoWithInit extends Segment {
+ Ship fifoShip = null;
+ public final long init;
+ public FifoWithInit(long init) {
+ super(1, 1);
+ this.init = init;
+ }
+ public Dock[] _setInputs() {
+ if (fifoShip == null) fifoShip = allocate("Fifo");
+ return new Dock[] { fifoShip.getDock("out") };
+ }
+ public void emitPrologue(ArrayList<Instruction> il) {
+ Util.literal(fifoShip.getDock("out"), init, il, false);
+ il.add(Util.setOLC(fifoShip.getDock("out"), 1));
+ }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ il.add(Util.sendto(inputs[0], true, fifoShip.getDock("in")));
+ il.add(Util.wait(inputs[0], true));
+
+ il.add(Util.setILCInfinity(fifoShip.getDock("in")));
+ il.add(Util.recvDeliverAck(fifoShip.getDock("in"), inputs[0]));
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) {
+ il.add(Util.collect(fifoShip.getDock("out"), true));
+ il.add(Util.tail(fifoShip.getDock("out")));
+ }
+ }
+
+ public class Video extends Segment {
+ Ship videoShip = null;
+ public Video() {
+ super(3, 0);
+ }
+ public Dock[] _setInputs() {
+ if (videoShip == null) videoShip = allocate("Video");
+ return new Dock[0];
+ }
+ public void emitPrologue(ArrayList<Instruction> il) { }
+ public void emitInstructions(ArrayList<Instruction> il) {
+ il.add(Util.setILCInfinity(videoShip.getDock("inX")));
+ il.add(Util.recvDeliverAck(videoShip.getDock("inX"), inputs[0]));
+ il.add(Util.sendto(inputs[0], true, videoShip.getDock("inX")));
+ il.add(Util.wait(inputs[0], true));
+
+ il.add(Util.setILCInfinity(videoShip.getDock("inY")));
+ il.add(Util.recvDeliverAck(videoShip.getDock("inY"), inputs[1]));
+ il.add(Util.sendto(inputs[1], true, videoShip.getDock("inY")));
+ il.add(Util.wait(inputs[1], true));
+
+ il.add(Util.setILCInfinity(videoShip.getDock("inData")));
+ il.add(Util.recvDeliverAck(videoShip.getDock("inData"), inputs[2]));
+ il.add(Util.sendto(inputs[2], true, videoShip.getDock("inData")));
+ il.add(Util.wait(inputs[2], true));
+ }
+ public void emitEpilogue(ArrayList<Instruction> il) { }
+ }
+
+ public static Dock bouncer(New n, int delt, int start, int min, int max) throws Exception {
+ Constant zeroes = n.new Constant(0);
+ FifoWithInit pos = n.new FifoWithInit(start);
+ FifoWithInit delta = n.new FifoWithInit(delt);
+
+ Dock pos_i = pos._setInputs()[0];
+ Dock delta_i = delta._setInputs()[0];
+
+ Alu negator = n.new Alu(3);
+ Dock zero_minus_delta_i = negator.setInputs(new Dock[] { zeroes.setInputs(new Dock[0])[0], delta_i })[0];
+
+ Between bet = n.new Between(min, max);
+ Dock selector_input = bet.setInputs(new Dock[] { pos_i })[0];
+
+ Alu selector = n.new Alu(-1);
+ Dock selected = selector.setInputs(new Dock[] { zero_minus_delta_i, delta_i, selector_input })[0];
+
+ Alu sum_alu = n.new Alu(2);
+ Dock sum = sum_alu.setInputs(new Dock[] { selected, pos_i })[0];
+
+ Dock pos_out = pos.setInputs(new Dock[] { sum })[0];
+ Dock delta_out = delta.setInputs(new Dock[] { selected })[0];
+ return pos_out;
+ }
+
+ public static void main(String[] s) throws Exception {
+
+
+ New n = null;
+
+ if (!s[0].equals("fpga")) n = new New(new Interpreter(new String[] {
+ "Debug",
+ "Fifo", "Fifo",
+ "Fifo", "Fifo",
+ "Fifo", "Fifo",
+ "Fifo", "Fifo",
+ "Fifo", "Fifo",
+ "Fifo", "Fifo",
+ "Alu2", "Alu2",
+ "Alu2", "Alu2",
+ "Alu2", "Alu2",
+ "Alu2", "Alu2",
+ "Alu2", "Alu2",
+ "Alu2", "Alu2",
+ "Video"
+ }, false));
+
+
+ if (s[0].equals("fpga")) n = new New(new Fpga());
+
+
+ //Debug debug = n.new Debug();
+
+ /*
+ Constant con12 = n.new Constant(12);
+ debug.setInputs(con12.setInputs(new Dock[0]));
+ */
+
+ /*
+ Alu alu = n.new Alu(2);
+ Constant con12 = n.new Constant(12);
+ Constant con13 = n.new Constant(13);
+ debug.setInputs(alu.setInputs(new Dock[] { con12.setInputs(new Dock[0])[0], con13.setInputs(new Dock[0])[0] }));
+ */
+
+ /*
+ Constant con12 = n.new Constant(12);
+ Counter con13 = n.new Counter(0, 2);
+ Alu alu = n.new Alu(2);
+ debug.setInputs(alu.setInputs(new Dock[] { con12.setInputs(new Dock[0])[0], con13.setInputs(new Dock[0])[0] }));
+ */
+
+ Dock x_pos = bouncer(n, 1, 6, 5, 634);
+ Dock y_pos = bouncer(n, 1, 6, 5, 474);
+ Dock color = n.new Constant(2).setInputs(new Dock[0])[0];
+ //Dock color = n.new Counter(0,1).setInputs(new Dock[0])[0];
+
+ //debug.setInputs(new Dock[] { x_pos });
+ Video vid = n.new Video();
+ vid.setInputs(new Dock[] { x_pos, y_pos, color });
+
+ ArrayList<Instruction> al = new ArrayList<Instruction>();
+ n.emit(al);
+
+
+ for(int i=0; i<al.size(); i++)
+ System.out.println(al.get(i));
+
+
+ FleetProcess fp = n.fleet.run((Instruction[])al.toArray(new Instruction[0]));
+ System.out.println("launching...");
+ while(true) {
+ System.out.println(fp.readWord().toLong());
+ }
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet.ir;
+
+// ScanRows+Fix: HARD!
+/**
+ * How do we know when a stream is done? In the case of Equalize?
+ */
+public class Sheets {
+
+ public static final int NUM_LANES = 3;
+ public static final int FIFO_SHIP_CAPACITY = 8;
+
+ /**
+ * A block is a set of statements which may be dispatched
+ * concurrently; no memory may be both read from and written to
+ * within a Block, each block may have at most one ReadBack, and
+ * each Block will completely finish before starting the next
+ * Block.
+ */
+ public static class Block {
+
+ private int var_idx = 0;
+
+ public Statement[] statements;
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("block {\n");
+ for(int i=0; i<statements.length; i++) {
+ sb.append(" ");
+ sb.append(statements[i].toString());
+ sb.append('\n');
+ }
+ sb.append("}\n");
+ return sb.toString();
+ }
+
+ /**
+ * Each variable is single-assignment, single-use. When
+ * compiling, each Var maps to an outbox at which the values
+ * in question will be made available.
+ */
+ public class Var {
+ private Statement assigner;
+ private Statement user;
+ public final int lane;
+ public final int idx;
+ public Var() { this(0); }
+ public Var(int lane) { this.lane = lane; this.idx = var_idx++; }
+ public String toString() { return "v"+idx; }
+ public Statement getAssigner() { return assigner; }
+ public void setAssigner(Statement assigner) {
+ if (this.assigner!=null) throw new RuntimeException();
+ this.assigner = assigner;
+ }
+ public Statement getUser() { return user; }
+ public void setUser(Statement user) {
+ if (this.user!=null) throw new RuntimeException();
+ this.user = user;
+ }
+ }
+
+ // Statements //////////////////////////////////////////////////////////////////////////////
+
+ public class Statement {
+ }
+
+ public class Literal extends Statement {
+ Var dest;
+ long[] vals;
+ public Literal(Var dest, long[] vals) {
+ this.dest = dest;
+ this.vals = vals;
+ dest.setAssigner(this);
+ }
+ /*
+ public void emitSetupInstructions() {
+ if (vals.length > FIFO_SHIP_CAPACITY) throw new RuntimeException();
+ Ship fifo = allocateShip("Fifo");
+ Dock fifo_in = fifo.getDock("in");
+ for(int i=0; i<vals.length; i++) {
+
+ }
+ dest.setOutbox(fifo.getDock("out"));
+ }
+ public void emitTeardownInstructions() {
+
+ }
+ */
+ }
+
+ public class ReadBack extends Statement {
+ Var values;
+ public ReadBack(Var values) {
+ this.values = values;
+ values.setUser(this);
+ }
+ }
+
+ public class Fanout extends Statement {
+ public final Var[] dests;
+ public final Var source;
+ public Fanout(Var[] dests, Var source) {
+ this.dests = dests;
+ this.source = source;
+ }
+ }
+
+ /** mainly used to relocate a value from one lane to another */
+ public class Move extends Statement {
+ public Move(Var dest, Var source) {
+ }
+ }
+
+ /**
+ * Repeat the first item from val enough times to match the
+ * length of mimic. [val] MUST be a single-element stream.
+ */
+ public class Equalize extends Statement {
+ public Equalize(Var dest, Var val, Var mimic) { }
+ }
+
+ // technically we could "fan out" tokens instead of fanning out counts, but...
+ /** Like VRep, but for the single-column case */
+ public class Replicate extends Statement {
+ public Replicate(Var dest, Var counts, Var vals) { }
+ }
+
+ public class Alu extends Statement {
+ public Alu(Var dest, Var opcodes, Var in1, Var in2) { }
+ }
+
+ public class Lut extends Statement {
+ public Lut(Var dest, Var table, Var in1, Var in2) { }
+ }
+
+ public class ReadMem extends Statement {
+ public ReadMem(Var dest, long whichMem, Var addresses) { }
+ }
+
+ public class WriteMem extends Statement {
+ public WriteMem(long whichMem, Var addresses, Var values) { }
+ }
+
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.fleet.ir;
+import java.util.*;
+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.SetDest;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+import edu.berkeley.fleet.two.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.SHIFT;
+
+public class Util {
+
+ public static Instruction tail(Dock dock) { return new Tail(dock); }
+ public static Instruction nop(Dock dock, boolean looping) {
+ return new Set(dock, looping, Predicate.Default, FlagFunction.ZERO, FlagFunction.ZERO);
+ }
+ public static Instruction setOLC(Dock dock, int val) {
+ return new Set(dock, false, Predicate.Default, Set.SetDest.OuterLoopCounter, val);
+ }
+ public static Instruction setILC(Dock dock, int val) {
+ return new Set(dock, false, Predicate.Default, Set.SetDest.InnerLoopCounter, val);
+ }
+ public static Instruction setILCInfinity(Dock dock) {
+ return new Set(dock, false, Predicate.Default, Set.SetDest.InnerLoopCounter, Set.SetSource.Infinity);
+ }
+
+ public static Instruction recvDeliver(Dock dock) {
+ return new Move(dock, false, Predicate.Default, false, null, false, true, true, false, true, false);
+ }
+ public static Instruction recvDeliverAck(Dock dock, Dock ackTo) { return recvDeliverAck(dock, ackTo, false); }
+ public static Instruction recvDeliverAck(Dock dock, Dock ackTo, boolean looping) {
+ Path path = dock.getPath(ackTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, false, true, true, false, true, true);
+ }
+
+ public static Instruction notify(Dock dock, boolean looping, Dock ackTo) {
+ Path path = dock.getPath(ackTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, false, false, false, false, false, true);
+ }
+
+ public static void infiniteLiteral(Dock dock, long literal, ArrayList<Instruction> il) {
+ literal(dock, literal, il);
+ il.add(Util.setILCInfinity(dock));
+ il.add(Util.deliver(dock));
+ }
+
+ public static void literal(Dock dock, long literal, ArrayList<Instruction> il) { literal(dock, literal, il, false); }
+ public static void literal(Dock dock, long literal, ArrayList<Instruction> il, boolean looping) {
+ if (FleetTwoFleet.isSmallEnoughToFit(literal)) {
+ il.add(new Set(dock, looping, Predicate.Default, SetDest.DataLatch, (literal)));
+ } else {
+ int counter = 0;
+ while(counter < dock.getShip().getFleet().getWordWidth()) counter += SHIFT.valmaskwidth;
+ while(counter > 0) {
+ il.add(new Shift(dock, looping, Predicate.Default,
+ new BitVector(dock.getShip().getFleet().getWordWidth())
+ .set(getField(counter-1, counter-SHIFT.valmaskwidth, literal))));
+ counter -= SHIFT.valmaskwidth;
+ }
+ }
+ }
+
+ public static Instruction deliver(Dock dock) { return deliver(dock, false); }
+ public static Instruction deliver(Dock dock, boolean looping) {
+ return new Move(dock, looping, Predicate.Default, false, null, false, false, false, false, true, false);
+ }
+
+ public static Instruction collectSendto(Dock dock, Dock sendTo) { return collectSendto(dock, sendTo); }
+ public static Instruction collect(Dock dock, boolean looping) {
+ return new Move(dock, looping, Predicate.Default, false, null, false, true, true, false, false, false);
+ }
+ public static Instruction collectSendto(Dock dock, boolean looping, Dock sendTo) {
+ Path path = dock.getPath(sendTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, false, true, true, false, true, false);
+ }
+ public static Instruction sendto(Dock dock, boolean looping, Dock sendTo) {
+ Path path = dock.getPath(sendTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, false, false, false, false, true, false);
+ }
+
+ public static Instruction collectWaitSendto(Dock dock, Dock sendTo) { return collectWaitSendto(dock, false, sendTo); }
+ public static Instruction collectWaitSendto(Dock dock, boolean looping, Dock sendTo) {
+ Path path = dock.getPath(sendTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, true, true, true, false, true, false);
+ }
+ public static Instruction waitSendto(Dock dock, boolean looping, Dock sendTo) {
+ Path path = dock.getPath(sendTo.getDataDestination(), new BitVector(0));
+ return new Move(dock, looping, Predicate.Default, false, path, true, false, false, false, true, false);
+ }
+ public static Instruction wait(Dock dock, boolean looping) {
+ return new Move(dock, looping, Predicate.Default, false, null, true, false, false, false, false, false);
+ }
+ public static Instruction waitDeliver(Dock dock, boolean looping) {
+ return new Move(dock, looping, Predicate.Default, false, null, true, false, false, false, true, false);
+ }
+
+ public static void transfer(Dock source, Dock dest, int inFlight, ArrayList<Instruction> il) {
+ if (inFlight != 1) throw new RuntimeException();
+ il.add(Util.setILCInfinity(dest));
+ il.add(Util.recvDeliverAck(dest, source));
+ il.add(Util.collectSendto(source, dest));
+ il.add(Util.setILCInfinity(source));
+ il.add(Util.collectWaitSendto(source, dest));
+ }
+
+}
\ No newline at end of file