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