diff --git a/eval_tree.cc b/eval_tree.cc index b51a77faa..8343f8f5b 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -358,6 +358,10 @@ NetEConst* NetEBComp::eval_less_(const NetExpr*le, const NetExpr*re) const NetEConst* NetEBComp::must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_flag) const { + // The following optimization is not valid if le can contain 'x' + // or 'z' values. + if (le->expr_type() == IVL_VT_LOGIC) return 0; + assert(le->expr_width() > 0); verinum lv (verinum::V1, le->expr_width()); if (le->has_sign() && rv.has_sign()) { diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 86d958bf8..a4d006de1 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1011,8 +1011,18 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval) ivl_expr_t lword_idx, rword_idx; unsigned long use_lword = 0, use_rword = 0; - if (ivl_expr_type(rval) != IVL_EX_SIGNAL) + if (ivl_expr_type(rval) != IVL_EX_SIGNAL) { + if (ivl_expr_type(rval) == IVL_EX_NUMBER || + ivl_expr_type(rval) == IVL_EX_REALNUM) + return; + + fprintf(stderr, "%s:%u: tgt-vvp sorry: procedural continuous " + "assignments are not yet fully supported. The RHS of " + "this assignment will only be evaluated once, at the " + "time the assignment statement is executed.\n", + ivl_stmt_file(net), ivl_stmt_lineno(net)); return; + } switch (ivl_statement_type(net)) { case IVL_ST_CASSIGN: diff --git a/vvp/arith.cc b/vvp/arith.cc index c7ee15e85..7b23e3bd6 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -453,35 +453,37 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, { dispatch_operand_(ptr, bit); - vvp_vector4_t res4; - if (signed_flag_) { - if (op_a_.has_xz() || op_b_.has_xz()) { - ptr.ptr()->send_vec4(x_val_, 0); - return; - } + vvp_vector2_t a2 (op_a_, true); + vvp_vector2_t b2 (op_b_, true); - 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_, resd); - } else { - 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); - return; - } - - vvp_vector2_t result = pow(a2, b2); - res4 = vector2_to_vector4(result, wid_); + // If we have an X or Z in the arguments return X. + if (a2.is_NaN() || b2.is_NaN()) { + ptr.ptr()->send_vec4(x_val_, 0); + return; } - ptr.ptr()->send_vec4(res4, 0); + // Is the exponent negative? If so, table 5-6 in IEEE1364-2005 + // defines what value is returned. + if (signed_flag_ && b2.value(b2.size()-1)) { + int a_val; + double r_val = 0.0; + if (vector2_to_value(a2, a_val, true)) { + if (a_val == 0) { + ptr.ptr()->send_vec4(x_val_, 0); + return; + } + if (a_val == 1) { + r_val = 1.0; + } + if (a_val == -1) { + r_val = b2.value(0) ? -1.0 : 1.0; + } + } + ptr.ptr()->send_vec4(vvp_vector4_t(wid_, r_val), 0); + return; + } + + ptr.ptr()->send_vec4(vector2_to_vector4(pow(a2, b2), wid_), 0); } diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 44edf1bcd..2f85a89f5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5058,7 +5058,7 @@ bool of_POP_VEC4(vthread_t thr, vvp_code_t cp) /* * %pow */ -bool of_POW(vthread_t thr, vvp_code_t) +static bool of_POW_base(vthread_t thr, vvp_code_t cp, bool signed_flag) { vvp_vector4_t valb = thr->pop_vec4(); vvp_vector4_t vala = thr->pop_vec4(); @@ -5076,6 +5076,32 @@ bool of_POW(vthread_t thr, vvp_code_t) return true; } + // Is the exponent negative? If so, table 5-6 in IEEE1364-2005 + // defines what value is returned. + if (signed_flag && yv2.value(yv2.size()-1)) { + int a_val; + vvp_bit4_t pad = BIT4_0, lsb = BIT4_0; + if (vector2_to_value(xv2, a_val, true)) { + if (a_val == 0) { + pad = BIT4_X; lsb = BIT4_X; + } + if (a_val == 1) { + pad = BIT4_0; lsb = BIT4_1; + } + if (a_val == -1) { + if (yv2.value(0)) { + pad = BIT4_1; lsb = BIT4_1; + } else { + pad = BIT4_0; lsb = BIT4_1; + } + } + } + vvp_vector4_t tmp (wid, pad); + tmp.set_bit(0, lsb); + thr->push_vec4(tmp); + return true; + } + vvp_vector2_t result = pow(xv2, yv2); /* Copy only what we need of the result. If the result is too @@ -5091,35 +5117,14 @@ bool of_POW(vthread_t thr, vvp_code_t) return true; } -/* - * %pow/s - */ -bool of_POW_S(vthread_t thr, vvp_code_t) +bool of_POW(vthread_t thr, vvp_code_t cp) { - vvp_vector4_t yv = thr->pop_vec4(); - vvp_vector4_t xv = thr->pop_vec4(); + return of_POW_base(thr, cp, false); +} - assert(xv.size()==yv.size()); - unsigned wid = xv.size(); - - /* If we have an X or Z in the arguments return X. */ - if (xv.has_xz() || yv.has_xz()) { - vvp_vector4_t tmp (wid, BIT4_X); - thr->push_vec4(tmp); - return true; - } - - /* Calculate the result using the double pow() function. */ - double xd, yd, resd; - vector4_to_value(xv, xd, true); - vector4_to_value(yv, yd, true); - /* 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); - - thr->push_vec4(res); - return true; +bool of_POW_S(vthread_t thr, vvp_code_t cp) +{ + return of_POW_base(thr, cp, true); } bool of_POW_WR(vthread_t thr, vvp_code_t) diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 58fd01555..33ac37d38 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -200,7 +200,11 @@ void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, break; case 1: // Continuous assign value - bits4_ = bit; + // Handle the simple case of the linked source being wider + // than this signal. Note we don't yet support the case of + // the linked source being narrower than this signal, or + // the case of an expression being assigned. + bits4_ = coerce_to_width(bit, bits4_.size()); assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, bits4_.size()); ptr.ptr()->send_vec4(bits4_, 0); break;