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:
Lars-Peter Clausen 2022-04-03 10:36:06 +02:00
parent d0613f24b8
commit d1fb3f8925
4 changed files with 31 additions and 48 deletions

View File

@ -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,8 +146,26 @@ 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;
}
/*

View File

@ -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;

View File

@ -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_) {

View File

@ -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;