f021242ff388cf88d865d0b9d1dd4c6f416a9f30
[fleet.git] / src / edu / berkeley / fleet / api / Instruction.java
1 package edu.berkeley.fleet.api;
2
3 public abstract class Instruction {
4
5     public final Pump pump;
6     public Instruction(Pump pump) { this.pump = pump; }
7     public String toString() { return pump+": "; }
8
9     public static abstract class CountingInstruction extends Instruction {
10         public final int count;
11         public CountingInstruction(Pump pump, int count) {
12             super(pump);
13             this.count = count;
14         }
15         public boolean isStanding() { return count==0; }
16         public abstract boolean isRequeueing();
17         public String toString() { return super.toString()+(count==1?"":(isRequeueing()?("("+(count==0?"*":(count+""))+")"):("["+(count==0?"*":(count+""))+"]")))+" "; }
18     }
19
20     public static class UnClog extends Instruction {
21         public UnClog(Pump pump) { super(pump); }
22         public String toString() { return super.toString() + "unclog;"; }
23     }
24
25     public static class Massacre extends Instruction {
26         public Massacre(Pump pump) { super(pump); }
27     }
28
29     public static class Clog extends Executable {
30         public Clog(Pump pump) { super(pump, 1); }
31         public String toString() { return super.toString() + "clog;"; }
32         public Instruction.Executable decrementCount() { return null; }
33         public boolean isRequeueing() { return false; }
34     }
35
36     public static class Kill extends CountingInstruction {
37         public Kill(Pump pump, int count) { super(pump, count); }
38         public boolean isRequeueing() { return false; }
39         public String toString() { return super.toString() + "kill;"; }
40     }
41
42     public static abstract class Executable extends CountingInstruction {
43         public Executable(Pump pump, int count) { super(pump, count); }
44         public abstract Instruction.Executable decrementCount();
45     }
46
47     public static class Move extends Executable {
48         public final Destination dest;
49
50         public final boolean     tokenIn;
51         public final boolean     dataIn;
52         public final boolean     latch;
53         public final boolean     dataOutDest;
54         public final boolean     dataOut;
55         public final boolean     tokenOut;
56         public final boolean     requeue;
57         public final boolean     ignoreUntilLast;
58
59         public boolean isRequeueing() { return requeue; }
60
61         /** count=0 denotes a standing move */
62         public Move(Pump        pump,
63                           Destination dest,
64                           int         count,
65                           boolean     tokenIn,
66                           boolean     dataIn,
67                           boolean     latch,
68                           boolean     dataOutDest,
69                           boolean     dataOut,
70                           boolean     tokenOut,
71                           boolean     requeue,
72                           boolean     ignoreUntilLast) {
73             super(pump, count);
74             this.dest = dest;
75             this.tokenIn = tokenIn;
76             this.dataIn = dataIn;
77             this.latch = latch;
78             this.dataOutDest = dataOutDest;
79             this.dataOut = dataOut;
80             this.tokenOut = tokenOut;
81             this.requeue = requeue;
82             this.ignoreUntilLast = ignoreUntilLast;
83             if (count < 0)
84                 throw new RuntimeException("count field of an instruction must be >=0");
85             if (pump.isInbox() && tokenIn && dataIn)
86                 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
87             if (pump.isOutbox() && tokenOut && dataOut)
88                 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
89             if (latch && !dataIn)
90                 throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
91         }
92
93         public Instruction.Executable decrementCount() {
94             if (count==1) return null;
95             return new Move(pump, dest, count==0 ? 0 : count-1,
96                             tokenIn, dataIn, latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast);
97         }
98
99         public String toString() {
100             // FIXME
101             String ret = super.toString();
102             boolean needcomma = false;
103             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
104             if (dataIn && latch)  {
105                 if (pump.isInbox())
106                     ret += (needcomma ? ", " : "") + "receive";
107                 else
108                     ret += (needcomma ? ", " : "") + "take";
109                 needcomma = true;
110             }
111             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
112             if (dataOut)  {
113                 if (pump.isInbox() || dest==null)
114                     ret += (needcomma ? ", " : "") + "deliver";
115                 else
116                     ret += (needcomma ? ", " : "") + "sendto "+dest;
117                 needcomma = true;
118             }
119             if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; }
120             return ret;
121         }
122
123     }
124
125     public static class LocalLiteral extends Executable {
126         public final long literal;
127         public boolean isRequeueing() { return true; }
128         public LocalLiteral(Pump pump, long literal, int count) {
129             super(pump, count);
130             this.literal = literal;
131         }
132         public Instruction.Executable decrementCount() {
133             if (count==1) return null;
134             return new LocalLiteral(pump, literal, count-1);
135         }
136     }
137
138     public static class CodeBagDescriptor extends Instruction {
139         /** address of CBD, relative to address that this instruction was loaded from */
140         public final long offset;
141         public final long size;
142         public CodeBagDescriptor(Pump pump, long offset, long size) {
143             super(pump);
144             this.offset = offset;
145             this.size = size;
146         }
147         public String toString() {
148             String off = ""+offset;
149             if (offset > 0) off = "+"+off;
150             return "(CBD @"+off+"+"+size+"): sendto " + pump;
151         }
152     }
153
154 }