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