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:
parent
3aaea46144
commit
2da50e1788
|
|
@ -632,9 +632,9 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
|
|||
use_lossless_flag = false;
|
||||
|
||||
tmp = new NetEBAdd(op_, lp, rp, use_lossless_flag);
|
||||
if (expr_wid > 0 && (tmp->expr_type() == IVL_VT_BOOL
|
||||
|| tmp->expr_type() == IVL_VT_LOGIC))
|
||||
if (expr_wid > 0 && type_is_vectorable(tmp->expr_type()))
|
||||
tmp->set_width(expr_wid);
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,20 +27,11 @@
|
|||
# include "netmisc.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;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
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;
|
||||
}
|
||||
verireal vrl(expr->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
NetNet* sig = rlval.synthesize(des, scope);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
|
@ -55,19 +46,26 @@ static bool process_binary_args(Design*des, NetScope*scope,
|
|||
right->expr_type() == IVL_VT_REAL) {
|
||||
real_args = true;
|
||||
|
||||
/* Currently we will have a runtime assert if both expressions
|
||||
are not real, though we can convert constants. */
|
||||
/* Convert the arguments to real. Handle the special
|
||||
cases of constants, which can be converted more directly. */
|
||||
if (left->expr_type() == IVL_VT_REAL) {
|
||||
lsig = left->synthesize(des, scope);
|
||||
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (left)) {
|
||||
lsig = convert_to_real_const(des, scope, tmp);
|
||||
} 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) {
|
||||
rsig = right->synthesize(des, scope);
|
||||
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (right)) {
|
||||
rsig = convert_to_real_const(des, scope, tmp);
|
||||
} else {
|
||||
rsig = convert_to_real_const(des, scope, right, obj);
|
||||
NetNet*tmp = right->synthesize(des, scope);
|
||||
rsig = cast_to_real(des, scope, tmp);
|
||||
}
|
||||
|
||||
} else {
|
||||
real_args = false;
|
||||
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() >= rsig->vector_width());
|
||||
|
||||
lsig = pad_to_width(des, lsig, expr_width());
|
||||
rsig = pad_to_width(des, rsig, expr_width());
|
||||
unsigned 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());
|
||||
unsigned width=lsig->vector_width();
|
||||
} else {
|
||||
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();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
|
|
|
|||
Loading…
Reference in New Issue