diff --git a/elab_expr.cc b/elab_expr.cc index 5edcf1a3b..65c1dc714 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; } @@ -4061,10 +4058,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, // If this is an array object, and there are members in // the member_path, check for array properties. if (net->darray_type() && member_path.size() > 0) { - cerr << get_fileline() << ": PEIdent::elaborate_expr: " - << "Ident " << base_path - << " look for array property " << member_path - << endl; + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr: " + << "Ident " << base_path + << " look for array property " << member_path + << endl; + } ivl_assert(*this, member_path.size() == 1); const name_component_t member_comp = member_path.front(); 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..36ac0ced0 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -925,20 +925,18 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe, if (tmp == 0) return 0; if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) { - if (cast_type != pe->expr_type()) { - switch (pe->expr_type()) { - case IVL_VT_BOOL: - case IVL_VT_LOGIC: - case IVL_VT_REAL: - break; - default: - cerr << tmp->get_fileline() << ": error: " - "this expression cannot be implicitly " - "cast to the target type." << endl; - des->errors += 1; - delete tmp; - return 0; - } + switch (tmp->expr_type()) { + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + case IVL_VT_REAL: + break; + default: + cerr << tmp->get_fileline() << ": error: " + "The expression '" << *pe << "' cannot be implicitly " + "cast to the target type." << endl; + des->errors += 1; + delete tmp; + return 0; } switch (cast_type) { case IVL_VT_REAL: @@ -1011,6 +1009,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; } diff --git a/parse.y b/parse.y index e0152f763..86d5de910 100644 --- a/parse.y +++ b/parse.y @@ -4890,15 +4890,27 @@ module_port_list_opt ports. These are simply advance ways to declare parameters, so that the port declarations may use them. */ module_parameter_port_list_opt - : - | '#' '(' module_parameter_port_list ')' - ; + : + | '#' '(' module_parameter_port_list ')' + ; module_parameter_port_list - : K_parameter param_type parameter_assign - | module_parameter_port_list ',' parameter_assign - | module_parameter_port_list ',' K_parameter param_type parameter_assign - ; + : K_parameter param_type parameter_assign + | K_localparam param_type localparam_assign + { if (!gn_system_verilog()) { + yyerror(@1, "error: Local parameters in module parameter " + "port lists requires SystemVerilog."); + } + } + | module_parameter_port_list ',' parameter_assign + | module_parameter_port_list ',' K_parameter param_type parameter_assign + | module_parameter_port_list ',' K_localparam param_type localparam_assign + { if (!gn_system_verilog()) { + yyerror(@3, "error: Local parameters in module parameter " + "port lists requires SystemVerilog."); + } + } + ; module_item