From 8aee9ba6da4db298198d9c3b40778baa14f76f35 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 8 Mar 2024 15:23:23 +0000 Subject: [PATCH] Fix crash when collapsing unconstrained port. Fixes #859 --- NEWS.md | 2 +- src/lower.c | 27 +++++++---- test/lower/issue859.vhd | 100 ++++++++++++++++++++++++++++++++++++++++ test/test_lower.c | 38 +++++++++++++++ 4 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 test/lower/issue859.vhd diff --git a/NEWS.md b/NEWS.md index fcc6e47e..b24522d1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -20,7 +20,7 @@ types with non-locally-static bounds (#851, #852). - The parameter for attributes with dimensions such as `'length(N)` may be any integer type when `--relaxed` is passed (#862). -- Resolved several other minor issues (#654, #854, #855, #863). +- Resolved several other minor issues (#654, #854, #855, #859, #863). ## Version 1.11.3 - 2024-02-04 - Fixed incorrect effective value when a signal has multiple sources due diff --git a/src/lower.c b/src/lower.c index 6bcc2b65..26a3e248 100644 --- a/src/lower.c +++ b/src/lower.c @@ -11957,31 +11957,40 @@ static void lower_direct_mapped_port(lower_unit_t *lu, driver_set_t *ds, lower_put_vcode_obj(port, var, lu); } + type_t field_type = port_type; + if (field != -1) { + tree_t f = type_field(port_type, field); + tree_t cons = type_constraint_for_field(port_type, f); + field_type = tree_type(cons ?: f); + } + vcode_reg_t bounds_reg = VCODE_INVALID_REG; - if (!type_const_bounds(port_type)) - bounds_reg = lower_get_type_bounds(lu, port_type); + if (!type_const_bounds(field_type)) + bounds_reg = lower_get_type_bounds(lu, field_type); if (type_is_array(type)) { vcode_reg_t locus = lower_debug_locus(map); - lower_check_array_sizes(lu, port_type, type, bounds_reg, src_reg, locus); + lower_check_array_sizes(lu, field_type, type, bounds_reg, src_reg, locus); } if (field != -1) { vcode_reg_t ptr_reg = emit_index(var, VCODE_INVALID_REG); vcode_reg_t field_reg = emit_record_ref(ptr_reg, field); - if (have_uarray_ptr(field_reg)) { - vcode_reg_t data_reg = lower_array_data(src_reg); - vcode_reg_t meta_reg = lower_rewrap(data_reg, bounds_reg); - emit_store_indirect(meta_reg, field_reg); - } + if (type_is_homogeneous(type)) + emit_store_indirect(src_reg, field_reg); else if (type_is_record(type)) emit_copy(field_reg, src_reg, VCODE_INVALID_REG); - else if (!type_is_homogeneous(type)) { + else if (!have_uarray_ptr(field_reg)) { vcode_reg_t data_reg = lower_array_data(src_reg); vcode_reg_t count_reg = lower_array_total_len(lu, type, bounds_reg); emit_copy(field_reg, data_reg, count_reg); } + else if (bounds_reg != VCODE_INVALID_REG) { + vcode_reg_t data_reg = lower_array_data(src_reg); + vcode_reg_t meta_reg = lower_rewrap(data_reg, bounds_reg); + emit_store_indirect(meta_reg, field_reg); + } else emit_store_indirect(src_reg, field_reg); } diff --git a/test/lower/issue859.vhd b/test/lower/issue859.vhd new file mode 100644 index 00000000..2650c834 --- /dev/null +++ b/test/lower/issue859.vhd @@ -0,0 +1,100 @@ +package model_pkg is + type t_axilite_rd_slave_in_if is record + araddr : bit_vector; + arvalid : bit; + rready : bit; + end record; + +end package model_pkg; + +use work.model_pkg.all; + +entity model is + port( + rd_port_in : in t_axilite_rd_slave_in_if(araddr(31 downto 0)) + ); +end entity model; + +architecture beh of model is +begin +end architecture beh; + +entity issue859 is +end entity; + +architecture tb of issue859 is + + -- AXI-Lite Interface signals + type t_axilite_write_address_channel is record + --DUT inputs + awaddr : bit_vector; + awvalid : bit; + awprot : bit_vector(2 downto 0); + --DUT outputs + awready : bit; + end record; + + type t_axilite_write_data_channel is record + --DUT inputs + wdata : bit_vector; + wstrb : bit_vector; + wvalid : bit; + --DUT outputs + wready : bit; + end record; + + type t_axilite_write_response_channel is record + --DUT inputs + bready : bit; + --DUT outputs + bresp : bit_vector(1 downto 0); + bvalid : bit; + end record; + + type t_axilite_read_address_channel is record + --DUT inputs + araddr : bit_vector; + arvalid : bit; + arprot : bit_vector(2 downto 0); + --DUT outputs + arready : bit; + end record; + + type t_axilite_read_data_channel is record + --DUT inputs + rready : bit; + --DUT outputs + rdata : bit_vector; + rresp : bit_vector(1 downto 0); + rvalid : bit; + end record; + + type t_axilite_if is record + write_address_channel : t_axilite_write_address_channel; + write_data_channel : t_axilite_write_data_channel; + write_response_channel : t_axilite_write_response_channel; + read_address_channel : t_axilite_read_address_channel; + read_data_channel : t_axilite_read_data_channel; + end record; + + constant C_ADDR_WIDTH_2 : natural := 32; + constant C_DATA_WIDTH_2 : natural := 64; + signal axilite_if_2 : t_axilite_if(write_address_channel(awaddr(31 downto 0)), + write_data_channel(wdata(63 downto 0), + wstrb(7 downto 0)), + read_address_channel(araddr(31 downto 0)), + read_data_channel(rdata(63 downto 0))); +begin + + i_model : entity work.model + port map( + rd_port_in.araddr => axilite_if_2.read_address_channel.araddr, + rd_port_in.arvalid => axilite_if_2.read_address_channel.arvalid, + rd_port_in.rready => axilite_if_2.read_data_channel.rready + ); + + p_main: process + begin + wait; + end process p_main; +end architecture; diff --git a/test/test_lower.c b/test/test_lower.c index 1188f971..f623427e 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -6130,6 +6130,43 @@ START_TEST(test_trigger1) } END_TEST +START_TEST(test_issue859) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/lower/issue859.vhd"); + + run_elab(); + + vcode_unit_t vu = find_unit("WORK.ISSUE859.I_MODEL"); + vcode_select_unit(vu); + + EXPECT_BB(0) = { + { VCODE_OP_PACKAGE_INIT, .name = "WORK.MODEL_PKG" }, + { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, + { VCODE_OP_VAR_UPREF, .hops = 1, .name = "AXILITE_IF_2" }, + { VCODE_OP_RECORD_REF, .field = 3 }, + { VCODE_OP_RECORD_REF, .field = 0 }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_RECORD_REF, .field = 1 }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_RECORD_REF, .field = 4 }, + { VCODE_OP_RECORD_REF, .field = 0 }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_INDEX, .name = "RD_PORT_IN" }, + { VCODE_OP_RECORD_REF, .field = 0 }, + { VCODE_OP_STORE_INDIRECT }, + { VCODE_OP_RECORD_REF, .field = 1 }, + { VCODE_OP_STORE_INDIRECT }, + { VCODE_OP_RECORD_REF, .field = 2 }, + { VCODE_OP_STORE_INDIRECT }, + { VCODE_OP_RETURN }, + }; + + CHECK_BB(0); +} +END_TEST + Suite *get_lower_tests(void) { Suite *s = suite_create("lower"); @@ -6275,6 +6312,7 @@ Suite *get_lower_tests(void) tcase_add_test(tc, test_directmap6); tcase_add_test(tc, test_issue844); tcase_add_test(tc, test_trigger1); + tcase_add_test(tc, test_issue859); suite_add_tcase(s, tc); return s; -- 2.39.2