From 3bf2ff2f9e012e02b0757a8c995bd4f3303c9da6 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 15 Jan 2024 21:17:45 +0000 Subject: [PATCH] Fix crash when generic default value depends on another generic Fixes #831 --- src/elab.c | 17 +++++- src/simp.c | 18 +++--- test/regress/issue831.vhd | 114 ++++++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 4 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 test/regress/issue831.vhd diff --git a/src/elab.c b/src/elab.c index 2c56b39f..3bc477da 100644 --- a/src/elab.c +++ b/src/elab.c @@ -986,6 +986,20 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, } break; + case T_OPEN: + // Make sure the default value comes from the component + // declaration rather than the entity + // XXX: if we followed LRM 93 section 9.6.1 correctly this + // wouldn't be necessary + if (tree_kind(comp) == T_COMPONENT && tree_has_value(cg)) { + map = tree_new(T_PARAM); + tree_set_loc(map, tree_loc(cg)); + tree_set_subkind(map, P_POS); + tree_set_pos(map, tree_pos(map)); + tree_set_value(map, tree_value(cg)); + } + break; + default: break; } @@ -1767,7 +1781,8 @@ static void elab_top_level_generics(tree_t arch, elab_ctx_t *ctx) tree_add_generic(ctx->out, g); tree_add_genmap(ctx->out, map); - hash_put(ctx->generics, g, value); + if (is_literal(value)) + hash_put(ctx->generics, g, value); } } diff --git a/src/simp.c b/src/simp.c index 3eed61d7..fbf88a95 100644 --- a/src/simp.c +++ b/src/simp.c @@ -1501,14 +1501,18 @@ static void simp_generic_map(tree_t t, tree_t unit) } } + if (value == NULL && kind != T_BINDING && tree_has_value(g)) { + // If the default value is a non-literal expression we may get + // the wrong result during elaboration of a recursive instantiation + tree_t def = tree_value(g); + if (is_literal(def)) + value = def; + } + if (value == NULL) { - if (kind == T_BINDING || !tree_has_value(g)) { - value = tree_new(T_OPEN); - tree_set_loc(value, tree_loc(t)); - tree_set_type(value, tree_type(g)); - } - else - value = tree_value(g); + value = tree_new(T_OPEN); + tree_set_loc(value, tree_loc(t)); + tree_set_type(value, tree_type(g)); } APUSH(values, value); diff --git a/test/regress/issue831.vhd b/test/regress/issue831.vhd new file mode 100644 index 00000000..fd8b3cbb --- /dev/null +++ b/test/regress/issue831.vhd @@ -0,0 +1,114 @@ +-- fft_types -------------------------------------------------------------------------- +library ieee; +use ieee.math_complex.all; +use std.textio.all; + +package fft_types is + subtype fft_data_type is complex; + type fft_data_vector is array (natural range <>) of fft_data_type; + pure function "+" (a, b : fft_data_vector) return fft_data_vector; + pure function "*" (a, b : fft_data_vector) return fft_data_vector; +end package fft_types; + +package body fft_types is + pure function "+" (a, b : fft_data_vector) return fft_data_vector is + variable res : fft_data_vector (a'range); + begin + for i in a'range loop + res(i) := a(i) + b(i); + end loop; + return res; + end function; + + pure function "*" (a, b : fft_data_vector) return fft_data_vector is + variable res : fft_data_vector (a'range); + begin + for i in a'range loop + res(i) := a(i) * b(i); + end loop; + return res; + end function; +end package body fft_types; + +-- fft -------------------------------------------------------------------------------- +library ieee; +use ieee.math_complex.all; +use work.fft_types.all; + +entity fft is + generic ( + POW : natural := 4; + DIM : positive := 2**POW); + port ( + x, w : in fft_data_vector (0 to DIM-1); + y : out fft_data_vector (0 to DIM-1) := (others => fft_data_type'(0.0,0.0))); +end entity fft; + +architecture recursive of fft is + subtype half_array is fft_data_vector (0 to DIM/2-1); + signal even, odd, x_e, x_o, w_e : half_array := (others => fft_data_type'(0.0,0.0)); + alias w_b : half_array is w(0 to DIM/2-1); + alias w_t : half_array is w(DIM/2 to DIM-1); +begin + stage : + if base_case: POW = 1 generate + y(0) <= x(0) + x(1); + y(1) <= x(0) - x(1); + else general_case: generate + split_even_odd : + for i in half_array'range generate + x_e(i) <= x(2*i); + x_o(i) <= x(2*i+1); + w_e(i) <= w(2*i); + end generate; + + even_fft : + entity fft + generic map ( + POW => POW-1) + port map ( + x => x_e, w => w_e, y => even); + + odd_fft : + entity fft + generic map ( + POW => POW-1) + port map ( + x => x_o, w => w_e, y => odd); + + y(0 to DIM/2-1) <= even + odd*w_b; + y(DIM/2 to DIM-1) <= even + odd*w_t; + end generate stage; +end architecture recursive; + +------------------------------------------------------------------------------- + +use work.fft_types.all; + +entity issue831 is + generic ( + POW : natural := 4; + DIM : positive := 2**POW); +end entity; + +architecture test of issue831 is + signal x, w, y : fft_data_vector(0 to DIM-1); +begin + + u: entity work.fft + port map ( x, w, y ); + + check: process is + begin + x <= (others => fft_data_type'(0.0,0.0)); + w <= (others => fft_data_type'(0.0,0.0)); + wait for 1 ns; + assert y(0).re = 0.0 report to_string(y(0).re); + x <= (others => fft_data_type'(1.0,0.0)); + w <= (others => fft_data_type'(0.0,1.0)); + wait for 1 ns; + assert y(0).re = -4.0 report to_string(y(0).re); + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index b26477b2..6c0fe0ee 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -922,3 +922,4 @@ issue825 normal issue826 normal,2008 issue827 normal,2008 cover22 shell +issue831 normal,2008 -- 2.39.2