From 75b9c114990f626460de86de09205a6f26e73e65 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 17 Feb 2024 09:45:16 +0000 Subject: [PATCH] Fix error when generic value depends on another generic Issue #844 --- src/lower.c | 36 ++++++++++++++++++++++++------------ test/lower/issue844.vhd | 23 +++++++++++++++++++++++ test/test_lower.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 test/lower/issue844.vhd diff --git a/src/lower.c b/src/lower.c index de3b066e..15400e8f 100644 --- a/src/lower.c +++ b/src/lower.c @@ -132,7 +132,7 @@ static void lower_check_array_sizes(lower_unit_t *lu, type_t ltype, static vcode_type_t lower_alias_type(tree_t alias); static void lower_predef(lower_unit_t *lu, object_t *obj); static ident_t lower_predef_func_name(type_t type, const char *op); -static void lower_generics(lower_unit_t *lu, tree_t block); +static void lower_generics(lower_unit_t *lu, tree_t block, tree_t primary); static vcode_reg_t lower_default_value(lower_unit_t *lu, type_t type, vcode_reg_t hint_reg); static vcode_reg_t lower_array_total_len(lower_unit_t *lu, type_t type, @@ -9602,7 +9602,7 @@ static void lower_instantiated_package(lower_unit_t *parent, tree_t decl) cover_push_scope(lu->cover, decl); - lower_generics(lu, decl); + lower_generics(lu, decl, NULL); lower_decls(lu, decl); emit_return(VCODE_INVALID_REG); @@ -11051,7 +11051,7 @@ static void lower_proc_body(lower_unit_t *lu, object_t *obj) emit_param(vcontext, vcontext, ident_new("context")); if (tree_kind(body) == T_PROC_INST) - lower_generics(lu, body); + lower_generics(lu, body, NULL); const bool never_waits = vcode_unit_kind(lu->vunit) == VCODE_UNIT_FUNCTION; const bool has_subprograms = lower_has_subprograms(body); @@ -11083,7 +11083,7 @@ static void lower_func_body(lower_unit_t *lu, object_t *obj) cover_push_scope(lu->cover, body); if (tree_kind(body) == T_FUNC_INST) - lower_generics(lu, body); + lower_generics(lu, body, NULL); const bool has_subprograms = lower_has_subprograms(body); lower_subprogram_ports(lu, body, has_subprograms); @@ -12319,7 +12319,7 @@ static void lower_pack_inst_generics(lower_unit_t *lu, tree_t inst, tree_t map) } } -static void lower_generics(lower_unit_t *lu, tree_t block) +static void lower_generics(lower_unit_t *lu, tree_t block, tree_t primary) { const int ngenerics = tree_generics(block); assert(ngenerics == tree_genmaps(block)); @@ -12396,6 +12396,15 @@ static void lower_generics(lower_unit_t *lu, tree_t block) emit_store(value_reg, var); lower_put_vcode_obj(g, var, lu); + + if (primary != NULL) { + // The generic object in the instance may have been copied in + // which case we also need to associate the variable with the + // original generic in the primary unit + tree_t g2 = tree_generic(primary, i); + assert(tree_ident(g2) == tree_ident(g)); + if (g2 != g) lower_put_vcode_obj(g2, var, lu); + } } } @@ -12495,7 +12504,7 @@ static void lower_package(lower_unit_t *lu, object_t *obj) const bool has_scope = lower_push_package_scope(pack); - lower_generics(lu, pack); + lower_generics(lu, pack, NULL); lower_decls(lu, pack); if (has_scope) @@ -12704,15 +12713,18 @@ lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, cover_push_scope(cover, block); - if (lu->cover != NULL) { - tree_t hier = tree_decl(block, 0); - assert(tree_kind(hier) == T_HIER); + tree_t hier = tree_decl(block, 0); + assert(tree_kind(hier) == T_HIER); - cover_ignore_from_pragmas(lu->cover, tree_ref(hier)); - } + tree_t unit = tree_ref(hier), primary = NULL; + if (is_design_unit(unit)) + primary = primary_unit_of(unit); + + if (lu->cover != NULL) + cover_ignore_from_pragmas(lu->cover, unit); lower_dependencies(lu, block); - lower_generics(lu, block); + lower_generics(lu, block, primary); lower_ports(lu, ds, block); lower_decls(lu, block); diff --git a/test/lower/issue844.vhd b/test/lower/issue844.vhd new file mode 100644 index 00000000..9fbbee8f --- /dev/null +++ b/test/lower/issue844.vhd @@ -0,0 +1,23 @@ +entity sub is + generic ( g1 : natural; g2 : natural := g1 ); + port ( p : bit_vector(1 to g2) ); +end entity; + +architecture test of sub is +begin + +end architecture; + +------------------------------------------------------------------------------- + +entity issue844 is +end entity; + +architecture test of issue844 is +begin + + u: entity work.sub + generic map ( g1 => 4 ) + port map ( p => (others => '0') ); + +end architecture; diff --git a/test/test_lower.c b/test/test_lower.c index e7f9c1ba..221b1add 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -6001,6 +6001,42 @@ START_TEST(test_directmap6) } END_TEST +START_TEST(test_issue844) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/lower/issue844.vhd"); + + run_elab(); + + vcode_unit_t vu = find_unit("WORK.ISSUE844.U"); + vcode_select_unit(vu); + + EXPECT_BB(0) = { + { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, + { VCODE_OP_CONST, .value = 4 }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_STORE, .name = "G1" }, + { VCODE_OP_STORE, .name = "G2" }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 4 }, + // TODO: just pass a scalar init value + { VCODE_OP_ALLOC }, + { VCODE_OP_MEMSET }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_INIT_SIGNAL }, + { VCODE_OP_WRAP }, + { VCODE_OP_STORE, .name = "P" }, + { VCODE_OP_MAP_CONST }, + { VCODE_OP_RETURN }, + }; + + CHECK_BB(0); +} +END_TEST + Suite *get_lower_tests(void) { Suite *s = suite_create("lower"); @@ -6144,6 +6180,7 @@ Suite *get_lower_tests(void) tcase_add_test(tc, test_directmap5); tcase_add_test(tc, test_issue837); tcase_add_test(tc, test_directmap6); + tcase_add_test(tc, test_issue844); suite_add_tcase(s, tc); return s; -- 2.39.2