V0.9: Fix a few problems with the power operator.

The power operator defines 2**-1 and -2**-1 to be zero. This patch fixes
both the procedural and continuous assignments to work correctly. It also
fixes a problem in the compiler power code so that the one constant value
always has at least two bits.
This commit is contained in:
Cary R 2011-04-11 11:22:20 -07:00 committed by Stephen Williams
parent 4c9853551c
commit 6f2fd4e169
3 changed files with 19 additions and 11 deletions

View File

@ -1053,15 +1053,17 @@ verinum pow(const verinum&left, const verinum&right)
long pow_count = right.as_long();
// We need positive and negative one in a few places.
verinum one (verinum::V0, left.len(), left.has_len());
unsigned len = left.len();
// Positive one must be at least two bits wide!
verinum one (verinum::V0, (len<2) ? 2 : len, left.has_len());
one.has_sign(left.has_sign());
one.set(0, verinum::V1);
verinum m_one (verinum::V1, left.len(), left.has_len());
verinum m_one (verinum::V1, len, left.has_len());
m_one.has_sign(true);
// If either the right or left values are undefined we return 'bx.
if (!right.is_defined() || !left.is_defined()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result = verinum(verinum::Vx, len, left.has_len());
result.has_sign(left.has_sign());
// If the right value is zero we need to set the result to 1.
} else if (pow_count == 0) {
@ -1069,7 +1071,7 @@ verinum pow(const verinum&left, const verinum&right)
} else if (pow_count < 0) {
// 0 ** <negative> is 'bx.
if (left.is_zero()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result = verinum(verinum::Vx, len, left.has_len());
result.has_sign(left.has_sign());
// 1 ** <negative> is 1.
} else if (left == one) {
@ -1083,7 +1085,7 @@ verinum pow(const verinum&left, const verinum&right)
}
// Everything else is 0.
} else {
result = verinum(verinum::V0, left.len(), left.has_len());
result = verinum(verinum::V0, len, left.has_len());
result.has_sign(left.has_sign());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -438,11 +438,14 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
return;
}
double ad, bd;
double ad, bd, resd;
vector4_to_value(op_a_, ad, true);
vector4_to_value(op_b_, bd, true);
/* 2**-1 and -2**-1 are defined to be zero. */
if ((bd == -1) && (fabs(ad) == 2.0)) resd = 0.0;
else resd = pow(ad, bd);
res4 = vvp_vector4_t(wid_, pow(ad, bd));
res4 = vvp_vector4_t(wid_, resd);
} else {
vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -3989,10 +3989,13 @@ bool of_POW_S(vthread_t thr, vvp_code_t cp)
}
/* Calculate the result using the double pow() function. */
double xd, yd;
double xd, yd, resd;
vector4_to_value(xv, xd, true);
vector4_to_value(yv, yd, true);
vvp_vector4_t res = vvp_vector4_t(wid, pow(xd, yd));
/* 2**-1 and -2**-1 are defined to be zero. */
if ((yd == -1.0) && (fabs(xd) == 2.0)) resd = 0.0;
else resd = pow(xd, yd);
vvp_vector4_t res = vvp_vector4_t(wid, resd);
/* Copy the result. */
for (unsigned jdx = 0; jdx < wid; jdx += 1)