From 348c46894f1d4e74af8f7deaf1586d8260100146 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 12 Mar 2023 19:24:35 +0000 Subject: [PATCH] Allow more cases of reading signal value during elaboration. Issue #640 --- src/lower.c | 41 +++++++++++++++++++++++++++++++++++++-- src/sem.c | 24 +++++++++-------------- test/regress/issue646.vhd | 18 +++++++++++++++++ tools/run.sh | 2 +- 4 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 test/regress/issue646.vhd diff --git a/src/lower.c b/src/lower.c index 956aa74a..b0e1f3d1 100644 --- a/src/lower.c +++ b/src/lower.c @@ -76,6 +76,7 @@ typedef struct _lower_unit { vcode_unit_t vunit; cover_tagging_t *cover; bool finished; + bool elaborating; } lower_unit_t; typedef enum { @@ -1183,6 +1184,12 @@ static vcode_reg_t lower_param(lower_unit_t *lu, tree_t value, tree_t port, class = tree_class(port); } + // This is not legal in VHDL anyway, but we allow it at analysis time + // with --relaxed + if (class == C_SIGNAL && lu->elaborating) + fatal_at(tree_loc(value), "cannot pass signal argument during " + "static elaboration"); + vcode_reg_t reg; if (class == C_SIGNAL && tree_kind(value) == T_AGGREGATE) { if (type_is_record(value_type)) @@ -2978,6 +2985,18 @@ static bool lower_is_trivial_constant(tree_t decl) return tree_kind(tree_value(decl)) == T_LITERAL; } +static vcode_reg_t lower_signal_dummy_rvalue(lower_unit_t *lu, tree_t decl) +{ + // This is a workaround to allow referencing signal initial values + // during elaboration with --relaxed + if (tree_has_value(decl)) + return lower_expr(lu, tree_value(decl), EXPR_RVALUE); + else { + type_t type = tree_type(decl); + return lower_default_value(lu, type, VCODE_INVALID_REG, NULL, 0); + } +} + static vcode_reg_t lower_ref(lower_unit_t *lu, tree_t ref, expr_ctx_t ctx) { tree_t decl = tree_ref(ref); @@ -2995,7 +3014,10 @@ static vcode_reg_t lower_ref(lower_unit_t *lu, tree_t ref, expr_ctx_t ctx) return lower_var_ref(lu, decl, ctx); case T_PORT_DECL: - return lower_port_ref(lu, decl); + if (ctx == EXPR_RVALUE && lu->elaborating) + return lower_signal_dummy_rvalue(lu, decl); + else + return lower_port_ref(lu, decl); case T_PARAM_DECL: return lower_param_ref(lu, decl); @@ -3005,7 +3027,10 @@ static vcode_reg_t lower_ref(lower_unit_t *lu, tree_t ref, expr_ctx_t ctx) case T_SIGNAL_DECL: case T_IMPLICIT_SIGNAL: - return lower_signal_ref(lu, decl); + if (ctx == EXPR_RVALUE && lu->elaborating) + return lower_signal_dummy_rvalue(lu, decl); + else + return lower_signal_ref(lu, decl); case T_TYPE_DECL: return VCODE_INVALID_REG; @@ -10892,6 +10917,18 @@ lower_unit_t *lower_unit_new(lower_unit_t *parent, vcode_unit_t vunit, new->vunit = vunit; new->cover = cover; + vcode_state_t state; + vcode_state_save(&state); + + vcode_select_unit(vunit); + const vunit_kind_t kind = vcode_unit_kind(); + + vcode_state_restore(&state); + + // Prevent access to resolved signals during static elaboration + new->elaborating = kind == VCODE_UNIT_INSTANCE + || kind == VCODE_UNIT_PROTECTED || kind == VCODE_UNIT_PACKAGE; + cover_push_scope(new->cover, container); return new; diff --git a/src/sem.c b/src/sem.c index af4b52fe..bf5d3b72 100644 --- a/src/sem.c +++ b/src/sem.c @@ -981,14 +981,6 @@ static bool sem_check_signal_decl(tree_t t, nametab_t *tab) sem_error(value, "type of initial value %s does not match type " "of declaration %s", type_pp2(tree_type(value), type), type_pp2(type, tree_type(value))); - - if (opt_get_int(OPT_RELAXED) && tree_kind(value) == T_REF - && class_of(value) == C_SIGNAL) { - // Kludgy workaround for UVVM - tree_t decl = tree_ref(value); - if (tree_has_value(decl)) - tree_set_value(t, tree_value(decl)); - } } return true; @@ -1622,13 +1614,15 @@ static void sem_check_static_elab(tree_t t) else id = tree_ident(t); - diag_t *d = diag_new(DIAG_ERROR, tree_loc(t)); - diag_printf(d, "cannot reference signal %s during static " - "elaboration", istr(id)); - diag_hint(d, NULL, "the value of a signal is not defined " - "until after the design hierarchy is elaborated"); - diag_lrm(d, STD_93, "12.3"); - diag_emit(d); + diag_t *d = pedantic_diag(t); + if (d != NULL) { + diag_printf(d, "cannot reference signal %s during static " + "elaboration", istr(id)); + diag_hint(d, NULL, "the value of a signal is not defined " + "until after the design hierarchy is elaborated"); + diag_lrm(d, STD_93, "12.3"); + diag_emit(d); + } } break; diff --git a/test/regress/issue646.vhd b/test/regress/issue646.vhd new file mode 100644 index 00000000..2444949b --- /dev/null +++ b/test/regress/issue646.vhd @@ -0,0 +1,18 @@ +entity issue646 is +end entity; + +architecture test of issue646 is + + function get_init (x : integer; y : bit_vector) return integer is + begin + assert x = 42; + assert y = "000"; + return 55; + end function; + + signal x : integer := 42; + signal y : bit_vector(1 to 3); + signal z : integer := get_init(x, y); +begin + assert z = 55; +end architecture; diff --git a/tools/run.sh b/tools/run.sh index 4f59712e..364cfcdd 100755 --- a/tools/run.sh +++ b/tools/run.sh @@ -14,4 +14,4 @@ if [ -z "$vlog" ] || [ -f $regress/$1.vhd ]; then vhd=$regress/$1.vhd fi PATH="./bin:../bin:$PATH" -nvc --std=$std -a --psl $vhd $vlog -e -V $* -r --trace --stats $vhpi +nvc --std=$std -a --relaxed --psl $vhd $vlog -e -V $* -r --trace --stats $vhpi -- 2.39.2