Fix for GitHub issue 7 : Undef propagation in power operator.

The vvp_vector2_t constructor that takes a vvp_vector4_t value was
documented as creating a NaN value if the supplied vector contained
any X or Z bits, but instead used the standard Verilog 4-state to
2-state conversion semantics (X or Z translate to 0). I've added an
optional second parameter to the constructor to allow the user to
choose which semantics they want, as both are needed.
This commit is contained in:
Martin Whitaker 2014-02-15 13:14:45 +00:00
parent ac3aee0172
commit 68f8de28af
3 changed files with 21 additions and 14 deletions

View File

@ -156,13 +156,13 @@ vvp_arith_div::~vvp_arith_div()
void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
{
vvp_vector2_t a2 (op_a_);
vvp_vector2_t a2 (op_a_, true);
if (a2.is_NaN()) {
ptr.ptr()->send_vec4(x_val_, 0);
return;
}
vvp_vector2_t b2 (op_b_);
vvp_vector2_t b2 (op_b_, true);
if (b2.is_NaN() || b2.is_zero()) {
ptr.ptr()->send_vec4(x_val_, 0);
return;
@ -270,13 +270,13 @@ vvp_arith_mod::~vvp_arith_mod()
void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
{
vvp_vector2_t a2 (op_a_);
vvp_vector2_t a2 (op_a_, true);
if (a2.is_NaN()) {
ptr.ptr()->send_vec4(x_val_, 0);
return;
}
vvp_vector2_t b2 (op_b_);
vvp_vector2_t b2 (op_b_, true);
if (b2.is_NaN() || b2.is_zero()) {
ptr.ptr()->send_vec4(x_val_, 0);
return;
@ -384,8 +384,8 @@ vvp_arith_mult::~vvp_arith_mult()
void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
{
vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_);
vvp_vector2_t a2 (op_a_, true);
vvp_vector2_t b2 (op_b_, true);
if (a2.is_NaN() || b2.is_NaN()) {
ptr.ptr()->send_vec4(x_val_, 0);
@ -469,8 +469,8 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
res4 = vvp_vector4_t(wid_, resd);
} else {
vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_);
vvp_vector2_t a2 (op_a_, true);
vvp_vector2_t b2 (op_b_, true);
if (a2.is_NaN() || b2.is_NaN()) {
ptr.ptr()->send_vec4(x_val_, 0);

View File

@ -4547,8 +4547,8 @@ bool of_POW(vthread_t thr, vvp_code_t cp)
unsigned idx = cp->bit_idx[0];
unsigned idy = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector2_t xv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idx, wid));
vvp_vector2_t yv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idy, wid));
vvp_vector2_t xv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idx, wid), true);
vvp_vector2_t yv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idy, wid), true);
/* If we have an X or Z in the arguments return X. */
if (xv2.is_NaN() || yv2.is_NaN()) {

View File

@ -619,9 +619,11 @@ class vvp_vector2_t {
vvp_vector2_t(const vvp_vector2_t&);
vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
vvp_vector2_t(const vvp_vector2_t&, unsigned base, unsigned wid);
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
// or Z bits, then the result becomes a NaN value.
vvp_vector2_t(const vvp_vector4_t&that);
// Make a vvp_vector2_t from a vvp_vector4_t. If enable_NaN
// is true and there are X or Z bits, then the result becomes
// a NaN value. If enable_NaN is false then X or Z bits are
// converted to 0 as per the standard Verilog rules.
vvp_vector2_t(const vvp_vector4_t&that, bool allow_NaN = false);
// Make from a native long and a specified width.
vvp_vector2_t(unsigned long val, unsigned wid);
// Make with the width, and filled with 1 or 0 bits.
@ -693,8 +695,13 @@ inline vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
copy_from_that_(that);
}
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that, bool enable_NaN)
{
if (enable_NaN && that.has_xz()) {
vec_ = 0;
wid_ = 0;
return;
}
copy_from_that_(that);
}