From: adam Date: Thu, 21 Aug 2008 10:37:45 +0000 (+0100) Subject: checkpoint X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=f90174c6dec3322e556fa9fcb9d1c7aca86be499;p=fleet.git checkpoint --- diff --git a/src/edu/berkeley/fleet/ir/Loops.java b/src/edu/berkeley/fleet/ir/Loops.java new file mode 100644 index 0000000..339e593 --- /dev/null +++ b/src/edu/berkeley/fleet/ir/Loops.java @@ -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 instructions = new ArrayList(); + + /** + * 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; 0 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 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 index 0000000..d75c296 --- /dev/null +++ b/src/edu/berkeley/fleet/ir/New.java @@ -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 segments = new HashSet(); + + private HashSet allocated = new HashSet(); + 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 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 il) { } + public abstract void emitInstructions(ArrayList il); + public void emitEpilogue(ArrayList 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 il) { } + public void emitInstructions(ArrayList 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 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 il) { + il.add(Util.setOLC(fifoShip.getDock("out"), 1)); + il.add(Util.collect(fifoShip.getDock("out"), true)); + } + public void emitInstructions(ArrayList 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 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 il) { + il.add(Util.setOLC(alu.getDock("out"), 1)); + il.add(Util.collect(alu.getDock("out"), true)); + } + public void emitInstructions(ArrayList 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 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 il) { + Util.literal(alu.getDock("out"), start, il); + il.add(Util.setOLC(alu.getDock("out"), 1)); + } + public void emitInstructions(ArrayList 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 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 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 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 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 il) { + Util.literal(fifoShip.getDock("out"), init, il, false); + il.add(Util.setOLC(fifoShip.getDock("out"), 1)); + } + public void emitInstructions(ArrayList 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 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 il) { } + public void emitInstructions(ArrayList 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 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 al = new ArrayList(); + n.emit(al); + + + for(int i=0; i FIFO_SHIP_CAPACITY) throw new RuntimeException(); + Ship fifo = allocateShip("Fifo"); + Dock fifo_in = fifo.getDock("in"); + for(int i=0; i il) { + literal(dock, literal, il); + il.add(Util.setILCInfinity(dock)); + il.add(Util.deliver(dock)); + } + + public static void literal(Dock dock, long literal, ArrayList il) { literal(dock, literal, il, false); } + public static void literal(Dock dock, long literal, ArrayList 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 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