Fix the debugger to finish correctly.
[iverilog.git] / vvp / arith.cc
blobfc3e70706fa0b163e8aa24e59cd7c68e13d7ed77
1 /*
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)
8 * any later version.
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: arith.cc,v 1.50 2007/01/20 02:09:54 steve Exp $"
21 #endif
23 # include "arith.h"
24 # include "schedule.h"
25 # include <limits.h>
26 # include <iostream>
27 # include <assert.h>
28 # include <stdlib.h>
29 #ifdef HAVE_MALLOC_H
30 # include <malloc.h>
31 #endif
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);
39 op_a_ = x_val_;
40 op_b_ = x_val_;
43 void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit)
45 unsigned port = ptr.port();
46 switch (port) {
47 case 0:
48 op_a_ = bit;
49 break;
50 case 1:
51 op_b_ = bit;
52 break;
53 default:
54 fprintf(stderr, "Unsupported port type %d.\n", port);
55 assert(0);
60 // Division
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_);
74 if (a2.is_NaN()) {
75 vvp_send_vec4(ptr.ptr()->out, x_val_);
76 return;
79 vvp_vector2_t b2 (op_b_);
80 if (b2.is_NaN()) {
81 vvp_send_vec4(ptr.ptr()->out, x_val_);
82 return;
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)) {
94 wide4_(ptr);
95 return ;
98 unsigned long a;
99 if (! vector4_to_value(op_a_, a)) {
100 vvp_send_vec4(ptr.ptr()->out, x_val_);
101 return;
104 unsigned long b;
105 if (! vector4_to_value(op_b_, b)) {
106 vvp_send_vec4(ptr.ptr()->out, x_val_);
107 return;
110 bool negate = false;
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
113 later. */
114 if (signed_flag_) {
115 if (op_a_.value(op_a_.size()-1)) {
116 a = (-a) & ~ (-1UL << op_a_.size());
117 negate = !negate;
120 if (op_b_.value(op_b_.size()-1)) {
121 b = (-b) & ~ (-1UL << op_b_.size());
122 negate = ! negate;
126 unsigned long val = a / b;
127 if (negate)
128 val = -val;
130 assert(wid_ <= 8*sizeof(val));
132 vvp_vector4_t vval (wid_);
133 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
134 if (val & 1)
135 vval.set_bit(idx, BIT4_1);
136 else
137 vval.set_bit(idx, BIT4_0);
139 val >>= 1;
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_);
158 if (a2.is_NaN()) {
159 vvp_send_vec4(ptr.ptr()->out, x_val_);
160 return;
163 vvp_vector2_t b2 (op_b_);
164 if (b2.is_NaN()) {
165 vvp_send_vec4(ptr.ptr()->out, x_val_);
166 return;
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)) {
178 wide_(ptr);
179 return ;
182 unsigned long a;
183 if (! vector4_to_value(op_a_, a)) {
184 vvp_send_vec4(ptr.ptr()->out, x_val_);
185 return;
188 unsigned long b;
189 if (! vector4_to_value(op_b_, b)) {
190 vvp_send_vec4(ptr.ptr()->out, x_val_);
191 return;
194 bool negate = false;
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
197 later. */
198 if (signed_flag_) {
199 if (op_a_.value(op_a_.size()-1)) {
200 a = (-a) & ~ (-1UL << op_a_.size());
201 negate = !negate;
204 if (op_b_.value(op_b_.size()-1)) {
205 b = (-b) & ~ (-1UL << op_b_.size());
206 negate = ! negate;
210 if (b == 0) {
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);
216 return;
219 unsigned long val = a % b;
220 if (negate)
221 val = -val;
223 assert(wid_ <= 8*sizeof(val));
225 vvp_vector4_t vval (wid_);
226 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
227 if (val & 1)
228 vval.set_bit(idx, BIT4_1);
229 else
230 vval.set_bit(idx, BIT4_0);
232 val >>= 1;
235 vvp_send_vec4(ptr.ptr()->out, vval);
239 // Multiplication
241 vvp_arith_mult::vvp_arith_mult(unsigned wid)
242 : vvp_arith_(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_);
257 return;
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)) {
271 wide_(ptr);
272 return ;
275 unsigned long a;
276 if (! vector4_to_value(op_a_, a)) {
277 vvp_send_vec4(ptr.ptr()->out, x_val_);
278 return;
281 unsigned long b;
282 if (! vector4_to_value(op_b_, b)) {
283 vvp_send_vec4(ptr.ptr()->out, x_val_);
284 return;
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) {
292 if (val & 1)
293 vval.set_bit(idx, BIT4_1);
294 else
295 vval.set_bit(idx, BIT4_0);
297 val >>= 1;
300 vvp_send_vec4(ptr.ptr()->out, vval);
304 #if 0
305 void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
307 put(i, val);
308 vvp_ipoint_t base = ipoint_make(i,0);
310 if(wid_ > 8*sizeof(unsigned long)) {
311 wide(base, push);
312 return;
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;
322 if (val & 0xaa) {
323 output_x_(base, push);
324 return;
327 if (val & 0x01)
328 a += 1UL << idx;
329 if (val & 0x04)
330 b += 1UL << idx;
333 output_val_(base, push, a*b);
335 #endif
337 #if 0
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_];
345 unsigned mxa = 0;
346 unsigned mxb = 0;
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;
353 if (ival & 0xaa) {
354 output_x_(base, push);
355 delete[]sum;
356 delete[]b;
357 delete[]a;
358 return;
361 if((a[idx] = ((ival & 0x01) != 0))) mxa=idx+1;
362 if((b[idx] = ((ival & 0x04) != 0))) mxb=idx;
363 sum[idx] = 0;
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) {
371 if(b[i]) {
372 unsigned char carry=0;
373 unsigned char temp;
375 for(unsigned j=0 ; j<=mxa ; j += 1) {
377 if((i+j) >= wid_)
378 break;
380 temp=sum[i+j] + a[j] + carry;
381 sum[i+j]=(temp&1);
382 carry=(temp>>1);
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);
396 delete[]sum;
397 delete[]b;
398 delete[]a;
400 #endif
402 // Addition
404 vvp_arith_sum::vvp_arith_sum(unsigned wid)
405 : vvp_arith_(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
422 output width. */
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);
431 if (cur == BIT4_X) {
432 vvp_send_vec4(net->out, x_val_);
433 return;
436 value.set_bit(idx, cur);
439 vvp_send_vec4(net->out, value);
442 vvp_arith_sub::vvp_arith_sub(unsigned wid)
443 : vvp_arith_(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
466 output width. */
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);
475 if (cur == BIT4_X) {
476 vvp_send_vec4(net->out, x_val_);
477 return;
480 value.set_bit(idx, cur);
483 vvp_send_vec4(net->out, value);
486 vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
487 : vvp_arith_(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);
502 break;
506 vvp_net_t*net = ptr.ptr();
507 vvp_send_vec4(net->out, eeq);
510 vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
511 : vvp_arith_(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);
526 break;
530 vvp_net_t*net = ptr.ptr();
531 vvp_send_vec4(net->out, eeq);
534 vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
535 : vvp_arith_(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,
543 * the result is 1.
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;
552 assert(0);
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);
562 if (a == BIT4_X)
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);
570 else if (a != b) {
571 res.set_bit(0, BIT4_0);
572 break;
576 vvp_net_t*net = ptr.ptr();
577 vvp_send_vec4(net->out, res);
581 vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
582 : vvp_arith_(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,
590 * the result is 0.
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);
605 if (a == BIT4_X)
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);
613 else if (a != b) {
614 res.set_bit(0, BIT4_1);
615 break;
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,
631 vvp_vector4_t bit,
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);
640 val.set_bit(0, out);
641 vvp_send_vec4(ptr.ptr()->out, val);
643 return;
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)
669 : vvp_arith_(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());
683 unsigned long shift;
684 if (! vector4_to_value(op_b_, shift)) {
685 vvp_send_vec4(ptr.ptr()->out, x_val_);
686 return;
689 if (shift > out.size())
690 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());
716 unsigned long shift;
717 if (! vector4_to_value(op_b_, shift)) {
718 vvp_send_vec4(ptr.ptr()->out, x_val_);
719 return;
722 if (shift > out.size())
723 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()) {
746 case 0:
747 op_a_ = bit;
748 break;
749 case 1:
750 op_b_ = bit;
751 break;
752 default:
753 fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
754 assert(0);
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);