3 == Ports ===========================================================
24 == TeX ==============================================================
26 {\tt Alu} is a ``two-input'' arithmetic logic unit. It includes
27 logic for performing arithmetic operations on a pair of arguments.
28 Currently this includes
30 subtraction ({\sc sub}),
31 maximum ({\sc max}), and
34 \subsection*{Semantics}
36 When a value is present at each of {\tt in1}, {\tt in2} and {\tt
37 inOp}, these three values are consumed. Based on the value consumed
38 at {\tt inOp}, the requested operation is performed on the values
39 consumed from {\tt in1} and {\tt in2}. The result of this operation
40 is then made available at {\tt out}.
45 IN1 - undefined; drain in1 only
46 IN2 - undefined; drain in2 only
49 MAX - if in1>in2 cflag=0 and drain in1, else cflag=1 and drain in2
50 MIN - if in1>in2 cflag=1 and drain in2, else cflag=0 and drain in1
51 CMP - if in1==in2 cflag=1, else cflag=0
52 DROP1 - consume in1, produce no output
53 DROP2 - consume in2, produce no output
54 MAXMERGE - if (in1<0 && in2<0) consume both, emit either, cflag=undef else act as MAX
59 The {\it link bit} and other features of \cite{ies31} are not yet
62 The carry-in, carry-out, zero-test, negative-test, and overflow-test
63 flags typically present in a conventional processor ALU are also not
66 == Fleeterpreter ====================================================
67 public void service() {
68 if (box_inOp.dataReadyForShip() &&
69 box_in1.dataReadyForShip() &&
70 box_in2.dataReadyForShip() &&
71 box_out.readyForDataFromShip()) {
74 long op = box_inOp.removeDataForShip();
77 a = box_in1.removeDataForShip();
78 box_out.addDataFromShip(a); // IN1
81 b = box_in2.removeDataForShip();
82 box_out.addDataFromShip(b); // IN2
85 a = box_in1.removeDataForShip();
86 b = box_in2.removeDataForShip();
87 box_out.addDataFromShip(a+b); // ADD
90 a = box_in1.removeDataForShip();
91 b = box_in2.removeDataForShip();
92 box_out.addDataFromShip(a-b); // SUB
96 if (box_in1.peekDataForShip()<0 && box_in2.peekDataForShip()<0) {
97 a = box_in1.removeDataForShip();
98 b = box_in2.removeDataForShip();
99 box_out.addDataFromShip(a, false);
102 // fall through to MAX
104 a = box_in1.peekDataForShip();
105 b = box_in2.peekDataForShip();
106 box_out.addDataFromShip(Math.max(a,b), !(a>b)); // MAX
107 if (a>b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
111 a = box_in1.peekDataForShip();
112 b = box_in2.peekDataForShip();
113 box_out.addDataFromShip(Math.min(a,b), a>b); // MIN
114 if (a<b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
117 a = box_in1.removeDataForShip();
118 b = box_in2.removeDataForShip();
119 box_out.addDataFromShip(0, a==b); // CMP
123 box_in1.removeDataForShip(); // DROP1
126 box_in2.removeDataForShip(); // DROP2
130 a = box_in1.removeDataForShip();
131 b = box_in2.removeDataForShip();
132 box_out.addDataFromShip(a & b); // CMP
135 a = box_in1.removeDataForShip();
136 b = box_in2.removeDataForShip();
137 box_out.addDataFromShip(a | b); // CMP
140 a = box_in1.removeDataForShip();
141 b = box_in2.removeDataForShip();
142 box_out.addDataFromShip(a ^ b); // CMP
145 throw new RuntimeException("invalid opcode: " + op);
150 == FleetSim ==============================================================
152 == FPGA ==============================================================
154 wire [`WORDWIDTH:0] sum;
156 wire [(`WORDWIDTH-1):0] in2_inverted;
158 wire [(`WORDWIDTH-1):0] res;
163 wire [4:0] inOp_d_trunc;
164 assign inOp_d_trunc = inOp_d[4:0];
166 assign isplus = inOp_d_trunc[4:0]==2;
167 assign cin = isplus ? 0 : 1;
168 assign in2_inverted = isplus ? in2_d : ~in2_d;
169 assign sum = {in1_d,cin} + {in2_inverted,cin};
170 assign res = sum[`WORDWIDTH:1];
171 assign greater = !res[`WORDWIDTH-1];
172 assign both_negative = in1_d[`WORDWIDTH-1] && in2_d[`WORDWIDTH-1];
173 assign eq = in1_d == in2_d;
174 assign cout = sum[`WORDWIDTH];
178 assign out_d_[`WORDWIDTH] =
179 (inOp_d_trunc==0) ? 1'b0 :
180 (inOp_d_trunc==1) ? 1'b0 :
181 (inOp_d_trunc==2) ? cout :
182 (inOp_d_trunc==3) ? cout :
183 (inOp_d_trunc==4) ? ~greater :
184 (inOp_d_trunc==5) ? greater :
185 (inOp_d_trunc==6) ? eq :
186 (inOp_d_trunc==9) ? ~greater :
189 assign out_d_[(`WORDWIDTH-1):0] =
190 (inOp_d_trunc==0) ? (in1_d) :
191 (inOp_d_trunc==1) ? (in2_d) :
192 (inOp_d_trunc==2) ? (res) :
193 (inOp_d_trunc==3) ? (res) :
194 (inOp_d_trunc==4) ? (greater ? in1_d : in2_d) :
195 (inOp_d_trunc==5) ? (greater ? in2_d : in1_d) :
196 (inOp_d_trunc==6) ? {{ (`WORDWIDTH-1) {1'b0 }}, eq } :
197 (inOp_d_trunc==9) ? (both_negative ? in1_d : (greater ? in1_d : in2_d)) :
198 (inOp_d_trunc==10) ? (in1_d & in2_d) :
199 (inOp_d_trunc==11) ? (in1_d | in2_d) :
200 (inOp_d_trunc==12) ? (in1_d ^ in2_d) :
203 always @(posedge clk) begin
209 if (out_draining && `out_empty) begin
212 if (inOp_d_trunc==0) `drain_in1
213 else if (inOp_d_trunc==1) `drain_in2
214 else if (inOp_d_trunc==9 && both_negative) begin `drain_in1 `drain_in2 end
215 else if (inOp_d_trunc==4 && greater) `drain_in1
216 else if (inOp_d_trunc==5 && greater) `drain_in2
217 else if (inOp_d_trunc==9 && greater) `drain_in1
218 else if (inOp_d_trunc==4 && !greater) `drain_in2
219 else if (inOp_d_trunc==5 && !greater) `drain_in1
220 else if (inOp_d_trunc==9 && !greater) `drain_in2
226 if (!out_draining && `out_empty && `in1_full && `in2_full && `inOp_full) begin
233 == Test ==============================================================================
235 // FIXME: need test for ADD carry-out c-flag
251 debug.in: set ilc=*; recv, deliver;
268 collect, send to debug.in;
270 set word= Alu.inOp[ADD]; deliver;
271 set word= Alu.inOp[SUB]; deliver;
272 set word= Alu.inOp[IN1]; deliver;
273 set word= Alu.inOp[IN2]; deliver;
274 set word= Alu.inOp[MIN]; deliver;
275 set word= Alu.inOp[MAX]; deliver;
276 set word= Alu.inOp[CMP]; deliver;
277 set word= Alu.inOp[CMP]; deliver;
280 collect, send to debug.in; // MIN
286 collect, send to debug.in; // MAX
304 == Contributors =========================================================
305 Adam Megacz <megacz@cs.berkeley.edu>