From 273d7c7e892922de2fd0724c48eb8c0793cf4953 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 4 Nov 2024 11:39:35 +0100 Subject: [PATCH 1/6] Fixed linting related to too many positional arguments --- tools/doc_support.py | 1 + vunit/cached.py | 2 +- vunit/configuration.py | 2 ++ vunit/design_unit.py | 3 ++- vunit/parsing/verilog/parser.py | 1 + vunit/parsing/verilog/preprocess.py | 8 +++++--- vunit/project.py | 1 + vunit/sim_if/ghdl.py | 12 ++++++++---- vunit/sim_if/incisive.py | 2 +- vunit/sim_if/nvc.py | 11 +++++++---- vunit/source_file.py | 12 +++++++++--- vunit/test/bench.py | 11 ++++++++++- vunit/test/runner.py | 11 ++++++++--- vunit/test/suites.py | 2 +- vunit/ui/__init__.py | 4 ++-- vunit/ui/library.py | 4 ++-- vunit/ui/test.py | 2 +- vunit/ui/testbench.py | 2 +- vunit/vhdl_parser.py | 1 + 19 files changed, 64 insertions(+), 28 deletions(-) diff --git a/tools/doc_support.py b/tools/doc_support.py index e8a9a289c..34b654797 100644 --- a/tools/doc_support.py +++ b/tools/doc_support.py @@ -66,6 +66,7 @@ def highlight_code( code_path, output_path, snippet_name=None, + *, line_no_offset=None, functions=None, types=None, diff --git a/vunit/cached.py b/vunit/cached.py index 5ec9874cd..e5b26eceb 100644 --- a/vunit/cached.py +++ b/vunit/cached.py @@ -13,7 +13,7 @@ from vunit.ostools import read_file -def cached(key, function, file_name, encoding, database=None, newline=None): +def cached(key, function, file_name, encoding, *, database=None, newline=None): """ Call function with file content if an update is needed """ diff --git a/vunit/configuration.py b/vunit/configuration.py index ff6724c32..9fff0d9a2 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -34,6 +34,7 @@ def __init__( # pylint: disable=too-many-arguments self, name, design_unit, + *, generics=None, sim_options=None, pre_config=None, @@ -282,6 +283,7 @@ def _check_architectures(design_unit): def add_config( # pylint: disable=too-many-arguments self, name, + *, generics=None, pre_config=None, post_check=None, diff --git a/vunit/design_unit.py b/vunit/design_unit.py index 870b12e61..928007cc0 100644 --- a/vunit/design_unit.py +++ b/vunit/design_unit.py @@ -52,6 +52,7 @@ def __init__( name, source_file, unit_type, + *, is_primary=True, primary_design_unit=None, ): @@ -66,7 +67,7 @@ class Entity(VHDLDesignUnit): """ def __init__(self, name, source_file, generic_names=None): - VHDLDesignUnit.__init__(self, name, source_file, "entity", True) + VHDLDesignUnit.__init__(self, name, source_file, "entity", is_primary=True) self.generic_names = [] if generic_names is None else generic_names self._add_architecture_callback = None self._architecture_names = {} diff --git a/vunit/parsing/verilog/parser.py b/vunit/parsing/verilog/parser.py index a8c73e3cd..f071f4004 100644 --- a/vunit/parsing/verilog/parser.py +++ b/vunit/parsing/verilog/parser.py @@ -164,6 +164,7 @@ class VerilogDesignFile(object): def __init__( # pylint: disable=too-many-arguments self, + *, modules=None, packages=None, imports=None, diff --git a/vunit/parsing/verilog/preprocess.py b/vunit/parsing/verilog/preprocess.py index ebff7ac79..dfbefff94 100644 --- a/vunit/parsing/verilog/preprocess.py +++ b/vunit/parsing/verilog/preprocess.py @@ -81,7 +81,7 @@ def _preprocess(self, tokens, defines=None, include_paths=None, included_files=N return result - def preprocessor( # pylint: disable=too-many-arguments,too-many-branches + def preprocessor( # pylint: disable=too-many-arguments,too-many-branches,too-many-positional-arguments self, token, stream, defines, include_paths, included_files ): """ @@ -162,7 +162,7 @@ def _skip_protected_region(stream): if token.value == "end_protected": return - def expand_macro( # pylint: disable=too-many-arguments + def expand_macro( # pylint: disable=too-many-arguments,too-many-positional-arguments self, macro_token, stream, defines, include_paths, included_files ): """ @@ -254,7 +254,9 @@ def determine_if_taken(if_token, arg): stream.skip_while(NEWLINE) return result - def include(self, token, stream, include_paths, included_files, defines): # pylint: disable=too-many-arguments + def include( + self, token, stream, include_paths, included_files, defines + ): # pylint: disable=too-many-arguments,too-many-positional-arguments """ Handle `include directive """ diff --git a/vunit/project.py b/vunit/project.py index c9bc4f14c..726869f4c 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -113,6 +113,7 @@ def add_source_file( # pylint: disable=too-many-arguments self, file_name, library_name, + *, file_type="vhdl", include_dirs=None, defines=None, diff --git a/vunit/sim_if/ghdl.py b/vunit/sim_if/ghdl.py index 6a6b3ca7d..4814fdb8d 100644 --- a/vunit/sim_if/ghdl.py +++ b/vunit/sim_if/ghdl.py @@ -93,6 +93,7 @@ def __init__( # pylint: disable=too-many-arguments self, output_path, prefix, + *, gui=False, viewer_fmt=None, viewer_args="", @@ -286,7 +287,7 @@ def compile_vhdl_file_command(self, source_file): def _get_command( self, config, output_path, elaborate_only, ghdl_e, test_suite_name, wave_file - ): # pylint: disable=too-many-branches,too-many-arguments + ): # pylint: disable=too-many-branches,too-many-arguments,too-many-positional-arguments """ Return GHDL simulation command """ @@ -392,9 +393,12 @@ def simulate(self, output_path, test_suite_name, config, elaborate_only): # pyl status = False if config.sim_options.get(self.name + ".gtkwave_script.gui", None): - LOGGER.warning("%s.gtkwave_script.gui is deprecated and will be removed " - "in a future version, use %s.viewer_script.gui instead", - self.name, self.name) + LOGGER.warning( + "%s.gtkwave_script.gui is deprecated and will be removed " + "in a future version, use %s.viewer_script.gui instead", + self.name, + self.name, + ) if self._gui and not elaborate_only: cmd = [self._get_viewer(config)] + shlex.split(self._viewer_args) + [data_file_name] diff --git a/vunit/sim_if/incisive.py b/vunit/sim_if/incisive.py index f4b829300..dabc438d5 100644 --- a/vunit/sim_if/incisive.py +++ b/vunit/sim_if/incisive.py @@ -84,7 +84,7 @@ def supports_vhdl_contexts(): return False def __init__( # pylint: disable=too-many-arguments - self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None + self, prefix, output_path, *, gui=False, log_level=None, cdslib=None, hdlvar=None ): SimulatorInterface.__init__(self, output_path, gui) self._prefix = prefix diff --git a/vunit/sim_if/nvc.py b/vunit/sim_if/nvc.py index 082c720e1..724913935 100644 --- a/vunit/sim_if/nvc.py +++ b/vunit/sim_if/nvc.py @@ -74,7 +74,7 @@ def find_prefix_from_path(cls): return cls.find_toolchain([cls.executable]) def __init__( # pylint: disable=too-many-arguments - self, output_path, prefix, num_threads, gui=False, viewer_fmt=None, viewer_args="", viewer=None + self, output_path, prefix, *, num_threads, gui=False, viewer_fmt=None, viewer_args="", viewer=None ): SimulatorInterface.__init__(self, output_path, gui) if viewer_fmt == "ghw": @@ -305,9 +305,12 @@ def simulate( status = False if config.sim_options.get(self.name + ".gtkwave_script.gui", None): - LOGGER.warning("%s.gtkwave_script.gui is deprecated and will be removed " - "in a future version, use %s.viewer_script.gui instead", - self.name, self.name) + LOGGER.warning( + "%s.gtkwave_script.gui is deprecated and will be removed " + "in a future version, use %s.viewer_script.gui instead", + self.name, + self.name, + ) if self._gui and not elaborate_only: cmd = [self._get_viewer(config)] + shlex.split(self._viewer_args) + [str(wave_file)] diff --git a/vunit/source_file.py b/vunit/source_file.py index 85265e7dc..75ddea0f1 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -129,6 +129,7 @@ def __init__( # pylint: disable=too-many-arguments file_type, name, library, + *, verilog_parser, database, include_dirs=None, @@ -206,6 +207,7 @@ def __init__( # pylint: disable=too-many-arguments self, name: Union[str, Path], library: Library, + *, vhdl_parser, database, vhdl_standard: VHDLStandard, @@ -311,8 +313,8 @@ def _find_design_units(self, design_file): architecture.identifier, self, "architecture", - False, - architecture.entity, + is_primary=False, + primary_design_unit=architecture.entity, ) ) @@ -320,7 +322,11 @@ def _find_design_units(self, design_file): result.append(VHDLDesignUnit(configuration.identifier, self, "configuration")) for body in design_file.package_bodies: - result.append(VHDLDesignUnit(body.identifier, self, "package body", False, body.identifier)) + result.append( + VHDLDesignUnit( + body.identifier, self, "package body", is_primary=False, primary_design_unit=body.identifier + ) + ) return result diff --git a/vunit/test/bench.py b/vunit/test/bench.py index e90a031a5..004df5c1b 100644 --- a/vunit/test/bench.py +++ b/vunit/test/bench.py @@ -229,6 +229,7 @@ def set_attribute(self, name, value): def add_config( # pylint: disable=too-many-arguments self, name, + *, generics=None, pre_config=None, post_check=None, @@ -257,7 +258,15 @@ def add_config( # pylint: disable=too-many-arguments self._individual_tests = not run_all_in_same_sim and len(self._test_cases) > 0 del attributes["run_all_in_same_sim"] - super().add_config(name, generics, pre_config, post_check, sim_options, attributes, vhdl_configuration_name) + super().add_config( + name, + generics=generics, + pre_config=pre_config, + post_check=post_check, + sim_options=sim_options, + attributes=attributes, + vhdl_configuration_name=vhdl_configuration_name, + ) class FileLocation(object): diff --git a/vunit/test/runner.py b/vunit/test/runner.py index 32b4a3950..00bc47446 100644 --- a/vunit/test/runner.py +++ b/vunit/test/runner.py @@ -39,6 +39,7 @@ def __init__( # pylint: disable=too-many-arguments self, report, output_path, + *, verbosity=VERBOSITY_NORMAL, num_threads=1, fail_fast=False, @@ -193,7 +194,9 @@ def _get_output_path(self, test_suite_name): return str(Path(output_path) / full_name) - def _add_skipped_tests(self, test_suite, results, start_time, num_tests, output_file_name): + def _add_skipped_tests( + self, test_suite, results, start_time, num_tests, output_file_name + ): # pylint: disable=too-many-positional-arguments """ Add skipped tests """ @@ -203,7 +206,7 @@ def _add_skipped_tests(self, test_suite, results, start_time, num_tests, output_ def _run_test_suite( # pylint: disable=too-many-locals self, test_suite, write_stdout, num_tests, output_path, output_file_name - ): + ): # pylint: disable=too-many-positional-arguments """ Run the actual test suite """ @@ -313,7 +316,9 @@ def _print_output(self, output_file_name): for line in fread.readlines(): self._stdout_ansi.write(line) - def _add_results(self, test_suite, results, start_time, num_tests, output_file_name): + def _add_results( + self, test_suite, results, start_time, num_tests, output_file_name + ): # pylint: disable=too-many-positional-arguments """ Add results to test report """ diff --git a/vunit/test/suites.py b/vunit/test/suites.py index 9f63ac4c2..b1c0c928d 100644 --- a/vunit/test/suites.py +++ b/vunit/test/suites.py @@ -149,7 +149,7 @@ class TestRun(object): A single simulation run yielding the results for one or several test cases """ - def __init__(self, simulator_if, config, elaborate_only, test_suite_name, test_cases): + def __init__(self, *, simulator_if, config, elaborate_only, test_suite_name, test_cases): self._simulator_if = simulator_if self._config = config self._elaborate_only = elaborate_only diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 3ddc531e3..ad8ccd413 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -518,7 +518,7 @@ def get_source_files( return SourceFileList(results) - def add_source_files( # pylint: disable=too-many-arguments + def add_source_files( # pylint: disable=too-many-arguments,too-many-positional-arguments self, pattern, library_name: str, @@ -563,7 +563,7 @@ def add_source_files( # pylint: disable=too-many-arguments file_type=file_type, ) - def add_source_file( # pylint: disable=too-many-arguments + def add_source_file( # pylint: disable=too-many-arguments,too-many-positional-arguments self, file_name: Union[str, Path], library_name: str, diff --git a/vunit/ui/library.py b/vunit/ui/library.py index 475a4c237..42047e295 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -329,7 +329,7 @@ def get_source_files(self, pattern="*", allow_empty=False): """ return self._parent.get_source_files(pattern, self._library_name, allow_empty) - def add_source_files( # pylint: disable=too-many-arguments + def add_source_files( # pylint: disable=too-many-arguments, too-many-positional-arguments self, pattern, preprocessors=None, @@ -375,7 +375,7 @@ def add_source_files( # pylint: disable=too-many-arguments ] ) - def add_source_file( # pylint: disable=too-many-arguments + def add_source_file( # pylint: disable=too-many-arguments,too-many-positional-arguments self, file_name, preprocessors=None, diff --git a/vunit/ui/test.py b/vunit/ui/test.py index ddb5f7be5..f644c1c82 100644 --- a/vunit/ui/test.py +++ b/vunit/ui/test.py @@ -27,7 +27,7 @@ def name(self): """ return self._test_case.name - def add_config( # pylint: disable=too-many-arguments + def add_config( # pylint: disable=too-many-arguments,too-many-positional-arguments self, name, generics=None, diff --git a/vunit/ui/testbench.py b/vunit/ui/testbench.py index 9a7b7d63c..3f4acc114 100644 --- a/vunit/ui/testbench.py +++ b/vunit/ui/testbench.py @@ -130,7 +130,7 @@ def set_post_check(self, value): """ self._test_bench.set_post_check(value) - def add_config( # pylint: disable=too-many-arguments + def add_config( # pylint: disable=too-many-arguments,too-many-positional-arguments self, name, generics=None, diff --git a/vunit/vhdl_parser.py b/vunit/vhdl_parser.py index 4805a05d7..218be4621 100644 --- a/vunit/vhdl_parser.py +++ b/vunit/vhdl_parser.py @@ -49,6 +49,7 @@ class VHDLDesignFile(object): # pylint: disable=too-many-instance-attributes def __init__( # pylint: disable=too-many-arguments self, + *, entities=None, packages=None, package_bodies=None, From 234ede0722aaa53dcde8f56b2a8d02e6b007c73e Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 4 Nov 2024 13:34:42 +0100 Subject: [PATCH 2/6] Pull NVC from docker. --- .github/workflows/images.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index 684811a04..a0091f748 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -57,7 +57,7 @@ jobs: - name: '๐Ÿ›ณ๏ธ Build container image' run: | docker build -t ghcr.io/vunit/dev/nvc -< Date: Mon, 4 Nov 2024 14:14:49 +0100 Subject: [PATCH 3/6] Bumped latest Python test version to 3.13 --- .github/publish_site.sh | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/docs.yml | 6 +++--- .github/workflows/push.yml | 14 +++++++------- pyproject.toml | 2 +- setup.py | 1 + 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/publish_site.sh b/.github/publish_site.sh index 10dda4fe8..63c15130a 100755 --- a/.github/publish_site.sh +++ b/.github/publish_site.sh @@ -10,7 +10,7 @@ set -e echo "isVUnit: $isVUnit" -cd $(dirname "$0")/../.tox/py312-docs/tmp/docsbuild/ +cd $(dirname "$0")/../.tox/py313-docs/tmp/docsbuild/ touch .nojekyll git init diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6ceb07b66..e2706cdc3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - name: Run coverage run: | diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d98daaaa5..7e2a8ac81 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - name: Install dependencies run: | @@ -30,12 +30,12 @@ jobs: pip install -U virtualenv tox --progress-bar off - name: Build docs - run: tox -e py312-docs -- --color + run: tox -e py313-docs -- --color - uses: actions/upload-artifact@v4 with: name: VUnit-site - path: .tox/py312-docs/tmp/docsbuild/ + path: .tox/py313-docs/tmp/docsbuild/ - name: '๐Ÿš€ Publish site' if: github.event_name != 'pull_request' && github.ref_name == 'master' diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 28f0a031b..9ed30c8f8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -28,7 +28,7 @@ jobs: - name: '๐Ÿ Setup Python' uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - name: '๐Ÿ Install dependencies' run: | @@ -36,7 +36,7 @@ jobs: pip install -U virtualenv tox --progress-bar off - name: '๐Ÿ Run black' - run: tox -e py312-fmt -- --diff --color + run: tox -e py313-fmt -- --diff --color # # Linux linting and unit tests @@ -48,9 +48,9 @@ jobs: fail-fast: false matrix: include: - - { py: '3.12' , task: 312-lint } + - { py: '3.13' , task: 313-lint } - { py: '3.7' , task: 37-unit } - - { py: '3.12' , task: 312-unit } + - { py: '3.13' , task: 313-unit } name: '๐Ÿง Ubuntu ยท ${{ matrix.task }}' steps: @@ -80,8 +80,8 @@ jobs: fail-fast: false matrix: task: [ - {do: 312-acceptance, tag: llvm}, - {do: 312-vcomponents, tag: mcode}, + {do: 313-acceptance, tag: llvm}, + {do: 313-vcomponents, tag: mcode}, ] name: '๐Ÿ›ณ๏ธ Container ยท ${{ matrix.task.do }} ยท ${{ matrix.task.tag }}' steps: @@ -188,7 +188,7 @@ jobs: - name: '๐Ÿ Setup Python' uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - name: '๐Ÿ Install dependencies' run: | diff --git a/pyproject.toml b/pyproject.toml index a2bf31cd7..8e4644bd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ underlines = ["-", "~"] [tool.tox] legacy_tox_ini = """ [tox] -envlist = py{36,37,38,39,310,311,312}-{fmt,unit,lint,docs}, py{36,37,38,39,310,311,312}-{acceptance,vcomponents}-{activehdl,ghdl,modelsim,nvc,rivierapro}, py{36,37,38,39,310,311,312}-coverage +envlist = py{36,37,38,39,310,311,312,313}-{fmt,unit,lint,docs}, py{36,37,38,39,310,311,312,313}-{acceptance,vcomponents}-{activehdl,ghdl,modelsim,nvc,rivierapro}, py{36,37,38,39,310,311,312,313}-coverage isolated_build = True [testenv] diff --git a/setup.py b/setup.py index 46bd9aa4e..8725ee25e 100644 --- a/setup.py +++ b/setup.py @@ -71,6 +71,7 @@ def find_all_files(directory, endings=None): "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX :: Linux", From 8da7ebe9fbcda1cb6a07a7457c0c8eee272c5c28 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 4 Nov 2024 15:19:48 +0100 Subject: [PATCH 4/6] Fixed docs build. --- docs/conf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index c2789fa88..ac5492f4e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -113,11 +113,14 @@ # -- InterSphinx -------------------------------------------------------------- intersphinx_mapping = { - "python": ("https://docs.python.org/3.8/", None), + "python": ("https://docs.python.org/3.13/", None), "pytest": ("https://docs.pytest.org/en/latest/", None), "osvb": ("https://umarcor.github.io/osvb", None), } +nitpick_ignore_regex = [ + ("py:class", r".*"), +] # -- ExtLinks ----------------------------------------------------------------- extlinks = { From c477669aa5021e6e5ffd94e5b46afc09bb3c3239 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Tue, 26 Nov 2024 15:43:18 +0100 Subject: [PATCH 5/6] Added integer representations for checkers, loggers, and actors. --- vunit/vhdl/check/src/checker_pkg-body.vhd | 10 ++++++++++ vunit/vhdl/check/src/checker_pkg.vhd | 3 +++ vunit/vhdl/check/test/tb_checker.vhd | 5 +++++ vunit/vhdl/com/src/com_types.vhd | 15 +++++++++++++++ vunit/vhdl/com/test/tb_com.vhd | 5 +++++ vunit/vhdl/logging/src/logger_pkg-body.vhd | 5 +++++ vunit/vhdl/logging/src/logger_pkg.vhd | 7 +++++++ vunit/vhdl/logging/test/tb_log.vhd | 4 ++++ 8 files changed, 54 insertions(+) diff --git a/vunit/vhdl/check/src/checker_pkg-body.vhd b/vunit/vhdl/check/src/checker_pkg-body.vhd index f400bff73..6b9ec7ea3 100644 --- a/vunit/vhdl/check/src/checker_pkg-body.vhd +++ b/vunit/vhdl/check/src/checker_pkg-body.vhd @@ -312,4 +312,14 @@ package body checker_pkg is ")"); end function; + impure function to_integer(checker : checker_t) return integer is + begin + return to_integer(checker.p_data); + end; + + impure function to_checker(value : integer) return checker_t is + begin + return (p_data => to_integer_vector_ptr(value)); + end; + end package body; diff --git a/vunit/vhdl/check/src/checker_pkg.vhd b/vunit/vhdl/check/src/checker_pkg.vhd index ffbe51965..209f26ea0 100644 --- a/vunit/vhdl/check/src/checker_pkg.vhd +++ b/vunit/vhdl/check/src/checker_pkg.vhd @@ -106,6 +106,9 @@ package checker_pkg is procedure get_checker_stat(checker : checker_t; variable stat : out checker_stat_t); + impure function to_integer(checker : checker_t) return integer; + impure function to_checker(value : integer) return checker_t; + -- Private impure function p_has_unhandled_checks return boolean; impure function p_register_unhandled_check(checker : checker_t) return unhandled_check_id_t; diff --git a/vunit/vhdl/check/test/tb_checker.vhd b/vunit/vhdl/check/test/tb_checker.vhd index 8ea0243f6..8faf5e649 100644 --- a/vunit/vhdl/check/test/tb_checker.vhd +++ b/vunit/vhdl/check/test/tb_checker.vhd @@ -94,6 +94,11 @@ begin assert_true(stat1 + stat2 = (31, 16, 15), "Expected sum = (31, 16, 15)"); passed := to_string(stat1) = "checker_stat'(n_checks => 20, n_failed => 13, n_passed => 7)"; assert_true(passed, "Format error of checker_stat_t. Got:" & to_string(stat1)); + + elsif run("Test checker to/from integer conversion") then + assert_true(to_checker(to_integer(my_checker)) = my_checker); + assert_true(to_checker(to_integer(null_checker)) = null_checker); + end if; end loop; diff --git a/vunit/vhdl/com/src/com_types.vhd b/vunit/vhdl/com/src/com_types.vhd index 91452f38f..51d673214 100644 --- a/vunit/vhdl/com/src/com_types.vhd +++ b/vunit/vhdl/com/src/com_types.vhd @@ -400,6 +400,9 @@ package com_types_pkg is alias push_dict_t_ref is push_ref[msg_t, dict_t]; alias pop_dict_t_ref is pop_ref[msg_t return dict_t]; + -- Misc + impure function to_integer(actor : actor_t) return integer; + impure function to_actor(value : integer) return actor_t; end package; package body com_types_pkg is @@ -870,5 +873,17 @@ package body com_types_pkg is return pop_ref(msg.data); end; + ----------------------------------------------------------------------------- + -- Misc + ----------------------------------------------------------------------------- + impure function to_integer(actor : actor_t) return integer is + begin + return actor.p_id_number; + end; + + impure function to_actor(value : integer) return actor_t is + begin + return (p_id_number => value); + end; end package body com_types_pkg; diff --git a/vunit/vhdl/com/test/tb_com.vhd b/vunit/vhdl/com/test/tb_com.vhd index eeb872f8e..cd216566b 100644 --- a/vunit/vhdl/com/test/tb_com.vhd +++ b/vunit/vhdl/com/test/tb_com.vhd @@ -1384,6 +1384,11 @@ begin unmock(com_logger); + elsif run("Test actor to/from integer conversion") then + actor := new_actor; + check(to_actor(to_integer(actor)) = actor); + check(to_actor(to_integer(null_actor)) = null_actor); + -- Deprecated APIs elsif run("Test that use of deprecated API leads to an error") then mock(com_logger); diff --git a/vunit/vhdl/logging/src/logger_pkg-body.vhd b/vunit/vhdl/logging/src/logger_pkg-body.vhd index 91b762809..2e2456b71 100644 --- a/vunit/vhdl/logging/src/logger_pkg-body.vhd +++ b/vunit/vhdl/logging/src/logger_pkg-body.vhd @@ -36,6 +36,11 @@ package body logger_pkg is return to_integer(logger.p_data); end; + impure function to_logger(value : integer) return logger_t is + begin + return (p_data => to_integer_vector_ptr(value)); + end; + procedure add_child(logger : logger_t; child : logger_t) is constant children : integer_vector_ptr_t := to_integer_vector_ptr(get(logger.p_data, children_idx)); begin diff --git a/vunit/vhdl/logging/src/logger_pkg.vhd b/vunit/vhdl/logging/src/logger_pkg.vhd index 44106ab72..9e2660137 100644 --- a/vunit/vhdl/logging/src/logger_pkg.vhd +++ b/vunit/vhdl/logging/src/logger_pkg.vhd @@ -427,4 +427,11 @@ package logger_pkg is -- Return the number of unchecked messages in the mock queue impure function mock_queue_length return natural; + ----------------------------------------------------------------------------- + -- Misc + ----------------------------------------------------------------------------- + impure function to_integer(logger : logger_t) return integer; + impure function to_logger(value : integer) return logger_t; + + end package; diff --git a/vunit/vhdl/logging/test/tb_log.vhd b/vunit/vhdl/logging/test/tb_log.vhd index 13ffd54d9..08c5b77bf 100644 --- a/vunit/vhdl/logging/test/tb_log.vhd +++ b/vunit/vhdl/logging/test/tb_log.vhd @@ -944,6 +944,10 @@ begin check_log_file(file_handlers(i), log_file_name & integer'image(i), entries); end loop; + elsif run("Test logger to/from integer conversion") then + assert_true(to_logger(to_integer(logger)) = logger); + assert_true(to_logger(to_integer(null_logger)) = null_logger); + end if; test_runner_cleanup(runner); From 51365a5a068a7247c1328cd2a8ed4af0813e647f Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Tue, 26 Nov 2024 15:44:53 +0100 Subject: [PATCH 6/6] Added support package for standard VCs --- vunit/vhdl/com/src/com_types.vhd | 3 + .../src/vc_context.vhd | 1 + .../verification_components/src/vc_pkg.vhd | 178 ++++++++++++++++++ .../test/tb_vc_pkg.vhd | 102 ++++++++++ 4 files changed, 284 insertions(+) create mode 100644 vunit/vhdl/verification_components/src/vc_pkg.vhd create mode 100644 vunit/vhdl/verification_components/test/tb_vc_pkg.vhd diff --git a/vunit/vhdl/com/src/com_types.vhd b/vunit/vhdl/com/src/com_types.vhd index 51d673214..6bc4cbd36 100644 --- a/vunit/vhdl/com/src/com_types.vhd +++ b/vunit/vhdl/com/src/com_types.vhd @@ -403,6 +403,9 @@ package com_types_pkg is -- Misc impure function to_integer(actor : actor_t) return integer; impure function to_actor(value : integer) return actor_t; + + -- Private + impure function is_valid(code : integer) return boolean; end package; package body com_types_pkg is diff --git a/vunit/vhdl/verification_components/src/vc_context.vhd b/vunit/vhdl/verification_components/src/vc_context.vhd index 71bba4de8..903083bbd 100644 --- a/vunit/vhdl/verification_components/src/vc_context.vhd +++ b/vunit/vhdl/verification_components/src/vc_context.vhd @@ -19,6 +19,7 @@ context vc_context is use vunit_lib.stream_slave_pkg.all; use vunit_lib.sync_pkg.all; use vunit_lib.uart_pkg.all; + use vunit_lib.vc_pkg.all; use vunit_lib.wishbone_pkg.all; context vunit_lib.com_context; end context; diff --git a/vunit/vhdl/verification_components/src/vc_pkg.vhd b/vunit/vhdl/verification_components/src/vc_pkg.vhd new file mode 100644 index 000000000..dd39ce993 --- /dev/null +++ b/vunit/vhdl/verification_components/src/vc_pkg.vhd @@ -0,0 +1,178 @@ +-- 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-2024, Lars Asplund lars.anders.asplund@gmail.com +-- +-- This package contains common functionality for VCs. + +context work.vunit_context; +context work.com_context; + +package vc_pkg is + type unexpected_msg_type_policy_t is (fail, ignore); + + type std_cfg_t is record + p_data : integer_vector_ptr_t; + end record; + + constant null_std_cfg : std_cfg_t := ( + p_data => null_integer_vector_ptr + ); + + -- Creates a standard VC configuration with an id, an actor, a logger, a + -- checker, and an unexpected message type policy. + -- + -- If id = null_id, the id will be assigned the name provider:vc_name:n where n is 1 + -- for the first instance and increasing with one for every additional instance. + -- + -- The id must not have an associated actor before the call as that may indicate + -- several users of the same actor. + -- + -- If a logger exist for the id, it will be reused. If not, a new logger is created. + -- A new checker is created that reports to the logger. + impure function create_std_cfg( + id : id_t := null_id; + provider : string := ""; + vc_name : string := ""; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return std_cfg_t; + + -- Used to create enumerated ids from a parent id. The first created + -- id will be :1, the second :2 and so on + impure function enumerate(parent : id_t) return id_t; + + -- These functions extracts information from the standard VC configuration + impure function get_id(std_cfg : std_cfg_t) return id_t; + impure function get_actor(std_cfg : std_cfg_t) return actor_t; + impure function get_logger(std_cfg : std_cfg_t) return logger_t; + impure function get_checker(std_cfg : std_cfg_t) return checker_t; + impure function unexpected_msg_type_policy(std_cfg : std_cfg_t) return unexpected_msg_type_policy_t; + + -- Handle messages with unexpected message type according to the standard configuration + procedure unexpected_msg_type(msg_type : msg_type_t; std_cfg : std_cfg_t); + +end package; + +package body vc_pkg is + constant vc_pkg_logger : logger_t := get_logger("vunit_lib:vc_pkg"); + constant vc_pkg_checker : checker_t := new_checker(vc_pkg_logger); + + constant id_idx : natural := 0; + constant actor_idx : natural := 1; + constant logger_idx : natural := 2; + constant checker_idx : natural := 3; + constant unexpected_msg_type_policy_idx : natural := 4; + constant std_cfg_length : natural := unexpected_msg_type_policy_idx + 1; + + impure function enumerate(parent : id_t) return id_t is + begin + return get_id(to_string(num_children(parent) + 1), parent => parent); + end; + + impure function create_std_cfg( + id : id_t := null_id; + provider : string := ""; + vc_name : string := ""; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return std_cfg_t is + variable std_cfg : std_cfg_t; + variable provider_id : id_t; + variable vc_id : id_t; + variable instance_id : id_t; + variable actor : actor_t; + variable logger : logger_t; + begin + std_cfg.p_data := new_integer_vector_ptr(std_cfg_length); + + if id /= null_id then + instance_id := id; + else + if provider = "" then + check_failed(vc_pkg_checker, "A provider must be provided."); + + -- Simplifies testing when vc_pkg_checker logger is mocked + return null_std_cfg; + end if; + + if vc_name = "" then + check_failed(vc_pkg_checker, "A VC name must be provided."); + + -- Simplifies testing when vc_pkg_checker logger is mocked + return null_std_cfg; + end if; + + provider_id := get_id(provider); + vc_id := get_id(vc_name, parent => provider_id); + instance_id := enumerate(vc_id); + end if; + set(std_cfg.p_data, id_idx, to_integer(instance_id)); + + if find(instance_id, enable_deferred_creation => false) /= null_actor then + check_failed(vc_pkg_checker, "An actor already exists for " & full_name(instance_id) & "."); + + -- Simplifies testing when vc_pkg_checker logger is mocked + return null_std_cfg; + else + actor := new_actor(instance_id); + end if; + set(std_cfg.p_data, actor_idx, to_integer(actor)); + + logger := get_logger(instance_id); + set(std_cfg.p_data, logger_idx, to_integer(logger)); + + set(std_cfg.p_data, checker_idx, to_integer(new_checker(logger))); + + set( + std_cfg.p_data, + unexpected_msg_type_policy_idx, + unexpected_msg_type_policy_t'pos(unexpected_msg_type_policy) + ); + + return std_cfg; + end; + + impure function get_id(std_cfg : std_cfg_t) return id_t is + begin + return to_id(get(std_cfg.p_data, id_idx)); + end; + + impure function get_actor(std_cfg : std_cfg_t) return actor_t is + begin + return to_actor(get(std_cfg.p_data, actor_idx)); + end; + + impure function get_logger(std_cfg : std_cfg_t) return logger_t is + begin + return to_logger(get(std_cfg.p_data, logger_idx)); + end; + + impure function get_checker(std_cfg : std_cfg_t) return checker_t is + begin + return to_checker(get(std_cfg.p_data, checker_idx)); + end; + + impure function unexpected_msg_type_policy(std_cfg : std_cfg_t) return unexpected_msg_type_policy_t is + begin + return unexpected_msg_type_policy_t'val(get(std_cfg.p_data, unexpected_msg_type_policy_idx)); + end; + + procedure unexpected_msg_type(msg_type : msg_type_t; + std_cfg : std_cfg_t) is + constant code : integer := msg_type.p_code; + begin + if is_already_handled(msg_type) or unexpected_msg_type_policy(std_cfg) = ignore then + null; + elsif is_valid(code) then + check_failed( + get_checker(std_cfg), + "Got unexpected message " & to_string(to_string_ptr(get(p_msg_types.p_name_ptrs, code))) + ); + else + check_failed( + get_checker(std_cfg), + "Got invalid message with code " & to_string(code) + ); + end if; + end procedure; +end package body; diff --git a/vunit/vhdl/verification_components/test/tb_vc_pkg.vhd b/vunit/vhdl/verification_components/test/tb_vc_pkg.vhd new file mode 100644 index 000000000..1cbd45826 --- /dev/null +++ b/vunit/vhdl/verification_components/test/tb_vc_pkg.vhd @@ -0,0 +1,102 @@ +-- 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-2024, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context work.com_context; +use work.vc_pkg.all; + +entity tb_vc_pkg is + generic(runner_cfg : string); +end entity; + +architecture a of tb_vc_pkg is +begin + + main : process + variable std_cfg : std_cfg_t; + variable id : id_t; + variable actor : actor_t; + + constant vc_pkg_logger : logger_t := get_logger("vunit_lib:vc_pkg"); + constant unknown_msg_type : msg_type_t := new_msg_type("unknown_msg"); + begin + test_runner_setup(runner, runner_cfg); + while test_suite loop + if run("Test that provider must be supplied with null_id") then + mock(vc_pkg_logger, error); + std_cfg := create_std_cfg(vc_name => "my_vc"); + check_only_log(vc_pkg_logger, "A provider must be provided.", error); + unmock(vc_pkg_logger); + + elsif run("Test that vc_name must be supplied with null_id") then + mock(vc_pkg_logger, error); + std_cfg := create_std_cfg(provider => "provider"); + check_only_log(vc_pkg_logger, "A VC name must be provided.", error); + unmock(vc_pkg_logger); + + elsif run("Test standard config with specified id") then + id := get_id("id"); + std_cfg := create_std_cfg(id => id); + check(get_id(std_cfg) = id); + check(get_actor(std_cfg) = find(id, enable_deferred_creation => false)); + check(get_logger(std_cfg) = get_logger(id)); + check(get_logger(get_checker(std_cfg)) = get_logger(id)); + check(unexpected_msg_type_policy(std_cfg) = fail); + + elsif run("Test standard config with null_id") then + for instance in 1 to 3 loop + std_cfg := create_std_cfg(provider => "provider", vc_name => "vc_name"); + id := get_id(std_cfg); + check(id = get_id("provider:vc_name:" & to_string(instance))); + check(get_actor(std_cfg) = find(id, enable_deferred_creation => false)); + check(get_logger(std_cfg) = get_logger(id)); + check(get_logger(get_checker(std_cfg)) = get_logger(id)); + check(unexpected_msg_type_policy(std_cfg) = fail); + end loop; + + elsif run("Test standard config with specified unexpected message type policy") then + std_cfg := create_std_cfg( + provider => "provider", + vc_name => "vc_name", + unexpected_msg_type_policy => ignore + ); + id := get_id(std_cfg); + check(id = get_id("provider:vc_name:1")); + check(get_actor(std_cfg) = find(id, enable_deferred_creation => false)); + check(get_logger(std_cfg) = get_logger(id)); + check(get_logger(get_checker(std_cfg)) = get_logger(id)); + check(unexpected_msg_type_policy(std_cfg) = ignore); + + elsif run("Test failing on reused actor") then + mock(vc_pkg_logger, error); + id := get_id("foo:bar"); + actor := new_actor(id); + std_cfg := create_std_cfg(id => id); + check_only_log(vc_pkg_logger, "An actor already exists for foo:bar.", error); + unmock(vc_pkg_logger); + + elsif run("Test failing on unexpected message") then + id := get_id("id"); + std_cfg := create_std_cfg(id => id); + mock(get_logger(id), error); + unexpected_msg_type(unknown_msg_type, std_cfg); + check_only_log(get_logger(id), "Got unexpected message unknown_msg", error); + unmock(get_logger(id)); + + elsif run("Test ignoring unexpected message") then + id := get_id("id"); + std_cfg := create_std_cfg(id => id, unexpected_msg_type_policy => ignore); + mock(get_logger(id), error); + unexpected_msg_type(unknown_msg_type, std_cfg); + check_no_log; + unmock(get_logger(id)); + + end if; + end loop; + test_runner_cleanup(runner, fail_on_warning => true); + end process; +end architecture;