FPGA-Fleet updates
[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.readyForItemFromShip() || !box_out2.readyForItemFromShip()) 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 = box_in.removeDataForShip();
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     } else {
88       box_out1.addDataFromShip(box_in1.removeDataForShip());
89       box_out2.addDataFromShip(box_in2.removeDataForShip());
90     }
91   } else if (port.startsWith("mux")) {
92     box_out1.addDataFromShip(condition ? box_in2.removeDataForShip() : box_in1.removeDataForShip());
93   } else if (port.startsWith("deMux")) {
94     (condition ? box_out2 : box_out1).addDataFromShip(box_in1.removeDataForShip());
95   }
96 }
97
98 == FleetSim ==============================================================
99
100 == FPGA ==============================================================
101
102   reg                       have_in1;
103   reg [(`DATAWIDTH-1):0]    reg_in1;
104   reg                       have_in2;
105   reg [(`DATAWIDTH-1):0]    reg_in2;
106   reg                       have_in;
107   reg [(`PACKET_WIDTH-1):0] reg_in;
108   reg                       have_out1;
109   reg                       have_out2;
110   reg fire;
111
112   always @(posedge clk) begin
113     if (!have_in1) begin
114       `onread(in1_r, in1_a) have_in1 = 1; reg_in1 = in1_d; end
115       end
116     if (!have_in2) begin
117       `onread(in2_r, in2_a) have_in2 = 1; reg_in2 = in2_d; end
118       end
119     if (!have_in) begin
120       `onread(in_r, in_a)   have_in = 1;  reg_in = in_d;   end
121       end
122
123     if (have_out1) begin
124       `onwrite(out1_r, out1_d) have_out1 = 0; end
125       end
126     if (have_out2) begin
127       `onwrite(out2_r, out2_d) have_out2 = 0; end
128       end
129
130     if (have_in && !have_out1 && !have_out2) begin
131       case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
132         00: /* in.swapIfZero */         fire = reg_in[`DATAWIDTH-1:0] == 0;
133         06: /* in.muxIfZero */          fire = reg_in[`DATAWIDTH-1:0] == 0;
134         12: /* in.deMuxIfZero */        fire = reg_in[`DATAWIDTH-1:0] == 0;
135         01: /* in.swapIfNonZero */      fire = reg_in[`DATAWIDTH-1:0] != 0;
136         07: /* in.muxIfNonZero */       fire = reg_in[`DATAWIDTH-1:0] != 0;
137         13: /* in.deMuxIfNonZero */     fire = reg_in[`DATAWIDTH-1:0] != 0;
138         02: /* in.swapIfNegative */     fire = reg_in[`DATAWIDTH-1:0] < 0;
139         08: /* in.muxIfNegative */      fire = reg_in[`DATAWIDTH-1:0] < 0;
140         14: /* in.deMuxIfNegative */    fire = reg_in[`DATAWIDTH-1:0] < 0;
141         03: /* in.swapIfPositive */     fire = reg_in[`DATAWIDTH-1:0] > 0;
142         09: /* in.muxIfPositive */      fire = reg_in[`DATAWIDTH-1:0] > 0;
143         15: /* in.deMuxIfPositive */    fire = reg_in[`DATAWIDTH-1:0] > 0;
144         04: /* in.swapIfNonNegative */  fire = reg_in[`DATAWIDTH-1:0] >= 0;
145         16: /* in.deMuxIfNonNegative */ fire = reg_in[`DATAWIDTH-1:0] >= 0;
146         10: /* in.muxIfNonNegative */   fire = reg_in[`DATAWIDTH-1:0] >= 0;
147         05: /* in.swapIfNonPositive */  fire = reg_in[`DATAWIDTH-1:0] <= 0;
148         11: /* in.muxIfNonPositive */   fire = reg_in[`DATAWIDTH-1:0] <= 0;
149         17: /* in.deMuxIfNonPositive */ fire = reg_in[`DATAWIDTH-1:0] <= 0;
150       endcase
151
152       if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
153             if (have_in1 && have_in2) begin
154               have_out1 = 1;
155               have_out2 = 1;
156               have_in1 = 0;
157               have_in2 = 0;
158               out1_d = fire ? reg_in2 : reg_in1;
159               out2_d = fire ? reg_in1 : reg_in2;
160             end
161       end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
162             if (fire && have_in2) begin
163               have_out1 = 1;
164               have_in2 = 0;
165               out1_d = in2_d;
166             end else if (!fire && have_in1) begin
167               have_out1 = 1;
168               have_in1 = 0;
169               out1_d = in1_d;
170             end
171       end else begin
172             if (have_in1) begin
173               if (fire) begin
174                 have_out2 = 1;
175                 out2_d = in1_d;
176                 have_in1 = 0;
177               end else begin
178                 have_out1 = 1;
179                 out1_d = in1_d;
180                 have_in1 = 0;
181               end
182             end
183       end
184    end
185   end
186
187
188
189 == Contributors =========================================================
190 Adam Megacz <megacz@cs.berkeley.edu>