rename ItemForShip to DataForShip for consistency
[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 BenkoBoxes, 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   action   condition    effect
49   ------   ---------    -------------------------------
50   swap     false        in1->out1   in2->out2
51   swap     true         in2->out1   in1->out2
52   mux      false        in1->out1
53   mux      true         in2->out1
54   demux    false        in1->out1
55   demux    true         in1->out2
56
57 In each case, the ship will wait for a datum to be available on all
58 input ports (and only those ports) mentioned in the appropriate row of
59 the "effect" column above, and will output them on the corresponding
60 output ports.
61
62
63 == Fleeterpreter ====================================================
64 private Packet selector;
65 public void service() {
66   if (!box_out1.readyForDataFromShip() || !box_out2.readyForDataFromShip()) return;
67   if (selector == null && !box_in.dataReadyForShip()) return;
68   if (selector == null) selector = box_in.removePacketForShip();
69   String port = selector.destination.getDestinationName();
70
71   if (port.startsWith("swap")  && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
72   if (port.startsWith("mux")   && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
73   if (port.startsWith("deMux") && (!box_in1.dataReadyForShip())) return;
74
75   long val = selector.value;
76   boolean condition = false;
77   if (port.endsWith("IfZero"))        condition = val==0;
78   if (port.endsWith("IfNonZero"))     condition = val!=0;
79   if (port.endsWith("IfPositive"))    condition = val>0;
80   if (port.endsWith("IfNegative"))    condition = val<0;
81   if (port.endsWith("IfNonPositive")) condition = val<=0;
82   if (port.endsWith("IfNonNegative")) condition = val>=0;
83   if (port.startsWith("swap")) {
84     if (condition) {
85       box_out1.addDataFromShip(box_in2.removeDataForShip());
86       box_out2.addDataFromShip(box_in1.removeDataForShip());
87       selector = null;
88     } else {
89       box_out1.addDataFromShip(box_in1.removeDataForShip());
90       box_out2.addDataFromShip(box_in2.removeDataForShip());
91       selector = null;
92     }
93   } else if (port.startsWith("mux")) {
94     box_out1.addDataFromShip(condition ? box_in2.removeDataForShip() : box_in1.removeDataForShip());
95     selector = null;
96   } else if (port.startsWith("deMux")) {
97     (condition ? box_out2 : box_out1).addDataFromShip(box_in1.removeDataForShip());
98     selector = null;
99   }
100 }
101
102 == FleetSim ==============================================================
103
104 == FPGA ==============================================================
105
106   reg                       have_in1;
107   reg [(`DATAWIDTH-1):0]    reg_in1;
108   reg                       have_in2;
109   reg [(`DATAWIDTH-1):0]    reg_in2;
110   reg                       have_in;
111   reg [(`PACKET_WIDTH-1):0] reg_in;
112   reg                       have_out1;
113   reg                       have_out2;
114   reg fire;
115
116   reg zero;
117   reg pos;
118   reg neg;
119
120   always @(posedge clk) begin
121
122     if (!have_in1) begin
123       `onread(in1_r, in1_a) have_in1 <= 1; reg_in1 <= in1_d; end
124       end
125     if (!have_in2) begin
126       `onread(in2_r, in2_a) have_in2 <= 1; reg_in2 <= in2_d; end
127       end
128     if (!have_in) begin
129       `onread(in_r,  in_a)  have_in  <= 1;  reg_in <= in_d;  end
130       end
131
132     if (have_out1) begin
133       `onwrite(out1_r, out1_a) have_out1 <= 0; end
134       end
135
136     if (have_out2) begin
137       `onwrite(out2_r, out2_a) have_out2 <= 0; end
138       end
139
140     if (have_in && !have_out1 && !have_out2) begin
141       zero = reg_in[`DATAWIDTH-1:0] == 0;
142       neg = reg_in[`DATAWIDTH-1];
143       pos = !zero && !neg;
144       case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
145         00: fire = zero;
146         06: fire = zero;
147         12: fire = zero;
148         01: fire = !zero;
149         07: fire = !zero;
150         13: fire = !zero;
151         02: fire = neg;
152         08: fire = neg;
153         14: fire = neg;
154         03: fire = pos;
155         09: fire = pos;
156         15: fire = pos;
157         04: fire = !neg;
158         16: fire = !neg;
159         10: fire = !neg;
160         05: fire = !pos;
161         11: fire = !pos;
162         17: fire = !pos;
163       endcase
164
165       if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
166             if (have_in1 && have_in2 && !have_out1 && !have_out2) begin
167               have_out1 <= 1;
168               have_out2 <= 1;
169               have_in1  <= 0;
170               have_in2  <= 0;
171               have_in   <= 0;
172               out1_d    <= fire ? reg_in2 : reg_in1;
173               out2_d    <= fire ? reg_in1 : reg_in2;
174             end
175       end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
176             if (fire && have_in2) begin
177               have_out1 <= 1;
178               have_in2  <= 0;
179               out1_d    <= in2_d;
180               have_in   <= 0;
181             end else if (!fire && have_in1) begin
182               have_out1 <= 1;
183               have_in1  <= 0;
184               out1_d    <= in1_d;
185               have_in   <= 0;
186             end
187       end else begin
188             if (have_in1) begin
189               if (fire) begin
190                 have_out2 <= 1;
191                 out2_d    <= in1_d;
192                 have_in1  <= 0;
193                 have_in   <= 0;
194               end else begin
195                 have_out1 <= 1;
196                 out1_d    <= in1_d;
197                 have_in1  <= 0;
198                 have_in   <= 0;
199               end
200             end
201       end
202
203    end
204
205   end
206
207
208
209 == Contributors =========================================================
210 Adam Megacz <megacz@cs.berkeley.edu>