diff --git a/docs/types.rst b/docs/types.rst index 165b2ee..1bd7d0e 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -37,8 +37,11 @@ integer_array_t and NumPy An ``integer_array_t`` argument is transferred to Python and referred to by the expression as a NumPy array of dtype ``int32``, so it can be reused in -several calls. It is indexed like VUnit, so that elements correspond -directly: +several calls. Since it is transferred when the argument is made, the +argument must be made after ``test_runner_setup``, not during elaboration, for +example in a constant. Otherwise ``arg`` and ``kwarg`` report a failure, see +`#17 `__. It is +indexed like VUnit, so that elements correspond directly: ============= ================================ =========================== Array VHDL Python diff --git a/release_notes/news.d/29.bugfix.md b/release_notes/news.d/29.bugfix.md new file mode 100644 index 0000000..981f56c --- /dev/null +++ b/release_notes/news.d/29.bugfix.md @@ -0,0 +1 @@ +An `integer_array_t` argument made before `test_runner_setup`, for example in a constant during elaboration, is reported as a failure naming the call, instead of crashing the simulator (NVC: "foreign function vpy_push_array not found", GHDL: CONSTRAINT_ERROR). See #17. diff --git a/src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd b/src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd index 3b2e491..ab9260d 100644 --- a/src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd +++ b/src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd @@ -26,6 +26,8 @@ use vunit_lib.id_pkg.all; use vunit_lib.integer_array_pkg.all; use vunit_lib.integer_vector_ptr_pkg.all; use vunit_lib.logger_pkg.all; +use vunit_lib.run_pkg.get_phase; +use vunit_lib.run_types_pkg.all; use work.python_bridge_pkg.all; package python_ffi_pkg is @@ -412,6 +414,14 @@ package body python_ffi_pkg is variable offset, n : natural := 0; variable staged_id : integer; begin + if get_phase < test_runner_setup then + failure( + python_logger, + operation & " failed:" & LF & + "An integer_array_t argument cannot be made before test_runner_setup." + ); + return -1; + end if; if not p_succeeded( vpy_push_array(len, width(arr), height(arr), depth(arr), bit_width(arr), boolean'pos(is_signed(arr))), operation diff --git a/tests/run.py b/tests/run.py index a6ffc9d..9307061 100644 --- a/tests/run.py +++ b/tests/run.py @@ -39,6 +39,10 @@ "lib.tb_python_pkg.Test eval of real with underflow from C to VHDL", ] +# Fails during elaboration, with this error rather than a crash, see #17 +ELABORATION_ARRAY_TEST = "lib.tb_elaboration_array.all" +ELABORATION_ARRAY_ERROR = "An integer_array_t argument cannot be made before test_runner_setup" + # Simulators where python_pkg is implemented by the VUnit Python bridge BRIDGE_SIMULATORS = ["nvc", "ghdl", "modelsim"] @@ -67,6 +71,11 @@ def verify(results, expected_failures): if missing: raise RuntimeError("Tests expected to fail but did not:\n" + "\n".join(missing)) + if ELABORATION_ARRAY_TEST in expected and ELABORATION_ARRAY_ERROR not in ( + tests[ELABORATION_ARRAY_TEST].path / "output.txt" + ).read_text(encoding="utf-8"): + raise RuntimeError(f"{ELABORATION_ARRAY_TEST} failed without the error: {ELABORATION_ARRAY_ERROR}") + if expected: print(f"Verified {len(expected)} expected failures: {', '.join(name.split('.')[-1] for name in expected)}") @@ -113,6 +122,8 @@ def main(): if simulator_name in BRIDGE_SIMULATORS: # The operations implemented by the Python bridge lib.add_source_file(ROOT / "tb_python_pkg_bridge.vhd") + lib.add_source_file(ROOT / "tb_elaboration_array.vhd") + expected_failures.append(ELABORATION_ARRAY_TEST) vu.set_compile_option("rivierapro.vcom_flags", ["-dbg"]) vu.set_sim_option("rivierapro.vsim_flags", ["-interceptcoutput"]) diff --git a/tests/tb_elaboration_array.vhd b/tests/tb_elaboration_array.vhd new file mode 100644 index 0000000..d5deae4 --- /dev/null +++ b/tests/tb_elaboration_array.vhd @@ -0,0 +1,38 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this file, +-- You can obtain one at http://mozilla.org/MPL/2.0/. +-- +-- Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com +-- +-- An integer_array_t argument made during elaboration must fail with a clear +-- error, not crash the simulator, see #17. tests/run.py expects it to fail +-- and checks the error. + +library vunit_lib; +context vunit_lib.vunit_context; +library python_bridge; +context python_bridge.python_context; + +entity tb_elaboration_array is + generic(runner_cfg : string); +end entity; + +architecture tb of tb_elaboration_array is + impure function one_to_four return integer_array_t is + variable values : integer_array_t := new_1d(4); + begin + for idx in 0 to 3 loop + set(values, idx, idx + 1); + end loop; + return values; + end; + + constant values_arg : arg_t := arg(one_to_four); +begin + main : process + begin + test_runner_setup(runner, runner_cfg); + check_equal(integer'(call("sum", values_arg)), 10); + test_runner_cleanup(runner); + end process; +end architecture;