convert many more test cases
[fleet.git] / ships / Choice.ship
1 ship: Choice
2
3 == Ports ===========================================================
4 data  in:   in1
5 data  in:   in2
6
7 data  in:   in.swapIfZero
8 data  in:   in.swapIfNonZero
9 data  in:   in.swapIfNegative
10 data  in:   in.swapIfPositive
11 data  in:   in.swapIfNonNegative
12 data  in:   in.swapIfNonPositive
13
14 data  in:   in.muxIfZero
15 data  in:   in.muxIfNonZero
16 data  in:   in.muxIfNegative
17 data  in:   in.muxIfPositive
18 data  in:   in.muxIfNonNegative
19 data  in:   in.muxIfNonPositive
20
21 data  in:   in.deMuxIfZero
22 data  in:   in.deMuxIfNonZero
23 data  in:   in.deMuxIfNegative
24 data  in:   in.deMuxIfPositive
25 data  in:   in.deMuxIfNonNegative
26 data  in:   in.deMuxIfNonPositive
27
28 data  out:  out1
29 data  out:  out2
30
31 == Constants ========================================================
32
33 == TeX ==============================================================
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 0: sendto debug.in;
216
217 == Contributors =========================================================
218 Adam Megacz <megacz@cs.berkeley.edu>