reorder Alu3 instructions to deal with two-instruction literals
[fleet.git] / ships / Choice.ship
1 ship: Choice
2
3 == Ports ===========================================================
4 data  in:   in1
5 data  in:   in2
6 data  in:   in.swapIfZero
7 data  in:   in.swapIfNonZero
8 data  in:   in.swapIfNegative
9 data  in:   in.swapIfPositive
10 data  in:   in.swapIfNonNegative
11 data  in:   in.swapIfNonPositive
12 data  in:   in.muxIfZero
13 data  in:   in.muxIfNonZero
14 data  in:   in.muxIfNegative
15 data  in:   in.muxIfPositive
16 data  in:   in.muxIfNonNegative
17 data  in:   in.muxIfNonPositive
18 data  in:   in.deMuxIfZero
19 data  in:   in.deMuxIfNonZero
20 data  in:   in.deMuxIfNegative
21 data  in:   in.deMuxIfPositive
22 data  in:   in.deMuxIfNonNegative
23 data  in:   in.deMuxIfNonPositive
24
25 data  out:  out1
26 data  out:  out2
27
28 == Constants ========================================================
29
30 == TeX ==============================================================
31
32 This ship needs to be updated to use opcode ports \cite{am25}.  For a
33 general idea of what this ship is supposed to do, see \cite{am17}.
34
35 %With judicious programming of its pumps, this ship can be used to
36 %implement nearly all forms of selection and branching.
37 %
38 %When data is available at the in port, it is examined.  Which
39 %destination the datum has arrived on determines the *condition* the
40 %datum should be tested for and the *action* which should be taken if
41 %the condition holds true.
42 %
43 %The latter portion of the name of the destination (IfZero,
44 %If(Non)Positive, If(Non)Negative) determines the condition which the
45 %datum on the in port is tested for.  The former portion (mux, demux,
46 %swap) determines the *action* to be taken if the condition tests true.
47 %
48 %\begin{verbatim}
49 %  action   condition    effect
50 %  ------   ---------    -------------------------------
51 %  swap     false        in1->out1   in2->out2
52 %  swap     true         in2->out1   in1->out2
53 %  mux      false        in1->out1
54 %  mux      true         in2->out1
55 %  demux    false        in1->out1
56 %  demux    true         in1->out2
57 %\end{verbatim}
58 %
59 %In each case, the ship will wait for a datum to be available on all
60 %input ports (and only those ports) mentioned in the appropriate row of
61 %the "effect" column above, and will output them on the corresponding
62 %output ports.
63
64
65 == Fleeterpreter ====================================================
66 private Packet selector;
67 public void service() {
68   if (!box_out1.readyForDataFromShip() || !box_out2.readyForDataFromShip()) return;
69   if (selector == null && !box_in.dataReadyForShip()) return;
70   if (selector == null) selector = box_in.removePacketForShip();
71   String port = selector.destination.getDestinationName();
72
73   if (port.startsWith("swap")  && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
74   if (port.startsWith("mux")   && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
75   if (port.startsWith("deMux") && (!box_in1.dataReadyForShip())) return;
76
77   long val = selector.value;
78   boolean condition = false;
79   if (port.endsWith("IfZero"))        condition = val==0;
80   if (port.endsWith("IfNonZero"))     condition = val!=0;
81   if (port.endsWith("IfPositive"))    condition = val>0;
82   if (port.endsWith("IfNegative"))    condition = val<0;
83   if (port.endsWith("IfNonPositive")) condition = val<=0;
84   if (port.endsWith("IfNonNegative")) condition = val>=0;
85   if (port.startsWith("swap")) {
86     if (condition) {
87       box_out1.addDataFromShip(box_in2.removeDataForShip());
88       box_out2.addDataFromShip(box_in1.removeDataForShip());
89       selector = null;
90     } else {
91       box_out1.addDataFromShip(box_in1.removeDataForShip());
92       box_out2.addDataFromShip(box_in2.removeDataForShip());
93       selector = null;
94     }
95   } else if (port.startsWith("mux")) {
96     box_out1.addDataFromShip(condition ? box_in2.removeDataForShip() : box_in1.removeDataForShip());
97     selector = null;
98   } else if (port.startsWith("deMux")) {
99     (condition ? box_out2 : box_out1).addDataFromShip(box_in1.removeDataForShip());
100     selector = null;
101   }
102 }
103
104 == FleetSim ==============================================================
105
106 == FPGA ==============================================================
107
108   reg                       have_in1;
109   reg [(`DATAWIDTH-1):0]    reg_in1;
110   reg                       have_in2;
111   reg [(`DATAWIDTH-1):0]    reg_in2;
112   reg                       have_in;
113   reg [(`PACKET_WIDTH-1):0] reg_in;
114   reg                       have_out1;
115   reg                       have_out2;
116   reg fire;
117
118   reg zero;
119   reg pos;
120   reg neg;
121
122   always @(posedge clk) begin
123
124     if (!have_in1) begin
125       `onread(in1_r, in1_a) have_in1 <= 1; reg_in1 <= in1_d; end
126       end
127     if (!have_in2) begin
128       `onread(in2_r, in2_a) have_in2 <= 1; reg_in2 <= in2_d; end
129       end
130     if (!have_in) begin
131       `onread(in_r,  in_a)  have_in  <= 1;  reg_in <= in_d;  end
132       end
133
134     if (have_out1) begin
135       `onwrite(out1_r, out1_a) have_out1 <= 0; end
136       end
137
138     if (have_out2) begin
139       `onwrite(out2_r, out2_a) have_out2 <= 0; end
140       end
141
142     if (have_in && !have_out1 && !have_out2) begin
143       zero = reg_in[`DATAWIDTH-1:0] == 0;
144       neg = reg_in[`DATAWIDTH-1];
145       pos = !zero && !neg;
146       case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
147         00: fire = zero;
148         06: fire = zero;
149         12: fire = zero;
150         01: fire = !zero;
151         07: fire = !zero;
152         13: fire = !zero;
153         02: fire = neg;
154         08: fire = neg;
155         14: fire = neg;
156         03: fire = pos;
157         09: fire = pos;
158         15: fire = pos;
159         04: fire = !neg;
160         16: fire = !neg;
161         10: fire = !neg;
162         05: fire = !pos;
163         11: fire = !pos;
164         17: fire = !pos;
165       endcase
166
167       if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
168             if (have_in1 && have_in2 && !have_out1 && !have_out2) begin
169               have_out1 <= 1;
170               have_out2 <= 1;
171               have_in1  <= 0;
172               have_in2  <= 0;
173               have_in   <= 0;
174               out1_d    <= fire ? reg_in2 : reg_in1;
175               out2_d    <= fire ? reg_in1 : reg_in2;
176             end
177       end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
178             if (fire && have_in2) begin
179               have_out1 <= 1;
180               have_in2  <= 0;
181               out1_d    <= in2_d;
182               have_in   <= 0;
183             end else if (!fire && have_in1) begin
184               have_out1 <= 1;
185               have_in1  <= 0;
186               out1_d    <= in1_d;
187               have_in   <= 0;
188             end
189       end else begin
190             if (have_in1) begin
191               if (fire) begin
192                 have_out2 <= 1;
193                 out2_d    <= in1_d;
194                 have_in1  <= 0;
195                 have_in   <= 0;
196               end else begin
197                 have_out1 <= 1;
198                 out1_d    <= in1_d;
199                 have_in1  <= 0;
200                 have_in   <= 0;
201               end
202             end
203       end
204
205    end
206
207   end
208
209
210
211 == Test ==============================================================================
212 #skip
213 #ship debug : Debug
214 #expect 0
215
216 == Contributors =========================================================
217 Adam Megacz <megacz@cs.berkeley.edu>