Cast to real when add arguments have mixed type.

When synthesizing, be careful (especiall for addition) that if the
arguments are mixed, then cast the non-IVL_VT_REAL arguments to
IVL_VT_REAL.
This commit is contained in:
Stephen Williams 2008-09-29 21:02:37 -07:00
parent 3aaea46144
commit 2da50e1788
2 changed files with 31 additions and 23 deletions

View File

@ -632,9 +632,9 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
use_lossless_flag = false; use_lossless_flag = false;
tmp = new NetEBAdd(op_, lp, rp, use_lossless_flag); tmp = new NetEBAdd(op_, lp, rp, use_lossless_flag);
if (expr_wid > 0 && (tmp->expr_type() == IVL_VT_BOOL if (expr_wid > 0 && type_is_vectorable(tmp->expr_type()))
|| tmp->expr_type() == IVL_VT_LOGIC))
tmp->set_width(expr_wid); tmp->set_width(expr_wid);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
} }

View File

@ -27,20 +27,11 @@
# include "netmisc.h" # include "netmisc.h"
# include "ivl_assert.h" # include "ivl_assert.h"
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetExpr*expr, NetExpr*obj) static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
{ {
NetNet* sig; verireal vrl(expr->value().as_double());
NetECReal rlval(vrl);
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) { NetNet* sig = rlval.synthesize(des, scope);
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
sig = rlval.synthesize(des, scope);
} else {
cerr << obj->get_fileline() << ": sorry: Cannot convert "
"bit based value (" << *expr << ") to real." << endl;
des->errors += 1;
sig = 0;
}
return sig; return sig;
} }
@ -55,19 +46,26 @@ static bool process_binary_args(Design*des, NetScope*scope,
right->expr_type() == IVL_VT_REAL) { right->expr_type() == IVL_VT_REAL) {
real_args = true; real_args = true;
/* Currently we will have a runtime assert if both expressions /* Convert the arguments to real. Handle the special
are not real, though we can convert constants. */ cases of constants, which can be converted more directly. */
if (left->expr_type() == IVL_VT_REAL) { if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des, scope); lsig = left->synthesize(des, scope);
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (left)) {
lsig = convert_to_real_const(des, scope, tmp);
} else { } else {
lsig = convert_to_real_const(des, scope, left, obj); NetNet*tmp = left->synthesize(des, scope);
lsig = cast_to_real(des, scope, tmp);
} }
if (right->expr_type() == IVL_VT_REAL) { if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des, scope); rsig = right->synthesize(des, scope);
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (right)) {
rsig = convert_to_real_const(des, scope, tmp);
} else { } else {
rsig = convert_to_real_const(des, scope, right, obj); NetNet*tmp = right->synthesize(des, scope);
rsig = cast_to_real(des, scope, tmp);
} }
} else { } else {
real_args = false; real_args = false;
lsig = left->synthesize(des, scope); lsig = left->synthesize(des, scope);
@ -104,11 +102,21 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
assert(expr_width() >= lsig->vector_width()); assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width()); assert(expr_width() >= rsig->vector_width());
lsig = pad_to_width(des, lsig, expr_width()); unsigned width;
rsig = pad_to_width(des, rsig, expr_width()); if (expr_type() == IVL_VT_REAL) {
width = 1;
if (lsig->data_type() != IVL_VT_REAL)
lsig = cast_to_real(des, scope, lsig);
if (rsig->data_type() != IVL_VT_REAL)
rsig = cast_to_real(des, scope, rsig);
assert(lsig->vector_width() == rsig->vector_width()); } else {
unsigned width=lsig->vector_width(); lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
assert(lsig->vector_width() == rsig->vector_width());
width=lsig->vector_width();
}
perm_string path = lsig->scope()->local_symbol(); perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width); NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);