1 package edu.berkeley.fleet.api;
4 /** a Fleet instruction; includes execution location but not full dispatch path */
5 public abstract class Instruction {
7 /** the dock which is to execute this instruction */
8 public final Dock dock;
10 /** true if the instruction is an outer-looping instruction */
11 public final boolean looping;
13 /** the instruction's predicate */
14 public final Predicate predicate;
16 Instruction(Dock dock, boolean looping, Predicate predicate) {
17 if (dock==null) throw new RuntimeException("dock may not be null");
18 if (predicate==null) throw new RuntimeException("predicate may not be null");
20 this.looping = looping;
21 this.predicate = predicate;
24 public String toString() {
25 String s = predicate.toString();
26 if (s.length()>0) s = "["+s+"] ";
31 * A <tt>set</tt> instruction.
33 * Note that immediates are supplied as Java <tt>long</tt> values
34 * because they are actual integers with two's complement
35 * sign-extension semantics. This is in contrast to most other
36 * immediate values in the API which are raw bit sequences of
37 * fixed length -- these are represented by instances of
40 public static class Set extends Instruction {
42 /** the destination (latch to be set) */
43 public final SetDest dest;
45 /** the source (what will be put in the <tt>dest</tt> latch) */
46 public final SetSource source;
48 /** if <tt>source</tt> is <tt>Immediate</tt>, this is the immediate value; an integer */
49 public final long immediate;
51 /** if <tt>source</tt> is <tt>ImmediatePath</tt>, this is the immediate path */
52 public final Path path;
54 /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "a" */
55 public final FlagFunction newFlagA;
57 /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "b" */
58 public final FlagFunction newFlagB;
60 /** basic constructor */
61 public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, SetSource source) {
62 super(dock, looping, predicate);
64 case InnerLoopCounter:
66 case Infinity: case DataLatch: case Immediate: break OUTER;
69 case OuterLoopCounter:
71 case Decrement: case DataLatch: case Immediate: break OUTER;
75 if (source==SetSource.Immediate) break;
76 default: throw new RuntimeException("cannot set " + dest + " to " + source);
86 /** constructor for set instructions with immediates */
87 public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, long immediate) {
88 super(dock, looping, predicate);
89 if (dest!=SetDest.InnerLoopCounter && dest!=SetDest.OuterLoopCounter && dest!=SetDest.DataLatch)
90 throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate");
91 this.source = SetSource.Immediate;
93 this.immediate = immediate;
99 /** constructor for set instructions with immediate paths */
100 public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, Path path) {
101 super(dock, looping, predicate);
102 if (dest!=SetDest.TAPL)
103 throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate path");
104 this.source = SetSource.ImmediatePath;
108 this.newFlagA = null;
109 this.newFlagB = null;
112 /** constructor for <tt>set flags</tt> instructions */
113 public Set(Dock dock, boolean looping, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) {
114 super(dock, looping, predicate);
115 this.source = SetSource.Immediate;
116 this.dest = SetDest.Flags;
119 this.newFlagA = newFlagA;
120 this.newFlagB = newFlagB;
123 /** possible sources for the Set instruction */
124 public static enum SetSource {
125 Infinity, DataLatch, Immediate, ImmediatePath, Decrement;
127 /** possible destinations for the Set instruction */
128 public static enum SetDest {
129 InnerLoopCounter, OuterLoopCounter, TAPL, Flags, DataLatch;
133 * (Immutable) a truth table describing how to update a flag
134 * based on the value of other flags; it is the logical OR of
135 * a set of flag predicates. This class is immutable; all
136 * methods that alter the function return a new object.
138 public static class FlagFunction implements Iterable<Predicate> {
140 /** the function that always assigns zero */
141 public static final FlagFunction ZERO = new FlagFunction();
143 /** the function that always assigns one */
144 public static final FlagFunction ONE = ZERO.add(Predicate.FlagA).add(Predicate.NotFlagA);
146 private final java.util.Set<Predicate> predicates;
148 public Iterator<Predicate> iterator() { return predicates.iterator(); }
150 private FlagFunction() { this(Collections.EMPTY_SET); }
151 private FlagFunction(java.util.Set<Predicate> set) { this.predicates = Collections.unmodifiableSet(set); }
153 /** returns the function which is the logical OR of this function and <tt>ff</tt> */
154 public FlagFunction add(FlagFunction ff) {
155 FlagFunction ret = this;
156 for(Predicate p : ff) ret = ret.add(p);
160 /** returns the function which is the logical OR of this function and <tt>p</tt> */
161 public FlagFunction add(Predicate p) {
162 HashSet h = new HashSet();
163 h.addAll(predicates);
165 case FlagA: case NotFlagA:
166 case FlagB: case NotFlagB:
167 case FlagC: case NotFlagC:
170 throw new RuntimeException("invalid predicate in FlagFunction: " + p);
173 return new FlagFunction(h);
176 /** remove <tt>p</tt> from the set of terms which this function is the logical OR of */
177 public FlagFunction remove(Predicate p) {
178 HashSet h = new HashSet();
179 h.addAll(predicates);
181 return new FlagFunction(h);
184 public String toString() {
185 if (predicates.isEmpty()) return "0";
186 if (predicates.contains(Predicate.FlagA) && predicates.contains(Predicate.NotFlagA)) return "1";
187 if (predicates.contains(Predicate.FlagB) && predicates.contains(Predicate.NotFlagB)) return "1";
188 if (predicates.contains(Predicate.FlagC) && predicates.contains(Predicate.NotFlagC)) return "1";
189 StringBuffer ret = new StringBuffer();
190 boolean empty = true;
191 for(Predicate p : new Predicate[] {
192 Predicate.FlagA, Predicate.NotFlagA,
193 Predicate.FlagB, Predicate.NotFlagB,
194 Predicate.FlagC, Predicate.NotFlagC })
195 if (predicates.contains(p)) {
196 if (!empty) ret.append("| ");
200 return ret.toString();
204 public String toString() {
206 case InnerLoopCounter:
208 case Infinity: return super.toString()+"set ilc=*";
209 case DataLatch: return super.toString()+"set ilc=data";
210 case Immediate: return super.toString()+"set ilc="+immediate;
212 case OuterLoopCounter:
214 case Decrement: return super.toString()+"set olc--";
215 case DataLatch: return super.toString()+"set olc=data";
216 case Immediate: return super.toString()+"set olc="+immediate;
218 case TAPL: return super.toString()+"set tapl="+path;
219 case Flags: return super.toString()+"set flags a="+newFlagA+" b="+newFlagB;
220 case DataLatch: return super.toString()+"set data="+immediate;
222 throw new Error("impossible");
226 /** shifts an immediate into the low-order bits of the data latch */
227 public static class Shift extends Instruction {
228 public final BitVector immediate;
229 public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) {
230 super(dock, looping, predicate);
231 this.immediate = immediate;
233 public String toString() { return super.toString()+"shift "+immediate; }
236 /** all communication is performed with this instruction */
237 public static class Move extends Instruction {
239 /** if true, this instruction is vulnerable to torpedoes */
240 public final boolean interruptible;
242 /** if non-null, the path to load into the path latch */
243 public final Path path;
245 /** if true, a token will be consumed before execution */
246 public final boolean tokenIn;
248 /** if true, data will be consumed before execution */
249 public final boolean dataIn;
251 /** if true, the data consumed will be copied into the data latch */
252 public final boolean latchData;
254 /** if true, the data consumed will be copied into the path latch */
255 public final boolean latchPath;
257 /** if true, the value in the data latch will be transmitted (to the location in the path latch if at an output dock) */
258 public final boolean dataOut;
260 /** if true, the a token will be transmitted to the location in the path latch */
261 public final boolean tokenOut;
263 public Move(Dock dock,
266 boolean interruptible,
275 super(dock, looping, predicate);
277 this.tokenIn = tokenIn;
278 this.dataIn = dataIn;
279 this.latchData = latchData;
280 this.latchPath = latchPath;
281 this.dataOut = dataOut;
282 this.tokenOut = tokenOut;
283 this.interruptible = interruptible;
284 if (dock != null && dock.isInputDock() && tokenIn && dataIn)
285 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an input dock: " + this);
286 if (dock != null && dock.isOutputDock() && tokenOut && dataOut)
287 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an output dock: " + this);
288 if (latchData && !dataIn)
289 throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this);
290 if (latchPath && !dataIn)
291 throw new RuntimeException("cannot have latchPath bit set without dataIn bit: " + this);
292 if (latchPath && path!=null)
293 throw new RuntimeException("cannot have latchPath and a non-null path: " + this);
296 public String toString() {
297 StringBuffer ret = new StringBuffer();
298 if (tokenIn) ret.append(", wait");
300 if (latchPath) ret.append(dock.isInputDock() ? ", collect path" : ", recv path");
301 if (latchData) ret.append(dock.isInputDock() ? ", collect" : ", recv");
302 if (!latchPath && !latchData) ret.append(", discard");
304 if (dataOut && dock.isInputDock()) ret.append(", deliver");
305 if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send" : "sendto " + path);
306 if (tokenOut) ret.append(path==null ? ", token" : "tokento " + path);
307 String s = ret.toString();
308 s = s.equals("") ? "nop" : s.substring(2);
309 if (interruptible) s = "[i] " + s;
310 return super.toString()+s;
314 /** marks the end of a loop; closes the hatch */
315 public static class Tail extends Instruction {
316 public Tail(Dock dock) { super(dock, false, Predicate.IgnoreOLC); }
317 public String toString() { return super.toString() + "tail;"; }