checkpoint
authoradam <adam@megacz.com>
Thu, 21 Aug 2008 10:37:45 +0000 (11:37 +0100)
committeradam <adam@megacz.com>
Thu, 21 Aug 2008 10:37:45 +0000 (11:37 +0100)
src/edu/berkeley/fleet/ir/Loops.java [new file with mode: 0644]
src/edu/berkeley/fleet/ir/New.java [new file with mode: 0644]
src/edu/berkeley/fleet/ir/Sheets.java [new file with mode: 0644]
src/edu/berkeley/fleet/ir/Util.java [new file with mode: 0644]

diff --git a/src/edu/berkeley/fleet/ir/Loops.java b/src/edu/berkeley/fleet/ir/Loops.java
new file mode 100644 (file)
index 0000000..339e593
--- /dev/null
@@ -0,0 +1,269 @@
+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); }
+
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/ir/New.java b/src/edu/berkeley/fleet/ir/New.java
new file mode 100644 (file)
index 0000000..d75c296
--- /dev/null
@@ -0,0 +1,404 @@
+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());
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/ir/Sheets.java b/src/edu/berkeley/fleet/ir/Sheets.java
new file mode 100644 (file)
index 0000000..bb32360
--- /dev/null
@@ -0,0 +1,146 @@
+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
diff --git a/src/edu/berkeley/fleet/ir/Util.java b/src/edu/berkeley/fleet/ir/Util.java
new file mode 100644 (file)
index 0000000..2b4bd27
--- /dev/null
@@ -0,0 +1,107 @@
+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