update tests
[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     if (!rst) begin
124       `reset
125       have_in1 = 0;
126       have_in2 = 0;
127       have_in = 0;
128       have_out1 = 0;
129       have_out2 = 0;
130       zero = 0;
131       pos = 0;
132       neg = 0;
133     end else begin
134
135     if (!have_in1) begin
136       `onread(in1_r, in1_a) have_in1 <= 1; reg_in1 <= in1_d; end
137       end
138     if (!have_in2) begin
139       `onread(in2_r, in2_a) have_in2 <= 1; reg_in2 <= in2_d; end
140       end
141     if (!have_in) begin
142       `onread(in_r,  in_a)  have_in  <= 1;  reg_in <= in_d;  end
143       end
144
145     if (have_out1) begin
146       `onwrite(out1_r, out1_a) have_out1 <= 0; end
147       end
148
149     if (have_out2) begin
150       `onwrite(out2_r, out2_a) have_out2 <= 0; end
151       end
152
153     if (have_in && !have_out1 && !have_out2) begin
154       zero = reg_in[`DATAWIDTH-1:0] == 0;
155       neg = reg_in[`DATAWIDTH-1];
156       pos = !zero && !neg;
157       case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
158         00: fire = zero;
159         06: fire = zero;
160         12: fire = zero;
161         01: fire = !zero;
162         07: fire = !zero;
163         13: fire = !zero;
164         02: fire = neg;
165         08: fire = neg;
166         14: fire = neg;
167         03: fire = pos;
168         09: fire = pos;
169         15: fire = pos;
170         04: fire = !neg;
171         16: fire = !neg;
172         10: fire = !neg;
173         05: fire = !pos;
174         11: fire = !pos;
175         17: fire = !pos;
176       endcase
177
178       if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
179             if (have_in1 && have_in2 && !have_out1 && !have_out2) begin
180               have_out1 <= 1;
181               have_out2 <= 1;
182               have_in1  <= 0;
183               have_in2  <= 0;
184               have_in   <= 0;
185               out1_d    <= fire ? reg_in2 : reg_in1;
186               out2_d    <= fire ? reg_in1 : reg_in2;
187             end
188       end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
189             if (fire && have_in2) begin
190               have_out1 <= 1;
191               have_in2  <= 0;
192               out1_d    <= in2_d;
193               have_in   <= 0;
194             end else if (!fire && have_in1) begin
195               have_out1 <= 1;
196               have_in1  <= 0;
197               out1_d    <= in1_d;
198               have_in   <= 0;
199             end
200       end else begin
201             if (have_in1) begin
202               if (fire) begin
203                 have_out2 <= 1;
204                 out2_d    <= in1_d;
205                 have_in1  <= 0;
206                 have_in   <= 0;
207               end else begin
208                 have_out1 <= 1;
209                 out1_d    <= in1_d;
210                 have_in1  <= 0;
211                 have_in   <= 0;
212               end
213             end
214       end
215
216    end
217    end
218
219   end
220
221
222
223 == Test ==============================================================================
224 #skip
225 #ship debug : Debug
226 #expect 0
227
228 == Contributors =========================================================
229 Adam Megacz <megacz@cs.berkeley.edu>