add some comments
[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 // FIXME: implement CodeBag compression
21
22 /**
23  *  A CodeBag is a collection of Loops which obey these rules:
24  *
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.
34  *
35  *  Definitions:
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
45  */
46
47 /*
48  *                          SF         works       works @diff    ok for non   size    ships
49  * Dispatch Method       Crossings     @inbox?       docks?       tail call?   limit   consumed
50  * ------------------------------------------------------------------------------------------
51  * 
52  * Inline                    0           Y              N             N        Small  None
53  * 
54  * Inline literals           1           N              Y             Y        Tiny   None
55  *  w/ "dispatch"
56  * 
57  * Send CBD to               2+          N              Y             Y        None   None (mem ship)
58  * memory ship
59  * 
60  * Send token to             3+          Y              Y             Y        None   One Output Dock
61  * assistant outbox first
62  * 
63  * Release from FIFO         2           Y              Y             Y        Med    1x FIFO, but can be shared
64  * 
65  */
66
67 public class CodeBag {
68
69     public final Fleet fleet;
70
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();
77                 seal();
78                 return descriptor;
79             } };
80     }
81
82     LinkedHashMap<Dock,LoopFactory> startupLoopFactories = new LinkedHashMap<Dock,LoopFactory>();
83     ArrayList<LoopFactory> loopFactories = new ArrayList<LoopFactory>();
84
85     // FIXME: currently not used
86     private boolean sealed = false;
87     public boolean isSealed() { return sealed; }
88     public void seal() {
89         if (sealed) return;
90         for(LoopFactory lf : loopFactories) lf.flush_pending();
91         sealed = true;
92         if (program!=null) descriptor = program.addInstructions(emit());
93     }
94
95     public CodeBag(Fleet fleet) { this(fleet, null); }
96     public CodeBag(Program prog) { this(prog.fleet, prog); }
97     public CodeBag(Fleet fleet, Program prog) {
98         this.fleet = fleet;
99         this.program = prog;
100     }
101
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)
107             ret = ret.getNext();
108         return ret.makeNext(count, torpedoable);
109     }
110
111     boolean autoflush = false;
112     public void setAutoflush(boolean a) { this.autoflush = a; }
113     public boolean getAutoflush() { return autoflush; }
114
115     public void emit(ArrayList<Instruction> ic) {
116         seal();
117         for(LoopFactory lf : startupLoopFactories.values())
118             lf.emit(ic);
119     }
120
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());
125     }
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);
130         hack.literal(bv);
131         hack.sendWord(dest);
132     }
133
134     public Instruction[] emit() {
135         ArrayList<Instruction> ic = new ArrayList<Instruction>();
136         emit(ic);
137         return (Instruction[])ic.toArray(new Instruction[0]);
138     }
139
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();
147     }
148
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");
153     }
154
155 }