Skip to content

Commit

Permalink
Inferring constraints from initial values for signals and variables
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jun 29, 2023
1 parent da95d97 commit 8cb57b6
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 15 deletions.
18 changes: 16 additions & 2 deletions src/lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -7497,11 +7497,19 @@ static void lower_sub_signals(lower_unit_t *lu, type_t type, type_t var_type,
field_reg = emit_load_indirect(field_reg);
}

vcode_reg_t fbounds_reg = VCODE_INVALID_REG;
if (bounds_reg != VCODE_INVALID_REG) {
fbounds_reg = emit_record_ref(bounds_reg, i);

if (have_uarray_ptr(fbounds_reg))
fbounds_reg = emit_load_indirect(fbounds_reg);
}

vcode_reg_t ptr_reg = emit_record_ref(sig_ptr, i);

lower_sub_signals(lu, et, ft, ft, f, fview, VCODE_INVALID_VAR, ptr_reg,
field_reg, resolution, null_field_reg, newflags,
VCODE_INVALID_REG);
fbounds_reg);
}

emit_pop_scope();
Expand All @@ -7526,13 +7534,19 @@ static void lower_signal_decl(lower_unit_t *lu, tree_t decl)
init_reg = lower_known_subtype(lu, value, type, VCODE_INVALID_REG);
}

vcode_reg_t bounds_reg = VCODE_INVALID_REG;
if (standard() >= STD_19 && type_is_unconstrained(type)) {
type = value_type;
bounds_reg = init_reg;
}

sig_flags_t flags = 0;
if (tree_flags(decl) & TREE_F_REGISTER)
flags |= NET_F_REGISTER;

lower_sub_signals(lu, type, type, value_type, decl, NULL, var,
VCODE_INVALID_REG, init_reg, VCODE_INVALID_REG,
VCODE_INVALID_REG, flags, VCODE_INVALID_REG);
VCODE_INVALID_REG, flags, bounds_reg);

if (cover_enabled(lu->cover, COVER_MASK_TOGGLE))
lower_toggle_coverage(lu, decl);
Expand Down
46 changes: 34 additions & 12 deletions src/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,12 +981,23 @@ static bool sem_check_signal_decl(tree_t t, nametab_t *tab)
return false;

if (type_is_unconstrained(type)) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of signal %s cannot have unconstrained "
"type %s", istr(tree_ident(t)), type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
if (standard() < STD_19) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of signal %s cannot have unconstrained "
"type %s", istr(tree_ident(t)), type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
}
else if (!tree_has_value(t)) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of signal %s without an initial value "
"cannot have unconstrained type %s",
istr(tree_ident(t)), type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
}
}
else if (type_is_incomplete(type))
sem_error(t, "declaration of signal %s cannot have incomplete type %s",
Expand Down Expand Up @@ -1022,12 +1033,23 @@ static bool sem_check_var_decl(tree_t t, nametab_t *tab)
return false;

if (type_is_unconstrained(type)) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of variable %s cannot have unconstrained "
"type %s", istr(tree_ident(t)), type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
if (standard() < STD_19) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of variable %s cannot have unconstrained "
"type %s", istr(tree_ident(t)), type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
}
else if (!tree_has_value(t)) {
diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
diag_printf(d, "declaration of variable %s without an initial value "
"cannot have unconstrained type %s", istr(tree_ident(t)),
type_pp(type));
sem_unconstrained_decl_hint(d, type);
diag_emit(d);
return false;
}
}
else if (type_is_incomplete(type))
sem_error(t, "declaration of variable %s cannot have incomplete type %s",
Expand Down
40 changes: 40 additions & 0 deletions test/regress/signal32.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- LCS 2016-019
entity signal32 is
end entity;

architecture test of signal32 is
type rec_t is record
x : integer_vector;
end record;

function get_rec return rec_t is
begin
return (x => (5, 6));
end function;

signal s1 : integer_vector := (1, 2, 3);
signal s2 : rec_t := get_rec;
begin

p1: process is
variable v1 : integer_vector := (1, 2, 3);
variable v2 : rec_t := get_rec;
begin
assert s1'length = 3;
assert s1'left = 0;
assert s1(1) = 2;
s1(2) <= 5;
wait for 1 ns;
assert s1 = (1, 2, 5);
assert v1'length = 3;
assert v1(2) = 3;
assert s2.x'length = 2;
assert s2.x = (5, 6);
assert v2.x'length = 2;
assert v2.x = (5, 6);
v2.x(1) := 9;
assert v2.x = (5, 9);
wait;
end process;

end architecture;
1 change: 1 addition & 0 deletions test/regress/testlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -812,3 +812,4 @@ issue724 normal,2019
issue653 normal,2008
protected10 normal,2019
reflect1 normal,2019
signal32 normal,2019
16 changes: 16 additions & 0 deletions test/sem/lcs2016_19.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
entity lcs2016_19 is
end entity;

architecture test of lcs2016_19 is
signal s1 : integer_vector := (1, 2, 3); -- OK
signal s2 : integer_vector; -- Error
begin

p1: process is
variable v1 : integer_vector := (1, 2, 3); -- OK
variable v2 : integer_vector; -- Error
begin
wait;
end process;

end architecture;
22 changes: 22 additions & 0 deletions test/test_sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -3209,6 +3209,27 @@ START_TEST(test_lcs2016_14a)
}
END_TEST

START_TEST(test_lcs2016_19)
{
set_standard(STD_19);

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

const error_t expect[] = {
{ 6, "declaration of signal S2 without an initial value cannot "
"have unconstrained type INTEGER_VECTOR" },
{ 11, "declaration of variable V2 without an initial value cannot "
"have unconstrained type INTEGER_VECTOR" },
{ -1, NULL }
};
expect_errors(expect);

parse_and_check(T_ENTITY, T_ARCH);

check_expected_errors();
}
END_TEST

Suite *get_sem_tests(void)
{
Suite *s = suite_create("sem");
Expand Down Expand Up @@ -3361,6 +3382,7 @@ Suite *get_sem_tests(void)
tcase_add_test(tc_core, test_issue713);
tcase_add_test(tc_core, test_lcs2016_41);
tcase_add_test(tc_core, test_lcs2016_14a);
tcase_add_test(tc_core, test_lcs2016_19);
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 @@ -238,7 +238,7 @@ table below.
<td><a href="http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/LCS2016_019">
LCS2016-019</td>
<td>Inferring constraints from initial values for signals and variables</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_023">
Expand Down

0 comments on commit 8cb57b6

Please sign in to comment.