-package edu.berkeley.fleet;
+package edu.berkeley.fleet.ir;
import java.util.*;
import java.net.*;
import edu.berkeley.fleet.two.*;
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 Context is a collection of Loops which obey these rules:
*
- * 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()
- *
+ * - There is a designated entry point loop which is invoked when the Context is loaded
+ * - Loops in a Context may only invoke other Loops in the same Context
+ * - A Context has exclusive control of all docks mentioned by any of its Loops
+ * - A Context does not exit until all of its Loops have exited.
*/
-public class Loops {
-
- public static abstract class Loop {
- private final Dock dock;
- private final String friendlyName;
- private final int count;
+public class Context {
+
+ private HashSet<LoopFactory> loopFactories = new HashSet<LoopFactory>();
+
+ public Context() { }
+
+ /**
+ *
+ * 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 LoopFactory {
+ public final Dock dock;
+ public final String friendlyName;
+ public final int count;
private Predicate predicate = Predicate.Default;
- private Loop next = null;
+ private LoopFactory 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
+ * @arg dock the dock at which to execute the instructions
+ * @arg friendlyName a descriptive string for debugging the compiler
+ * @arg prev a loop for which this is the successor loop (if any)
+ * @arg 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) {
+ public LoopFactory(Dock dock, int count) { this(dock, count, dock.toString(), null); }
+ public LoopFactory(Dock dock, int count, String friendlyName) { this(dock, count, friendlyName, null); }
+ public LoopFactory(Dock dock, int count, String friendlyName, LoopFactory prev) {
this.dock = dock;
this.count = count;
this.friendlyName = friendlyName;
- if (prev.getNext() != null) throw new RuntimeException();
- prev.setNext(this);
+ Context.this.loopFactories.add(this);
+ if (prev != null) {
+ if (prev.getNext() != null) throw new RuntimeException();
+ prev.setNext(this);
+ }
}
- public Loop getNext() { return next; }
- public void setNext(Loop next) { this.next = next; }
+ public LoopFactory getNext() { return next; }
+ public void setNext(LoopFactory next) {
+ if (this.next != null) throw new RuntimeException("attempt to setNext() twice");
+ this.next = next;
+ }
// Building Loops //////////////////////////////////////////////////////////////////////////////
newFlagB));
}
+ // FIXME: what if we're using an ILC-loop?
+ /** abort the loop immediately (if predicate is met) */
+ public void abort() {
+ flush_pending();
+ instructions.add(new Instruction.Set(dock,
+ count!=1,
+ predicate,
+ SetDest.OuterLoopCounter,
+ 0));
+ }
// Emitting Code //////////////////////////////////////////////////////////////////////////////
void optimize() {
flush_pending();
+ // FEATURE: find loops of 1 instruction, use ILC
// 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...
ic.add(i);
}
- if (count!=1) {
+ if (count==1) {
+ if (numInstructionsNotIncludingNonblockingPrefix > dock.getInstructionFifoSize())
+ throw new RuntimeException("instruction sequence is too long for instruction fifo");
+ } else {
+ if (count != 0) {
+ ic.add(new Instruction.Set(dock, true, Predicate.Default, SetDest.OuterLoopCounter, SetSource.Decrement));
+ if (blockingInstructionEncountered)
+ numInstructionsNotIncludingNonblockingPrefix++;
+ loopSize++;
+ }
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");
+ if (next != null) {
+ if (count != 1) throw new RuntimeException("no support for successor loops when count!=1 yet");
+ // FIXME: must include check based on reduced FIFO capacity
+ // FIXME: review this
+ next.emit(ic);
+ }
}
void warn(String warning) {
// Helpers //////////////////////////////////////////////////////////////////////////////
- public void recvData() { recv(true, false); }
+ public void recvWord() { recv(true, false); }
+ public void recvPath() { recv(false, true); }
public void recvPacket() { recv(true, true); }
- public void collectData() { collect(true, false); }
+ public void collectWord() { collect(true, false); }
+ public void collectPath() { collect(false, true); }
public void collectPacket() { collect(true, true); }
}