From 68f8de28afc4a5d559742d7c8189bff97e6568bf Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 15 Feb 2014 13:14:45 +0000 Subject: [PATCH] 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. --- vvp/arith.cc | 16 ++++++++-------- vvp/vthread.cc | 4 ++-- vvp/vvp_net.h | 15 +++++++++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/vvp/arith.cc b/vvp/arith.cc index 28abcf3a7..c7ee15e85 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -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); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index dbf2c3a2d..b2b9fd8ce 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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()) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 3554be58f..5d9e80138 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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); }