Skip to content

Commit

Permalink
Relax library requirement on configurations
Browse files Browse the repository at this point in the history
VHDL-2019 feature
  • Loading branch information
nickg committed Aug 12, 2023
1 parent d417c79 commit d8bbc2a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 74 deletions.
1 change: 1 addition & 0 deletions src/diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ static const struct {
{ "Interface package declarations", { [STD_08] = "6.5.5" } },
{ "Selected names", { [STD_08] = "8.3", [STD_93] = "6.3" } },
{ "Simple variable assignments", { [STD_08] = "10.6.2" } },
{ "Configuration declarations", { [STD_08] = "3.4", [STD_93] = "1.4" } },
};

diag_t *diag_new(diag_level_t level, const loc_t *loc)
Expand Down
104 changes: 42 additions & 62 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,44 +494,6 @@ static tree_t error_expr(void)
return t;
}

static tree_t find_unit(const loc_t *where, ident_t name, const char *hint)
{
// TODO: should be able to replace this with resolve_name

ident_t lname = ident_until(name, '.');
lib_t lib = lib_loaded(lname);
if (lib != NULL) {
bool error;
tree_t unit = lib_get_allow_error(lib, name, &error);
if (unit == NULL) {
if (hint != NULL)
parse_error(where, "missing declaration for %s %s",
hint, istr(name));
else
parse_error(where, "cannot find unit %s", istr(name));
}
else if (error) {
parse_error(where, "design unit depends on %s which was analysed"
" with errors", istr(name));
suppress_errors(nametab);
return NULL;
}

return unit;
}
else if (name == error_marker())
return NULL;
else if (lname == name) {
parse_error(where, "%s does not name a visible component or design unit",
istr(name));
return NULL;
}
else {
parse_error(where, "missing library clause for %s", istr(lname));
return NULL;
}
}

static tree_t find_binding(tree_t inst)
{
ident_t name;
Expand Down Expand Up @@ -2578,14 +2540,14 @@ static void p_context_reference(tree_t unit)
tree_set_ident(c, name);
tree_set_loc(c, CURRENT_LOC);

tree_t ctx = find_unit(CURRENT_LOC, name, "context");
tree_t ctx = resolve_name(nametab, CURRENT_LOC, name);
if (ctx != NULL && tree_kind(ctx) == T_CONTEXT) {
insert_names_from_context(nametab, ctx);
tree_set_ref(c, ctx);
}
else if (ctx != NULL)
parse_error(CURRENT_LOC, "unit %s is not a context declaration",
istr(name));
parse_error(CURRENT_LOC, "%s%s is not a context declaration",
is_design_unit(ctx) ? "design unit " : "", istr(name));

tree_add_context(unit, c);
} while (optional(tCOMMA));
Expand Down Expand Up @@ -3195,7 +3157,7 @@ static tree_t p_selected_name(tree_t prefix, name_mask_t *mask)
const tree_kind_t kind = tree_kind(decl);
if (kind == T_LIBRARY) {
ident_t unit_name = ident_prefix(tree_ident(decl), suffix, '.');
tree_t unit = find_unit(CURRENT_LOC, unit_name, NULL);
tree_t unit = resolve_name(nametab, CURRENT_LOC, unit_name);
if (unit == NULL) {
tree_t dummy = tree_new(T_REF);
tree_set_ident(dummy, unit_name);
Expand Down Expand Up @@ -5304,7 +5266,7 @@ static void p_interface_package_declaration(tree_t parent, tree_kind_t kind)

ident_t unit_name = p_selected_identifier();

tree_t pack = find_unit(CURRENT_LOC, unit_name, "package");
tree_t pack = resolve_name(nametab, CURRENT_LOC, unit_name);
if (pack != NULL && !is_uninstantiated_package(pack)) {
parse_error(CURRENT_LOC, "unit %s is not an uninstantiated package",
istr(unit_name));
Expand Down Expand Up @@ -8699,7 +8661,7 @@ static tree_t p_block_configuration(tree_t of)
case T_ENTITY:
{
ident_t qual = ident_prefix(tree_ident(of), tree_ident(b), '-');
sub = find_unit(CURRENT_LOC, qual, NULL);
sub = resolve_name(nametab, CURRENT_LOC, qual);
}
break;
case T_ARCH:
Expand Down Expand Up @@ -8763,6 +8725,34 @@ static tree_t p_block_configuration(tree_t of)
return b;
}

static ident_t p_entity_name(tree_t *entity)
{
// name

BEGIN("entity name");

ident_t ename = p_selected_identifier();

ident_t qual = ename;
if (ident_runtil(ename, '.') == ename)
qual = ident_prefix(lib_name(lib_work()), ename, '.');

*entity = resolve_name(nametab, CURRENT_LOC, qual);

if (*entity != NULL && tree_kind(*entity) != T_ENTITY) {
diag_t *d = diag_new(DIAG_ERROR, CURRENT_LOC);
diag_printf(d, "%s%s is not an entity",
is_design_unit(*entity) ? "design unit " : "", istr(ename));
diag_hint(d, tree_loc(*entity), "%s is a %s", istr(ename),
class_str(class_of(*entity)));
diag_emit(d);
*entity = NULL;
return ename;
}

return ename;
}

static void p_configuration_declaration(tree_t unit)
{
// configuration identifier of name is configuration_declarative_part
Expand All @@ -8781,17 +8771,11 @@ static void p_configuration_declaration(tree_t unit)

consume(tOF);

ident_t ename = p_identifier();
ident_t qual = ident_prefix(lib_name(lib_work()), ename, '.');
tree_set_ident2(unit, qual);
tree_t of = NULL;
ident_t ename = p_entity_name(&of);
tree_set_ident2(unit, ename);

tree_t of = find_unit(CURRENT_LOC, qual, "entity");
if (of != NULL && tree_kind(of) != T_ENTITY) {
parse_error(CURRENT_LOC, "%s does not name an entity in library %s",
istr(ename), istr(lib_name(lib_work())));
of = NULL;
}
else if (of != NULL) {
if (of != NULL) {
tree_set_primary(unit, of);
insert_name(nametab, of, ename);
insert_decls(nametab, of);
Expand Down Expand Up @@ -12202,27 +12186,23 @@ static void p_architecture_body(tree_t unit)

consume(tOF);

ident_t entity_name = p_identifier();
tree_t e = NULL;
ident_t entity_name = p_entity_name(&e);
tree_set_ident2(unit, entity_name);

consume(tIS);

ident_t ename = ident_prefix(lib_name(lib_work()), entity_name, '.');
tree_t e = find_unit(CURRENT_LOC, ename, "entity");
if (e != NULL && tree_kind(e) == T_ENTITY) {
if (e != NULL) {
tree_set_primary(unit, e);
insert_names_from_context(nametab, e);
}
else if (e != NULL) {
parse_error(CURRENT_LOC, "unit %s is not an entity", istr(ename));
e = NULL;
}

push_scope(nametab);

if (entity_name != arch_name && e != NULL)
insert_name(nametab, e, entity_name);

ident_t ename = ident_prefix(lib_name(lib_work()), entity_name, '.');
ident_t qual = ident_prefix(ename, arch_name, '-');
scope_set_prefix(nametab, qual);

Expand Down
25 changes: 25 additions & 0 deletions src/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5543,6 +5543,31 @@ static bool sem_check_spec(tree_t t, nametab_t *tab)

static bool sem_check_configuration(tree_t t, nametab_t *tab)
{
if (!tree_has_primary(t))
return false; // Was parse error

tree_t of = tree_primary(t);

// LRM 08 section 3.4.1: for a configuration of a given design
// entity, both the configuration declaration and the corresponding
// entity declaration shall reside in the same library
ident_t elib = ident_until(tree_ident(of), '.');
if (standard() < STD_19 && elib != lib_name(lib_work())) {
diag_t *d = pedantic_diag(t);
if (d != NULL) {
ident_t ename = ident_rfrom(tree_ident(of), '.');
diag_printf(d, "configuration declaration %s must reside in the "
"same library as entity %s", istr(tree_ident(t)),
istr(ename));
diag_hint(d, NULL, "entity %s is in library %s which is not the same "
"as the current working library %s",
istr(ename), istr(elib), istr(lib_name(lib_work())));
diag_lrm(d, STD_08, "3.4");
diag_emit(d);
return false;
}
}

return true;
}

Expand Down
18 changes: 18 additions & 0 deletions test/sem/lcs2016_23.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- library foo
entity foo_e is
end entity;

architecture test of foo_e is
begin
end architecture;

-------------------------------------------------------------------------------
-- library bar

library foo;

configuration foo_cfg of foo.foo_e is
for test
end for;
end configuration;

2 changes: 1 addition & 1 deletion test/test_charset.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Suite *get_charset_tests(void)
TCase *tc = nvc_unit_test();
tcase_add_test(tc, test_iso88591);
tcase_add_test(tc, test_utf8);
tcase_add_loop_test(tc, test_strings, STD_93, STD_19);
tcase_add_loop_test(tc, test_strings, STD_93, STD_19 + 1);
suite_add_tcase(s, tc);

return s;
Expand Down
14 changes: 7 additions & 7 deletions test/test_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2892,7 +2892,7 @@ START_TEST(test_error)
{ 47, "S1 already declared in this region" },
{ 50, "B1 already declared in this region" },
{ 56, "C1 already declared in this region" },
{ 64, "missing declaration for entity WORK.NOT_HERE" },
{ 64, "design unit NOT_HERE not found in library WORK" },
{ -1, NULL }
};
expect_errors(expect);
Expand All @@ -2915,9 +2915,9 @@ START_TEST(test_config)

const error_t expect[] = {
{ 29, "no visible declaration for X" },
{ 38, "CONF does not name an entity in library WORK" },
{ 38, "design unit CONF is not an entity" },
{ 39, "no visible declaration for ARCH" },
{ 45, "cannot find unit WORK.ENT-BAD" },
{ 45, "design unit ENT-BAD not found in library WORK" },
{ 52, "P is not a block that can be configured" },
{ 55, "instance P not found" },
{ -1, NULL }
Expand Down Expand Up @@ -2953,7 +2953,7 @@ START_TEST(test_config)
fail_if(c == NULL);
fail_unless(tree_kind(c) == T_CONFIGURATION);
fail_unless(tree_ident(c) == ident_new("WORK.CONF"));
fail_unless(tree_ident2(c) == ident_new("WORK.ENT"));
fail_unless(tree_ident2(c) == ident_new("ENT"));
fail_unless(tree_decls(c) == 3);
fail_unless(tree_kind(tree_decl(c, 0)) == T_USE);
fail_unless(tree_kind(tree_decl(c, 1)) == T_ATTR_SPEC);
Expand Down Expand Up @@ -3578,7 +3578,7 @@ START_TEST(test_error2)
{ 2, "no visible declaration for BAR" },
{ 5, "no visible declaration for SDFF" },
{ 10, "no visible declaration for SGHBBX" },
{ 17, "cannot find unit STD.NOTHERE" },
{ 17, "design unit NOTHERE not found in library STD" },
{ 22, "unexpected identifier while parsing range" },
{ 29, "expected physical type definition trailing" },
{ 33, "expected record type definition trailing identifier" },
Expand Down Expand Up @@ -3931,7 +3931,7 @@ START_TEST(test_badprimary)
input_from_file(TESTDIR "/parse/badprimary.vhd");

const error_t expect[] = {
{ 17, "missing declaration for entity WORK.NOT_HERE" },
{ 17, "design unit NOT_HERE not found in library WORK" },
{ 26, "depends on WORK.NOT_HERE-BAD which was analysed with errors" },
{ -1, NULL }
};
Expand Down Expand Up @@ -4603,7 +4603,7 @@ START_TEST(test_issue468)
input_from_file(TESTDIR "/parse/issue468.vhd");

const error_t expect[] = {
{ 2, "cannot find unit WORK.TEST3" },
{ 2, "design unit TEST3 not found in library WORK" },
{ -1, NULL }
};
expect_errors(expect);
Expand Down
37 changes: 34 additions & 3 deletions test/test_sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ START_TEST(test_entity)
const error_t expect[] = {
{ 23, "design unit E-INVALID not found in library WORK" },
{ 26, "design unit WORK.PACK is not an entity" },
{ 30, "unit WORK.PACK is not an entity" },
{ 30, "design unit PACK is not an entity" },
{ 61, "signal assignment statement not allowed inside passive process" },
{ -1, NULL }
};
Expand Down Expand Up @@ -1565,8 +1565,8 @@ START_TEST(test_context)
input_from_file(TESTDIR "/sem/context.vhd");

const error_t expect[] = {
{ 27, "unit FOO.PACK is not a context declaration" },
{ 42, "missing declaration for context WORK.BLAH" },
{ 27, "no visible declaration for FOO.PACK" },
{ 42, "design unit BLAH not found in library WORK" },
{ 40, "library clause in a context declaration may not have logical" },
{ 41, "context declaration use clause may not have WORK" },
{ 42, "context declaration context reference may not have WORK" },
Expand Down Expand Up @@ -3172,6 +3172,36 @@ START_TEST(test_lcs2016_07)
}
END_TEST

START_TEST(test_lcs2016_23)
{
set_standard(_i);

input_from_file(TESTDIR "/sem/lcs2016_23.vhd");

const error_t expect[] = {
{ 14, "configuration declaration FOO_CFG must reside in the same "
"library as entity FOO_E" },
{ -1, NULL }
};
expect_errors(expect);

lib_t foo = lib_tmp("foo");
lib_set_work(foo);

parse_and_check(T_ENTITY, T_ARCH, -1);

lib_t bar = lib_tmp("bar");
lib_set_work(bar);

parse_and_check(T_CONFIGURATION);

if (_i < STD_19)
check_expected_errors();
else
fail_if_errors();
}
END_TEST

Suite *get_sem_tests(void)
{
Suite *s = suite_create("sem");
Expand Down Expand Up @@ -3326,6 +3356,7 @@ Suite *get_sem_tests(void)
tcase_add_test(tc_core, test_lcs2016_14a);
tcase_add_test(tc_core, test_lcs2016_19);
tcase_add_test(tc_core, test_lcs2016_07);
tcase_add_loop_test(tc_core, test_lcs2016_23, STD_08, STD_19 + 1);
suite_add_tcase(s, tc_core);

return s;
Expand Down
2 changes: 1 addition & 1 deletion www/features.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ table below.
<td><a href="http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/LCS2016_023">
LCS2016-023</td>
<td>Relax library requirement on configurations</td>
<td class="feature-missing"></td>
<td class="feature-done">master</td>
</tr>
<tr>
<td><a href="http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/LCS2016_026c">
Expand Down

0 comments on commit d8bbc2a

Please sign in to comment.