Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
3 changed files
with
21 additions
and
14 deletions .
+8
−8
vvp/arith.cc
+2
−2
vvp/vthread.cc
+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);
}
Toggle all file notes