Enforce enum type compatibility in more places
In SystemVerilog it is not allowed to assign a value to a enum variable that is not of the same time as the enum variable. This is currently enforced for assignment and continuous assignment. But ignored in other places such as function parameter passing. Move the enum type check into `elab_rval_expr()` to cover more cases. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
d0613f24b8
commit
d1fb3f8925
29
elab_expr.cc
29
elab_expr.cc
|
|
@ -117,7 +117,9 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
|||
<< endl;
|
||||
}
|
||||
|
||||
NetExpr *rval;
|
||||
int context_wid = -1;
|
||||
bool fallback = true;
|
||||
switch (lv_type) {
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
|
|
@ -125,8 +127,11 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
|||
// For these types, use a different elab_and_eval that
|
||||
// uses the lv_net_type. We should eventually transition
|
||||
// all the types to this new form.
|
||||
if (lv_net_type)
|
||||
return elab_and_eval(des, scope, expr, lv_net_type, need_const);
|
||||
if (lv_net_type) {
|
||||
rval = elab_and_eval(des, scope, expr, lv_net_type, need_const);
|
||||
fallback = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
case IVL_VT_STRING:
|
||||
|
|
@ -141,10 +146,28 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
|||
break;
|
||||
}
|
||||
|
||||
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||
if (fallback) {
|
||||
rval = elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||
false, lv_type, force_unsigned);
|
||||
}
|
||||
|
||||
const netenum_t *lval_enum = dynamic_cast<const netenum_t*>(lv_net_type);
|
||||
if (lval_enum) {
|
||||
const netenum_t *rval_enum = rval->enumeration();
|
||||
if (!rval_enum) {
|
||||
cerr << expr->get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (!lval_enum->matches(rval_enum)) {
|
||||
cerr << expr->get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the mode is UPSIZE, make sure the final expression width is at
|
||||
* least integer_width, but return the calculated lossless width to
|
||||
|
|
|
|||
39
elaborate.cc
39
elaborate.cc
|
|
@ -150,18 +150,6 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
return;
|
||||
}
|
||||
|
||||
if (lval->enumeration()) {
|
||||
if (! rval_expr->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lval->enumeration()->matches(rval_expr->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet*rval = rval_expr->synthesize(des, scope, rval_expr);
|
||||
|
||||
if (rval == 0) {
|
||||
|
|
@ -2395,7 +2383,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval_, net_type, is_constant_);
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, net_type, rval_,
|
||||
is_constant_);
|
||||
|
||||
if (!is_constant_ || !rv) return rv;
|
||||
|
||||
|
|
@ -2416,10 +2405,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
// Don't have a good value for the lv_net_type argument to
|
||||
// elaborate_rval_expr, so punt and pass nil. In the future we
|
||||
// should look into fixing calls to this method to pass a
|
||||
// net_type instead of the separate lv_width/lv_type values.
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
|
||||
rval(), is_constant_, force_unsigned);
|
||||
|
||||
|
|
@ -2790,18 +2775,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
return bl;
|
||||
}
|
||||
|
||||
if (lv->enumeration()) {
|
||||
if (! rv->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lv->enumeration()->matches(rv->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, rv);
|
||||
cur->set_line(*this);
|
||||
|
||||
|
|
@ -2851,7 +2824,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
<< endl;
|
||||
}
|
||||
|
||||
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
|
||||
NetExpr*rv = elaborate_rval_(des, scope, lv->net_type(), lv->expr_type(), count_lval_width(lv));
|
||||
if (rv == 0) return 0;
|
||||
|
||||
NetExpr*delay = 0;
|
||||
|
|
@ -4497,11 +4470,7 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned lwid = count_lval_width(lval);
|
||||
ivl_variable_type_t ltype = lval->expr_type();
|
||||
|
||||
// Need to figure out a better thing to do about the
|
||||
// lv_net_type argument to elaborate_rval_expr here. This
|
||||
// would entail getting the NetAssign_ to give us an
|
||||
// ivl_type_t as needed.
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_);
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, lval->net_type(), ltype, lwid, expr_);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -172,11 +172,6 @@ ivl_type_t NetAssign_::net_type() const
|
|||
return ntype;
|
||||
}
|
||||
|
||||
const netenum_t*NetAssign_::enumeration() const
|
||||
{
|
||||
return dynamic_cast<const netenum_t*>(net_type());
|
||||
}
|
||||
|
||||
perm_string NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
|
|
|
|||
|
|
@ -2863,10 +2863,6 @@ class NetAssign_ {
|
|||
// example a darray is indexed.
|
||||
ivl_type_t net_type() const;
|
||||
|
||||
// Return the enumeration type of this l-value, or nil if it's
|
||||
// not an enumeration.
|
||||
const netenum_t*enumeration() const;
|
||||
|
||||
// Get the name of the underlying object.
|
||||
perm_string name() const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue