1 /*
2 * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
3 *
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.
9 *
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.
14 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "arith.h"
21 # include "schedule.h"
22 # include <climits>
23 # include <iostream>
24 # include <cassert>
25 # include <cstdlib>
26 # include <cmath>
27
vvp_arith_(unsigned wid)28 vvp_arith_::vvp_arith_(unsigned wid)
29 : wid_(wid), op_a_(wid), op_b_(wid), x_val_(wid)
30 {
31 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
32 op_a_ .set_bit(idx, BIT4_Z);
33 op_b_ .set_bit(idx, BIT4_Z);
34 x_val_.set_bit(idx, BIT4_X);
35 }
36 }
37
dispatch_operand_(vvp_net_ptr_t ptr,vvp_vector4_t bit)38 void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit)
39 {
40 unsigned port = ptr.port();
41 switch (port) {
42 case 0:
43 op_a_ = bit;
44 break;
45 case 1:
46 op_b_ = bit;
47 break;
48 default:
49 fprintf(stderr, "Unsupported port type %u.\n", port);
50 assert(0);
51 }
52 }
53
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)54 void vvp_arith_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
55 unsigned base, unsigned wid, unsigned vwid,
56 vvp_context_t ctx)
57 {
58 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
59 }
60
vvp_arith_abs()61 vvp_arith_abs::vvp_arith_abs()
62 {
63 }
64
~vvp_arith_abs()65 vvp_arith_abs::~vvp_arith_abs()
66 {
67 }
68
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)69 void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
70 vvp_context_t)
71 {
72 vvp_vector4_t out (bit.size(), BIT4_0);;
73
74 vvp_bit4_t cmp = compare_gtge_signed(bit, out, BIT4_1);
75 switch (cmp) {
76 case BIT4_1: // bit >= 0
77 out = bit;
78 break;
79 case BIT4_0: // bit < 0
80 out = ~bit;
81 out += 1;
82 break;
83 default: // There's an X.
84 out = vvp_vector4_t(bit.size(), BIT4_X);
85 break;
86 }
87
88 ptr.ptr()->send_vec4(out, 0);
89 }
90
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)91 void vvp_arith_abs::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
92 unsigned base, unsigned wid, unsigned vwid,
93 vvp_context_t ctx)
94 {
95 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
96 }
97
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)98 void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
99 vvp_context_t)
100 {
101 double out = fabs(bit);
102 ptr.ptr()->send_real(out, 0);
103 }
104
vvp_arith_cast_int(unsigned wid)105 vvp_arith_cast_int::vvp_arith_cast_int(unsigned wid)
106 : wid_(wid)
107 {
108 }
109
~vvp_arith_cast_int()110 vvp_arith_cast_int::~vvp_arith_cast_int()
111 {
112 }
113
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)114 void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit,
115 vvp_context_t)
116 {
117 ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
118 }
119
vvp_arith_cast_real(bool signed_flag)120 vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
121 : signed_(signed_flag)
122 {
123 }
124
~vvp_arith_cast_real()125 vvp_arith_cast_real::~vvp_arith_cast_real()
126 {
127 }
128
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)129 void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
130 vvp_context_t)
131 {
132 double val;
133 vector4_to_value(bit, val, signed_);
134 ptr.ptr()->send_real(val, 0);
135 }
136
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)137 void vvp_arith_cast_real::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
138 unsigned base, unsigned wid, unsigned vwid,
139 vvp_context_t ctx)
140 {
141 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
142 }
143
vvp_arith_cast_vec2(unsigned wid)144 vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
145 : wid_(wid)
146 {
147 }
148
~vvp_arith_cast_vec2()149 vvp_arith_cast_vec2::~vvp_arith_cast_vec2()
150 {
151 }
152
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)153 void vvp_arith_cast_vec2::recv_real(vvp_net_ptr_t ptr, double bit,
154 vvp_context_t)
155 {
156 ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
157 }
158
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)159 void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
160 vvp_context_t)
161 {
162 vvp_vector2_t tmp = bit;
163 ptr.ptr()->send_vec4(vector2_to_vector4(tmp,wid_), 0);
164 }
165
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)166 void vvp_arith_cast_vec2::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
167 unsigned base, unsigned wid, unsigned vwid,
168 vvp_context_t ctx)
169 {
170 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
171 }
172
173 // Division
174
vvp_arith_div(unsigned wid,bool signed_flag)175 vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
176 : vvp_arith_(wid), signed_flag_(signed_flag)
177 {
178 }
179
~vvp_arith_div()180 vvp_arith_div::~vvp_arith_div()
181 {
182 }
183
wide4_(vvp_net_ptr_t ptr)184 void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
185 {
186 vvp_vector2_t a2 (op_a_, true);
187 if (a2.is_NaN()) {
188 ptr.ptr()->send_vec4(x_val_, 0);
189 return;
190 }
191
192 vvp_vector2_t b2 (op_b_, true);
193 if (b2.is_NaN() || b2.is_zero()) {
194 ptr.ptr()->send_vec4(x_val_, 0);
195 return;
196 }
197
198 bool negate = false;
199 if (signed_flag_) {
200 if (a2.value(a2.size()-1)) {
201 a2 = -a2;
202 negate = true;
203 }
204 if (b2.value(b2.size()-1)) {
205 b2 = -b2;
206 negate = !negate;
207 }
208 }
209 vvp_vector2_t res = a2 / b2;
210 if (negate) res = -res;
211 ptr.ptr()->send_vec4(vector2_to_vector4(res, wid_), 0);
212 }
213
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)214 void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
215 vvp_context_t)
216 {
217 dispatch_operand_(ptr, bit);
218
219 if (wid_ > 8 * sizeof(unsigned long)) {
220 wide4_(ptr);
221 return ;
222 }
223
224 unsigned long a;
225 if (! vector4_to_value(op_a_, a)) {
226 ptr.ptr()->send_vec4(x_val_, 0);
227 return;
228 }
229
230 unsigned long b;
231 if (! vector4_to_value(op_b_, b)) {
232 ptr.ptr()->send_vec4(x_val_, 0);
233 return;
234 }
235
236 bool negate = false;
237 /* If we are doing signed divide, then take the sign out of
238 the operands for now, and remember to put the sign back
239 later. */
240 if (signed_flag_) {
241 unsigned long sign_mask = 0;
242 if (op_a_.size() != 8 * sizeof(unsigned long)) {
243 sign_mask = -1UL << op_a_.size();
244 }
245 if (op_a_.value(op_a_.size()-1)) {
246 a = (-a) & ~sign_mask;
247 negate = !negate;
248 }
249
250 sign_mask = 0;
251 if (op_b_.size() != 8 * sizeof(unsigned long)) {
252 sign_mask = -1UL << op_b_.size();
253 }
254 if (op_b_.value(op_b_.size()-1)) {
255 b = (-b) & ~sign_mask;
256 negate = ! negate;
257 }
258 }
259
260 if (b == 0) {
261 vvp_vector4_t xval (wid_);
262 for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
263 xval.set_bit(idx, BIT4_X);
264
265 ptr.ptr()->send_vec4(xval, 0);
266 return;
267 }
268
269 unsigned long val = a / b;
270 if (negate)
271 val = -val;
272
273 assert(wid_ <= 8*sizeof(val));
274
275 vvp_vector4_t vval (wid_);
276 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
277 if (val & 1)
278 vval.set_bit(idx, BIT4_1);
279 else
280 vval.set_bit(idx, BIT4_0);
281
282 val >>= 1;
283 }
284
285 ptr.ptr()->send_vec4(vval, 0);
286 }
287
288
vvp_arith_mod(unsigned wid,bool sf)289 vvp_arith_mod::vvp_arith_mod(unsigned wid, bool sf)
290 : vvp_arith_(wid), signed_flag_(sf)
291 {
292 }
293
~vvp_arith_mod()294 vvp_arith_mod::~vvp_arith_mod()
295 {
296 }
297
wide_(vvp_net_ptr_t ptr)298 void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
299 {
300 vvp_vector2_t a2 (op_a_, true);
301 if (a2.is_NaN()) {
302 ptr.ptr()->send_vec4(x_val_, 0);
303 return;
304 }
305
306 vvp_vector2_t b2 (op_b_, true);
307 if (b2.is_NaN() || b2.is_zero()) {
308 ptr.ptr()->send_vec4(x_val_, 0);
309 return;
310 }
311
312 bool negate = false;
313 if (signed_flag_) {
314 if (a2.value(a2.size()-1)) {
315 a2 = -a2;
316 negate = true;
317 }
318 if (b2.value(b2.size()-1)) {
319 b2 = -b2;
320 }
321 }
322 vvp_vector2_t res = a2 % b2;
323 if (negate) res = -res;
324 ptr.ptr()->send_vec4(vector2_to_vector4(res, res.size()), 0);
325 }
326
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)327 void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
328 vvp_context_t)
329 {
330 dispatch_operand_(ptr, bit);
331
332 if (wid_ > 8 * sizeof(unsigned long)) {
333 wide_(ptr);
334 return ;
335 }
336
337 unsigned long a;
338 if (! vector4_to_value(op_a_, a)) {
339 ptr.ptr()->send_vec4(x_val_, 0);
340 return;
341 }
342
343 unsigned long b;
344 if (! vector4_to_value(op_b_, b)) {
345 ptr.ptr()->send_vec4(x_val_, 0);
346 return;
347 }
348
349 bool negate = false;
350 /* If we are doing signed divide, then take the sign out of
351 the operands for now, and remember to put the sign back
352 later. */
353 if (signed_flag_) {
354 unsigned long sign_mask = 0;
355 if (op_a_.size() != 8 * sizeof(unsigned long)) {
356 sign_mask = -1UL << op_a_.size();
357 }
358 if (op_a_.value(op_a_.size()-1)) {
359 a = (-a) & ~sign_mask;
360 negate = !negate;
361 }
362
363 sign_mask = 0;
364 if (op_b_.size() != 8 * sizeof(unsigned long)) {
365 sign_mask = -1UL << op_b_.size();
366 }
367 if (op_b_.value(op_b_.size()-1)) {
368 b = (-b) & ~sign_mask;
369 }
370 }
371
372 if (b == 0) {
373 vvp_vector4_t xval (wid_);
374 for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
375 xval.set_bit(idx, BIT4_X);
376
377 ptr.ptr()->send_vec4(xval, 0);
378 return;
379 }
380
381 unsigned long val = a % b;
382 if (negate)
383 val = -val;
384
385 assert(wid_ <= 8*sizeof(val));
386
387 vvp_vector4_t vval (wid_);
388 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
389 if (val & 1)
390 vval.set_bit(idx, BIT4_1);
391 else
392 vval.set_bit(idx, BIT4_0);
393
394 val >>= 1;
395 }
396
397 ptr.ptr()->send_vec4(vval, 0);
398 }
399
400
401 // Multiplication
402
vvp_arith_mult(unsigned wid)403 vvp_arith_mult::vvp_arith_mult(unsigned wid)
404 : vvp_arith_(wid)
405 {
406 }
407
~vvp_arith_mult()408 vvp_arith_mult::~vvp_arith_mult()
409 {
410 }
411
wide_(vvp_net_ptr_t ptr)412 void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
413 {
414 vvp_vector2_t a2 (op_a_, true);
415 vvp_vector2_t b2 (op_b_, true);
416
417 if (a2.is_NaN() || b2.is_NaN()) {
418 ptr.ptr()->send_vec4(x_val_, 0);
419 return;
420 }
421
422 vvp_vector2_t result = a2 * b2;
423
424 vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
425 ptr.ptr()->send_vec4(res4, 0);
426 }
427
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)428 void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
429 vvp_context_t)
430 {
431 dispatch_operand_(ptr, bit);
432
433 if (wid_ > 8 * sizeof(int64_t)) {
434 wide_(ptr);
435 return ;
436 }
437
438 int64_t a;
439 if (! vector4_to_value(op_a_, a, false, true)) {
440 ptr.ptr()->send_vec4(x_val_, 0);
441 return;
442 }
443
444 int64_t b;
445 if (! vector4_to_value(op_b_, b, false, true)) {
446 ptr.ptr()->send_vec4(x_val_, 0);
447 return;
448 }
449
450 int64_t val = a * b;
451 assert(wid_ <= 8*sizeof(val));
452
453 vvp_vector4_t vval (wid_);
454 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
455 if (val & 1)
456 vval.set_bit(idx, BIT4_1);
457 else
458 vval.set_bit(idx, BIT4_0);
459
460 val >>= 1;
461 }
462
463 ptr.ptr()->send_vec4(vval, 0);
464 }
465
466
467 // Power
468
vvp_arith_pow(unsigned wid,bool signed_flag)469 vvp_arith_pow::vvp_arith_pow(unsigned wid, bool signed_flag)
470 : vvp_arith_(wid), signed_flag_(signed_flag)
471 {
472 }
473
~vvp_arith_pow()474 vvp_arith_pow::~vvp_arith_pow()
475 {
476 }
477
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)478 void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
479 vvp_context_t)
480 {
481 dispatch_operand_(ptr, bit);
482
483 vvp_vector2_t a2 (op_a_, true);
484 vvp_vector2_t b2 (op_b_, true);
485
486 // If we have an X or Z in the arguments return X.
487 if (a2.is_NaN() || b2.is_NaN()) {
488 ptr.ptr()->send_vec4(x_val_, 0);
489 return;
490 }
491
492 // Is the exponent negative? If so, table 5-6 in IEEE1364-2005
493 // defines what value is returned.
494 if (signed_flag_ && b2.value(b2.size()-1)) {
495 int a_val;
496 double r_val = 0.0;
497 if (vector2_to_value(a2, a_val, true)) {
498 if (a_val == 0) {
499 ptr.ptr()->send_vec4(x_val_, 0);
500 return;
501 }
502 if (a_val == 1) {
503 r_val = 1.0;
504 }
505 if (a_val == -1) {
506 r_val = b2.value(0) ? -1.0 : 1.0;
507 }
508 }
509 ptr.ptr()->send_vec4(vvp_vector4_t(wid_, r_val), 0);
510 return;
511 }
512
513 ptr.ptr()->send_vec4(vector2_to_vector4(pow(a2, b2), wid_), 0);
514 }
515
516
517 // Addition
518
vvp_arith_sum(unsigned wid)519 vvp_arith_sum::vvp_arith_sum(unsigned wid)
520 : vvp_arith_(wid)
521 {
522 }
523
~vvp_arith_sum()524 vvp_arith_sum::~vvp_arith_sum()
525 {
526 }
527
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)528 void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
529 vvp_context_t)
530 {
531 dispatch_operand_(ptr, bit);
532
533 vvp_net_t*net = ptr.ptr();
534
535 vvp_vector4_t value (wid_);
536
537 /* Pad input vectors with this value to widen to the desired
538 output width. */
539 const vvp_bit4_t pad = BIT4_0;
540
541 vvp_bit4_t carry = BIT4_0;
542 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
543 vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
544 vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
545 vvp_bit4_t cur = add_with_carry(a, b, carry);
546
547 if (cur == BIT4_X) {
548 net->send_vec4(x_val_, 0);
549 return;
550 }
551
552 value.set_bit(idx, cur);
553 }
554
555 net->send_vec4(value, 0);
556 }
557
vvp_arith_sub(unsigned wid)558 vvp_arith_sub::vvp_arith_sub(unsigned wid)
559 : vvp_arith_(wid)
560 {
561 }
562
~vvp_arith_sub()563 vvp_arith_sub::~vvp_arith_sub()
564 {
565 }
566
567 /*
568 * Subtraction works by adding the 2s complement of the B input from
569 * the A input. The 2s complement is the 1s complement plus one, so we
570 * further reduce the operation to adding in the inverted value and
571 * adding a correction.
572 */
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)573 void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
574 vvp_context_t)
575 {
576 dispatch_operand_(ptr, bit);
577
578 vvp_net_t*net = ptr.ptr();
579
580 vvp_vector4_t value (wid_);
581
582 /* Pad input vectors with this value to widen to the desired
583 output width. */
584 const vvp_bit4_t pad = BIT4_1;
585
586 vvp_bit4_t carry = BIT4_1;
587 for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
588 vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
589 vvp_bit4_t b = (idx >= op_b_.size())? pad : ~op_b_.value(idx);
590 vvp_bit4_t cur = add_with_carry(a, b, carry);
591
592 if (cur == BIT4_X) {
593 net->send_vec4(x_val_, 0);
594 return;
595 }
596
597 value.set_bit(idx, cur);
598 }
599
600 net->send_vec4(value, 0);
601 }
602
vvp_cmp_eeq(unsigned wid)603 vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
604 : vvp_arith_(wid)
605 {
606 }
607
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)608 void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
609 vvp_context_t)
610 {
611 dispatch_operand_(ptr, bit);
612
613 vvp_vector4_t eeq (1);
614 eeq.set_bit(0, BIT4_1);
615
616 assert(op_a_.size() == op_b_.size());
617 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1)
618 if (op_a_.value(idx) != op_b_.value(idx)) {
619 eeq.set_bit(0, BIT4_0);
620 break;
621 }
622
623
624 vvp_net_t*net = ptr.ptr();
625 net->send_vec4(eeq, 0);
626 }
627
vvp_cmp_nee(unsigned wid)628 vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
629 : vvp_arith_(wid)
630 {
631 }
632
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)633 void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
634 vvp_context_t)
635 {
636 dispatch_operand_(ptr, bit);
637
638 vvp_vector4_t eeq (1);
639 eeq.set_bit(0, BIT4_0);
640
641 assert(op_a_.size() == op_b_.size());
642 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1)
643 if (op_a_.value(idx) != op_b_.value(idx)) {
644 eeq.set_bit(0, BIT4_1);
645 break;
646 }
647
648
649 vvp_net_t*net = ptr.ptr();
650 net->send_vec4(eeq, 0);
651 }
652
vvp_cmp_eq(unsigned wid)653 vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
654 : vvp_arith_(wid)
655 {
656 }
657
658 /*
659 * Compare Vector a and Vector b. If in any bit position the a and b
660 * bits are known and different, then the result is 0. Otherwise, if
661 * there are X/Z bits anywhere in A or B, the result is X. Finally,
662 * the result is 1.
663 */
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)664 void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
665 vvp_context_t)
666 {
667 dispatch_operand_(ptr, bit);
668
669 if (op_a_.size() != op_b_.size()) {
670 cerr << "COMPARISON size mismatch. "
671 << "a=" << op_a_ << ", b=" << op_b_ << endl;
672 assert(0);
673 }
674
675 vvp_vector4_t res (1);
676 res.set_bit(0, BIT4_1);
677
678 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
679 vvp_bit4_t a = op_a_.value(idx);
680 vvp_bit4_t b = op_b_.value(idx);
681
682 if (a == BIT4_X)
683 res.set_bit(0, BIT4_X);
684 else if (a == BIT4_Z)
685 res.set_bit(0, BIT4_X);
686 else if (b == BIT4_X)
687 res.set_bit(0, BIT4_X);
688 else if (b == BIT4_Z)
689 res.set_bit(0, BIT4_X);
690 else if (a != b) {
691 res.set_bit(0, BIT4_0);
692 break;
693 }
694 }
695
696 vvp_net_t*net = ptr.ptr();
697 net->send_vec4(res, 0);
698 }
699
vvp_cmp_eqx(unsigned wid)700 vvp_cmp_eqx::vvp_cmp_eqx(unsigned wid)
701 : vvp_arith_(wid)
702 {
703 }
704
705 /*
706 * Compare Vector a and Vector b. If in any bit position the a and b
707 * bits are known and different, then the result is 0. Otherwise, if
708 * there are X/Z bits anywhere in A or B, the result is X. Finally,
709 * the result is 1.
710 */
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)711 void vvp_cmp_eqx::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
712 vvp_context_t)
713 {
714 dispatch_operand_(ptr, bit);
715
716 if (op_a_.size() != op_b_.size()) {
717 cerr << "COMPARISON size mismatch. "
718 << "a=" << op_a_ << ", b=" << op_b_ << endl;
719 assert(0);
720 }
721
722 vvp_vector4_t res (1);
723 res.set_bit(0, BIT4_1);
724
725 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
726 vvp_bit4_t a = op_a_.value(idx);
727 vvp_bit4_t b = op_b_.value(idx);
728
729 if (b == BIT4_X)
730 continue;
731 if (b == BIT4_Z)
732 continue;
733 if (a != b) {
734 res.set_bit(0, BIT4_0);
735 break;
736 }
737 }
738
739 vvp_net_t*net = ptr.ptr();
740 net->send_vec4(res, 0);
741 }
742
vvp_cmp_eqz(unsigned wid)743 vvp_cmp_eqz::vvp_cmp_eqz(unsigned wid)
744 : vvp_arith_(wid)
745 {
746 }
747
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)748 void vvp_cmp_eqz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
749 vvp_context_t)
750 {
751 dispatch_operand_(ptr, bit);
752
753 if (op_a_.size() != op_b_.size()) {
754 cerr << "COMPARISON size mismatch. "
755 << "a=" << op_a_ << ", b=" << op_b_ << endl;
756 assert(0);
757 }
758
759 vvp_vector4_t res (1);
760 res.set_bit(0, BIT4_1);
761
762 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
763 vvp_bit4_t a = op_a_.value(idx);
764 vvp_bit4_t b = op_b_.value(idx);
765
766 if (b == BIT4_Z)
767 continue;
768 if (a != b) {
769 res.set_bit(0, BIT4_0);
770 break;
771 }
772 }
773
774 vvp_net_t*net = ptr.ptr();
775 net->send_vec4(res, 0);
776 }
777
vvp_cmp_ne(unsigned wid)778 vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
779 : vvp_arith_(wid)
780 {
781 }
782
783 /*
784 * Compare Vector a and Vector b. If in any bit position the a and b
785 * bits are known and different, then the result is 1. Otherwise, if
786 * there are X/Z bits anywhere in A or B, the result is X. Finally,
787 * the result is 0.
788 */
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)789 void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
790 vvp_context_t)
791 {
792 dispatch_operand_(ptr, bit);
793
794 if (op_a_.size() != op_b_.size()) {
795 cerr << "internal error: vvp_cmp_ne: op_a_=" << op_a_
796 << ", op_b_=" << op_b_ << endl;
797 assert(op_a_.size() == op_b_.size());
798 }
799
800 vvp_vector4_t res (1);
801 res.set_bit(0, BIT4_0);
802
803 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
804 vvp_bit4_t a = op_a_.value(idx);
805 vvp_bit4_t b = op_b_.value(idx);
806
807 if (a == BIT4_X)
808 res.set_bit(0, BIT4_X);
809 else if (a == BIT4_Z)
810 res.set_bit(0, BIT4_X);
811 else if (b == BIT4_X)
812 res.set_bit(0, BIT4_X);
813 else if (b == BIT4_Z)
814 res.set_bit(0, BIT4_X);
815 else if (a != b) {
816 res.set_bit(0, BIT4_1);
817 break;
818 }
819 }
820
821 vvp_net_t*net = ptr.ptr();
822 net->send_vec4(res, 0);
823 }
824
825
vvp_cmp_gtge_base_(unsigned wid,bool flag)826 vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag)
827 : vvp_arith_(wid), signed_flag_(flag)
828 {
829 }
830
831
recv_vec4_base_(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_bit4_t out_if_equal)832 void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr,
833 const vvp_vector4_t&bit,
834 vvp_bit4_t out_if_equal)
835 {
836 dispatch_operand_(ptr, bit);
837
838 vvp_bit4_t out = signed_flag_
839 ? compare_gtge_signed(op_a_, op_b_, out_if_equal)
840 : compare_gtge(op_a_, op_b_, out_if_equal);
841 vvp_vector4_t val (1);
842 val.set_bit(0, out);
843 ptr.ptr()->send_vec4(val, 0);
844
845 return;
846 }
847
848
vvp_cmp_ge(unsigned wid,bool flag)849 vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
850 : vvp_cmp_gtge_base_(wid, flag)
851 {
852 }
853
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)854 void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
855 vvp_context_t)
856 {
857 recv_vec4_base_(ptr, bit, BIT4_1);
858 }
859
vvp_cmp_gt(unsigned wid,bool flag)860 vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
861 : vvp_cmp_gtge_base_(wid, flag)
862 {
863 }
864
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)865 void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
866 vvp_context_t)
867 {
868 recv_vec4_base_(ptr, bit, BIT4_0);
869 }
870
vvp_cmp_weq(unsigned wid)871 vvp_cmp_weq::vvp_cmp_weq(unsigned wid)
872 : vvp_arith_(wid)
873 {
874 }
875
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)876 void vvp_cmp_weq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
877 vvp_context_t)
878 {
879 dispatch_operand_(ptr, bit);
880
881 vvp_vector4_t eeq (1);
882 eeq.set_bit(0, BIT4_1);
883
884 assert(op_a_.size() == op_b_.size());
885 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
886 vvp_bit4_t a = op_a_.value(idx);
887 vvp_bit4_t b = op_b_.value(idx);
888 if (b == BIT4_X)
889 continue;
890 else if (b == BIT4_Z)
891 continue;
892 else if (a == BIT4_X)
893 eeq.set_bit(0, BIT4_X);
894 else if (a == BIT4_Z)
895 eeq.set_bit(0, BIT4_X);
896 else if (a != b) {
897 eeq.set_bit(0, BIT4_0);
898 break;
899 }
900 }
901
902 vvp_net_t*net = ptr.ptr();
903 net->send_vec4(eeq, 0);
904 }
905
vvp_cmp_wne(unsigned wid)906 vvp_cmp_wne::vvp_cmp_wne(unsigned wid)
907 : vvp_arith_(wid)
908 {
909 }
910
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)911 void vvp_cmp_wne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
912 vvp_context_t)
913 {
914 dispatch_operand_(ptr, bit);
915
916 vvp_vector4_t eeq (1);
917 eeq.set_bit(0, BIT4_0);
918
919 assert(op_a_.size() == op_b_.size());
920 for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
921 vvp_bit4_t a = op_a_.value(idx);
922 vvp_bit4_t b = op_b_.value(idx);
923 if (b == BIT4_X)
924 continue;
925 else if (b == BIT4_Z)
926 continue;
927 else if (a == BIT4_X)
928 eeq.set_bit(0, BIT4_X);
929 else if (a == BIT4_Z)
930 eeq.set_bit(0, BIT4_X);
931 else if (a != b) {
932 eeq.set_bit(0, BIT4_1);
933 break;
934 }
935 }
936
937 vvp_net_t*net = ptr.ptr();
938 net->send_vec4(eeq, 0);
939 }
940
941
vvp_shiftl(unsigned wid)942 vvp_shiftl::vvp_shiftl(unsigned wid)
943 : vvp_arith_(wid)
944 {
945 }
946
~vvp_shiftl()947 vvp_shiftl::~vvp_shiftl()
948 {
949 }
950
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)951 void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
952 vvp_context_t)
953 {
954 dispatch_operand_(ptr, bit);
955
956 vvp_vector4_t out (op_a_.size());
957
958 bool overflow_flag;
959 unsigned long shift;
960 if (! vector4_to_value(op_b_, overflow_flag, shift)) {
961 ptr.ptr()->send_vec4(x_val_, 0);
962 return;
963 }
964
965 if (overflow_flag || shift > out.size())
966 shift = out.size();
967
968 for (unsigned idx = 0 ; idx < shift ; idx += 1)
969 out.set_bit(idx, BIT4_0);
970
971 for (unsigned idx = shift ; idx < out.size() ; idx += 1)
972 out.set_bit(idx, op_a_.value(idx-shift));
973
974 ptr.ptr()->send_vec4(out, 0);
975 }
976
vvp_shiftr(unsigned wid,bool signed_flag)977 vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
978 : vvp_arith_(wid), signed_flag_(signed_flag)
979 {
980 }
981
~vvp_shiftr()982 vvp_shiftr::~vvp_shiftr()
983 {
984 }
985
recv_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,vvp_context_t)986 void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
987 vvp_context_t)
988 {
989 dispatch_operand_(ptr, bit);
990
991 vvp_vector4_t out (op_a_.size());
992
993 bool overflow_flag;
994 unsigned long shift;
995 if (! vector4_to_value(op_b_, overflow_flag, shift)) {
996 ptr.ptr()->send_vec4(x_val_, 0);
997 return;
998 }
999
1000 if (overflow_flag || shift > out.size())
1001 shift = out.size();
1002
1003 for (unsigned idx = shift ; idx < out.size() ; idx += 1)
1004 out.set_bit(idx-shift, op_a_.value(idx));
1005
1006 vvp_bit4_t pad = BIT4_0;
1007 if (signed_flag_ && op_a_.size() > 0)
1008 pad = op_a_.value(op_a_.size()-1);
1009
1010 for (unsigned idx = 0 ; idx < shift ; idx += 1)
1011 out.set_bit(idx+out.size()-shift, pad);
1012
1013 ptr.ptr()->send_vec4(out, 0);
1014 }
1015
1016
vvp_arith_real_()1017 vvp_arith_real_::vvp_arith_real_()
1018 {
1019 op_a_ = 0.0;
1020 op_b_ = 0.0;
1021 }
1022
dispatch_operand_(vvp_net_ptr_t ptr,double bit)1023 void vvp_arith_real_::dispatch_operand_(vvp_net_ptr_t ptr, double bit)
1024 {
1025 switch (ptr.port()) {
1026 case 0:
1027 op_a_ = bit;
1028 break;
1029 case 1:
1030 op_b_ = bit;
1031 break;
1032 default:
1033 fprintf(stderr, "Unsupported port type %u.\n", ptr.port());
1034 assert(0);
1035 }
1036 }
1037
1038
1039 /* Real multiplication. */
vvp_arith_mult_real()1040 vvp_arith_mult_real::vvp_arith_mult_real()
1041 {
1042 }
1043
~vvp_arith_mult_real()1044 vvp_arith_mult_real::~vvp_arith_mult_real()
1045 {
1046 }
1047
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1048 void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit,
1049 vvp_context_t)
1050 {
1051 dispatch_operand_(ptr, bit);
1052
1053 double val = op_a_ * op_b_;
1054 ptr.ptr()->send_real(val, 0);
1055 }
1056
1057 /* Real power. */
vvp_arith_pow_real()1058 vvp_arith_pow_real::vvp_arith_pow_real()
1059 {
1060 }
1061
~vvp_arith_pow_real()1062 vvp_arith_pow_real::~vvp_arith_pow_real()
1063 {
1064 }
1065
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1066 void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit,
1067 vvp_context_t)
1068 {
1069 dispatch_operand_(ptr, bit);
1070
1071 double val = pow(op_a_, op_b_);
1072 ptr.ptr()->send_real(val, 0);
1073 }
1074
1075 /* Real division. */
vvp_arith_div_real()1076 vvp_arith_div_real::vvp_arith_div_real()
1077 {
1078 }
1079
~vvp_arith_div_real()1080 vvp_arith_div_real::~vvp_arith_div_real()
1081 {
1082 }
1083
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1084 void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit,
1085 vvp_context_t)
1086 {
1087 dispatch_operand_(ptr, bit);
1088
1089 double val = op_a_ / op_b_;
1090 ptr.ptr()->send_real(val, 0);
1091 }
1092
1093 /* Real modulus. */
vvp_arith_mod_real()1094 vvp_arith_mod_real::vvp_arith_mod_real()
1095 {
1096 }
1097
~vvp_arith_mod_real()1098 vvp_arith_mod_real::~vvp_arith_mod_real()
1099 {
1100 }
1101
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1102 void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit,
1103 vvp_context_t)
1104 {
1105 dispatch_operand_(ptr, bit);
1106
1107 double val = fmod(op_a_, op_b_);
1108 ptr.ptr()->send_real(val, 0);
1109 }
1110
1111 /* Real summation. */
vvp_arith_sum_real()1112 vvp_arith_sum_real::vvp_arith_sum_real()
1113 {
1114 }
1115
~vvp_arith_sum_real()1116 vvp_arith_sum_real::~vvp_arith_sum_real()
1117 {
1118 }
1119
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1120 void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit,
1121 vvp_context_t)
1122 {
1123 dispatch_operand_(ptr, bit);
1124
1125 double val = op_a_ + op_b_;
1126 ptr.ptr()->send_real(val, 0);
1127 }
1128
1129 /* Real subtraction. */
vvp_arith_sub_real()1130 vvp_arith_sub_real::vvp_arith_sub_real()
1131 {
1132 }
1133
~vvp_arith_sub_real()1134 vvp_arith_sub_real::~vvp_arith_sub_real()
1135 {
1136 }
1137
recv_real(vvp_net_ptr_t ptr,double bit,vvp_context_t)1138 void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit,
1139 vvp_context_t)
1140 {
1141 dispatch_operand_(ptr, bit);
1142
1143 double val = op_a_ - op_b_;
1144 ptr.ptr()->send_real(val, 0);
1145 }
1146
1147 /* Real compare equal. */
vvp_cmp_eq_real()1148 vvp_cmp_eq_real::vvp_cmp_eq_real()
1149 {
1150 }
1151
recv_real(vvp_net_ptr_t ptr,const double bit,vvp_context_t)1152 void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit,
1153 vvp_context_t)
1154 {
1155 dispatch_operand_(ptr, bit);
1156
1157 vvp_vector4_t res (1);
1158 if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
1159 else res.set_bit(0, BIT4_0);
1160
1161 ptr.ptr()->send_vec4(res, 0);
1162 }
1163
1164 /* Real compare not equal. */
vvp_cmp_ne_real()1165 vvp_cmp_ne_real::vvp_cmp_ne_real()
1166 {
1167 }
1168
recv_real(vvp_net_ptr_t ptr,const double bit,vvp_context_t)1169 void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit,
1170 vvp_context_t)
1171 {
1172 dispatch_operand_(ptr, bit);
1173
1174 vvp_vector4_t res (1);
1175 if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
1176 else res.set_bit(0, BIT4_0);
1177
1178 ptr.ptr()->send_vec4(res, 0);
1179 }
1180
1181 /* Real compare greater than or equal. */
vvp_cmp_ge_real()1182 vvp_cmp_ge_real::vvp_cmp_ge_real()
1183 {
1184 }
1185
recv_real(vvp_net_ptr_t ptr,const double bit,vvp_context_t)1186 void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit,
1187 vvp_context_t)
1188 {
1189 dispatch_operand_(ptr, bit);
1190
1191 vvp_vector4_t res (1);
1192 if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
1193 else res.set_bit(0, BIT4_0);
1194
1195 ptr.ptr()->send_vec4(res, 0);
1196 }
1197
1198 /* Real compare greater than. */
vvp_cmp_gt_real()1199 vvp_cmp_gt_real::vvp_cmp_gt_real()
1200 {
1201 }
1202
recv_real(vvp_net_ptr_t ptr,const double bit,vvp_context_t)1203 void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit,
1204 vvp_context_t)
1205 {
1206 dispatch_operand_(ptr, bit);
1207
1208 vvp_vector4_t res (1);
1209 if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
1210 else res.set_bit(0, BIT4_0);
1211
1212 ptr.ptr()->send_vec4(res, 0);
1213 }
1214