2001-06-05 05:05:41 +02:00
|
|
|
/*
|
2021-01-02 22:52:25 +01:00
|
|
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
2001-06-05 05:05:41 +02:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2001-06-05 05:05:41 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "arith.h"
|
|
|
|
|
# include "schedule.h"
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <climits>
|
2005-09-16 00:54:04 +02:00
|
|
|
# include <iostream>
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cassert>
|
|
|
|
|
# include <cstdlib>
|
|
|
|
|
# include <cmath>
|
2001-06-05 05:05:41 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_arith_::vvp_arith_(unsigned wid)
|
2016-04-04 23:29:54 +02:00
|
|
|
: wid_(wid), op_a_(wid), op_b_(wid), x_val_(wid)
|
2001-06-05 05:05:41 +02:00
|
|
|
{
|
2016-04-04 23:29:54 +02:00
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
|
|
|
|
op_a_ .set_bit(idx, BIT4_Z);
|
|
|
|
|
op_b_ .set_bit(idx, BIT4_Z);
|
2004-12-11 03:31:25 +01:00
|
|
|
x_val_.set_bit(idx, BIT4_X);
|
2016-04-04 23:29:54 +02:00
|
|
|
}
|
2005-01-22 02:06:20 +01:00
|
|
|
}
|
|
|
|
|
|
2021-01-02 22:52:25 +01:00
|
|
|
void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
2005-01-22 02:06:20 +01:00
|
|
|
{
|
|
|
|
|
unsigned port = ptr.port();
|
|
|
|
|
switch (port) {
|
|
|
|
|
case 0:
|
|
|
|
|
op_a_ = bit;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
op_b_ = bit;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2012-09-01 03:22:11 +02:00
|
|
|
fprintf(stderr, "Unsupported port type %u.\n", port);
|
2005-01-22 02:06:20 +01:00
|
|
|
assert(0);
|
|
|
|
|
}
|
2001-10-31 05:27:46 +01:00
|
|
|
}
|
2001-10-16 04:47:37 +02:00
|
|
|
|
2016-04-04 23:29:54 +02:00
|
|
|
void vvp_arith_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid,
|
2016-04-19 00:47:43 +02:00
|
|
|
vvp_context_t ctx)
|
2016-04-04 23:29:54 +02:00
|
|
|
{
|
2016-04-19 00:47:43 +02:00
|
|
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
2016-04-04 23:29:54 +02:00
|
|
|
}
|
|
|
|
|
|
2008-05-07 05:37:00 +02:00
|
|
|
vvp_arith_abs::vvp_arith_abs()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_abs::~vvp_arith_abs()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2008-05-07 05:37:00 +02:00
|
|
|
{
|
|
|
|
|
vvp_vector4_t out (bit.size(), BIT4_0);;
|
|
|
|
|
|
|
|
|
|
vvp_bit4_t cmp = compare_gtge_signed(bit, out, BIT4_1);
|
|
|
|
|
switch (cmp) {
|
|
|
|
|
case BIT4_1: // bit >= 0
|
|
|
|
|
out = bit;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_0: // bit < 0
|
|
|
|
|
out = ~bit;
|
|
|
|
|
out += 1;
|
|
|
|
|
break;
|
|
|
|
|
default: // There's an X.
|
|
|
|
|
out = vvp_vector4_t(bit.size(), BIT4_X);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(out, 0);
|
2008-05-07 05:37:00 +02:00
|
|
|
}
|
|
|
|
|
|
2016-04-19 00:47:43 +02:00
|
|
|
void vvp_arith_abs::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid,
|
|
|
|
|
vvp_context_t ctx)
|
|
|
|
|
{
|
|
|
|
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-05-07 05:37:00 +02:00
|
|
|
{
|
|
|
|
|
double out = fabs(bit);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(out, 0);
|
2008-05-07 05:37:00 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-21 03:11:11 +02:00
|
|
|
vvp_arith_cast_int::vvp_arith_cast_int(unsigned wid)
|
|
|
|
|
: wid_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_cast_int::~vvp_arith_cast_int()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-06-21 03:11:11 +02:00
|
|
|
{
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
|
2008-06-21 03:11:11 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-18 02:07:19 +02:00
|
|
|
vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
|
|
|
|
|
: signed_(signed_flag)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_cast_real::~vvp_arith_cast_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2008-06-18 02:07:19 +02:00
|
|
|
{
|
|
|
|
|
double val;
|
|
|
|
|
vector4_to_value(bit, val, signed_);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2008-06-18 02:07:19 +02:00
|
|
|
}
|
|
|
|
|
|
2016-04-19 00:47:43 +02:00
|
|
|
void vvp_arith_cast_real::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid,
|
|
|
|
|
vvp_context_t ctx)
|
|
|
|
|
{
|
|
|
|
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 19:53:20 +02:00
|
|
|
vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
|
|
|
|
|
: wid_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_cast_vec2::~vvp_arith_cast_vec2()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_arith_cast_vec2::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
|
|
|
|
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
2021-01-02 22:52:25 +01:00
|
|
|
vvp_vector2_t tmp = vvp_vector2_t(bit);
|
2013-02-25 21:32:56 +01:00
|
|
|
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,wid_), 0);
|
2010-10-16 19:53:20 +02:00
|
|
|
}
|
|
|
|
|
|
2016-04-19 00:47:43 +02:00
|
|
|
void vvp_arith_cast_vec2::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid,
|
|
|
|
|
vvp_context_t ctx)
|
|
|
|
|
{
|
|
|
|
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
// Division
|
2001-10-16 04:47:37 +02:00
|
|
|
|
2005-02-19 02:32:52 +01:00
|
|
|
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
|
|
|
|
: vvp_arith_(wid), signed_flag_(signed_flag)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_div::~vvp_arith_div()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-03 07:19:31 +01:00
|
|
|
void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
2001-10-31 05:27:46 +01:00
|
|
|
{
|
2014-02-15 14:14:45 +01:00
|
|
|
vvp_vector2_t a2 (op_a_, true);
|
2006-01-03 07:19:31 +01:00
|
|
|
if (a2.is_NaN()) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2006-01-03 07:19:31 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-15 14:14:45 +01:00
|
|
|
vvp_vector2_t b2 (op_b_, true);
|
2008-11-08 03:23:04 +01:00
|
|
|
if (b2.is_NaN() || b2.is_zero()) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2006-01-03 07:19:31 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
bool negate = false;
|
|
|
|
|
if (signed_flag_) {
|
|
|
|
|
if (a2.value(a2.size()-1)) {
|
|
|
|
|
a2 = -a2;
|
|
|
|
|
negate = true;
|
|
|
|
|
}
|
|
|
|
|
if (b2.value(b2.size()-1)) {
|
|
|
|
|
b2 = -b2;
|
|
|
|
|
negate = !negate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vvp_vector2_t res = a2 / b2;
|
|
|
|
|
if (negate) res = -res;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vector2_to_vector4(res, wid_), 0);
|
2001-10-31 05:27:46 +01:00
|
|
|
}
|
2001-10-16 04:47:37 +02:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-02-19 02:32:52 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
if (wid_ > 8 * sizeof(unsigned long)) {
|
2006-01-03 07:19:31 +01:00
|
|
|
wide4_(ptr);
|
2005-02-19 02:32:52 +01:00
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long a;
|
|
|
|
|
if (! vector4_to_value(op_a_, a)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-02-19 02:32:52 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long b;
|
|
|
|
|
if (! vector4_to_value(op_b_, b)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-02-19 02:32:52 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:41:23 +01:00
|
|
|
bool negate = false;
|
|
|
|
|
/* If we are doing signed divide, then take the sign out of
|
|
|
|
|
the operands for now, and remember to put the sign back
|
|
|
|
|
later. */
|
|
|
|
|
if (signed_flag_) {
|
2008-11-08 03:23:04 +01:00
|
|
|
unsigned long sign_mask = 0;
|
|
|
|
|
if (op_a_.size() != 8 * sizeof(unsigned long)) {
|
|
|
|
|
sign_mask = -1UL << op_a_.size();
|
|
|
|
|
}
|
2005-02-19 03:41:23 +01:00
|
|
|
if (op_a_.value(op_a_.size()-1)) {
|
2008-11-08 03:23:04 +01:00
|
|
|
a = (-a) & ~sign_mask;
|
2005-02-19 03:41:23 +01:00
|
|
|
negate = !negate;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
sign_mask = 0;
|
|
|
|
|
if (op_b_.size() != 8 * sizeof(unsigned long)) {
|
|
|
|
|
sign_mask = -1UL << op_b_.size();
|
|
|
|
|
}
|
2005-02-19 03:41:23 +01:00
|
|
|
if (op_b_.value(op_b_.size()-1)) {
|
2008-11-08 03:23:04 +01:00
|
|
|
b = (-b) & ~sign_mask;
|
2005-02-19 03:41:23 +01:00
|
|
|
negate = ! negate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
if (b == 0) {
|
|
|
|
|
vvp_vector4_t xval (wid_);
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
|
|
|
|
xval.set_bit(idx, BIT4_X);
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(xval, 0);
|
2008-11-08 03:23:04 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 02:32:52 +01:00
|
|
|
unsigned long val = a / b;
|
2005-02-19 03:41:23 +01:00
|
|
|
if (negate)
|
|
|
|
|
val = -val;
|
|
|
|
|
|
2005-02-19 02:32:52 +01:00
|
|
|
assert(wid_ <= 8*sizeof(val));
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t vval (wid_);
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
|
|
|
|
if (val & 1)
|
|
|
|
|
vval.set_bit(idx, BIT4_1);
|
|
|
|
|
else
|
|
|
|
|
vval.set_bit(idx, BIT4_0);
|
2001-10-16 04:47:37 +02:00
|
|
|
|
2005-02-19 02:32:52 +01:00
|
|
|
val >>= 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vval, 0);
|
2005-02-19 02:32:52 +01:00
|
|
|
}
|
|
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
|
|
|
|
|
vvp_arith_mod::vvp_arith_mod(unsigned wid, bool sf)
|
|
|
|
|
: vvp_arith_(wid), signed_flag_(sf)
|
2001-10-31 05:27:46 +01:00
|
|
|
{
|
2005-03-12 07:42:28 +01:00
|
|
|
}
|
2001-10-16 04:47:37 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
vvp_arith_mod::~vvp_arith_mod()
|
|
|
|
|
{
|
|
|
|
|
}
|
2001-06-17 01:45:05 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
|
|
|
|
{
|
2014-02-15 14:14:45 +01:00
|
|
|
vvp_vector2_t a2 (op_a_, true);
|
2005-11-10 14:27:16 +01:00
|
|
|
if (a2.is_NaN()) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-11-10 14:27:16 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-15 14:14:45 +01:00
|
|
|
vvp_vector2_t b2 (op_b_, true);
|
2008-11-08 03:23:04 +01:00
|
|
|
if (b2.is_NaN() || b2.is_zero()) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-11-10 14:27:16 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
bool negate = false;
|
|
|
|
|
if (signed_flag_) {
|
|
|
|
|
if (a2.value(a2.size()-1)) {
|
|
|
|
|
a2 = -a2;
|
|
|
|
|
negate = true;
|
|
|
|
|
}
|
|
|
|
|
if (b2.value(b2.size()-1)) {
|
|
|
|
|
b2 = -b2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-11-10 14:27:16 +01:00
|
|
|
vvp_vector2_t res = a2 % b2;
|
2008-11-08 03:23:04 +01:00
|
|
|
if (negate) res = -res;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vector2_to_vector4(res, res.size()), 0);
|
2005-03-12 07:42:28 +01:00
|
|
|
}
|
2004-06-30 04:15:57 +02:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-03-12 07:42:28 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
if (wid_ > 8 * sizeof(unsigned long)) {
|
|
|
|
|
wide_(ptr);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
unsigned long a;
|
|
|
|
|
if (! vector4_to_value(op_a_, a)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-03-12 07:42:28 +01:00
|
|
|
return;
|
2001-10-31 05:27:46 +01:00
|
|
|
}
|
2001-06-17 01:45:05 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
unsigned long b;
|
|
|
|
|
if (! vector4_to_value(op_b_, b)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-03-12 07:42:28 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool negate = false;
|
|
|
|
|
/* If we are doing signed divide, then take the sign out of
|
|
|
|
|
the operands for now, and remember to put the sign back
|
|
|
|
|
later. */
|
2004-06-30 04:15:57 +02:00
|
|
|
if (signed_flag_) {
|
2008-11-08 03:23:04 +01:00
|
|
|
unsigned long sign_mask = 0;
|
|
|
|
|
if (op_a_.size() != 8 * sizeof(unsigned long)) {
|
|
|
|
|
sign_mask = -1UL << op_a_.size();
|
|
|
|
|
}
|
2005-03-12 07:42:28 +01:00
|
|
|
if (op_a_.value(op_a_.size()-1)) {
|
2008-11-08 03:23:04 +01:00
|
|
|
a = (-a) & ~sign_mask;
|
2005-03-12 07:42:28 +01:00
|
|
|
negate = !negate;
|
2004-06-30 04:15:57 +02:00
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
sign_mask = 0;
|
|
|
|
|
if (op_b_.size() != 8 * sizeof(unsigned long)) {
|
|
|
|
|
sign_mask = -1UL << op_b_.size();
|
|
|
|
|
}
|
2005-03-12 07:42:28 +01:00
|
|
|
if (op_b_.value(op_b_.size()-1)) {
|
2008-11-08 03:23:04 +01:00
|
|
|
b = (-b) & ~sign_mask;
|
2004-06-30 04:15:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
if (b == 0) {
|
2005-03-12 07:42:28 +01:00
|
|
|
vvp_vector4_t xval (wid_);
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
|
|
|
|
xval.set_bit(idx, BIT4_X);
|
2002-01-03 05:19:01 +01:00
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(xval, 0);
|
2002-01-03 05:19:01 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
unsigned long val = a % b;
|
|
|
|
|
if (negate)
|
|
|
|
|
val = -val;
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
assert(wid_ <= 8*sizeof(val));
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
vvp_vector4_t vval (wid_);
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
|
|
|
|
if (val & 1)
|
|
|
|
|
vval.set_bit(idx, BIT4_1);
|
|
|
|
|
else
|
|
|
|
|
vval.set_bit(idx, BIT4_0);
|
2002-01-03 05:19:01 +01:00
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
val >>= 1;
|
2002-01-03 05:19:01 +01:00
|
|
|
}
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vval, 0);
|
2002-01-03 05:19:01 +01:00
|
|
|
}
|
|
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
// Multiplication
|
|
|
|
|
|
2005-01-28 06:34:25 +01:00
|
|
|
vvp_arith_mult::vvp_arith_mult(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_mult::~vvp_arith_mult()
|
2001-10-31 05:27:46 +01:00
|
|
|
{
|
2005-01-28 06:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2005-02-04 06:13:02 +01:00
|
|
|
void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
|
|
|
|
|
{
|
2014-02-15 14:14:45 +01:00
|
|
|
vvp_vector2_t a2 (op_a_, true);
|
|
|
|
|
vvp_vector2_t b2 (op_b_, true);
|
2005-02-04 06:13:02 +01:00
|
|
|
|
|
|
|
|
if (a2.is_NaN() || b2.is_NaN()) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-02-04 06:13:02 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_vector2_t result = a2 * b2;
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(res4, 0);
|
2005-02-04 06:13:02 +01:00
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-01-28 06:34:25 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
2012-10-25 18:13:09 +02:00
|
|
|
if (wid_ > 8 * sizeof(int64_t)) {
|
2005-02-04 06:13:02 +01:00
|
|
|
wide_(ptr);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-25 18:13:09 +02:00
|
|
|
int64_t a;
|
2008-10-12 06:08:14 +02:00
|
|
|
if (! vector4_to_value(op_a_, a, false, true)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-01-28 06:34:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-25 18:13:09 +02:00
|
|
|
int64_t b;
|
2008-10-12 06:08:14 +02:00
|
|
|
if (! vector4_to_value(op_b_, b, false, true)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2005-01-28 06:34:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-25 18:13:09 +02:00
|
|
|
int64_t val = a * b;
|
2005-01-28 06:34:25 +01:00
|
|
|
assert(wid_ <= 8*sizeof(val));
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t vval (wid_);
|
2005-02-04 06:13:02 +01:00
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
2005-01-28 06:34:25 +01:00
|
|
|
if (val & 1)
|
|
|
|
|
vval.set_bit(idx, BIT4_1);
|
|
|
|
|
else
|
|
|
|
|
vval.set_bit(idx, BIT4_0);
|
|
|
|
|
|
|
|
|
|
val >>= 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(vval, 0);
|
2005-01-28 06:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-02-06 04:09:30 +01:00
|
|
|
// Power
|
|
|
|
|
|
2008-02-09 02:32:57 +01:00
|
|
|
vvp_arith_pow::vvp_arith_pow(unsigned wid, bool signed_flag)
|
|
|
|
|
: vvp_arith_(wid), signed_flag_(signed_flag)
|
2008-02-06 04:09:30 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_pow::~vvp_arith_pow()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2008-02-06 04:09:30 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
2014-02-19 21:11:57 +01:00
|
|
|
vvp_vector2_t a2 (op_a_, true);
|
|
|
|
|
vvp_vector2_t b2 (op_b_, true);
|
2008-02-06 04:09:30 +01:00
|
|
|
|
2014-02-19 21:11:57 +01:00
|
|
|
// If we have an X or Z in the arguments return X.
|
|
|
|
|
if (a2.is_NaN() || b2.is_NaN()) {
|
|
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-02-09 02:32:57 +01:00
|
|
|
|
2014-02-19 21:11:57 +01:00
|
|
|
// Is the exponent negative? If so, table 5-6 in IEEE1364-2005
|
|
|
|
|
// defines what value is returned.
|
|
|
|
|
if (signed_flag_ && b2.value(b2.size()-1)) {
|
|
|
|
|
int a_val;
|
|
|
|
|
double r_val = 0.0;
|
|
|
|
|
if (vector2_to_value(a2, a_val, true)) {
|
|
|
|
|
if (a_val == 0) {
|
|
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (a_val == 1) {
|
|
|
|
|
r_val = 1.0;
|
|
|
|
|
}
|
|
|
|
|
if (a_val == -1) {
|
|
|
|
|
r_val = b2.value(0) ? -1.0 : 1.0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, r_val), 0);
|
|
|
|
|
return;
|
2008-02-09 02:32:57 +01:00
|
|
|
}
|
2008-02-06 04:09:30 +01:00
|
|
|
|
2014-02-19 21:11:57 +01:00
|
|
|
ptr.ptr()->send_vec4(vector2_to_vector4(pow(a2, b2), wid_), 0);
|
2008-02-06 04:09:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
// Addition
|
2001-06-29 03:20:20 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_arith_sum::vvp_arith_sum(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
2001-06-29 03:20:20 +02:00
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_sum::~vvp_arith_sum()
|
|
|
|
|
{
|
|
|
|
|
}
|
2001-06-07 05:09:03 +02:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2004-12-11 03:31:25 +01:00
|
|
|
{
|
2005-01-28 06:34:25 +01:00
|
|
|
dispatch_operand_(ptr, bit);
|
2001-06-29 03:20:20 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t*net = ptr.ptr();
|
2001-06-05 05:05:41 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_vector4_t value (wid_);
|
|
|
|
|
|
|
|
|
|
/* Pad input vectors with this value to widen to the desired
|
|
|
|
|
output width. */
|
|
|
|
|
const vvp_bit4_t pad = BIT4_0;
|
|
|
|
|
|
|
|
|
|
vvp_bit4_t carry = BIT4_0;
|
2001-06-05 05:05:41 +02:00
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
|
|
|
|
|
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
2001-06-05 05:05:41 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
if (cur == BIT4_X) {
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(x_val_, 0);
|
2001-06-05 05:05:41 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
value.set_bit(idx, cur);
|
2001-06-05 05:05:41 +02:00
|
|
|
}
|
2001-06-29 03:20:20 +02:00
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(value, 0);
|
2001-06-05 05:05:41 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_arith_sub::vvp_arith_sub(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_sub::~vvp_arith_sub()
|
|
|
|
|
{
|
|
|
|
|
}
|
2001-06-07 05:09:03 +02:00
|
|
|
|
2001-07-13 02:38:57 +02:00
|
|
|
/*
|
2005-01-30 06:06:49 +01:00
|
|
|
* Subtraction works by adding the 2s complement of the B input from
|
|
|
|
|
* the A input. The 2s complement is the 1s complement plus one, so we
|
|
|
|
|
* further reduce the operation to adding in the inverted value and
|
|
|
|
|
* adding a correction.
|
2001-07-13 02:38:57 +02:00
|
|
|
*/
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2001-06-07 05:09:03 +02:00
|
|
|
{
|
2005-01-22 02:06:20 +01:00
|
|
|
dispatch_operand_(ptr, bit);
|
2001-10-31 05:27:46 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t*net = ptr.ptr();
|
2001-07-13 02:38:57 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_vector4_t value (wid_);
|
2001-06-07 05:09:03 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* Pad input vectors with this value to widen to the desired
|
|
|
|
|
output width. */
|
|
|
|
|
const vvp_bit4_t pad = BIT4_1;
|
|
|
|
|
|
|
|
|
|
vvp_bit4_t carry = BIT4_1;
|
2001-06-07 05:09:03 +02:00
|
|
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
|
2005-01-30 06:06:49 +01:00
|
|
|
vvp_bit4_t b = (idx >= op_b_.size())? pad : ~op_b_.value(idx);
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
2001-06-07 05:09:03 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
if (cur == BIT4_X) {
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(x_val_, 0);
|
2001-06-07 05:09:03 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
value.set_bit(idx, cur);
|
2001-06-07 05:09:03 +02:00
|
|
|
}
|
2001-07-13 02:38:57 +02:00
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(value, 0);
|
2001-06-07 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
|
2005-01-22 02:06:20 +01:00
|
|
|
vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-01-22 02:06:20 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t eeq (1);
|
|
|
|
|
eeq.set_bit(0, BIT4_1);
|
|
|
|
|
|
|
|
|
|
assert(op_a_.size() == op_b_.size());
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1)
|
|
|
|
|
if (op_a_.value(idx) != op_b_.value(idx)) {
|
|
|
|
|
eeq.set_bit(0, BIT4_0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-09 06:52:03 +01:00
|
|
|
|
|
|
|
|
vvp_net_t*net = ptr.ptr();
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(eeq, 0);
|
2005-03-09 06:52:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-03-09 06:52:03 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t eeq (1);
|
|
|
|
|
eeq.set_bit(0, BIT4_0);
|
|
|
|
|
|
|
|
|
|
assert(op_a_.size() == op_b_.size());
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1)
|
|
|
|
|
if (op_a_.value(idx) != op_b_.value(idx)) {
|
|
|
|
|
eeq.set_bit(0, BIT4_1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-01-22 02:06:20 +01:00
|
|
|
vvp_net_t*net = ptr.ptr();
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(eeq, 0);
|
2005-01-22 02:06:20 +01:00
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2004-06-16 18:33:25 +02:00
|
|
|
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
/*
|
|
|
|
|
* Compare Vector a and Vector b. If in any bit position the a and b
|
|
|
|
|
* bits are known and different, then the result is 0. Otherwise, if
|
|
|
|
|
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
|
|
|
|
* the result is 1.
|
|
|
|
|
*/
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2004-06-16 18:33:25 +02:00
|
|
|
{
|
2005-01-22 17:21:11 +01:00
|
|
|
dispatch_operand_(ptr, bit);
|
2004-06-16 18:33:25 +02:00
|
|
|
|
2007-01-20 03:09:54 +01:00
|
|
|
if (op_a_.size() != op_b_.size()) {
|
|
|
|
|
cerr << "COMPARISON size mismatch. "
|
|
|
|
|
<< "a=" << op_a_ << ", b=" << op_b_ << endl;
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
2004-06-16 18:33:25 +02:00
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
res.set_bit(0, BIT4_1);
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
|
|
|
|
|
if (a == BIT4_X)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a == BIT4_Z)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (b == BIT4_X)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (b == BIT4_Z)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a != b) {
|
|
|
|
|
res.set_bit(0, BIT4_0);
|
2004-06-16 18:33:25 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
vvp_net_t*net = ptr.ptr();
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(res, 0);
|
2004-06-16 18:33:25 +02:00
|
|
|
}
|
2005-01-22 17:21:11 +01:00
|
|
|
|
2014-06-14 03:01:41 +02:00
|
|
|
vvp_cmp_eqx::vvp_cmp_eqx(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Compare Vector a and Vector b. If in any bit position the a and b
|
|
|
|
|
* bits are known and different, then the result is 0. Otherwise, if
|
|
|
|
|
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
|
|
|
|
* the result is 1.
|
|
|
|
|
*/
|
|
|
|
|
void vvp_cmp_eqx::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
if (op_a_.size() != op_b_.size()) {
|
|
|
|
|
cerr << "COMPARISON size mismatch. "
|
|
|
|
|
<< "a=" << op_a_ << ", b=" << op_b_ << endl;
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
res.set_bit(0, BIT4_1);
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
|
|
|
|
|
if (b == BIT4_X)
|
|
|
|
|
continue;
|
|
|
|
|
if (b == BIT4_Z)
|
|
|
|
|
continue;
|
|
|
|
|
if (a != b) {
|
|
|
|
|
res.set_bit(0, BIT4_0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_net_t*net = ptr.ptr();
|
|
|
|
|
net->send_vec4(res, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_cmp_eqz::vvp_cmp_eqz(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_cmp_eqz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
if (op_a_.size() != op_b_.size()) {
|
|
|
|
|
cerr << "COMPARISON size mismatch. "
|
|
|
|
|
<< "a=" << op_a_ << ", b=" << op_b_ << endl;
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
res.set_bit(0, BIT4_1);
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
|
|
|
|
|
if (b == BIT4_Z)
|
|
|
|
|
continue;
|
|
|
|
|
if (a != b) {
|
|
|
|
|
res.set_bit(0, BIT4_0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_net_t*net = ptr.ptr();
|
|
|
|
|
net->send_vec4(res, 0);
|
|
|
|
|
}
|
2004-06-16 18:33:25 +02:00
|
|
|
|
|
|
|
|
vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
/*
|
|
|
|
|
* Compare Vector a and Vector b. If in any bit position the a and b
|
|
|
|
|
* bits are known and different, then the result is 1. Otherwise, if
|
|
|
|
|
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
|
|
|
|
* the result is 0.
|
|
|
|
|
*/
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2004-06-16 18:33:25 +02:00
|
|
|
{
|
2005-01-22 17:21:11 +01:00
|
|
|
dispatch_operand_(ptr, bit);
|
2004-06-16 18:33:25 +02:00
|
|
|
|
2008-08-17 04:02:09 +02:00
|
|
|
if (op_a_.size() != op_b_.size()) {
|
|
|
|
|
cerr << "internal error: vvp_cmp_ne: op_a_=" << op_a_
|
|
|
|
|
<< ", op_b_=" << op_b_ << endl;
|
|
|
|
|
assert(op_a_.size() == op_b_.size());
|
|
|
|
|
}
|
2004-06-16 18:33:25 +02:00
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
res.set_bit(0, BIT4_0);
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
|
|
|
|
|
if (a == BIT4_X)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a == BIT4_Z)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (b == BIT4_X)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (b == BIT4_Z)
|
|
|
|
|
res.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a != b) {
|
|
|
|
|
res.set_bit(0, BIT4_1);
|
2004-06-16 18:33:25 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
vvp_net_t*net = ptr.ptr();
|
2009-04-04 05:40:26 +02:00
|
|
|
net->send_vec4(res, 0);
|
2004-06-16 18:33:25 +02:00
|
|
|
}
|
2005-01-22 17:21:11 +01:00
|
|
|
|
2004-06-16 18:33:25 +02:00
|
|
|
|
2004-09-22 18:44:07 +02:00
|
|
|
vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag)
|
2003-04-11 07:15:38 +02:00
|
|
|
: vvp_arith_(wid), signed_flag_(flag)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-01-16 05:19:08 +01:00
|
|
|
void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr,
|
2016-08-15 06:16:21 +02:00
|
|
|
const vvp_vector4_t&bit,
|
2005-01-16 05:19:08 +01:00
|
|
|
vvp_bit4_t out_if_equal)
|
|
|
|
|
{
|
2005-01-22 18:36:15 +01:00
|
|
|
dispatch_operand_(ptr, bit);
|
2001-06-16 05:36:03 +02:00
|
|
|
|
2005-01-22 18:36:15 +01:00
|
|
|
vvp_bit4_t out = signed_flag_
|
|
|
|
|
? compare_gtge_signed(op_a_, op_b_, out_if_equal)
|
|
|
|
|
: compare_gtge(op_a_, op_b_, out_if_equal);
|
|
|
|
|
vvp_vector4_t val (1);
|
|
|
|
|
val.set_bit(0, out);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(val, 0);
|
2001-06-15 06:07:57 +02:00
|
|
|
|
2005-01-22 18:36:15 +01:00
|
|
|
return;
|
2001-06-15 06:07:57 +02:00
|
|
|
}
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2004-09-22 18:44:07 +02:00
|
|
|
|
|
|
|
|
vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
|
|
|
|
|
: vvp_cmp_gtge_base_(wid, flag)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2004-09-22 18:44:07 +02:00
|
|
|
{
|
2005-01-16 05:19:08 +01:00
|
|
|
recv_vec4_base_(ptr, bit, BIT4_1);
|
2004-09-22 18:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
|
|
|
|
|
: vvp_cmp_gtge_base_(wid, flag)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2004-09-22 18:44:07 +02:00
|
|
|
{
|
2005-01-16 05:19:08 +01:00
|
|
|
recv_vec4_base_(ptr, bit, BIT4_0);
|
2004-09-22 18:44:07 +02:00
|
|
|
}
|
2005-01-16 05:19:08 +01:00
|
|
|
|
2017-11-18 04:32:09 +01:00
|
|
|
vvp_cmp_weq::vvp_cmp_weq(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_cmp_weq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t eeq (1);
|
|
|
|
|
eeq.set_bit(0, BIT4_1);
|
|
|
|
|
|
|
|
|
|
assert(op_a_.size() == op_b_.size());
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
if (b == BIT4_X)
|
|
|
|
|
continue;
|
|
|
|
|
else if (b == BIT4_Z)
|
|
|
|
|
continue;
|
|
|
|
|
else if (a == BIT4_X)
|
|
|
|
|
eeq.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a == BIT4_Z)
|
|
|
|
|
eeq.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a != b) {
|
|
|
|
|
eeq.set_bit(0, BIT4_0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_net_t*net = ptr.ptr();
|
|
|
|
|
net->send_vec4(eeq, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_cmp_wne::vvp_cmp_wne(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_cmp_wne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
|
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t eeq (1);
|
|
|
|
|
eeq.set_bit(0, BIT4_0);
|
|
|
|
|
|
|
|
|
|
assert(op_a_.size() == op_b_.size());
|
|
|
|
|
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
|
|
|
|
vvp_bit4_t a = op_a_.value(idx);
|
|
|
|
|
vvp_bit4_t b = op_b_.value(idx);
|
|
|
|
|
if (b == BIT4_X)
|
|
|
|
|
continue;
|
|
|
|
|
else if (b == BIT4_Z)
|
|
|
|
|
continue;
|
|
|
|
|
else if (a == BIT4_X)
|
|
|
|
|
eeq.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a == BIT4_Z)
|
|
|
|
|
eeq.set_bit(0, BIT4_X);
|
|
|
|
|
else if (a != b) {
|
|
|
|
|
eeq.set_bit(0, BIT4_1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_net_t*net = ptr.ptr();
|
|
|
|
|
net->send_vec4(eeq, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-22 18:44:07 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
vvp_shiftl::vvp_shiftl(unsigned wid)
|
|
|
|
|
: vvp_arith_(wid)
|
2001-07-06 06:46:44 +02:00
|
|
|
{
|
2005-03-19 07:23:49 +01:00
|
|
|
}
|
2001-10-31 05:27:46 +01:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
vvp_shiftl::~vvp_shiftl()
|
|
|
|
|
{
|
|
|
|
|
}
|
2001-10-31 05:27:46 +01:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-03-19 07:23:49 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
vvp_vector4_t out (op_a_.size());
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2019-11-16 13:11:49 +01:00
|
|
|
bool overflow_flag;
|
2005-03-19 07:23:49 +01:00
|
|
|
unsigned long shift;
|
2019-11-16 13:11:49 +01:00
|
|
|
if (! vector4_to_value(op_b_, overflow_flag, shift)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2001-10-31 05:27:46 +01:00
|
|
|
return;
|
2005-03-19 07:23:49 +01:00
|
|
|
}
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2019-11-16 13:11:49 +01:00
|
|
|
if (overflow_flag || shift > out.size())
|
2005-03-19 07:23:49 +01:00
|
|
|
shift = out.size();
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
|
|
|
|
out.set_bit(idx, BIT4_0);
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
|
|
|
|
out.set_bit(idx, op_a_.value(idx-shift));
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(out, 0);
|
2001-07-06 06:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2006-07-30 04:51:35 +02:00
|
|
|
vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
|
|
|
|
|
: vvp_arith_(wid), signed_flag_(signed_flag)
|
2001-07-07 04:57:33 +02:00
|
|
|
{
|
2005-03-19 07:23:49 +01:00
|
|
|
}
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
vvp_shiftr::~vvp_shiftr()
|
|
|
|
|
{
|
|
|
|
|
}
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|
|
|
|
vvp_context_t)
|
2005-03-19 07:23:49 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
vvp_vector4_t out (op_a_.size());
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2019-11-16 13:11:49 +01:00
|
|
|
bool overflow_flag;
|
2005-03-19 07:23:49 +01:00
|
|
|
unsigned long shift;
|
2019-11-16 13:11:49 +01:00
|
|
|
if (! vector4_to_value(op_b_, overflow_flag, shift)) {
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(x_val_, 0);
|
2001-10-31 05:27:46 +01:00
|
|
|
return;
|
2005-03-19 07:23:49 +01:00
|
|
|
}
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2019-11-16 13:11:49 +01:00
|
|
|
if (overflow_flag || shift > out.size())
|
2005-03-19 07:23:49 +01:00
|
|
|
shift = out.size();
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
|
|
|
|
out.set_bit(idx-shift, op_a_.value(idx));
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2006-07-30 04:51:35 +02:00
|
|
|
vvp_bit4_t pad = BIT4_0;
|
|
|
|
|
if (signed_flag_ && op_a_.size() > 0)
|
|
|
|
|
pad = op_a_.value(op_a_.size()-1);
|
|
|
|
|
|
2005-03-19 07:23:49 +01:00
|
|
|
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
2006-07-30 04:51:35 +02:00
|
|
|
out.set_bit(idx+out.size()-shift, pad);
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(out, 0);
|
2001-07-07 04:57:33 +02:00
|
|
|
}
|
2005-03-19 07:23:49 +01:00
|
|
|
|
2001-07-07 04:57:33 +02:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
vvp_arith_real_::vvp_arith_real_()
|
|
|
|
|
{
|
2008-02-15 23:10:53 +01:00
|
|
|
op_a_ = 0.0;
|
|
|
|
|
op_b_ = 0.0;
|
2005-07-06 06:29:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_arith_real_::dispatch_operand_(vvp_net_ptr_t ptr, double bit)
|
|
|
|
|
{
|
|
|
|
|
switch (ptr.port()) {
|
|
|
|
|
case 0:
|
|
|
|
|
op_a_ = bit;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
op_b_ = bit;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2013-09-09 22:32:55 +02:00
|
|
|
fprintf(stderr, "Unsupported port type %u.\n", ptr.port());
|
2005-07-06 06:29:25 +02:00
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-04 08:44:14 +01:00
|
|
|
/* Real multiplication. */
|
|
|
|
|
vvp_arith_mult_real::vvp_arith_mult_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_mult_real::~vvp_arith_mult_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-04 08:44:14 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = op_a_ * op_b_;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2008-01-04 08:44:14 +01:00
|
|
|
}
|
|
|
|
|
|
2008-01-31 02:53:06 +01:00
|
|
|
/* Real power. */
|
|
|
|
|
vvp_arith_pow_real::vvp_arith_pow_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_pow_real::~vvp_arith_pow_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-31 02:53:06 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = pow(op_a_, op_b_);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2008-01-31 02:53:06 +01:00
|
|
|
}
|
|
|
|
|
|
2008-01-04 08:44:14 +01:00
|
|
|
/* Real division. */
|
2005-07-06 06:29:25 +02:00
|
|
|
vvp_arith_div_real::vvp_arith_div_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_div_real::~vvp_arith_div_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2005-07-06 06:29:25 +02:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = op_a_ / op_b_;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2005-07-06 06:29:25 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-31 03:32:27 +01:00
|
|
|
/* Real modulus. */
|
|
|
|
|
vvp_arith_mod_real::vvp_arith_mod_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_mod_real::~vvp_arith_mod_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-31 03:32:27 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = fmod(op_a_, op_b_);
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2008-01-31 03:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
2008-01-04 08:44:14 +01:00
|
|
|
/* Real summation. */
|
|
|
|
|
vvp_arith_sum_real::vvp_arith_sum_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_sum_real::~vvp_arith_sum_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-04 08:44:14 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = op_a_ + op_b_;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2008-01-04 08:44:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Real subtraction. */
|
2005-07-06 06:29:25 +02:00
|
|
|
vvp_arith_sub_real::vvp_arith_sub_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_sub_real::~vvp_arith_sub_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|
|
|
|
vvp_context_t)
|
2005-07-06 06:29:25 +02:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
double val = op_a_ - op_b_;
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_real(val, 0);
|
2005-07-06 06:29:25 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-15 19:54:04 +01:00
|
|
|
/* Real compare equal. */
|
|
|
|
|
vvp_cmp_eq_real::vvp_cmp_eq_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-15 19:54:04 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
|
|
|
|
|
else res.set_bit(0, BIT4_0);
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(res, 0);
|
2008-01-15 19:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Real compare not equal. */
|
|
|
|
|
vvp_cmp_ne_real::vvp_cmp_ne_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-15 19:54:04 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
|
|
|
|
|
else res.set_bit(0, BIT4_0);
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(res, 0);
|
2008-01-15 19:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Real compare greater than or equal. */
|
|
|
|
|
vvp_cmp_ge_real::vvp_cmp_ge_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-15 19:54:04 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
|
|
|
|
|
else res.set_bit(0, BIT4_0);
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(res, 0);
|
2008-01-15 19:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Real compare greater than. */
|
|
|
|
|
vvp_cmp_gt_real::vvp_cmp_gt_real()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-28 18:52:39 +01:00
|
|
|
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|
|
|
|
vvp_context_t)
|
2008-01-15 19:54:04 +01:00
|
|
|
{
|
|
|
|
|
dispatch_operand_(ptr, bit);
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t res (1);
|
|
|
|
|
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
|
|
|
|
|
else res.set_bit(0, BIT4_0);
|
|
|
|
|
|
2009-04-04 05:40:26 +02:00
|
|
|
ptr.ptr()->send_vec4(res, 0);
|
2008-01-15 19:54:04 +01:00
|
|
|
}
|