1 package edu.berkeley.fleet.loops;
4 import edu.berkeley.fleet.two.*;
5 import edu.berkeley.fleet.api.*;
6 import edu.berkeley.fleet.api.Instruction.*;
7 import edu.berkeley.fleet.api.Instruction.Set;
8 import edu.berkeley.fleet.api.Instruction.Set.*;
9 import static edu.berkeley.fleet.util.BitManipulations.*;
12 // QUESTION: does each dock mentioned by a context have a linear chain
13 // of loops, or can it branch?
15 // - or should we use "sub-contexts" for that
16 // - advantage: it lets us convey the fact that a bunch of loops are dispatched together
17 // - should loops have an "invoke context" opcode?
20 // FIXME: implement CodeBag compression
23 * A CodeBag is a collection of Loops which obey these rules:
25 * - A CodeBag has exclusive control of all docks mentioned by any of its Loops.
26 * - A CodeBag includes a "starting loop" for every dock it mentions.
27 * - When a CodeBag is spawned, it starts the "starting loop" on all of its docks.
28 * - A loop may or may not have a successor.
29 * - Control may transfer only two ways:
30 * - If a loop has a successor, control will transfer to the successor when the loop finishes.
31 * - A loop may explicitly transfer control to another loop via abortAndInvoke(). The
32 * invoked loop must belong to the same Dock and the same CodeBag.
33 * - A CodeBag finishes when all of its docks have finished executing a loop with no successor.
36 * - A Move instruction is a blocking instruction if either its tokenIn or dataIn bits are set.
37 * - All other instructions are non-blocking.
38 * - A dock is quiescent if its instruction ring is empty.
39 * - A dock is pre-quiescent if
40 * - all instructions which remain in the target dock's instruction
41 * fifo are nonblocking instructions,
42 * - either the docks' OLC=0 or all instructions which remain
43 * in its instruction fifo are one-shot instructions
44 * - after executing these remaining instructions, the dock's hatch is open
48 * SF works works @diff ok for non size ships
49 * Dispatch Method Crossings @inbox? docks? tail call? limit consumed
50 * ------------------------------------------------------------------------------------------
52 * Inline 0 Y N N Small None
54 * Inline literals 1 N Y Y Tiny None
57 * Send CBD to 2+ N Y Y None None (mem ship)
60 * Send token to 3+ Y Y Y None One Output Dock
61 * assistant outbox first
63 * Release from FIFO 2 Y Y Y Med 1x FIFO, but can be shared
67 public class CodeBag {
69 public final Fleet fleet;
71 private Program program = null;
72 private BitVector descriptor = null;
73 public DeferredBitVector getDescriptor() {
74 return new DeferredBitVector() {
75 public BitVector getBitVector() {
76 if (program==null) throw new RuntimeException();
82 LinkedHashMap<Dock,LoopFactory> startupLoopFactories = new LinkedHashMap<Dock,LoopFactory>();
83 ArrayList<LoopFactory> loopFactories = new ArrayList<LoopFactory>();
85 // FIXME: currently not used
86 private boolean sealed = false;
87 public boolean isSealed() { return sealed; }
90 for(LoopFactory lf : loopFactories) lf.flush_pending();
92 if (program!=null) descriptor = program.addInstructions(emit());
95 public CodeBag(Fleet fleet) { this(fleet, null); }
96 public CodeBag(Program prog) { this(prog.fleet, prog); }
97 public CodeBag(Fleet fleet, Program prog) {
102 public LoopFactory loopFactory(Dock dock, int count) { return loopFactory(dock, count, count==0); }
103 public LoopFactory loopFactory(Dock dock, int count, boolean torpedoable) {
104 LoopFactory ret = startupLoopFactories.get(dock);
105 if (ret == null) return new LoopFactory(this, dock, count, torpedoable);
106 while (ret.getNext()!=null)
108 return ret.makeNext(count, torpedoable);
111 boolean autoflush = false;
112 public void setAutoflush(boolean a) { this.autoflush = a; }
113 public boolean getAutoflush() { return autoflush; }
115 public void emit(ArrayList<Instruction> ic) {
117 for(LoopFactory lf : startupLoopFactories.values())
121 private LoopFactory hack = null;
122 public void sendTorpedo(Dock dock) {
123 if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
124 hack.sendToken(dock.getInstructionDestination());
126 public void sendWord(DeferredBitVector bv, Destination dest) {
127 // problem: this isn't actually atomic -- two uncoordinated
128 // actors might invoke these commands at the same time
129 if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
134 public Instruction[] emit() {
135 ArrayList<Instruction> ic = new ArrayList<Instruction>();
137 return (Instruction[])ic.toArray(new Instruction[0]);
140 public void dispatch(FleetProcess fp) { dispatch(fp, false); }
141 public void dispatch(FleetProcess fp, boolean flushWhenDone) {
142 ArrayList<Instruction> ai;
143 emit(ai = new ArrayList<Instruction>());
144 for(Instruction ins : ai)
145 fp.sendInstruction(ins);
146 if (flushWhenDone) fp.flush();
149 public void append(CodeBag ctx) {
150 if (sealed) throw new RuntimeException("already sealed");
151 // how to handle ship pools?
152 throw new RuntimeException("not implemented");