major refactoring of edu.berkeley.fleet.loops, includes renaming Context to CodeBag
[fleet.git] / src / edu / berkeley / fleet / loops / CodeBag.java
1 package edu.berkeley.fleet.loops;
2 import java.util.*;
3 import java.net.*;
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.*;
10
11
12 // QUESTION: does each dock mentioned by a context have a linear chain
13 // of loops, or can it branch?
14
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?
18
19 /**
20  *  A CodeBag is a collection of Loops which obey these rules:
21  *
22  *    - A CodeBag has exclusive control of all docks mentioned by any of its Loops.
23  *    - A CodeBag includes a "starting loop" for every dock it mentions.
24  *    - When a CodeBag is spawned, it starts the "starting loop" on all of its docks.
25  *    - A loop may or may not have a successor.
26  *    - Control may transfer only two ways:
27  *        - If a loop has a successor, control will transfer to the successor when the loop finishes.
28  *        - A loop may explicitly transfer control to another loop via abortAndInvoke().  The
29  *          invoked loop must belong to the same Dock and the same CodeBag.
30  *    - A CodeBag finishes when all of its docks have finished executing a loop with no successor.
31  *
32  *  Definitions:
33  *    - A Move instruction is a blocking instruction if either its   tokenIn or dataIn bits are set.
34  *    - All other instructions  are non-blocking.
35  *    - A dock is quiescent if its instruction ring is empty.
36  *    - A dock is pre-quiescent if 
37  *        - all instructions which remain in the target dock's instruction
38  *          fifo are nonblocking instructions,
39  *        - either the docks' OLC=0 or all instructions which remain
40  *          in its instruction fifo are one-shot instructions
41  *        - after executing these remaining instructions, the dock's hatch is open
42  */
43
44 /*
45  *                          SF         works       works @diff    ok for non   size    ships
46  * Dispatch Method       Crossings     @inbox?       docks?       tail call?   limit   consumed
47  * ------------------------------------------------------------------------------------------
48  * 
49  * Inline                    0           Y              N             N        Small  None
50  * 
51  * Inline literals           1           N              Y             Y        Tiny   None
52  *  w/ "dispatch"
53  * 
54  * Send CBD to               2+          N              Y             Y        None   None (mem ship)
55  * memory ship
56  * 
57  * Send token to             3+          Y              Y             Y        None   One Output Dock
58  * assistant outbox first
59  * 
60  * Release from FIFO         2           Y              Y             Y        Med    1x FIFO, but can be shared
61  * 
62  */
63
64 public class CodeBag {
65
66     public final Fleet fleet;
67
68     private Program program = null;
69     private BitVector descriptor = null;
70     public DeferredBitVector getDescriptor() {
71         return new DeferredBitVector() {
72             public BitVector getBitVector() {
73                 if (program==null) throw new RuntimeException();
74                 seal();
75                 return descriptor;
76             } };
77     }
78
79     LinkedHashMap<Dock,LoopFactory> startupLoopFactories = new LinkedHashMap<Dock,LoopFactory>();
80     ArrayList<LoopFactory> loopFactories = new ArrayList<LoopFactory>();
81
82     // FIXME: currently not used
83     private boolean sealed = false;
84     public boolean isSealed() { return sealed; }
85     public void seal() {
86         if (sealed) return;
87         for(LoopFactory lf : loopFactories) lf.flush_pending();
88         sealed = true;
89         if (program!=null) descriptor = program.addInstructions(emit());
90     }
91
92     public CodeBag(Fleet fleet) { this(fleet, null); }
93     public CodeBag(Program prog) { this(prog.fleet, prog); }
94     public CodeBag(Fleet fleet, Program prog) {
95         this.fleet = fleet;
96         this.program = prog;
97     }
98
99     public LoopFactory loopFactory(Dock dock, int count) { return loopFactory(dock, count, count==0); }
100     public LoopFactory loopFactory(Dock dock, int count, boolean torpedoable) {
101         LoopFactory ret = startupLoopFactories.get(dock);
102         if (ret == null) return new LoopFactory(this, dock, count, torpedoable);
103         while (ret.getNext()!=null)
104             ret = ret.getNext();
105         return ret.makeNext(count, torpedoable);
106     }
107
108     boolean autoflush = false;
109     public void setAutoflush(boolean a) { this.autoflush = a; }
110     public boolean getAutoflush() { return autoflush; }
111
112     public void emit(ArrayList<Instruction> ic) {
113         seal();
114         for(LoopFactory lf : startupLoopFactories.values())
115             lf.emit(ic);
116     }
117
118     private LoopFactory hack = null;
119     public void sendTorpedo(Dock dock) {
120         if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
121         hack.sendToken(dock.getInstructionDestination());
122     }
123     public void sendWord(DeferredBitVector bv, Destination dest) {
124         // problem: this isn't actually atomic -- two uncoordinated
125         // actors might invoke these commands at the same time
126         if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
127         hack.literal(bv);
128         hack.sendWord(dest);
129     }
130
131     public Instruction[] emit() {
132         ArrayList<Instruction> ic = new ArrayList<Instruction>();
133         emit(ic);
134         return (Instruction[])ic.toArray(new Instruction[0]);
135     }
136
137     public void dispatch(FleetProcess fp) { dispatch(fp, false); }
138     public void dispatch(FleetProcess fp, boolean flushWhenDone) {
139         ArrayList<Instruction> ai;
140         emit(ai = new ArrayList<Instruction>());
141         for(Instruction ins : ai)
142             fp.sendInstruction(ins);
143         if (flushWhenDone) fp.flush();
144     }
145
146     public void append(CodeBag ctx) {
147         if (sealed) throw new RuntimeException("already sealed");
148         // how to handle ship pools?
149         throw new RuntimeException("not implemented");
150     }
151
152 }