From d1fb3f8925b2d117e5fd1ee4f75e241d720c9fbd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 3 Apr 2022 10:36:06 +0200 Subject: [PATCH] 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 --- elab_expr.cc | 31 +++++++++++++++++++++++++++---- elaborate.cc | 39 ++++----------------------------------- net_assign.cc | 5 ----- netlist.h | 4 ---- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index d8e889e08..bfd994e93 100644 --- a/elab_expr.cc +++ b/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,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, - false, lv_type, force_unsigned); + 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(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; } /* diff --git a/elaborate.cc b/elaborate.cc index fa0b99768..2d9481bd0 100644 --- a/elaborate.cc +++ b/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; diff --git a/net_assign.cc b/net_assign.cc index fc8ffdb55..6f8334d77 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -172,11 +172,6 @@ ivl_type_t NetAssign_::net_type() const return ntype; } -const netenum_t*NetAssign_::enumeration() const -{ - return dynamic_cast(net_type()); -} - perm_string NetAssign_::name() const { if (sig_) { diff --git a/netlist.h b/netlist.h index 14e28832c..56ae221ff 100644 --- a/netlist.h +++ b/netlist.h @@ -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;