From 5bde671869b71b854d0219480039ae11c49d04a2 Mon Sep 17 00:00:00 2001 From: Sebastian Abrahamsson Date: Wed, 14 Oct 2026 18:47:07 +0200 Subject: [PATCH 1/4] Report integer_array_t arguments made during elaboration as a failure An integer_array_t argument is transferred to Python when it is made, which the bridge library cannot do during elaboration: NVC aborted with "foreign function vpy_push_array not found" and GHDL with a CONSTRAINT_ERROR. Before test_runner_setup, p_stage_array now reports a failure naming the call instead. See #17. Co-Authored-By: Claude Opus 5.5 --- docs/types.rst | 7 +++- .../hdl/src/python_ffi_pkg_bridge.vhd | 12 ++++++ tests/run.py | 11 ++++++ tests/tb_elaboration_array.vhd | 38 +++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/tb_elaboration_array.vhd 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/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..ee01ff0 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,16 @@ package body python_ffi_pkg is variable offset, n : natural := 0; variable staged_id : integer; begin + -- The bridge library cannot be called during elaboration, see #17 + if get_phase = test_runner_entry then + failure( + python_logger, + operation & " failed:" & LF & + "An integer_array_t argument cannot be made before test_runner_setup, for example in a constant. " & + "Make it in a process after 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; From e9f93a837da6c36b2db5d5f5c8b73c890352b359 Mon Sep 17 00:00:00 2001 From: Sebastian Abrahamsson Date: Wed, 14 Oct 2026 18:50:41 +0200 Subject: [PATCH 2/4] Address review: shorter error, phase compared with < Co-Authored-By: Claude Opus 5.5 --- src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 ee01ff0..c027bc2 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 @@ -414,13 +414,11 @@ package body python_ffi_pkg is variable offset, n : natural := 0; variable staged_id : integer; begin - -- The bridge library cannot be called during elaboration, see #17 - if get_phase = test_runner_entry then + 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, for example in a constant. " & - "Make it in a process after test_runner_setup." + "An integer_array_t argument cannot be made before test_runner_setup, for example in a constant." ); return -1; end if; From 65e1ebbf93a3c4b43b01c4321ea897d20215506d Mon Sep 17 00:00:00 2001 From: Sebastian Abrahamsson Date: Wed, 14 Oct 2026 18:53:57 +0200 Subject: [PATCH 3/4] Address review: shorter error Co-Authored-By: Claude Opus 5.5 --- src/vunit_python_bridge/hdl/src/python_ffi_pkg_bridge.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c027bc2..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 @@ -418,7 +418,7 @@ package body python_ffi_pkg is failure( python_logger, operation & " failed:" & LF & - "An integer_array_t argument cannot be made before test_runner_setup, for example in a constant." + "An integer_array_t argument cannot be made before test_runner_setup." ); return -1; end if; From bbb9c360ab90cbda2eeccb29d4f2d7c77503c7c9 Mon Sep 17 00:00:00 2001 From: Sebastian Abrahamsson Date: Thu, 15 Oct 2026 17:08:35 +0200 Subject: [PATCH 4/4] Make the release note a news fragment Co-Authored-By: Claude Opus 5.5 --- release_notes/news.d/29.bugfix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 release_notes/news.d/29.bugfix.md 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.