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 abstract Instruction withLooping(boolean newLooping);
25 //public abstract Instruction withPredicate(Predicate newPredicate);
27 public String toString() {
28 String s = predicate.toString();
29 if (s.length()>0) s = "["+s+"] ";
30 if (looping) s += "[L] ";
35 * A <tt>set</tt> instruction.
37 * Note that immediates are supplied as Java <tt>long</tt> values
38 * because they are actual integers with two's complement
39 * sign-extension semantics. This is in contrast to most other
40 * immediate values in the API which are raw bit sequences of
41 * fixed length -- these are represented by instances of
44 public static class Set extends Instruction {
46 /** the destination (latch to be set) */
47 public final SetDest dest;
49 /** the source (what will be put in the <tt>dest</tt> latch) */
50 public final SetSource source;
52 /** if <tt>source</tt> is <tt>Immediate</tt>, this is the immediate value; an integer */
53 public final long immediate;
55 /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "a" */
56 public final FlagFunction newFlagA;
58 /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "b" */
59 public final FlagFunction newFlagB;
61 /** basic constructor */
62 public Set(Dock dock, SetDest dest, SetSource source) { this(dock, false, Predicate.Default, dest, source); }
63 public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, SetSource source) {
64 super(dock, looping, predicate);
66 case InnerLoopCounter:
68 case Infinity: case DataLatch: case Immediate: break OUTER;
71 case OuterLoopCounter:
73 case Decrement: case DataLatch: case Immediate: break OUTER;
77 if (source==SetSource.Immediate) break;
78 default: throw new RuntimeException("cannot set " + dest + " to " + source);
87 /** constructor for set instructions with immediates */
88 public Set(Dock dock, SetDest dest, long immediate) { this(dock, false, Predicate.Default, dest, immediate); }
89 public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, long immediate) {
90 super(dock, looping, predicate);
91 if (dest!=SetDest.InnerLoopCounter && dest!=SetDest.OuterLoopCounter && dest!=SetDest.DataLatch)
92 throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate");
93 this.source = SetSource.Immediate;
95 this.immediate = immediate;
100 /** constructor for <tt>set flags</tt> instructions */
101 public Set(Dock dock, FlagFunction newFlagA, FlagFunction newFlagB) { this(dock, false, Predicate.Default, newFlagA, newFlagB); }
102 public Set(Dock dock, boolean looping, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) {
103 super(dock, looping, predicate);
104 this.source = SetSource.Immediate;
105 this.dest = SetDest.Flags;
107 this.newFlagA = newFlagA;
108 this.newFlagB = newFlagB;
111 /** possible sources for the Set instruction */
112 public static enum SetSource {
113 Infinity, DataLatch, Immediate, Decrement;
115 /** possible destinations for the Set instruction */
116 public static enum SetDest {
117 InnerLoopCounter, OuterLoopCounter, Flags, DataLatch;
121 * (Immutable) a truth table describing how to update a flag
122 * based on the value of other flags; it is the logical OR of
123 * a set of flag predicates. This class is immutable; all
124 * methods that alter the function return a new object.
126 public static class FlagFunction implements Iterable<Predicate> {
128 /** the function that always assigns zero */
129 public static final FlagFunction ZERO = new FlagFunction();
131 /** the function that always assigns one */
132 public static final FlagFunction ONE = ZERO.add(Predicate.FlagA).add(Predicate.NotFlagA);
134 private final java.util.Set<Predicate> predicates;
136 public Iterator<Predicate> iterator() { return predicates.iterator(); }
138 private FlagFunction() { this(Collections.EMPTY_SET); }
139 private FlagFunction(java.util.Set<Predicate> set) { this.predicates = Collections.unmodifiableSet(set); }
141 /** returns the function which is the logical OR of this function and <tt>ff</tt> */
142 public FlagFunction add(FlagFunction ff) {
143 FlagFunction ret = this;
144 for(Predicate p : ff) ret = ret.add(p);
148 /** returns the function which is the logical OR of this function and <tt>p</tt> */
149 public FlagFunction add(Predicate p) {
150 HashSet h = new HashSet();
151 h.addAll(predicates);
153 case FlagA: case NotFlagA:
154 case FlagB: case NotFlagB:
155 case FlagC: case NotFlagC:
158 throw new RuntimeException("invalid predicate in FlagFunction: " + p);
161 return new FlagFunction(h);
164 /** remove <tt>p</tt> from the set of terms which this function is the logical OR of */
165 public FlagFunction remove(Predicate p) {
166 HashSet h = new HashSet();
167 h.addAll(predicates);
169 return new FlagFunction(h);
172 public String toString() {
173 if (predicates.isEmpty()) return "0";
174 if (predicates.contains(Predicate.FlagA) && predicates.contains(Predicate.NotFlagA)) return "1";
175 if (predicates.contains(Predicate.FlagB) && predicates.contains(Predicate.NotFlagB)) return "1";
176 if (predicates.contains(Predicate.FlagC) && predicates.contains(Predicate.NotFlagC)) return "1";
177 StringBuffer ret = new StringBuffer();
178 boolean empty = true;
179 for(Predicate p : new Predicate[] {
180 Predicate.FlagA, Predicate.NotFlagA,
181 Predicate.FlagB, Predicate.NotFlagB,
182 Predicate.FlagC, Predicate.NotFlagC })
183 if (predicates.contains(p)) {
184 if (!empty) ret.append("| ");
188 return ret.toString();
192 public String toString() {
194 case InnerLoopCounter:
197 case Infinity: return super.toString()+"set ilc=*";
198 case DataLatch: return super.toString()+"set ilc=data";
199 case Immediate: return super.toString()+"set ilc="+immediate;
201 case Infinity: return super.toString()+"load repeat counter with *;";
202 case DataLatch: return super.toString()+"set ilc=data";
203 case Immediate: return super.toString()+"load repeat counter with "+immediate+";";
205 case OuterLoopCounter:
208 case Decrement: return super.toString()+"set olc--";
209 case DataLatch: return super.toString()+"set olc=data";
210 case Immediate: return super.toString()+"set olc="+immediate;
212 case Decrement: return super.toString()+"decrement loop counter;";
213 case DataLatch: return super.toString()+"set olc=data;";
214 case Immediate: return super.toString()+"load loop counter with "+immediate+";";
216 case Flags: return super.toString()+"set flags a="+newFlagA+" b="+newFlagB;
217 case DataLatch: return super.toString()+"literal "+immediate+";";
219 throw new Error("impossible");
223 /** shifts an immediate into the low-order bits of the data latch */
224 public static class Shift extends Instruction {
225 public final BitVector immediate;
226 public Shift(Dock dock, BitVector immediate) { this(dock, false, Predicate.Default, immediate); }
227 public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) {
228 super(dock, looping, predicate);
229 this.immediate = immediate;
230 this.immediate.setImmutable();
232 public String toString() { return super.toString()+"shift "+immediate; }
235 /** all communication is performed with this instruction */
236 public static class Move extends Instruction {
238 /** if true, this instruction is vulnerable to torpedoes */
239 public final boolean interruptible;
241 /** if non-null, the path to load into the path latch */
242 public final Path path;
244 /** if true, a token will be consumed before execution */
245 public final boolean tokenIn;
247 /** if true, data will be consumed before execution */
248 public final boolean dataIn;
250 /** if true, the data consumed will be copied into the data latch */
251 public final boolean latchData;
253 /** if true, the data consumed will be copied into the path latch */
254 public final boolean latchPath;
256 /** if true, the value in the data latch will be transmitted (to the location in the path latch if at an output dock) */
257 public final boolean dataOut;
259 /** if true, the a token will be transmitted to the location in the path latch */
260 public final boolean tokenOut;
262 public Move(Dock dock,
271 this(dock, false, Predicate.Default, false, path, tokenIn, dataIn, latchData, latchPath, dataOut, tokenOut); }
272 public Move(Dock dock,
275 boolean interruptible,
284 super(dock, looping, predicate);
286 this.tokenIn = tokenIn;
287 this.dataIn = dataIn;
288 this.latchData = latchData;
289 this.latchPath = latchPath;
290 this.dataOut = dataOut;
291 this.tokenOut = tokenOut;
292 this.interruptible = interruptible;
293 if (dock != null && dock.isInputDock() && tokenIn && dataIn)
294 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an input dock: " + this);
295 if (dock != null && dock.isOutputDock() && tokenOut && dataOut)
296 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an output dock: " + this);
297 if (latchData && !dataIn)
298 throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this);
299 if (latchPath && !dataIn)
300 throw new RuntimeException("cannot have latchPath bit set without dataIn bit: " + this);
301 if (latchPath && path!=null)
302 throw new RuntimeException("cannot have latchPath and a non-null path: " + this);
305 public String toString() {
306 StringBuffer ret = new StringBuffer();
307 if (tokenIn) ret.append(", wait");
309 if (latchPath) ret.append(!dock.isInputDock() ? ", collect path" : ", recv path");
310 if (latchData) ret.append(!dock.isInputDock() ? ", collect" : ", recv");
311 if (!latchPath && !latchData) ret.append(", discard");
313 if (dataOut && dock.isInputDock()) ret.append(", deliver");
314 if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send" : ", sendto " + path.getDestination().getDock());
315 if (tokenOut) ret.append(path==null ? ", token" : ", notify " + path.getDestination().getDock());
316 String s = ret.toString();
317 s = s.equals("") ? "nop" : s.substring(2);
318 if (interruptible) s = "[T] " + s;
319 return super.toString()+s+";";
323 /** marks the end of a loop; closes the hatch */
324 public static class Tail extends Instruction {
325 public Tail(Dock dock) { super(dock, false, Predicate.IgnoreOLC); }
326 public String toString() { return super.toString() + "tail;"; }