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 += "[Rq] ";
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:
196 case Infinity: return super.toString()+"set ilc=*;";
197 case DataLatch: return super.toString()+"set ilc=data;";
198 case Immediate: return super.toString()+"set ilc="+immediate+";";
200 case OuterLoopCounter:
202 case Decrement: return super.toString()+"set olc--;";
203 case DataLatch: return super.toString()+"set olc=data;";
204 case Immediate: return super.toString()+"set olc="+immediate+";";
206 case Flags: return super.toString()+"set flags a="+newFlagA+", b="+newFlagB+";";
207 case DataLatch: return super.toString()+"set word="+immediate+";";
209 throw new Error("impossible");
213 /** shifts an immediate into the low-order bits of the data latch */
214 public static class Shift extends Instruction {
215 public final BitVector immediate;
216 public Shift(Dock dock, BitVector immediate) { this(dock, false, Predicate.Default, immediate); }
217 public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) {
218 super(dock, looping, predicate);
219 this.immediate = immediate;
220 this.immediate.setImmutable();
222 public String toString() { return super.toString()+"shift "+immediate; }
225 /** all communication is performed with this instruction */
226 public static class Move extends Instruction {
228 /** if true, this instruction is vulnerable to torpedoes */
229 public final boolean interruptible;
231 /** if non-null, the path to load into the path latch */
232 public final Path path;
234 /** if true, a token will be consumed before execution */
235 public final boolean tokenIn;
237 /** if true, data will be consumed before execution */
238 public final boolean dataIn;
240 /** if true, the data consumed will be copied into the data latch */
241 public final boolean latchData;
243 /** if true, the data consumed will be copied into the path latch */
244 public final boolean latchPath;
246 /** if true, the value in the data latch will be transmitted (to the location in the path latch if at an output dock) */
247 public final boolean dataOut;
249 /** if true, the a token will be transmitted to the location in the path latch */
250 public final boolean tokenOut;
252 public Move(Dock dock,
261 this(dock, false, Predicate.Default, false, path, tokenIn, dataIn, latchData, latchPath, dataOut, tokenOut); }
262 public Move(Dock dock,
265 boolean interruptible,
274 super(dock, looping, predicate);
276 this.tokenIn = tokenIn;
277 this.dataIn = dataIn;
278 this.latchData = latchData;
279 this.latchPath = latchPath;
280 this.dataOut = dataOut;
281 this.tokenOut = tokenOut;
282 this.interruptible = interruptible;
283 if (dock != null && dock.isInputDock() && tokenIn && dataIn)
284 throw new RuntimeException("cannot have two \"recv\"s: " + this);
285 if (dock != null && dock.isOutputDock() && tokenOut && dataOut)
286 throw new RuntimeException("cannot have two \"send\"s: " + this);
287 if (latchData && !dataIn)
288 throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this);
289 if (latchPath && !dataIn)
290 throw new RuntimeException("cannot have latchPath bit set without dataIn bit: " + this);
291 if (latchPath && path!=null)
292 throw new RuntimeException("cannot have latchPath and a non-null path: " + this);
295 public String toString() {
296 StringBuffer ret = new StringBuffer();
297 if (tokenIn) ret.append(", recv token");
299 if (latchPath) ret.append(!dock.isInputDock() ? ", collect path" : ", recv path");
300 if (latchData) ret.append(!dock.isInputDock() ? ", collect" : ", recv");
301 if (!latchPath && !latchData) ret.append(", discard");
303 if (dataOut && dock.isInputDock()) ret.append(", deliver");
304 if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send" : ", send to " + path.getDestination().getDock());
305 if (tokenOut) ret.append(path==null ? ", token" : ", send token to " + path.getDestination().getDock());
306 String s = ret.toString();
307 s = s.equals("") ? "nop" : s.substring(2);
308 if (interruptible) s = "[T] " + s;
309 return super.toString()+s+";";
313 /** marks the end of a loop; closes the hatch */
314 public static class Tail extends Instruction {
315 public Tail(Dock dock) { super(dock, false, Predicate.IgnoreOLC); }
316 public String toString() { return dock+": tail;"; }