Elaborate array assignment pattern values in the right context

The expressions within an array assignment pattern should be evaluated in a
context that is equivalent to an assignment to a variable of the element
type of the l-value array.

This is defined in section 10.9.1 ("Array assignment patterns") of the LRM
(1800-2017).

At the moment the values in an assignment pattern are evaluated in a self
determined context, which can lead to incorrect behavior.

Use the existing `elaborate_rval_expr()` function, which is meant for
elaborating assignments, to elaborate the assignment pattern values.

This solves the following issues:
 * implicit width conversion (including sign extension)
 * implicit type conversion (e.g. real to vector)
 * math operators that depend on the target width (e.g. addition)
 * use of expressions that require `test_width()` to be called. (e.g.
   unary operator)
 * use of concatenations
 * use of named constants (e.g. parameters or enums)

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-04-03 20:21:32 +02:00
parent f19ba64614
commit 5b8fb089bf
2 changed files with 8 additions and 5 deletions

View File

@ -91,8 +91,8 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
return 0;
}
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
PExpr*expr, bool need_const, bool force_unsigned)
NetExpr* elaborate_rval_expr(Design *des, NetScope *scope, ivl_type_t lv_net_type,
PExpr *expr, bool need_const, bool force_unsigned)
{
return elaborate_rval_expr(des, scope, lv_net_type,
lv_net_type->base_type(),
@ -236,13 +236,16 @@ NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope,
const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype);
ivl_assert(*this, array_type);
bool need_const = NEED_CONST & flags;
// This is an array pattern, so run through the elements of
// the expression and elaborate each as if they are
// element_type expressions.
ivl_type_t elem_type = array_type->element_type();
vector<NetExpr*> elem_exprs (parms_.size());
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags);
NetExpr*tmp = elaborate_rval_expr(des, scope, elem_type,
parms_[idx], need_const);
elem_exprs[idx] = tmp;
}

View File

@ -411,8 +411,8 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
/*
* Same as above, but lv_width and lv_type are derived from the lv_net_type.
*/
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_type_t lv_net_type, PExpr*expr,
extern NetExpr* elaborate_rval_expr(Design *des, NetScope *scope,
ivl_type_t lv_net_type, PExpr *expr,
bool need_const = false,
bool force_unsigned = false);