add flush support to ships
[fleet.git] / ships / Alu.ship
1 ship: Alu
2
3 == Ports ===========================================================
4 data  in:   in1
5 data  in:   in2
6 data  in:   inOp
7   constant IN1: 0
8   constant IN2: 1
9   constant ADD: 2
10   constant SUB: 3
11   constant MAX: 4
12   constant MIN: 5
13   constant CMP: 6
14   constant DROP1: 7
15   constant DROP2: 8
16   constant MAXMERGE: 9
17
18 data  out:  out
19
20
21 == TeX ==============================================================
22
23 {\tt Alu} is a ``two-input'' arithmetic logic unit.  It includes
24 logic for performing arithmetic operations on a pair of arguments.
25 Currently this includes
26 addition ({\sc add}),
27 subtraction ({\sc sub}),
28 maximum ({\sc max}), and
29 minimum ({\sc min}).
30
31 \subsection*{Semantics}
32
33 When a value is present at each of {\tt in1}, {\tt in2} and {\tt
34 inOp}, these three values are consumed.  Based on the value consumed
35 at {\tt inOp}, the requested operation is performed on the values
36 consumed from {\tt in1} and {\tt in2}.  The result of this operation
37 is then made available at {\tt out}.
38
39 \subsection*{C-Flag}
40
41 \begin{verbatim}
42 IN1      - undefined; drain in1 only
43 IN2      - undefined; drain in2 only
44 ADD      - carry-out
45 SUB      - undefined
46 MAX      - if in1>in2 cflag=0 and drain in1, else cflag=1 and drain in2
47 MIN      - if in1>in2 cflag=1 and drain in2, else cflag=0 and drain in1
48 CMP      - if in1==in2 cflag=1, else cflag=0
49 DROP1    - consume in1, produce no output
50 DROP2    - consume in2, produce no output
51 MAXMERGE - if (in1<0 && in2<0) consume both, emit either, cflag=undef else act as MAX
52 \end{verbatim}
53
54 \subsection*{To Do}
55
56 The {\it link bit} and other features of \cite{ies31} are not yet
57 implemented.
58
59 The carry-in, carry-out, zero-test, negative-test, and overflow-test
60 flags typically present in a conventional processor ALU are also not
61 yet implemented.
62
63 == Fleeterpreter ====================================================
64 public void service() {
65   if (box_inOp.dataReadyForShip() &&
66       box_in1.dataReadyForShip() &&
67       box_in2.dataReadyForShip() &&
68       box_out.readyForDataFromShip()) {
69       long a;
70       long b;
71       long op     = box_inOp.removeDataForShip();
72       switch((int)op) {
73           case 0:
74               a = box_in1.removeDataForShip();
75               box_out.addDataFromShip(a); // IN1
76               break;
77           case 1:
78               b = box_in2.removeDataForShip();
79               box_out.addDataFromShip(b); // IN2
80               break;
81           case 2:
82               a = box_in1.removeDataForShip();
83               b = box_in2.removeDataForShip();
84               box_out.addDataFromShip(a+b); // ADD
85               break;
86           case 3:
87               a = box_in1.removeDataForShip();
88               b = box_in2.removeDataForShip();
89               box_out.addDataFromShip(a-b); // SUB
90               break;
91           case 4:
92               a = box_in1.peekDataForShip();
93               b = box_in2.peekDataForShip();
94               box_out.addDataFromShip(Math.max(a,b)); // MAX
95               box_out.flag_c = !(a>b);
96               if (a<b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
97               break;
98           case 5:
99               a = box_in1.peekDataForShip();
100               b = box_in2.peekDataForShip();
101               box_out.addDataFromShip(Math.min(a,b)); // MIN
102               box_out.flag_c = a>b;
103               if (a>b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
104               break;
105           case 6:
106               a = box_in1.removeDataForShip();
107               b = box_in2.removeDataForShip();
108               box_out.addDataFromShip(0); // CMP
109               box_out.flag_c = a==b;
110               break;
111           default:
112               a = box_in1.removeDataForShip();
113               b = box_in2.removeDataForShip();
114               box_out.addDataFromShip(0);
115               break;
116       }
117   }
118 }
119
120 == FleetSim ==============================================================
121
122 == FPGA ==============================================================
123
124   wire [`DATAWIDTH:0]     sum;
125   wire                    cin;
126   wire [(`DATAWIDTH-1):0] in2_inverted;
127
128   wire [(`DATAWIDTH-1):0] res;
129   wire                    isplus;
130   wire                    eq;
131   wire                    cout;
132
133   assign isplus        = inOp_d[2:0]==2;
134   assign cin           = isplus ? 0 : 1;
135   assign in2_inverted  = isplus ? in2_d : ~in2_d;
136   assign sum           = {in1_d,cin} + {in2_inverted,cin};
137   assign res           = sum[`DATAWIDTH:1];
138   assign greater       = !res[`DATAWIDTH-1];
139   assign both_negative = in1_d[`DATAWIDTH-1] && in2_d[`DATAWIDTH-1];
140   assign eq            = in1_d == in2_d;
141   assign cout          = sum[`DATAWIDTH];
142
143   assign out_d_[`DATAWIDTH] =
144           (inOp_d==0) ? 1'b0 :
145           (inOp_d==1) ? 1'b0 :
146           (inOp_d==2) ? cout :
147           (inOp_d==3) ? cout :
148           (inOp_d==4) ? ~greater :
149           (inOp_d==5) ?  greater :
150           (inOp_d==6) ?  eq :
151           (inOp_d==9) ? ~greater :
152           0;
153
154   assign out_d_[(`DATAWIDTH-1):0] =
155           (inOp_d==0) ? (in1_d)  :
156           (inOp_d==1) ? (in2_d)  :
157           (inOp_d==2) ? (res)  :
158           (inOp_d==3) ? (res)  :
159           (inOp_d==4) ? (greater ? in1_d : in2_d)  :
160           (inOp_d==5) ? (greater ? in2_d : in1_d)  :
161           (inOp_d==6) ? {{ (`DATAWIDTH-1) {1'b0 }}, eq  } :
162           (inOp_d==9) ? (both_negative ? in1_d : (greater ? in1_d : in2_d)) :
163           0;
164
165   always @(posedge clk) begin
166     if (!rst) begin
167       `reset
168     end else begin
169       `flush
170       if (!in1_r_  && in1_a)    in1_a    <= 0;
171       if (!in2_r_  && in2_a)    in2_a    <= 0;
172       if (!inOp_r_ && inOp_a)   inOp_a   <= 0;
173       if (out_r    && out_a) begin
174         out_r  <= 0;
175         inOp_a <= 1;
176
177         if      (inOp_d==0) in1_a <= 1;
178         else if (inOp_d==1) in2_a <= 1;
179         else if (inOp_d==9 &&  both_negative) begin in1_a <= 1; in2_a <= 1; end
180         else if (inOp_d==4 &&  greater) in1_a <= 1;
181         else if (inOp_d==5 &&  greater) in2_a <= 1;
182         else if (inOp_d==9 &&  greater) in1_a <= 1;
183         else if (inOp_d==4 && !greater) in2_a <= 1;
184         else if (inOp_d==5 && !greater) in1_a <= 1;
185         else if (inOp_d==9 && !greater) in2_a <= 1;
186         else begin
187           in1_a <= 1;
188           in2_a <= 1;
189         end
190       end
191       if (!out_r && !out_a && in1_r && !in1_a && in2_r && !in2_a && inOp_r && !inOp_a) begin
192         out_r <= 1;
193       end
194     end
195   end
196
197 == Test ==============================================================================
198
199 // FIXME: need test for ADD carry-out c-flag
200
201 #ship debug : Debug
202 #ship alu   : Alu
203
204 #expect 17
205 #expect 1
206 #expect 9
207 #expect 8
208 #expect 8
209 #expect 1
210 #expect 9
211 #expect 0
212 #expect 0
213 #expect 1
214
215 debug.in:   set ilc=*;  recv, deliver;
216 alu.in1:
217   set word= 9;
218   set ilc=5;
219   deliver;
220   set word= 9;
221   deliver;
222
223 alu.in2:
224   set word= 8;
225   set ilc=5;
226   deliver;
227   set word= 9;
228   deliver;
229
230 alu.out:
231   set ilc=4;
232   collect, send to debug.in;
233 alu.inOp:
234  set word= Alu.inOp[ADD]; deliver;
235  set word= Alu.inOp[SUB]; deliver;
236  set word= Alu.inOp[IN1]; deliver;
237  set word= Alu.inOp[IN2]; deliver;
238  set word= Alu.inOp[MIN]; deliver;
239  set word= Alu.inOp[MAX]; deliver;
240  set word= Alu.inOp[CMP]; deliver;
241  set word= Alu.inOp[CMP]; deliver;
242
243 alu.out:
244   collect, send to debug.in;        // MIN
245   set flags a=c, b=b;
246   [a]  set word= 1;
247   [!a] set word= 0;
248   send to debug.in;
249
250   collect, send to debug.in;        // MAX
251   set flags a=c, b=b;
252   [a]  set word= 1;
253   [!a] set word= 0;
254   send to debug.in;
255
256   collect;        // CMP
257   set flags a=c, b=b;
258   [a]  set word= 1;
259   [!a] set word= 0;
260   send to debug.in;
261
262   collect;        // CMP
263   set flags a=c, b=b;
264   [a]  set word= 1;
265   [!a] set word= 0;
266   send to debug.in;
267
268 == Contributors =========================================================
269 Adam Megacz <megacz@cs.berkeley.edu>