Skip to content
Permalink
Browse files

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.
  • Loading branch information
martinwhitaker committed Feb 15, 2014
1 parent ac3aee0 commit 68f8de28afc4a5d559742d7c8189bff97e6568bf
Showing with 21 additions and 14 deletions.
  1. +8 −8 vvp/arith.cc
  2. +2 −2 vvp/vthread.cc
  3. +11 −4 vvp/vvp_net.h
@@ -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);
@@ -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()) {
@@ -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);
}

0 comments on commit 68f8de2

Please sign in to comment.