2 * Copyright (c) 2001-2005 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: arith.cc,v 1.50 2007/01/20 02:09:54 steve Exp $"
24 # include "schedule.h"
33 vvp_arith_::vvp_arith_(unsigned wid
)
34 : wid_(wid
), x_val_(wid
)
36 for (unsigned idx
= 0 ; idx
< wid
; idx
+= 1)
37 x_val_
.set_bit(idx
, BIT4_X
);
43 void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr
, vvp_vector4_t bit
)
45 unsigned port
= ptr
.port();
54 fprintf(stderr
, "Unsupported port type %d.\n", port
);
62 vvp_arith_div::vvp_arith_div(unsigned wid
, bool signed_flag
)
63 : vvp_arith_(wid
), signed_flag_(signed_flag
)
67 vvp_arith_div::~vvp_arith_div()
71 void vvp_arith_div::wide4_(vvp_net_ptr_t ptr
)
73 vvp_vector2_t
a2 (op_a_
);
75 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
79 vvp_vector2_t
b2 (op_b_
);
81 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
85 vvp_vector2_t res2
= a2
/ b2
;
86 vvp_send_vec4(ptr
.ptr()->out
, vector2_to_vector4(res2
, wid_
));
89 void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
91 dispatch_operand_(ptr
, bit
);
93 if (wid_
> 8 * sizeof(unsigned long)) {
99 if (! vector4_to_value(op_a_
, a
)) {
100 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
105 if (! vector4_to_value(op_b_
, b
)) {
106 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
111 /* If we are doing signed divide, then take the sign out of
112 the operands for now, and remember to put the sign back
115 if (op_a_
.value(op_a_
.size()-1)) {
116 a
= (-a
) & ~ (-1UL << op_a_
.size());
120 if (op_b_
.value(op_b_
.size()-1)) {
121 b
= (-b
) & ~ (-1UL << op_b_
.size());
126 unsigned long val
= a
/ b
;
130 assert(wid_
<= 8*sizeof(val
));
132 vvp_vector4_t
vval (wid_
);
133 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
135 vval
.set_bit(idx
, BIT4_1
);
137 vval
.set_bit(idx
, BIT4_0
);
142 vvp_send_vec4(ptr
.ptr()->out
, vval
);
146 vvp_arith_mod::vvp_arith_mod(unsigned wid
, bool sf
)
147 : vvp_arith_(wid
), signed_flag_(sf
)
151 vvp_arith_mod::~vvp_arith_mod()
155 void vvp_arith_mod::wide_(vvp_net_ptr_t ptr
)
157 vvp_vector2_t
a2 (op_a_
);
159 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
163 vvp_vector2_t
b2 (op_b_
);
165 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
169 vvp_vector2_t res
= a2
% b2
;
170 vvp_send_vec4(ptr
.ptr()->out
, vector2_to_vector4(res
, res
.size()));
173 void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
175 dispatch_operand_(ptr
, bit
);
177 if (wid_
> 8 * sizeof(unsigned long)) {
183 if (! vector4_to_value(op_a_
, a
)) {
184 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
189 if (! vector4_to_value(op_b_
, b
)) {
190 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
195 /* If we are doing signed divide, then take the sign out of
196 the operands for now, and remember to put the sign back
199 if (op_a_
.value(op_a_
.size()-1)) {
200 a
= (-a
) & ~ (-1UL << op_a_
.size());
204 if (op_b_
.value(op_b_
.size()-1)) {
205 b
= (-b
) & ~ (-1UL << op_b_
.size());
211 vvp_vector4_t
xval (wid_
);
212 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1)
213 xval
.set_bit(idx
, BIT4_X
);
215 vvp_send_vec4(ptr
.ptr()->out
, xval
);
219 unsigned long val
= a
% b
;
223 assert(wid_
<= 8*sizeof(val
));
225 vvp_vector4_t
vval (wid_
);
226 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
228 vval
.set_bit(idx
, BIT4_1
);
230 vval
.set_bit(idx
, BIT4_0
);
235 vvp_send_vec4(ptr
.ptr()->out
, vval
);
241 vvp_arith_mult::vvp_arith_mult(unsigned wid
)
246 vvp_arith_mult::~vvp_arith_mult()
250 void vvp_arith_mult::wide_(vvp_net_ptr_t ptr
)
252 vvp_vector2_t
a2 (op_a_
);
253 vvp_vector2_t
b2 (op_b_
);
255 if (a2
.is_NaN() || b2
.is_NaN()) {
256 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
260 vvp_vector2_t result
= a2
* b2
;
262 vvp_vector4_t res4
= vector2_to_vector4(result
, wid_
);
263 vvp_send_vec4(ptr
.ptr()->out
, res4
);
266 void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
268 dispatch_operand_(ptr
, bit
);
270 if (wid_
> 8 * sizeof(unsigned long)) {
276 if (! vector4_to_value(op_a_
, a
)) {
277 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
282 if (! vector4_to_value(op_b_
, b
)) {
283 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
287 unsigned long val
= a
* b
;
288 assert(wid_
<= 8*sizeof(val
));
290 vvp_vector4_t
vval (wid_
);
291 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
293 vval
.set_bit(idx
, BIT4_1
);
295 vval
.set_bit(idx
, BIT4_0
);
300 vvp_send_vec4(ptr
.ptr()->out
, vval
);
305 void vvp_arith_mult::set(vvp_ipoint_t i
, bool push
, unsigned val
, unsigned)
308 vvp_ipoint_t base
= ipoint_make(i
,0);
310 if(wid_
> 8*sizeof(unsigned long)) {
315 unsigned long a
= 0, b
= 0;
317 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
318 vvp_ipoint_t ptr
= ipoint_index(base
,idx
);
319 functor_t obj
= functor_index(ptr
);
321 unsigned val
= obj
->ival
;
323 output_x_(base
, push
);
333 output_val_(base
, push
, a
*b
);
338 void vvp_arith_mult::wide(vvp_ipoint_t base
, bool push
)
340 unsigned char *a
, *b
, *sum
;
341 a
= new unsigned char[wid_
];
342 b
= new unsigned char[wid_
];
343 sum
= new unsigned char[wid_
];
348 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
349 vvp_ipoint_t ptr
= ipoint_index(base
, idx
);
350 functor_t obj
= functor_index(ptr
);
352 unsigned ival
= obj
->ival
;
354 output_x_(base
, push
);
361 if((a
[idx
] = ((ival
& 0x01) != 0))) mxa
=idx
+1;
362 if((b
[idx
] = ((ival
& 0x04) != 0))) mxb
=idx
;
366 /* do the a*b multiply using the long method we learned in
367 grade school. We know at this point that there are no X or
368 Z values in the a or b vectors. */
370 for(unsigned i
=0 ; i
<=mxb
; i
+= 1) {
372 unsigned char carry
=0;
375 for(unsigned j
=0 ; j
<=mxa
; j
+= 1) {
380 temp
=sum
[i
+j
] + a
[j
] + carry
;
387 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
388 vvp_ipoint_t ptr
= ipoint_index(base
,idx
);
389 functor_t obj
= functor_index(ptr
);
391 unsigned val
= sum
[idx
];
393 obj
->put_oval(val
, push
);
404 vvp_arith_sum::vvp_arith_sum(unsigned wid
)
409 vvp_arith_sum::~vvp_arith_sum()
413 void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
415 dispatch_operand_(ptr
, bit
);
417 vvp_net_t
*net
= ptr
.ptr();
419 vvp_vector4_t
value (wid_
);
421 /* Pad input vectors with this value to widen to the desired
423 const vvp_bit4_t pad
= BIT4_0
;
425 vvp_bit4_t carry
= BIT4_0
;
426 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
427 vvp_bit4_t a
= (idx
>= op_a_
.size())? pad
: op_a_
.value(idx
);
428 vvp_bit4_t b
= (idx
>= op_b_
.size())? pad
: op_b_
.value(idx
);
429 vvp_bit4_t cur
= add_with_carry(a
, b
, carry
);
432 vvp_send_vec4(net
->out
, x_val_
);
436 value
.set_bit(idx
, cur
);
439 vvp_send_vec4(net
->out
, value
);
442 vvp_arith_sub::vvp_arith_sub(unsigned wid
)
447 vvp_arith_sub::~vvp_arith_sub()
452 * Subtraction works by adding the 2s complement of the B input from
453 * the A input. The 2s complement is the 1s complement plus one, so we
454 * further reduce the operation to adding in the inverted value and
455 * adding a correction.
457 void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
459 dispatch_operand_(ptr
, bit
);
461 vvp_net_t
*net
= ptr
.ptr();
463 vvp_vector4_t
value (wid_
);
465 /* Pad input vectors with this value to widen to the desired
467 const vvp_bit4_t pad
= BIT4_1
;
469 vvp_bit4_t carry
= BIT4_1
;
470 for (unsigned idx
= 0 ; idx
< wid_
; idx
+= 1) {
471 vvp_bit4_t a
= (idx
>= op_a_
.size())? pad
: op_a_
.value(idx
);
472 vvp_bit4_t b
= (idx
>= op_b_
.size())? pad
: ~op_b_
.value(idx
);
473 vvp_bit4_t cur
= add_with_carry(a
, b
, carry
);
476 vvp_send_vec4(net
->out
, x_val_
);
480 value
.set_bit(idx
, cur
);
483 vvp_send_vec4(net
->out
, value
);
486 vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid
)
491 void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
493 dispatch_operand_(ptr
, bit
);
495 vvp_vector4_t
eeq (1);
496 eeq
.set_bit(0, BIT4_1
);
498 assert(op_a_
.size() == op_b_
.size());
499 for (unsigned idx
= 0 ; idx
< op_a_
.size() ; idx
+= 1)
500 if (op_a_
.value(idx
) != op_b_
.value(idx
)) {
501 eeq
.set_bit(0, BIT4_0
);
506 vvp_net_t
*net
= ptr
.ptr();
507 vvp_send_vec4(net
->out
, eeq
);
510 vvp_cmp_nee::vvp_cmp_nee(unsigned wid
)
515 void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
517 dispatch_operand_(ptr
, bit
);
519 vvp_vector4_t
eeq (1);
520 eeq
.set_bit(0, BIT4_0
);
522 assert(op_a_
.size() == op_b_
.size());
523 for (unsigned idx
= 0 ; idx
< op_a_
.size() ; idx
+= 1)
524 if (op_a_
.value(idx
) != op_b_
.value(idx
)) {
525 eeq
.set_bit(0, BIT4_1
);
530 vvp_net_t
*net
= ptr
.ptr();
531 vvp_send_vec4(net
->out
, eeq
);
534 vvp_cmp_eq::vvp_cmp_eq(unsigned wid
)
540 * Compare Vector a and Vector b. If in any bit position the a and b
541 * bits are known and different, then the result is 0. Otherwise, if
542 * there are X/Z bits anywhere in A or B, the result is X. Finally,
545 void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
547 dispatch_operand_(ptr
, bit
);
549 if (op_a_
.size() != op_b_
.size()) {
550 cerr
<< "COMPARISON size mismatch. "
551 << "a=" << op_a_
<< ", b=" << op_b_
<< endl
;
555 vvp_vector4_t
res (1);
556 res
.set_bit(0, BIT4_1
);
558 for (unsigned idx
= 0 ; idx
< op_a_
.size() ; idx
+= 1) {
559 vvp_bit4_t a
= op_a_
.value(idx
);
560 vvp_bit4_t b
= op_b_
.value(idx
);
563 res
.set_bit(0, BIT4_X
);
564 else if (a
== BIT4_Z
)
565 res
.set_bit(0, BIT4_X
);
566 else if (b
== BIT4_X
)
567 res
.set_bit(0, BIT4_X
);
568 else if (b
== BIT4_Z
)
569 res
.set_bit(0, BIT4_X
);
571 res
.set_bit(0, BIT4_0
);
576 vvp_net_t
*net
= ptr
.ptr();
577 vvp_send_vec4(net
->out
, res
);
581 vvp_cmp_ne::vvp_cmp_ne(unsigned wid
)
587 * Compare Vector a and Vector b. If in any bit position the a and b
588 * bits are known and different, then the result is 1. Otherwise, if
589 * there are X/Z bits anywhere in A or B, the result is X. Finally,
592 void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
594 dispatch_operand_(ptr
, bit
);
596 assert(op_a_
.size() == op_b_
.size());
598 vvp_vector4_t
res (1);
599 res
.set_bit(0, BIT4_0
);
601 for (unsigned idx
= 0 ; idx
< op_a_
.size() ; idx
+= 1) {
602 vvp_bit4_t a
= op_a_
.value(idx
);
603 vvp_bit4_t b
= op_b_
.value(idx
);
606 res
.set_bit(0, BIT4_X
);
607 else if (a
== BIT4_Z
)
608 res
.set_bit(0, BIT4_X
);
609 else if (b
== BIT4_X
)
610 res
.set_bit(0, BIT4_X
);
611 else if (b
== BIT4_Z
)
612 res
.set_bit(0, BIT4_X
);
614 res
.set_bit(0, BIT4_1
);
619 vvp_net_t
*net
= ptr
.ptr();
620 vvp_send_vec4(net
->out
, res
);
624 vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid
, bool flag
)
625 : vvp_arith_(wid
), signed_flag_(flag
)
630 void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr
,
632 vvp_bit4_t out_if_equal
)
634 dispatch_operand_(ptr
, bit
);
636 vvp_bit4_t out
= signed_flag_
637 ? compare_gtge_signed(op_a_
, op_b_
, out_if_equal
)
638 : compare_gtge(op_a_
, op_b_
, out_if_equal
);
639 vvp_vector4_t
val (1);
641 vvp_send_vec4(ptr
.ptr()->out
, val
);
647 vvp_cmp_ge::vvp_cmp_ge(unsigned wid
, bool flag
)
648 : vvp_cmp_gtge_base_(wid
, flag
)
652 void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
654 recv_vec4_base_(ptr
, bit
, BIT4_1
);
657 vvp_cmp_gt::vvp_cmp_gt(unsigned wid
, bool flag
)
658 : vvp_cmp_gtge_base_(wid
, flag
)
662 void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
664 recv_vec4_base_(ptr
, bit
, BIT4_0
);
668 vvp_shiftl::vvp_shiftl(unsigned wid
)
673 vvp_shiftl::~vvp_shiftl()
677 void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
679 dispatch_operand_(ptr
, bit
);
681 vvp_vector4_t
out (op_a_
.size());
684 if (! vector4_to_value(op_b_
, shift
)) {
685 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
689 if (shift
> out
.size())
692 for (unsigned idx
= 0 ; idx
< shift
; idx
+= 1)
693 out
.set_bit(idx
, BIT4_0
);
695 for (unsigned idx
= shift
; idx
< out
.size() ; idx
+= 1)
696 out
.set_bit(idx
, op_a_
.value(idx
-shift
));
698 vvp_send_vec4(ptr
.ptr()->out
, out
);
701 vvp_shiftr::vvp_shiftr(unsigned wid
, bool signed_flag
)
702 : vvp_arith_(wid
), signed_flag_(signed_flag
)
706 vvp_shiftr::~vvp_shiftr()
710 void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr
, const vvp_vector4_t
&bit
)
712 dispatch_operand_(ptr
, bit
);
714 vvp_vector4_t
out (op_a_
.size());
717 if (! vector4_to_value(op_b_
, shift
)) {
718 vvp_send_vec4(ptr
.ptr()->out
, x_val_
);
722 if (shift
> out
.size())
725 for (unsigned idx
= shift
; idx
< out
.size() ; idx
+= 1)
726 out
.set_bit(idx
-shift
, op_a_
.value(idx
));
728 vvp_bit4_t pad
= BIT4_0
;
729 if (signed_flag_
&& op_a_
.size() > 0)
730 pad
= op_a_
.value(op_a_
.size()-1);
732 for (unsigned idx
= 0 ; idx
< shift
; idx
+= 1)
733 out
.set_bit(idx
+out
.size()-shift
, pad
);
735 vvp_send_vec4(ptr
.ptr()->out
, out
);
739 vvp_arith_real_::vvp_arith_real_()
743 void vvp_arith_real_::dispatch_operand_(vvp_net_ptr_t ptr
, double bit
)
745 switch (ptr
.port()) {
753 fprintf(stderr
, "Unsupported port type %d.\n", ptr
.port());
759 vvp_arith_div_real::vvp_arith_div_real()
763 vvp_arith_div_real::~vvp_arith_div_real()
767 void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr
, double bit
)
769 dispatch_operand_(ptr
, bit
);
771 double val
= op_a_
/ op_b_
;
772 vvp_send_real(ptr
.ptr()->out
, val
);
775 vvp_arith_sub_real::vvp_arith_sub_real()
779 vvp_arith_sub_real::~vvp_arith_sub_real()
783 void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr
, double bit
)
785 dispatch_operand_(ptr
, bit
);
787 double val
= op_a_
- op_b_
;
788 vvp_send_real(ptr
.ptr()->out
, val
);