diff --git a/elab_expr.cc b/elab_expr.cc index 5edcf1a3b..4c22f9c6b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -163,15 +163,11 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&) return 1; } -NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) const +NetExpr* PExpr::elaborate_expr(Design*des, NetScope*scope, ivl_type_t, unsigned flags) const { - cerr << get_fileline() << ": internal error: I do not know how to" - << " elaborate (ivl_type_t) this expression. " << endl; - cerr << get_fileline() << ": : Expression is: " << *this - << endl; - cerr << get_fileline() << ": : Expression type: " << typeid(*this).name() << endl; - des->errors += 1; - return 0; + // Fall back to the old method. Currently the new method won't be used + // if the target is a vector type, so we can use an arbitrary width. + return elaborate_expr(des, scope, 1, flags); } @@ -181,6 +177,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const << " elaborate this expression. " << endl; cerr << get_fileline() << ": : Expression is: " << *this << endl; + cerr << get_fileline() << ": : Expression type: " << typeid(*this).name() << endl; des->errors += 1; return 0; } diff --git a/elaborate.cc b/elaborate.cc index 5af51cc64..25a4b979f 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2317,7 +2317,7 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, { ivl_assert(*this, rval_); - NetExpr*rv = rval_->elaborate_expr(des, scope, net_type, 0); + NetExpr*rv = elab_and_eval(des, scope, rval_, net_type, is_constant_); if (!is_constant_ || !rv) return rv; diff --git a/netmisc.cc b/netmisc.cc index f9e9a8b44..450eb6c05 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1011,6 +1011,36 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, flags |= PExpr::NEED_CONST; NetExpr*tmp = pe->elaborate_expr(des, scope, lv_net_type, flags); + if (tmp == 0) return 0; + + ivl_variable_type_t cast_type = ivl_type_base(lv_net_type); + if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) { + // Catch some special cases. + switch (cast_type) { + case IVL_VT_DARRAY: + case IVL_VT_QUEUE: + if (dynamic_cast(pe)) + return tmp; + // fall through + case IVL_VT_STRING: + if (dynamic_cast(pe)) + return tmp; + break; + case IVL_VT_CLASS: + if (dynamic_cast(pe)) + return tmp; + break; + default: + break; + } + + cerr << tmp->get_fileline() << ": error: " + "The expression '" << *pe << "' cannot be implicitly " + "cast to the target type." << endl; + des->errors += 1; + delete tmp; + return 0; + } return tmp; }