From 7e32c2b741f1420cdaefeebccf4685d67dba0bf8 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sat, 30 May 2020 20:07:32 +0200 Subject: [PATCH 01/21] Added support for new VC/VCI standard --- docs/verification_components/user_guide.rst | 200 ++++- setup.py | 1 + ...b_vc_with_template_compliance_template.vhd | 61 ++ tests/acceptance/artificial/vhdl/run.py | 75 +- tests/acceptance/artificial/vhdl/vc.vhd | 50 ++ .../vhdl/vc_not_supporting_custom_actor.vhd | 35 + .../vc_not_supporting_custom_actor_pkg.vhd | 75 ++ .../vhdl/vc_not_supporting_custom_logger.vhd | 35 + .../vc_not_supporting_custom_logger_pkg.vhd | 69 ++ .../vhdl/vc_not_supporting_sync.vhd | 34 + .../vhdl/vc_not_supporting_sync_pkg.vhd | 56 ++ ...not_supporting_unexpected_msg_handling.vhd | 36 + ...supporting_unexpected_msg_handling_pkg.vhd | 57 ++ tests/acceptance/artificial/vhdl/vc_pkg.vhd | 54 ++ .../artificial/vhdl/vc_pkg_with_template.vhd | 56 ++ .../artificial/vhdl/vc_with_template.vhd | 49 ++ tests/acceptance/test_artificial.py | 127 ++++ tests/lint/test_license.py | 2 + tests/unit/test_compliance_test.py | 703 ++++++++++++++++++ tests/unit/test_vhdl_parser.py | 199 ++++- vunit/__init__.py | 1 + vunit/project.py | 3 + vunit/source_file.py | 5 +- vunit/ui/entity.py | 41 + vunit/ui/library.py | 31 +- .../{packagefacade.py => package_facade.py} | 21 + vunit/vc/__init__.py | 12 + vunit/vc/compliance_test.py | 139 ++++ vunit/vc/vc_template.py | 135 ++++ vunit/vc/vci_template.py | 135 ++++ vunit/vc/verification_component.py | 481 ++++++++++++ vunit/vc/verification_component_interface.py | 480 ++++++++++++ vunit/vhdl/com/src/com_types.vhd | 10 + .../verification_components/src/vc_pkg.vhd | 117 +++ vunit/vhdl_parser.py | 276 +++++-- 35 files changed, 3749 insertions(+), 112 deletions(-) create mode 100644 tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_pkg.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd create mode 100644 tests/acceptance/artificial/vhdl/vc_with_template.vhd create mode 100644 tests/unit/test_compliance_test.py create mode 100644 vunit/ui/entity.py rename vunit/ui/{packagefacade.py => package_facade.py} (75%) create mode 100644 vunit/vc/__init__.py create mode 100644 vunit/vc/compliance_test.py create mode 100644 vunit/vc/vc_template.py create mode 100644 vunit/vc/vci_template.py create mode 100644 vunit/vc/verification_component.py create mode 100644 vunit/vc/verification_component_interface.py create mode 100644 vunit/vhdl/verification_components/src/vc_pkg.vhd diff --git a/docs/verification_components/user_guide.rst b/docs/verification_components/user_guide.rst index 705e47b53..19fc8bae5 100644 --- a/docs/verification_components/user_guide.rst +++ b/docs/verification_components/user_guide.rst @@ -13,7 +13,7 @@ as well as a set of utilities for writing your own verification component. Verification components allow a better overview in the test bench by raising the abstraction level of bus transactions. Even if you do not need the advanced features that VCs offer you may still -benefit from using per-verified models of an AXI-bus instead of +benefit from using pre-verified models of an AXI-bus instead of re-implementing it yourself. Included verification components (VCs): @@ -51,7 +51,7 @@ synchronization VCI while also supporting their own bus specific VCIs. have been used. Without generic VCIs copy pasting the code and changing the type of read/write procedure call would be required. -Neither a VC or a VCI there is the :ref:`memory model ` +Neither a VC or a VCI, there is the :ref:`memory model ` which is a model of a memory space such as the DRAM address space in a computer system. The memory mapped slave VCs such as AXI and Wishbone make transactions against the memory model which provides access @@ -64,6 +64,25 @@ reading and writing data. memory_model +.. _verification_components: + +Verification Components +----------------------- + +A verification component (VC) is an entity that is normally connected +to the DUT via a bus signal interface such as AXI-Lite. The main test +sequence in the test bench sends messages to the VCs that will then +perform the actual bus signal transactions. The benefit of this is +both to raise the abstraction level of the test bench as well as +making it easy to have parallel activity on several bus interfaces. + +A VC typically has an associated package defining procedures for +sending to and receiving messages from the VC. Each VC instance is +associated with a handle that is created by a _constructor_ function +in the test bench and set as a generic on the VC instantiation. +The handle is given as an argument to the procedure calls to direct +messages to the specfic VC instance. + .. _verification_component_interfaces: Verification Component Interfaces @@ -76,8 +95,6 @@ and the VC-developers. List of VCIs included in the main repository: -Included verification component interfaces (VCIs): - * :ref:`Bus master `: generic read and write of bus with address and byte enable. * :ref:`Stream `: push and pop of data stream without address. * :ref:`Synchronization `: wait for time and events. @@ -88,20 +105,167 @@ Included verification component interfaces (VCIs): vci -.. _verification_components: +VC and VCI Compliance Testing +----------------------------- -Verification Components ------------------------ +VUnit also provides a set of compliance tests to help VC and VCI developers adhere +to good design principles. These rules aim at creating flexible, reusable, interoperable +and future proof VCs and VCIs. -A verification component (VC) is an entity that is normally connected -to the DUT via a bus signal interface such as AXI-Lite. The main test -sequence in the test bench sends messages to the VCs that will then -perform the actual bus signal transactions. The benefit of this is -both to raise the abstraction level of the test bench as well as -making it easy to have parallel activity on several bus interfaces. +---- -A VC typically has an associated package defining procedures for -sending to and receiving messages from the VC. Each VC instance is -associated with a handle that is created in the test bench and set as -a generic on the VC instantiation. The handle is given as and argument -to the procedure calls to direct messages to the specfic VC instance. +**Rule 1** + The file containing the VC entity shall only contain one entity and the file containing the VCI package shall only contain one package. + +**Rationale** + The VC/VCI can be referenced by file name which makes compliance testing simpler. + +---- + +**Rule 2** + The name of the function used to create a new instance handle for a VC, aka the constructor, shall start with ``new_``. +**Rationale** + Makes it easier for the compliance test to automatically find a constructor and evaluate that with respect to the other applicable rules. + +---- + +**Rule 3** + A VC constructor shall have a ``logger`` parameter giving the user the option to specify the logger to use for VC reporting. +**Rationale** + It enables user control of the logging, for example enabling debug messages. + +---- + +**Rule 4** + A VC constructor shall have a ``checker`` parameter giving the user the option to specify the checker to use for VC checking. +**Rationale** + It enables user control of the checking, for example setting properties like the stop-level (without affecting the logger used above). + +---- + +**Rule 5** + A VC constructor shall have an ``actor`` parameter giving the user the option to specify the actor to use for VC communication. +**Rationale** + It enables user control of the communication, for example setting name for better trace logs. + +---- + +**Rule 6** + A VC constructor shall have an ``unexpected_msg_type_policy`` parameter giving the user the option to specify the action taken when the VC receives an unexpected message type. +**Rationale** + A VC actor setup to subscribe to another actor may receive messages not relevant for its operation. OTOH, VCs just addressed directly should only recieve messages it can handle. + +---- + +**Rule 7** + A VC constructor shall have a default value for all required parameters above. +**Rationale** + Makes it easier for the user if there is no preference on what to use. + +---- + +**Rule 8** + The default value for the logger parameter shall not be ``default_logger``. +**Rationale** + Using a logger more associated with the VC makes the logger output easier to understand. + +---- + +**Rule 9** + The default value for the checker parameter shall not be ``default_checker``. +**Rationale** + Using a checker more associated with the VC makes the checker output easier to understand. + +---- + +**Rule 10** + All fields in the handle returned by the constructor shall start with ``p_``. +**Rationale** + All field shall be considered private and this is a way to emphasize this. Keeping them private makes updates easier without breaking backward compatibility. + +---- + +**Rule 11** + The standard configuration, ``std_cfg_t``, of a VC consisting of the required parameters to the constructor shall be possible to get from the handle using a call to ``get_std_cfg``. +**Rationale** + Makes it possible to reuse operations such as ``get_logger`` between VCs. + +---- + +**Rule 12** + A VC shall only have one generic. +**Rationale** + Representing a VC with a single object makes it easier to handle in code. Since all fields of the handle are private future updates have less risk of breaking backward compatibility. + +---- + +**Rule 13** + All VCs shall support the sync interface. +**Rationale** + Being able to check that a VC is idle and to add a delay between transactions are commonly useful operations for VC users. + +---- + +Compliance testing is done separately for the VC and the VCI and each test consists of two parts. One part tests the code by parsing it and the other part tests the code by running a VHDL testbench. + +The VHDL testbenches cannot be automatically created because of: + +* A VC constructor can have VC specific parameters without default values +* A VC port list can constain unconstrained ports + +These issues are solved by creating a templates for the VHDL testbenches. The template is created by calling the compliance_test.py script (--help for instructions). Some rules are checked in this process and any violation is reported. +When all violations have been fixed the script will generate a template file which needs to modified manually according to the instructions in the template file. + +The run.py file verifying the VC and the VCI can then add compliance tests by using the VerificationComponentInterface and VerificationComponent classes. These classes provides methods to generate the full VHDL testbenches from the +templates and some extra parameters. + +.. code-block:: python + + # Find the VCI for the Avalon sink VC located in the avalon_stream_pkg package which has been added + # to library lib (lib.add_source_files). The return type for the VC constructor, avalon_sink_t, which + # allow the constructor to be found analyzed. + avalon_sink_vci = VerificationComponentInterface.find( + lib, "avalon_stream_pkg", "avalon_sink_t" + ) + + # Add a VCI compliance testbench to library test_lib. The generated testbench will be saved in the + # compliance_test directory and the final path identifies the previously generated testbench template + avalon_sink_vci.add_vhdl_testbench( + test_lib, + join(root, "compliance_test"), + join(root, ".vc", "avalon_stream_pkg", "tb_avalon_sink_t_compliance_template.vhd") + ) + + # Find the Avalon_sink VC located in the lib library + avalon_sink_vc = VerificationComponent.find(lib, "avalon_sink", avalon_sink_vci) + + # Add a VC compliance testbench to library test_lib. The generated testbench will be saved in the + # compliance_test directory and the final path identifies the previously generated testbench template + avalon_sink_vc.add_vhdl_testbench( + test_lib, + join(root, "compliance_test"), + join(root, ".vc", "tb_avalon_sink_compliance_template.vhd") + ) + + +The Avalon sink test suite will now have a number of extra test cases verifying that it is compliant + +.. code-block:: console + + ==== Summary ============================================================================================================================ + pass test_lib.tb_avalon_sink_t_compliance.Test standard configuration (1.5 seconds) + pass test_lib.tb_avalon_sink_t_compliance.Test handle independence (0.7 seconds) + pass test_lib.tb_avalon_sink_t_compliance.Test default logger (0.8 seconds) + pass test_lib.tb_avalon_sink_t_compliance.Test default checker (0.7 seconds) + pass test_lib.tb_avalon_sink_compliance.Test that sync interface is supported (0.8 seconds) + pass test_lib.tb_avalon_sink_compliance.Test that the actor can be customised (0.8 seconds) + pass test_lib.tb_avalon_sink_compliance.accept_unexpected_msg_type.Test unexpected message handling (0.8 seconds) + pass test_lib.tb_avalon_sink_compliance.fail_unexpected_msg_type_with_null_checker.Test unexpected message handling (0.8 seconds) + pass test_lib.tb_avalon_sink_compliance.fail_unexpected_msg_type_with_custom_checker.Test unexpected message handling (0.8 seconds) + ========================================================================================================================================= + pass 9 of 9 + ========================================================================================================================================= + Total time was 7.6 seconds + Elapsed time was 7.7 seconds + ========================================================================================================================================= + All passed! diff --git a/setup.py b/setup.py index 2af9d102c..b6dd34462 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ def find_all_files(directory, endings=None): "vunit.sim_if", "vunit.test", "vunit.ui", + "vunit.vc", "vunit.vivado", ], package_data={"vunit": DATA_FILES}, diff --git a/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd b/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd new file mode 100644 index 000000000..88a4d7ab9 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd @@ -0,0 +1,61 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library lib; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vc_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use lib.vc_pkg_with_template.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_vc_with_template_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_vc_with_template_compliance is + + constant vc_h : vc_handle_t := new_vc( + unspecified => true + ); + + signal a : std_logic; + signal c, d : std_logic_vector(7 downto 0); + signal f : std_logic; + signal j : std_logic; + signal k, l : std_logic; + signal m : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity lib.vc_with_template + generic map(vc_h) + port map( + a => a, + b => open, + c => c, + d => d, + e => open, + f => f, + g => open, + h => open, + i => open, + j => j, + k => k, + l => l, + m => m + ); + +end architecture; diff --git a/tests/acceptance/artificial/vhdl/run.py b/tests/acceptance/artificial/vhdl/run.py index a3df9b08c..5c57c4777 100644 --- a/tests/acceptance/artificial/vhdl/run.py +++ b/tests/acceptance/artificial/vhdl/run.py @@ -5,11 +5,13 @@ # Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com from pathlib import Path -from vunit import VUnit +from vunit import VUnit, VerificationComponentInterface, VerificationComponent ROOT = Path(__file__).parent VU = VUnit.from_argv() +VU.add_com() +VU.add_verification_components() LIB = VU.add_library("lib") LIB.add_source_files(ROOT / "*.vhd") @@ -69,7 +71,9 @@ def configure_tb_set_generic(ui): tb.set_generic("str_quote_val", 'a"b') str_long_num = 512 tb.set_generic("str_long_num", str_long_num) - tb.set_generic("str_long_val", "".join(["0123456789abcdef" for x in range(str_long_num)])) + tb.set_generic( + "str_long_val", "".join(["0123456789abcdef" for x in range(str_long_num)]) + ) def configure_tb_assert_stop_level(ui): @@ -77,7 +81,10 @@ def configure_tb_assert_stop_level(ui): for vhdl_assert_stop_level in ["warning", "error", "failure"]: for report_level in ["warning", "error", "failure"]: - test = tb.test("Report %s when VHDL assert stop level = %s" % (report_level, vhdl_assert_stop_level)) + test = tb.test( + "Report %s when VHDL assert stop level = %s" + % (report_level, vhdl_assert_stop_level) + ) test.set_sim_option("vhdl_assert_stop_level", vhdl_assert_stop_level) @@ -87,5 +94,65 @@ def configure_tb_assert_stop_level(ui): configure_tb_assert_stop_level(VU) LIB.entity("tb_no_generic_override").set_generic("g_val", False) LIB.entity("tb_ieee_warning").test("pass").set_sim_option("disable_ieee_warnings", True) -LIB.entity("tb_other_file_tests").scan_tests_from_file(str(ROOT / "other_file_tests.vhd")) +LIB.entity("tb_other_file_tests").scan_tests_from_file( + str(ROOT / "other_file_tests.vhd") +) + +TEST_LIB = VU.add_library("test_lib") + +VCI = VerificationComponentInterface.find(LIB, "vc_pkg", "vc_handle_t") +VerificationComponent.find(LIB, "vc", VCI).add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test" +) + +VCI = VerificationComponentInterface.find(LIB, "vc_pkg_with_template", "vc_handle_t") +VerificationComponent.find(LIB, "vc_with_template", VCI).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_vc_with_template_compliance_template.vhd", +) + + +vci = VerificationComponentInterface.find( + LIB, "vc_not_supporting_sync_pkg", "vc_not_supporting_sync_handle_t" +) +VerificationComponent.find(LIB, "vc_not_supporting_sync", vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", +) + +vci = VerificationComponentInterface.find( + LIB, "vc_not_supporting_custom_actor_pkg", "vc_not_supporting_custom_actor_handle_t" +) +VerificationComponent.find( + LIB, "vc_not_supporting_custom_actor", vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", +) + +vci = VerificationComponentInterface.find( + LIB, + "vc_not_supporting_custom_logger_pkg", + "vc_not_supporting_custom_logger_handle_t", +) +VerificationComponent.find( + LIB, "vc_not_supporting_custom_logger", vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", +) + +vci = VerificationComponentInterface.find( + LIB, + "vc_not_supporting_unexpected_msg_handling_pkg", + "vc_not_supporting_unexpected_msg_handling_handle_t", +) +VerificationComponent.find( + LIB, "vc_not_supporting_unexpected_msg_handling", vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", +) + VU.main() diff --git a/tests/acceptance/artificial/vhdl/vc.vhd b/tests/acceptance/artificial/vhdl/vc.vhd new file mode 100644 index 000000000..ab9a7e5eb --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc.vhd @@ -0,0 +1,50 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +library ieee; +use ieee.std_logic_1164.all; + +use work.vc_pkg.all; + +entity vc is + generic( + vc_h : vc_handle_t + ); + port( + a : in std_logic; + b : in std_logic := '1'; + c, d : in std_logic_vector(0 to 1); + e : in std_logic_vector := X"00"; + f : inout std_logic; + g : inout std_logic := '0'; + h, i : inout std_logic := '0'; + j : out std_logic; + k, l : out std_logic; + m : out std_logic := '1' + ); +end entity; + +architecture a of vc is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(vc_h.p_std_cfg), msg); + + msg_type := message_type(msg); + + handle_sync_message(net, msg_type, msg); + unexpected_msg_type(msg_type, vc_h.p_std_cfg); + end process; +end architecture; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd new file mode 100644 index 000000000..d02f0f74b --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +use work.vc_not_supporting_custom_actor_pkg.all; + +entity vc_not_supporting_custom_actor is + generic( + vc_h : vc_not_supporting_custom_actor_handle_t + ); +end entity; + +architecture a of vc_not_supporting_custom_actor is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, actor_vec_t'(vc_not_supporting_custom_actor_actor, get_actor(vc_h.p_std_cfg)), msg); + + msg_type := message_type(msg); + + handle_sync_message(net, msg_type, msg); + unexpected_msg_type(msg_type, vc_h.p_std_cfg); + end process; +end architecture; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd new file mode 100644 index 000000000..ef3030343 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd @@ -0,0 +1,75 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_not_supporting_custom_actor_pkg is + type vc_not_supporting_custom_actor_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_not_supporting_custom_actor_logger : logger_t := get_logger("vc_not_supporting_custom_actor"); + constant vc_not_supporting_custom_actor_checker : checker_t := new_checker(vc_not_supporting_custom_actor_logger); + constant vc_not_supporting_custom_actor_actor : actor_t := new_actor("vc_not_supporting_custom_actor_actor"); + + constant transaction_msg : msg_type_t := new_msg_type("transaction"); + + impure function new_vc_not_supporting_custom_actor( + logger : logger_t := vc_not_supporting_custom_actor_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_custom_actor_handle_t; + + procedure transaction( + signal net : inout network_t; + vc_h : vc_not_supporting_custom_actor_handle_t + ); + + impure function as_sync( + vc_h : vc_not_supporting_custom_actor_handle_t + ) return sync_handle_t; + +end package; + +package body vc_not_supporting_custom_actor_pkg is + impure function new_vc_not_supporting_custom_actor( + logger : logger_t := vc_not_supporting_custom_actor_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_custom_actor_handle_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + vc_not_supporting_custom_actor_logger, vc_not_supporting_custom_actor_checker, actor, logger, checker, unexpected_msg_type_policy + ); + + begin + return (p_std_cfg => p_std_cfg); + end; + + procedure transaction( + signal net : inout network_t; + vc_h : vc_not_supporting_custom_actor_handle_t + ) is + variable msg : msg_t; + begin + msg := new_msg(transaction_msg); + send(net, vc_not_supporting_custom_actor_actor, msg); + end procedure; + + impure function as_sync( + vc_h : vc_not_supporting_custom_actor_handle_t + ) return sync_handle_t is + begin + return vc_not_supporting_custom_actor_actor; + end; + +end package body; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd new file mode 100644 index 000000000..7823899bb --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +use work.vc_not_supporting_custom_logger_pkg.all; + +entity vc_not_supporting_custom_logger is + generic( + vc_h : vc_not_supporting_custom_logger_handle_t + ); +end entity; + +architecture a of vc_not_supporting_custom_logger is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(vc_h.p_std_cfg), msg); + + msg_type := message_type(msg); + + handle_sync_message(net, msg_type, msg); + unexpected_msg_type(msg_type, vc_h.p_std_cfg); + end process; +end architecture; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd new file mode 100644 index 000000000..90a5058a9 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd @@ -0,0 +1,69 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_not_supporting_custom_logger_pkg is + type vc_not_supporting_custom_logger_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_not_supporting_custom_logger_logger : logger_t := get_logger("vc_not_supporting_custom_logger"); + constant vc_not_supporting_custom_logger_checker : checker_t := new_checker(vc_not_supporting_custom_logger_logger); + + impure function new_vc_not_supporting_custom_logger( + logger : logger_t := vc_not_supporting_custom_logger_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_custom_logger_handle_t; + + impure function as_sync( + vc_h : vc_not_supporting_custom_logger_handle_t + ) return sync_handle_t; + +end package; + +package body vc_not_supporting_custom_logger_pkg is + impure function new_vc_not_supporting_custom_logger( + logger : logger_t := vc_not_supporting_custom_logger_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_custom_logger_handle_t is + variable p_std_cfg : std_cfg_t; + + begin + if actor = null_actor then + p_std_cfg.p_actor := new_actor; + else + p_std_cfg.p_actor := actor; + end if; + + if checker = null_checker then + p_std_cfg.p_checker := vc_not_supporting_custom_logger_checker; + else + p_std_cfg.p_checker := checker; + end if; + p_std_cfg.p_logger := vc_not_supporting_custom_logger_logger; + p_std_cfg.p_unexpected_msg_type_policy := unexpected_msg_type_policy; + + return (p_std_cfg => p_std_cfg); + end; + + impure function as_sync( + vc_h : vc_not_supporting_custom_logger_handle_t + ) return sync_handle_t is + begin + return get_actor(vc_h.p_std_cfg); + end; + +end package body; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd new file mode 100644 index 000000000..4329cab3b --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd @@ -0,0 +1,34 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +use work.vc_not_supporting_sync_pkg.all; + +entity vc_not_supporting_sync is + generic( + vc_h : vc_not_supporting_sync_handle_t + ); +end entity; + +architecture a of vc_not_supporting_sync is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(vc_h.p_std_cfg), msg); + + msg_type := message_type(msg); + + unexpected_msg_type(msg_type, vc_h.p_std_cfg); + end process; +end architecture; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd new file mode 100644 index 000000000..dc4bfee40 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd @@ -0,0 +1,56 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_not_supporting_sync_pkg is + type vc_not_supporting_sync_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_not_supporting_sync_logger : logger_t := get_logger("vc_not_supporting_sync"); + constant vc_not_supporting_sync_checker : checker_t := new_checker(vc_not_supporting_sync_logger); + + impure function new_vc_not_supporting_sync( + logger : logger_t := vc_not_supporting_sync_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_sync_handle_t; + + impure function as_sync( + vc_h : vc_not_supporting_sync_handle_t + ) return sync_handle_t; + +end package; + +package body vc_not_supporting_sync_pkg is + impure function new_vc_not_supporting_sync( + logger : logger_t := vc_not_supporting_sync_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_sync_handle_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + vc_not_supporting_sync_logger, vc_not_supporting_sync_checker, actor, logger, checker, unexpected_msg_type_policy + ); + begin + return (p_std_cfg => p_std_cfg); + end; + + impure function as_sync( + vc_h : vc_not_supporting_sync_handle_t + ) return sync_handle_t is + begin + return get_actor(vc_h.p_std_cfg); + end; + +end package body; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd new file mode 100644 index 000000000..64f78a581 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd @@ -0,0 +1,36 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +use work.vc_not_supporting_unexpected_msg_handling_pkg.all; + +entity vc_not_supporting_unexpected_msg_handling is + generic( + vc_h : vc_not_supporting_unexpected_msg_handling_handle_t + ); +end entity; + +architecture a of vc_not_supporting_unexpected_msg_handling is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(vc_h.p_std_cfg), msg); + + msg_type := message_type(msg); + + handle_sync_message(net, msg_type, msg); + + unexpected_msg_type(msg_type, get_checker(vc_h.p_std_cfg)); + end process; +end architecture; + diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd new file mode 100644 index 000000000..9ccf6231a --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd @@ -0,0 +1,57 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_not_supporting_unexpected_msg_handling_pkg is + type vc_not_supporting_unexpected_msg_handling_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_not_supporting_unexpected_msg_handling_logger : logger_t := get_logger("vc_not_supporting_unexpected_msg_handling"); + constant vc_not_supporting_unexpected_msg_handling_checker : checker_t := new_checker(vc_not_supporting_unexpected_msg_handling_logger); + + impure function new_vc_not_supporting_unexpected_msg_handling( + logger : logger_t := vc_not_supporting_unexpected_msg_handling_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_unexpected_msg_handling_handle_t; + + impure function as_sync( + vc_h : vc_not_supporting_unexpected_msg_handling_handle_t + ) return sync_handle_t; + +end package; + +package body vc_not_supporting_unexpected_msg_handling_pkg is + impure function new_vc_not_supporting_unexpected_msg_handling( + logger : logger_t := vc_not_supporting_unexpected_msg_handling_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_not_supporting_unexpected_msg_handling_handle_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + vc_not_supporting_unexpected_msg_handling_logger, vc_not_supporting_unexpected_msg_handling_checker, + actor, logger, checker, unexpected_msg_type_policy + ); + begin + return (p_std_cfg => p_std_cfg); + end; + + impure function as_sync( + vc_h : vc_not_supporting_unexpected_msg_handling_handle_t + ) return sync_handle_t is + begin + return get_actor(vc_h.p_std_cfg); + end; + +end package body; + diff --git a/tests/acceptance/artificial/vhdl/vc_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_pkg.vhd new file mode 100644 index 000000000..0d5da6d2d --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_pkg.vhd @@ -0,0 +1,54 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_logger : logger_t := get_logger("vc"); + constant vc_checker : checker_t := new_checker(vc_logger); + + impure function new_vc( + logger : logger_t := vc_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t; + + impure function as_sync( + vc_h : vc_handle_t + ) return sync_handle_t; + +end package; + +package body vc_pkg is + impure function new_vc( + logger : logger_t := vc_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + vc_logger, vc_checker, actor, logger, checker, unexpected_msg_type_policy + ); + begin + return (p_std_cfg => p_std_cfg); + end; + + impure function as_sync(vc_h : vc_handle_t) return sync_handle_t is + begin + return get_actor(vc_h.p_std_cfg); + end; + +end package body; + diff --git a/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd new file mode 100644 index 000000000..733893334 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd @@ -0,0 +1,56 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +package vc_pkg_with_template is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + constant vc_logger : logger_t := get_logger("vc"); + constant vc_checker : checker_t := new_checker(vc_logger); + + impure function new_vc( + unspecified : boolean; + logger : logger_t := vc_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t; + + impure function as_sync( + vc_h : vc_handle_t + ) return sync_handle_t; + +end package; + +package body vc_pkg_with_template is + impure function new_vc( + unspecified : boolean; + logger : logger_t := vc_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + vc_logger, vc_checker, actor, logger, checker, unexpected_msg_type_policy + ); + + begin + return (p_std_cfg => p_std_cfg); + end; + + impure function as_sync(vc_h : vc_handle_t) return sync_handle_t is + begin + return get_actor(vc_h.p_std_cfg); + end; + +end package body; diff --git a/tests/acceptance/artificial/vhdl/vc_with_template.vhd b/tests/acceptance/artificial/vhdl/vc_with_template.vhd new file mode 100644 index 000000000..22e6a85f5 --- /dev/null +++ b/tests/acceptance/artificial/vhdl/vc_with_template.vhd @@ -0,0 +1,49 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library vunit_lib; +context vunit_lib.vunit_context; +context vunit_lib.com_context; +context vunit_lib.vc_context; +use vunit_lib.vc_pkg.all; + +library ieee; +use ieee.std_logic_1164.all; + +use work.vc_pkg_with_template.all; + +entity vc_with_template is + generic( + vc_h : vc_handle_t + ); + port( + a : in std_logic; + b : in std_logic := '1'; + c, d : in std_logic_vector; + e : in std_logic_vector := X"00"; + f : inout std_logic; + g : inout std_logic := '0'; + h, i : inout std_logic := '0'; + j : out std_logic; + k, l : out std_logic; + m : out std_logic := '1' + ); +end entity; + +architecture a of vc_with_template is +begin + controller : process + variable msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(vc_h.p_std_cfg), msg); + + msg_type := message_type(msg); + + handle_sync_message(net, msg_type, msg); + unexpected_msg_type(msg_type, vc_h.p_std_cfg); + end process; +end architecture; diff --git a/tests/acceptance/test_artificial.py b/tests/acceptance/test_artificial.py index 7f400a245..7414503b6 100644 --- a/tests/acceptance/test_artificial.py +++ b/tests/acceptance/test_artificial.py @@ -245,4 +245,131 @@ def test_exit_0_flag(self): "failed", "lib.tb_assert_stop_level.Report failure when VHDL assert stop level = failure", ), + ("passed", "test_lib.tb_vc_compliance.Test that sync interface is supported"), + ("passed", "test_lib.tb_vc_compliance.Test that the actor can be customised"), + ( + "passed", + "test_lib.tb_vc_compliance.accept_unexpected_msg_type.Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_compliance.fail_unexpected_msg_type_with_null_checker.Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_compliance.fail_unexpected_msg_type_with_custom_checker.Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_sync_compliance.accept_unexpected_msg_type.Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_sync_compliance.fail_unexpected_msg_type_with_null_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_sync_compliance.fail_unexpected_msg_type_with_custom_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_actor_compliance.Test that sync interface is supported", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_actor_compliance.accept_unexpected_msg_type." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_actor_compliance.fail_unexpected_msg_type_with_null_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_actor_compliance.fail_unexpected_msg_type_with_custom_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_logger_compliance.Test that sync interface is supported", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_logger_compliance.Test that the actor can be customised", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_logger_compliance.accept_unexpected_msg_type." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_custom_logger_compliance.fail_unexpected_msg_type_with_custom_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_unexpected_msg_handling_compliance.Test that sync interface is supported", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_unexpected_msg_handling_compliance.Test that the actor can be customised", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_unexpected_msg_handling_compliance.fail_unexpected_msg_type_with_null_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_not_supporting_unexpected_msg_handling_compliance." + "fail_unexpected_msg_type_with_custom_checker.Test unexpected message handling", + ), + ( + "failed", + "test_lib.tb_vc_not_supporting_sync_compliance.Test that sync interface is supported", + ), + ( + "failed", + "test_lib.tb_vc_not_supporting_sync_compliance.Test that the actor can be customised", + ), + ( + "failed", + "test_lib.tb_vc_not_supporting_custom_actor_compliance.Test that the actor can be customised", + ), + ( + "failed", + "test_lib.tb_vc_not_supporting_custom_logger_compliance.fail_unexpected_msg_type_with_null_checker." + "Test unexpected message handling", + ), + ( + "failed", + "test_lib.tb_vc_not_supporting_unexpected_msg_handling_compliance.accept_unexpected_msg_type." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_with_template_compliance.Test that sync interface is supported", + ), + ( + "passed", + "test_lib.tb_vc_with_template_compliance.Test that the actor can be customised", + ), + ( + "passed", + "test_lib.tb_vc_with_template_compliance.accept_unexpected_msg_type.Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_with_template_compliance.fail_unexpected_msg_type_with_null_checker." + "Test unexpected message handling", + ), + ( + "passed", + "test_lib.tb_vc_with_template_compliance.fail_unexpected_msg_type_with_custom_checker." + "Test unexpected message handling", + ), ) diff --git a/tests/lint/test_license.py b/tests/lint/test_license.py index 6f28b58b6..c4b02fb85 100644 --- a/tests/lint/test_license.py +++ b/tests/lint/test_license.py @@ -131,6 +131,8 @@ def find_licensed_files(): continue if "codecs" in root: continue + if "compliance_test" in root: + continue if root == str(ROOT / "docs"): continue if str(ROOT / "venv") in root: diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py new file mode 100644 index 000000000..0813dad4a --- /dev/null +++ b/tests/unit/test_compliance_test.py @@ -0,0 +1,703 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +""" +Test the compliance test. +""" +from unittest import TestCase, mock +from shutil import rmtree +from pathlib import Path +from itertools import product +import re +from vunit.ostools import renew_path +from vunit.vc.verification_component_interface import ( + VerificationComponentInterface, + LOGGER, +) +from vunit.vc.verification_component import VerificationComponent +from vunit.vc.compliance_test import main +from vunit import VUnit +from vunit.vhdl_parser import VHDLDesignFile, VHDLReference + + +class TestComplianceTest(TestCase): # pylint: disable=too-many-public-methods + """Tests the ComplianceTest class.""" + + def setUp(self): + self.tmp_dir = Path(__file__).parent / "vc_tmp" + renew_path(str(self.tmp_dir)) + self.vc_contents = """ +library ieee +use ieee.std_logic_1164.all; + +entity vc is + generic(vc_h : vc_handle_t); + port( + a, b : in std_logic; + c : in std_logic := '0'; + d, e : inout std_logic; + f, g : inout std_logic := '1'; + h, i : out std_logic := '0'; + j : out std_logic); + +end entity; +""" + self.vc_path = self.make_file("vc.vhd", self.vc_contents) + + self.vci_contents = """ +package vc_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function new_vc( + logger : logger_t := default_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t; +end package; +""" + self.vci_path = self.make_file("vci.vhd", self.vci_contents) + + self.ui = VUnit.from_argv([]) + + self.vc_lib = self.ui.add_library("vc_lib") + self.vc_lib.add_source_files(str(self.tmp_dir / "*.vhd")) + + def tearDown(self): + if self.tmp_dir.exists(): + rmtree(self.tmp_dir) + + def make_file(self, file_name, contents): + """ + Create a file in the temporary directory with contents + Returns the absolute path to the file. + """ + full_file_name = (self.tmp_dir / file_name).resolve() + with full_file_name.open("w") as outfile: + outfile.write(contents) + return str(full_file_name) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_not_finding_vc(self, error_mock): + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "other_vc", vci + ) + error_mock.assert_called_once_with("Failed to find VC %s", "other_vc") + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_not_finding_vci(self, error_mock): + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_pkg", + "vc_handle_t", + ) + error_mock.assert_called_once_with("Failed to find VCI %s", "other_vc_pkg") + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_on_multiple_entities(self, error_mock): + vc_contents = """ +entity vc1 is + generic(a : bit); +end entity; + +entity vc2 is + generic(b : bit); +end entity; +""" + self.vc_lib.add_source_file(self.make_file("vc1_2.vhd", vc_contents)) + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci + ) + error_mock.assert_called_once_with( + "%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd" + ) + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci + ) + error_mock.assert_called_with( + "%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd" + ) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_on_multiple_package(self, error_mock): + vci_contents = """ +package vc_pkg1 is +end package; + +package vc_pkg2 is +end package; +""" + self.vc_lib.add_source_file(self.make_file("vci1_2.vhd", vci_contents)) + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "vc_pkg1", + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd" + ) + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "vc_pkg2", + "vc_handle_t", + ) + error_mock.assert_called_with( + "%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd" + ) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_evaluating_vc_generics(self, error_mock): + vc1_contents = """ +entity vc1 is +end entity; +""" + self.vc_lib.add_source_file(self.make_file("vc1.vhd", vc1_contents)) + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci + ) + error_mock.assert_called_once_with("%s must have a single generic", "vc1") + + vc2_contents = """ +entity vc2 is + generic(a : bit; b : bit); +end entity; +""" + self.vc_lib.add_source_file(self.make_file("vc2.vhd", vc2_contents)) + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci + ) + error_mock.assert_called_with("%s must have a single generic", "vc2") + + vc3_contents = """ +entity vc3 is + generic(a, b : bit); +end entity; +""" + self.vc_lib.add_source_file(self.make_file("vc3.vhd", vc3_contents)) + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + self.assertRaises( + SystemExit, VerificationComponent.find, self.vc_lib, "vc3", vci + ) + error_mock.assert_called_with("%s must have a single generic", "vc3") + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_with_no_constructor(self, error_mock): + vci_contents = """\ +package other_vc_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function create_vc return vc_handle_t; +end package; +""" + self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) + + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_pkg", + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "Failed to find a constructor function for vc_handle_t starting with new_" + ) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_with_wrong_constructor_return_type(self, error_mock): + vci_contents = """\ +package other_vc_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function new_vc return vc_t; +end package; +""" + self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) + + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_pkg", + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "Found constructor function new_vc but not with the correct return type vc_handle_t" + ) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_on_incorrect_constructor_parameters(self, error_mock): + parameters = dict( + logger=("logger_t", "default_logger"), + actor=("actor_t", "null_actor"), + checker=("checker_t", "null_checker"), + unexpected_msg_type_policy=("unexpected_msg_type_policy_t", "fail"), + ) + reasons_for_failure = [ + "missing_parameter", + "invalid_type", + "invalid_default_value", + ] + + for iteration, (invalid_parameter, invalid_reason) in enumerate( + product(parameters, reasons_for_failure) + ): + if (invalid_parameter in ["unexpected_msg_type_policy", "logger"]) and ( + invalid_reason == "invalid_default_value" + ): + continue + + vci_contents = ( + """\ +package other_vc_%d_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function new_vc( +""" + % iteration + ) + for parameter_name, parameter_data in parameters.items(): + if parameter_name != invalid_parameter: + vci_contents += " %s : %s := %s;\n" % ( + parameter_name, + parameter_data[0], + parameter_data[1], + ) + elif invalid_reason == "invalid_type": + vci_contents += " %s : invalid_type := %s;\n" % ( + parameter_name, + parameter_data[1], + ) + elif invalid_reason == "invalid_default_value": + vci_contents += " %s : %s := invalid_default_value;\n" % ( + parameter_name, + parameter_data[0], + ) + + vci_contents = ( + vci_contents[:-2] + + """ + ) return vc_handle_t; +end package; +""" + ) + self.vc_lib.add_source_file( + self.make_file("other_vci_%d.vhd" % iteration, vci_contents) + ) + + if invalid_reason == "missing_parameter": + error_msg = ( + "Found constructor function new_vc for vc_handle_t but the %s parameter is missing" + % invalid_parameter + ) + elif invalid_reason == "invalid_type": + error_msg = ( + "Found constructor function new_vc for vc_handle_t but the %s parameter is not of type %s" + % (invalid_parameter, parameters[invalid_parameter][0]) + ) + elif invalid_reason == "invalid_default_value": + error_msg = ( + "Found constructor function new_vc for vc_handle_t but null_%s is the only allowed " + "default value for the %s parameter" + % (invalid_parameter, invalid_parameter) + ) + + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_%d_pkg" % iteration, + "vc_handle_t", + ) + error_mock.assert_called_with(error_msg) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_on_non_private_handle_elements(self, error_mock): + vci_contents = """\ +package other_vc_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + foo : bar_t; + end record; + + impure function new_vc( + logger : logger_t := default_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t; +end package; +""" + + self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) + + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_pkg", + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "%s in %s doesn't start with p_", "foo", "vc_handle_t" + ) + + @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") + def test_failing_on_missing_handle_record(self, error_mock): + vci_contents = """\ +package other_vc_pkg is + type handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function new_vc( + logger : logger_t := default_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return vc_handle_t; +end package; +""" + + self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) + + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_pkg", + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "Failed to find %s record", "vc_handle_t", + ) + + def test_error_on_missing_default_value(self): + parameters = dict( + logger=("logger_t", "default_logger"), + actor=("actor_t", "null_actor"), + checker=("checker_t", "null_checker"), + unexpected_msg_type_policy=("unexpected_msg_type_policy_t", "fail"), + ) + + for iteration, parameter_wo_init_value in enumerate(parameters): + vci_contents = ( + """\ +package other_vc_%d_pkg is + type vc_handle_t is record + p_std_cfg : std_cfg_t; + end record; + + impure function new_vc( +""" + % iteration + ) + for parameter_name, parameter_data in parameters.items(): + if parameter_name != parameter_wo_init_value: + vci_contents += " %s : %s := %s;\n" % ( + parameter_name, + parameter_data[0], + parameter_data[1], + ) + else: + vci_contents += " %s : %s;\n" % ( + parameter_name, + parameter_data[0], + ) + + vci_contents = ( + vci_contents[:-2] + + """ + ) return vc_handle_t; +end package; +""" + ) + self.vc_lib.add_source_file( + self.make_file("other_vci_%d.vhd" % iteration, vci_contents) + ) + + with mock.patch.object(LOGGER, "error") as error_mock: + self.assertRaises( + SystemExit, + VerificationComponentInterface.find, + self.vc_lib, + "other_vc_%d_pkg" % iteration, + "vc_handle_t", + ) + error_mock.assert_called_once_with( + "Found constructor function new_vc for vc_handle_t but %s is lacking a default value" + % parameter_wo_init_value + ) + + def test_create_vhdl_testbench_template_references(self): + vc_contents = """\ +library std; +library work; +library a_lib; + +use std.a.all; +use work.b.c; +use a_lib.x.y; + +context work.spam; +context a_lib.eggs; + +entity vc2 is + generic(vc_h : vc_handle_t); +end entity; +""" + + vc_path = self.make_file("vc2.vhd", vc_contents) + template, _ = VerificationComponent.create_vhdl_testbench_template( + "vc_lib", vc_path, self.vci_path + ) + template = VHDLDesignFile.parse(template) + refs = template.references + self.assertEqual(len(refs), 13) + self.assertIn(VHDLReference("library", "vunit_lib"), refs) + self.assertIn(VHDLReference("library", "vc_lib"), refs) + self.assertIn(VHDLReference("library", "a_lib"), refs) + self.assertIn(VHDLReference("package", "std", "a", "all"), refs) + self.assertIn(VHDLReference("package", "vc_lib", "b", "c"), refs) + self.assertIn(VHDLReference("package", "vc_lib", "vc_pkg", "all"), refs) + self.assertIn(VHDLReference("package", "a_lib", "x", "y"), refs) + self.assertIn(VHDLReference("package", "vunit_lib", "sync_pkg", "all"), refs) + self.assertIn(VHDLReference("context", "vc_lib", "spam"), refs) + self.assertIn(VHDLReference("context", "a_lib", "eggs"), refs) + self.assertIn(VHDLReference("context", "vunit_lib", "vunit_context"), refs) + self.assertIn(VHDLReference("context", "vunit_lib", "com_context"), refs) + self.assertIn(VHDLReference("entity", "vc_lib", "vc2"), refs) + + def test_template_with_wrong_name(self): + template_contents = """\ +entity tb_vc2_compliance is + generic(runner_cfg : string); +end entity; + +architecture a of tb_vc2_compliance is + constant vc_h : vc_handle_t := new_vc; +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" + + template_path = self.make_file("template.vhd", template_contents) + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vc = VerificationComponent.find(self.vc_lib, "vc", vci) + self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) + + def test_template_missing_contructor(self): + template_contents = """\ +entity tb_vc_compliance is + generic(runner_cfg : string); +end entity; + +architecture a of tb_vc_compliance is +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" + + template_path = self.make_file("template.vhd", template_contents) + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vc = VerificationComponent.find(self.vc_lib, "vc", vci) + self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) + + def test_template_missing_runner_cfg(self): + template_contents = """\ +entity tb_vc_compliance is + generic(foo : bar); +end entity; + +architecture a of tb_vc_compliance is + constant vc_h : vc_handle_t := new_vc; +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" + + template_path = self.make_file("template.vhd", template_contents) + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vc = VerificationComponent.find(self.vc_lib, "vc", vci) + self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) + + def test_template_missing_test_runner(self): + template_contents = """\ +entity tb_vc_compliance is + generic(runner_cfg : string); +end entity; + +architecture a of tb_vc_compliance is + constant vc_h : vc_handle_t := new_vc; +begin + main : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" + + template_path = self.make_file("template.vhd", template_contents) + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vc = VerificationComponent.find(self.vc_lib, "vc", vci) + self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) + + def test_creating_template_without_output_path(self): + with mock.patch( + "sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path] + ): + main() + + self.assertTrue( + ( + Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" + ).exists() + ) + + def test_creating_template_with_output_dir(self): + output_dir = self.tmp_dir / "template" + output_dir.mkdir(parents=True) + with mock.patch( + "sys.argv", + [ + "compliance_test.py", + "create-vc", + "-o", + str(output_dir), + self.vc_path, + self.vci_path, + ], + ): + main() + self.assertTrue((output_dir / "tb_vc_compliance_template.vhd").exists()) + + def test_creating_template_with_output_file(self): + output_dir = self.tmp_dir / "template" + output_dir.mkdir(parents=True) + output_path = output_dir / "template.vhd" + with mock.patch( + "sys.argv", + [ + "compliance_test.py", + "create-vc", + "--output-path", + str(output_path), + self.vc_path, + self.vci_path, + ], + ): + main() + self.assertTrue(output_path.exists()) + + def test_creating_template_with_invalid_output_path(self): + output_dir = self.tmp_dir / "test" + output_path = output_dir / "template.vhd" + with mock.patch( + "sys.argv", + [ + "compliance_test.py", + "create-vc", + "--output-path", + str(output_path), + self.vc_path, + self.vci_path, + ], + ): + self.assertRaises(IOError, main) + + def test_creating_template_with_default_vc_lib(self): + with mock.patch( + "sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path] + ): + main() + with ( + Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" + ).open() as fptr: + self.assertIsNotNone( + re.search( + r"library\s+vc_lib\s*;", + fptr.read(), + re.IGNORECASE | re.MULTILINE, + ) + ) + + def test_creating_template_with_specified_vc_lib(self): + with mock.patch( + "sys.argv", + [ + "compliance_test.py", + "create-vc", + "-l", + "my_vc_lib", + self.vc_path, + self.vci_path, + ], + ): + main() + with ( + Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" + ).open() as fptr: + self.assertIsNotNone( + re.search( + r"library\s+my_vc_lib\s*;", + fptr.read(), + re.IGNORECASE | re.MULTILINE, + ) + ) + + def test_adding_vhdl_testbench(self): + vc_test_lib = self.ui.add_library("vc_test_lib") + + vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vc = VerificationComponent.find(self.vc_lib, "vc", vci) + + vc.add_vhdl_testbench(vc_test_lib, str(self.tmp_dir / "compliance_test")) + + self.assertTrue( + (self.tmp_dir / "compliance_test" / "tb_vc_compliance.vhd").exists() + ) + self.assertRaises( + RuntimeError, + vc.add_vhdl_testbench, + vc_test_lib, + str(self.tmp_dir / "compliance_test"), + ) diff --git a/tests/unit/test_vhdl_parser.py b/tests/unit/test_vhdl_parser.py index a7bbedf00..51caadb95 100644 --- a/tests/unit/test_vhdl_parser.py +++ b/tests/unit/test_vhdl_parser.py @@ -18,6 +18,7 @@ VHDLArrayType, VHDLReference, VHDLRecordType, + VHDLFunctionSpecification, remove_comments, ) @@ -58,7 +59,7 @@ def test_parsing_entity_with_package_generic(self): self.assertEqual(entity.identifier, "ent") self.assertEqual(entity.ports, []) self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "package_g") + self.assertEqual(entity.generics[0].identifier_list, ["package_g"]) self.assertEqual(entity.generics[0].subtype_indication.type_mark, "integer") def test_parsing_entity_with_type_generic(self): @@ -75,7 +76,7 @@ def test_parsing_entity_with_type_generic(self): self.assertEqual(entity.identifier, "ent") self.assertEqual(entity.ports, []) self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "type_g") + self.assertEqual(entity.generics[0].identifier_list, ["type_g"]) self.assertEqual(entity.generics[0].subtype_indication.type_mark, "integer") def test_parsing_entity_with_string_semicolon_colon(self): @@ -93,13 +94,13 @@ def test_parsing_entity_with_string_semicolon_colon(self): self.assertEqual(entity.identifier, "ent") self.assertEqual(entity.ports, []) self.assertEqual(len(entity.generics), 3) - self.assertEqual(entity.generics[0].identifier, "const") + self.assertEqual(entity.generics[0].identifier_list, ["const"]) self.assertEqual(entity.generics[0].subtype_indication.type_mark, "string") self.assertEqual(entity.generics[0].init_value, '"a;a"') - self.assertEqual(entity.generics[1].identifier, "const2") + self.assertEqual(entity.generics[1].identifier_list, ["const2"]) self.assertEqual(entity.generics[1].subtype_indication.type_mark, "string") self.assertEqual(entity.generics[1].init_value, '";a""a;a"') - self.assertEqual(entity.generics[2].identifier, "const3") + self.assertEqual(entity.generics[2].identifier_list, ["const3"]) self.assertEqual(entity.generics[2].subtype_indication.type_mark, "string") self.assertEqual(entity.generics[2].init_value, '": a b c :"') @@ -120,9 +121,9 @@ def test_parsing_entity_with_function_generic(self): self.assertEqual(entity.identifier, "ent") self.assertEqual(entity.ports, []) self.assertEqual(len(entity.generics), 2) - self.assertEqual(entity.generics[0].identifier, "function_g") + self.assertEqual(entity.generics[0].identifier_list, ["function_g"]) self.assertEqual(entity.generics[0].subtype_indication.type_mark, "boolean") - self.assertEqual(entity.generics[1].identifier, "procedure_g") + self.assertEqual(entity.generics[1].identifier_list, ["procedure_g"]) self.assertEqual(entity.generics[1].subtype_indication.type_mark, "boolean") def test_getting_entities_from_design_file(self): @@ -190,7 +191,7 @@ def test_parsing_references(self): package new_pkg is new lib.pkg; """ ) - self.assertEqual(len(design_file.references), 14) + self.assertEqual(len(design_file.references), 19) self.assertEqual( sorted(design_file.references, key=repr), sorted( @@ -209,6 +210,11 @@ def test_parsing_references(self): VHDLReference("package", "name1", "bla", "all"), VHDLReference("package", "name1", "foo", "all"), VHDLReference("package", "lib", "pkg", None), + VHDLReference("library", "ieee", None, None), + VHDLReference("library", "name1", None, None), + VHDLReference("library", "lib1", None, None), + VHDLReference("library", "lib2", None, None), + VHDLReference("library", "lib3", None, None), ], key=repr, ), @@ -230,14 +236,16 @@ def test_parsing_entity_with_generics(self): generics = entity.generics self.assertEqual(len(generics), 2) - self.assertEqual(generics[0].identifier, "max_value") + self.assertEqual(generics[0].identifier_list, ["max_value"]) self.assertEqual(generics[0].init_value, "(2-19)*4") self.assertEqual(generics[0].mode, None) - self.assertEqual(generics[0].subtype_indication.code, "integer range 2-2 to 2**10") + self.assertEqual( + generics[0].subtype_indication.code, "integer range 2-2 to 2**10" + ) self.assertEqual(generics[0].subtype_indication.type_mark, "integer") # @TODO does not work # self.assertEqual(generics[0].subtypeIndication.constraint, "range 2-2 to 2**10") - self.assertEqual(generics[1].identifier, "enable_foo") + self.assertEqual(generics[1].identifier_list, ["enable_foo"]) self.assertEqual(generics[1].init_value, None) self.assertEqual(generics[1].mode, None) self.assertEqual(generics[1].subtype_indication.code, "boolean") @@ -256,7 +264,7 @@ def test_parsing_entity_with_generics_corner_cases(self): """ ) self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "g") + self.assertEqual(entity.generics[0].identifier_list, ["g"]) entity = self.parse_single_entity( """\ @@ -268,7 +276,7 @@ def test_parsing_entity_with_generics_corner_cases(self): """ ) self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "g") + self.assertEqual(entity.generics[0].identifier_list, ["g"]) entity = self.parse_single_entity( """\ @@ -280,7 +288,7 @@ def test_parsing_entity_with_generics_corner_cases(self): """ ) self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "g") + self.assertEqual(entity.generics[0].identifier_list, ["g"]) entity = self.parse_single_entity( """\ @@ -310,16 +318,20 @@ def test_parsing_entity_with_ports(self): ports = entity.ports self.assertEqual(len(ports), 2) - self.assertEqual(ports[0].identifier, "clk") + self.assertEqual(ports[0].entity_class, "signal") + self.assertEqual(ports[0].identifier_list, ["clk"]) self.assertEqual(ports[0].init_value, None) self.assertEqual(ports[0].mode, "in") self.assertEqual(ports[0].subtype_indication.code, "std_logic") self.assertEqual(ports[0].subtype_indication.type_mark, "std_logic") - self.assertEqual(ports[1].identifier, "data") + self.assertEqual(ports[1].entity_class, "signal") + self.assertEqual(ports[1].identifier_list, ["data"]) self.assertEqual(ports[1].init_value, None) self.assertEqual(ports[1].mode, "out") - self.assertEqual(ports[1].subtype_indication.code, "std_logic_vector(11-1 downto 0)") + self.assertEqual( + ports[1].subtype_indication.code, "std_logic_vector(11-1 downto 0)" + ) self.assertEqual(ports[1].subtype_indication.type_mark, "std_logic_vector") self.assertEqual(ports[1].subtype_indication.constraint, "(11-1 downto 0)") @@ -447,7 +459,8 @@ def test_adding_generics_to_entity(self): entity = VHDLEntity("name") entity.add_generic("max_value", "boolean", "20") self.assertEqual(len(entity.generics), 1) - self.assertEqual(entity.generics[0].identifier, "max_value") + self.assertEqual(entity.generics[0].entity_class, "constant") + self.assertEqual(entity.generics[0].identifier_list, ["max_value"]) self.assertEqual(entity.generics[0].subtype_indication.type_mark, "boolean") self.assertEqual(entity.generics[0].init_value, "20") @@ -455,7 +468,8 @@ def test_adding_ports_to_entity(self): entity = VHDLEntity("name") entity.add_port("foo", "inout", "foo_t") self.assertEqual(len(entity.ports), 1) - self.assertEqual(entity.ports[0].identifier, "foo") + self.assertEqual(entity.ports[0].entity_class, "signal") + self.assertEqual(entity.ports[0].identifier_list, ["foo"]) self.assertEqual(entity.ports[0].mode, "inout") self.assertEqual(entity.ports[0].subtype_indication.type_mark, "foo_t") @@ -476,7 +490,10 @@ def test_that_array_type_declarations_are_found(self): type constrained_badgers_array_t is array ( -1 downto 0 ) of badger_t; type unconstrained_natural_array_t is array ( integer range <> ) of natural; """ - arrays = {e.identifier: e.subtype_indication.type_mark for e in VHDLArrayType.find(code)} + arrays = { + e.identifier: e.subtype_indication.type_mark + for e in VHDLArrayType.find(code) + } expect = { "constrained_integer_array_t": "integer", "unconstrained_fish_array_t": "fish_t", @@ -506,9 +523,13 @@ def test_that_record_type_declarations_are_found(self): self.assertIn("space_time_t", records) self.assertEqual(records["space_time_t"][0].identifier_list, ["x", "y", "z"]) - self.assertEqual(records["space_time_t"][0].subtype_indication.type_mark, "real") + self.assertEqual( + records["space_time_t"][0].subtype_indication.type_mark, "real" + ) self.assertEqual(records["space_time_t"][1].identifier_list, ["t"]) - self.assertEqual(records["space_time_t"][1].subtype_indication.type_mark, "time") + self.assertEqual( + records["space_time_t"][1].subtype_indication.type_mark, "time" + ) self.assertIn("complex_t", records) self.assertEqual(records["complex_t"][0].identifier_list, ["im", "re"]) @@ -516,10 +537,130 @@ def test_that_record_type_declarations_are_found(self): self.assertIn("foo", records) self.assertEqual(records["foo"][0].identifier_list, ["bar"]) - self.assertEqual(records["foo"][0].subtype_indication.type_mark, "std_logic_vector") - self.assertEqual(records["foo"][0].subtype_indication.constraint, "(7 downto 0)") + self.assertEqual( + records["foo"][0].subtype_indication.type_mark, "std_logic_vector" + ) + self.assertEqual( + records["foo"][0].subtype_indication.constraint, "(7 downto 0)" + ) self.assertTrue(records["foo"][0].subtype_indication.array_type) + def test_parsing_interface_element(self): + element = VHDLInterfaceElement.parse("a : bit") + self.assertEqual(element.identifier_list, ["a"]) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, None) + self.assertEqual(element.mode, None) + self.assertEqual(element.init_value, None) + + element = VHDLInterfaceElement.parse("a : in bit") + self.assertEqual(element.identifier_list, ["a"]) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, None) + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, None) + + element = VHDLInterfaceElement.parse( + "a : in bit", default_entity_class="constant" + ) + self.assertEqual(element.identifier_list, ["a"]) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, "constant") + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, None) + + element = VHDLInterfaceElement.parse( + "signal a : in bit", default_entity_class="constant" + ) + self.assertEqual(element.identifier_list, ["a"]) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, "signal") + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, None) + + element = VHDLInterfaceElement.parse( + "signal a : in bit := '1'", default_entity_class="constant" + ) + self.assertEqual(element.identifier_list, ["a"]) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, "signal") + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, "'1'") + + element = VHDLInterfaceElement.parse("signal a, b : in bit := '1'") + self.assertEqual(len(element.identifier_list), 2) + self.assertIn("a", element.identifier_list) + self.assertIn("b", element.identifier_list) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, "signal") + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, "'1'") + + element = VHDLInterfaceElement.parse( + """\ +signal a ,b, + c:in bit:='1'""" + ) + self.assertEqual(len(element.identifier_list), 3) + self.assertIn("a", element.identifier_list) + self.assertIn("b", element.identifier_list) + self.assertIn("c", element.identifier_list) + self.assertEqual(element.subtype_indication.type_mark, "bit") + self.assertEqual(element.entity_class, "signal") + self.assertEqual(element.mode, "in") + self.assertEqual(element.init_value, "'1'") + + def test_that_function_declarations_are_found(self): + code = """\ +function with_no_parameters return boolean; +impure function with_side_effects return boolean; +function with_single_parameter(a : bit) return integer; +function with_multiple_parameters(a : bit; b : boolean) return integer; +function with_whitespaces ( a:bit ;b : boolean ) +return integer ; +""" + + functions = {f.identifier: f for f in VHDLFunctionSpecification.find(code)} + self.assertEqual(len(functions), 5) + + self.assertIn("with_no_parameters", functions) + self.assertEqual(functions["with_no_parameters"].return_type_mark, "boolean") + self.assertFalse(functions["with_no_parameters"].parameter_list) + + self.assertIn("with_side_effects", functions) + self.assertEqual(functions["with_side_effects"].return_type_mark, "boolean") + self.assertFalse(functions["with_side_effects"].parameter_list) + + self.assertIn("with_single_parameter", functions) + func = functions["with_single_parameter"] + self.assertEqual(func.return_type_mark, "integer") + self.assertEqual(len(func.parameter_list), 1) + self.assertEqual(func.parameter_list[0].entity_class, "constant") + self.assertEqual(func.parameter_list[0].identifier_list, ["a"]) + self.assertEqual(func.parameter_list[0].subtype_indication.type_mark, "bit") + + self.assertIn("with_multiple_parameters", functions) + func = functions["with_multiple_parameters"] + self.assertEqual(func.return_type_mark, "integer") + self.assertEqual(len(func.parameter_list), 2) + self.assertEqual(func.parameter_list[0].entity_class, "constant") + self.assertEqual(func.parameter_list[0].identifier_list, ["a"]) + self.assertEqual(func.parameter_list[0].subtype_indication.type_mark, "bit") + self.assertEqual(func.parameter_list[1].entity_class, "constant") + self.assertEqual(func.parameter_list[1].identifier_list, ["b"]) + self.assertEqual(func.parameter_list[1].subtype_indication.type_mark, "boolean") + + self.assertIn("with_whitespaces", functions) + func = functions["with_whitespaces"] + self.assertEqual(func.return_type_mark, "integer") + self.assertEqual(len(func.parameter_list), 2) + self.assertEqual(func.parameter_list[0].entity_class, "constant") + self.assertEqual(func.parameter_list[0].identifier_list, ["a"]) + self.assertEqual(func.parameter_list[0].subtype_indication.type_mark, "bit") + self.assertEqual(func.parameter_list[1].entity_class, "constant") + self.assertEqual(func.parameter_list[1].identifier_list, ["b"]) + self.assertEqual(func.parameter_list[1].subtype_indication.type_mark, "boolean") + def test_remove_comments(self): self.assertEqual(remove_comments("a\n-- foo \nb"), "a\n \nb") @@ -564,11 +705,15 @@ def _create_entity(): """ Helper function to create a VHDLEntity """ - data_width = VHDLInterfaceElement("data_width", VHDLSubtypeIndication.parse("natural := 16")) + data_width = VHDLInterfaceElement( + "constant", "data_width", VHDLSubtypeIndication.parse("natural := 16") + ) - clk = VHDLInterfaceElement("clk", VHDLSubtypeIndication.parse("std_logic"), "in") + clk = VHDLInterfaceElement( + "signal", "clk", VHDLSubtypeIndication.parse("std_logic"), "in" + ) data = VHDLInterfaceElement( - "data", + "signal" "data", VHDLSubtypeIndication.parse("std_logic_vector(data_width-1 downto 0)"), "out", ) diff --git a/vunit/__init__.py b/vunit/__init__.py index 133bc692b..b376dfc35 100644 --- a/vunit/__init__.py +++ b/vunit/__init__.py @@ -13,6 +13,7 @@ from vunit.ui import VUnit from vunit.vunit_cli import VUnitCLI from vunit.about import version, doc +from vunit.vc import VerificationComponent, VerificationComponentInterface # Repository root ROOT = str(Path(__file__).parent.parent.resolve()) diff --git a/vunit/project.py b/vunit/project.py index d79b9dfb9..872a000e7 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -213,6 +213,9 @@ def _find_other_vhdl_design_unit_dependencies( # pylint: disable=too-many-branc LOGGER.warning("%s: failed to find library '%s'", source_file.name, ref.library) continue + if ref.is_library_reference(): + continue + if ref.is_entity_reference() and ref.design_unit in library.modules: # Is a verilog module instantiation yield library.modules[ref.design_unit].source_file diff --git a/vunit/source_file.py b/vunit/source_file.py index 608c5ebe3..0c1d92692 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -297,7 +297,10 @@ def _find_design_units(self, design_file): """ result = [] for entity in design_file.entities: - generic_names = [generic.identifier for generic in entity.generics] + generic_names = [] + for generic in entity.generics: + for identifier in generic.identifier_list: + generic_names.append(identifier) result.append(Entity(entity.identifier, self, generic_names)) for context in design_file.contexts: diff --git a/vunit/ui/entity.py b/vunit/ui/entity.py new file mode 100644 index 000000000..d5ae9ac9c --- /dev/null +++ b/vunit/ui/entity.py @@ -0,0 +1,41 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +""" +UI class Entity +""" + + +class Entity(object): + """ + User interface of an Entity + """ + + def __init__(self, library_name, entity_name, source_file): + self._library_name = library_name + self._entity_name = entity_name + self._source_file = source_file + + @property + def name(self): + """ + :returns: The entity name + """ + return self._entity_name + + @property + def library(self): + """ + :returns: The library that contains this entity + """ + return self._library_name + + @property + def source_file(self): + """ + :returns: The source file that contains this entity + """ + return self._source_file diff --git a/vunit/ui/library.py b/vunit/ui/library.py index 7ccf625c9..e5c1e3251 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -18,7 +18,8 @@ from .common import check_not_empty, get_checked_file_names_from_globs from .source import SourceFile, SourceFileList from .testbench import TestBench -from .packagefacade import PackageFacade +from .package_facade import PackageFacade +from .entity import Entity class Library(object): @@ -261,25 +262,45 @@ def add_source_file( # pylint: disable=too-many-arguments return SourceFile(source_file, self._project, self._parent) - def package(self, name): + def _get_design_unit(self, name): """ - Get a package within the library + Get design unit from name """ library = self._project.get_library(self._library_name) design_unit = library.primary_design_units.get(name) if design_unit is None: raise KeyError(name) + + return design_unit + + def package(self, name): + """ + Get a package within the library + """ + design_unit = self._get_design_unit(name) + if design_unit.unit_type != "package": raise KeyError(name) return PackageFacade(self._parent, self._library_name, name, design_unit) - def entity(self, name): + def get_entity(self, name): """ Get an entity within the library + """ + design_unit = self._get_design_unit(name) + + if design_unit.unit_type != "entity": + raise KeyError(name) + + return Entity(self._library_name, name, design_unit.source_file) + + def entity(self, name): + """ + Get a test bench within this library - :param name: The name of the entity + :param name: The name of the test bench entity :returns: A :class:`.TestBench` object :raises: KeyError """ diff --git a/vunit/ui/packagefacade.py b/vunit/ui/package_facade.py similarity index 75% rename from vunit/ui/packagefacade.py rename to vunit/ui/package_facade.py index 8d675d097..1388b8421 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/package_facade.py @@ -38,3 +38,24 @@ def generate_codecs(self, codec_package_name=None, used_packages=None, output_fi codec_generator.generate_codecs(self._design_unit, codec_package_name, used_packages, output_file_name) return self._parent.add_source_files(output_file_name, self._library_name) + + @property + def name(self): + """ + :returns: The package name + """ + return self._package_name + + @property + def library(self): + """ + :returns: The library that contains this package + """ + return self._library_name + + @property + def source_file(self): + """ + :returns: The source file that contains this package + """ + return self._design_unit.source_file diff --git a/vunit/vc/__init__.py b/vunit/vc/__init__.py new file mode 100644 index 000000000..787597729 --- /dev/null +++ b/vunit/vc/__init__.py @@ -0,0 +1,12 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +""" +Code related to VUnit verification components. +""" + +from vunit.vc.verification_component import VerificationComponent +from vunit.vc.verification_component_interface import VerificationComponentInterface diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py new file mode 100644 index 000000000..b41a0f004 --- /dev/null +++ b/vunit/vc/compliance_test.py @@ -0,0 +1,139 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +""" +Module for generating a compliance test for a VUnit verification component +""" + +import argparse +import sys +import logging +from pathlib import Path +from vunit.vc.verification_component import VerificationComponent +from vunit.vc.verification_component_interface import VerificationComponentInterface + + +def _create_vc_template(args): + """Creates VC testbench template from args.""" + template_code, vc_name = VerificationComponent.create_vhdl_testbench_template( + args.vc_lib_name, args.vc_path, args.vci_path + ) + if not template_code or not vc_name: + sys.exit(1) + + if not args.output_path: + output_dir = args.vc_path.parent / ".vc" + if not output_dir.exists(): + output_dir.mkdir(parents=True) + + output_path = output_dir / ("tb_%s_compliance_template.vhd" % vc_name) + elif args.output_path.is_dir(): + output_path = args.output_path / ("tb_%s_compliance_template.vhd" % vc_name) + else: + output_path = args.output_path + + output_path.write_text(template_code) + print( + "Open %s and read the TODOs to complete the template." % output_path.resolve() + ) + + +def _create_vci_template(args): + """Creates VCI testbench template from args.""" + ( + template_code, + vci_name, + ) = VerificationComponentInterface.create_vhdl_testbench_template( + args.vc_lib_name, args.vci_path, args.vc_handle_t + ) + if not template_code or not vci_name: + sys.exit(1) + + if not args.output_path: + output_dir = args.vc_path.parent / ".vc" / vci_name + if not output_dir.exists(): + output_dir.mkdir(parents=True) + + output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) + elif args.output_path.is_dir(): + output_dir = args.output_path / vci_name + if not output_dir.exists(): + output_dir.exists(parents=True) + output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) + else: + output_path = args.output_path + + output_path.write_text(template_code) + print( + "Open %s and read the TODOs to complete the template." % output_path.resolve() + ) + + +def main(): + """Parses the command line arguments and acts accordingly.""" + + def create_vc_parser(subparsers): + parser = subparsers.add_parser( + "create-vc", help="Creates a VC compliance test template" + ) + parser.add_argument( + "-l", + "--vc-lib-name", + help="Name of library hosting the VC and the VCI (default: vc_lib)", + default="vc_lib", + ) + parser.add_argument( + "-o", + "--output-path", + type=Path, + help="Path to the template (default: ./compliance_test/tb__compliance_template.vhd)", + ) + parser.add_argument( + "vc_path", type=Path, help="Path to file containing the VC entity" + ) + parser.add_argument( + "vci_path", type=Path, help="Path to file containing the VCI package" + ) + + def create_vci_parser(subparsers): + parser = subparsers.add_parser( + "create-vci", help="Creates a VCI compliance test template" + ) + parser.add_argument( + "-l", + "--vc-lib-name", + help="Name of library hosting the VC and the VCI (default: vc_lib)", + default="vc_lib", + ) + parser.add_argument( + "-o", + "--output-path", + type=Path, + help="Path to the template (default: ./compliance_test/tb__compliance_template.vhd)", + ) + parser.add_argument( + "vci_path", type=Path, help="Path to file containing the VCI package" + ) + parser.add_argument("vc_handle_t", help="VC handle type") + + parser = argparse.ArgumentParser(description="Compliance test tool") + subparsers = parser.add_subparsers(dest="subparser_name", help="sub-command help") + + create_vc_parser(subparsers) + create_vci_parser(subparsers) + + args = parser.parse_args(sys.argv[1:]) + + logging.basicConfig(format="%(levelname)s: %(message)s") + + if args.subparser_name == "create-vc": + _create_vc_template(args) + elif args.subparser_name == "create-vci": + _create_vci_template(args) + + +if __name__ == "__main__": + main() diff --git a/vunit/vc/vc_template.py b/vunit/vc/vc_template.py new file mode 100644 index 000000000..cace9a997 --- /dev/null +++ b/vunit/vc/vc_template.py @@ -0,0 +1,135 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +"""Templates for the verification component testbench.""" + +from string import Template + + +TB_TEMPLATE_TEMPLATE = Template( + """\ +-- Read the TODOs to complete this template. + +${context_items} +entity tb_${vc_name}_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_${vc_name}_compliance is + +${constructor} +${signal_declarations} +begin + -- DO NOT modify the test runner process. + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + +${vc_instantiation} +end architecture; +""" +) + +ARCHITECTURE_DECLARATIONS_TEMPLATE = Template( + """\ + constant custom_actor : actor_t := new_actor("vc", inbox_size => 1); + constant custom_logger : logger_t := get_logger("vc"); + constant custom_checker : checker_t := new_checker(get_logger("vc_check")); + + impure function create_handle return ${vc_handle_t} is + variable handle : ${vc_handle_t}; + variable logger : logger_t := ${default_logger}; + variable actor : actor_t := ${default_actor}; + variable checker : checker_t := ${default_checker}; + begin + if use_custom_logger then + logger := custom_logger; + end if; + + if use_custom_actor then + actor := custom_actor; + end if; + + if use_custom_checker then + checker := custom_checker; + end if; + + return ${vc_constructor_name}( + ${specified_parameters} + logger => logger, + actor => actor, + checker => checker, + unexpected_msg_type_policy => unexpected_msg_type_policy); + end; + + constant ${vc_handle_name} : ${vc_handle_t} := create_handle; + constant unexpected_msg : msg_type_t := new_msg_type("unexpected msg"); +""" +) + +TEST_RUNNER_TEMPLATE = Template( + """\ +test_runner : process + variable t_start : time; + variable msg : msg_t; + variable error_logger : logger_t; +begin + test_runner_setup(runner, runner_cfg); + + while test_suite loop + + if run("Test that sync interface is supported") then + t_start := now; + wait_for_time(net, as_sync(${vc_handle_name}), 1 ns); + wait_for_time(net, as_sync(${vc_handle_name}), 2 ns); + wait_for_time(net, as_sync(${vc_handle_name}), 3 ns); + check_equal(now - t_start, 0 ns); + t_start := now; + wait_until_idle(net, as_sync(${vc_handle_name})); + check_equal(now - t_start, 6 ns); + + elsif run("Test that the actor can be customised") then + t_start := now; + wait_for_time(net, as_sync(${vc_handle_name}), 1 ns); + wait_for_time(net, as_sync(${vc_handle_name}), 2 ns); + check_equal(now - t_start, 0 ns); + wait_for_time(net, as_sync(${vc_handle_name}), 3 ns); + check_equal(now - t_start, 1 ns); + wait_until_idle(net, as_sync(${vc_handle_name})); + check_equal(now - t_start, 6 ns); + + elsif run("Test unexpected message handling") then + if use_custom_checker then + error_logger := get_logger(custom_checker); + else + error_logger := custom_logger; + end if; + mock(error_logger, failure); + msg := new_msg(unexpected_msg); + send(net, custom_actor, msg); + wait for 1 ns; + if unexpected_msg_type_policy = fail then + check_only_log(error_logger, "Got unexpected message unexpected msg", failure); + else + check_no_log; + end if; + unmock(error_logger); + end if; + + end loop; + + test_runner_cleanup(runner); +end process test_runner;""" +) + +GENERICS_TEMPLATE = """use_custom_logger : boolean := false; + use_custom_checker : boolean := false; + use_custom_actor : boolean := false; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + runner_cfg : string""" diff --git a/vunit/vc/vci_template.py b/vunit/vc/vci_template.py new file mode 100644 index 000000000..f25ae9710 --- /dev/null +++ b/vunit/vc/vci_template.py @@ -0,0 +1,135 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +"""Templates for the verification component interface testbench""" + +from string import Template + +TB_TEMPLATE_TEMPLATE = Template( + """\ +-- Read the TODOs to complete this template. + +${context_items} +entity tb_${vc_handle_t}_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_${vc_handle_t}_compliance is +begin + test_runner : process + -- TODO: Specify a value for all listed constants. +${constant_declarations} + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" +) + +TB_EPILOGUE_TEMPLATE = Template( + """ + constant actor1 : actor_t := new_actor("actor1"); + constant logger1 : logger_t := get_logger("logger1"); + constant checker_logger1 : logger_t := get_logger("checker1"); + constant checker1 : checker_t := new_checker(checker_logger1); + + constant actor2 : actor_t := new_actor("actor2"); + constant logger2 : logger_t := get_logger("logger2"); + constant checker_logger2 : logger_t := get_logger("checker2"); + constant checker2 : checker_t := new_checker(checker_logger2); + + constant actor3 : actor_t := new_actor("actor3"); + constant logger3 : logger_t := get_logger("logger3"); + constant checker_logger3 : logger_t := get_logger("checker3"); + constant checker3 : checker_t := new_checker(checker_logger3); + + variable handle1, handle2, handle3 : ${vc_handle_t}; + variable std_cfg1, std_cfg2, std_cfg3 : std_cfg_t; + begin + test_runner_setup(runner, runner_cfg); + + while test_suite loop + if run("Test standard configuration") then +${handle1} + std_cfg1 := get_std_cfg(handle1); + + check(get_actor(std_cfg1) = actor1, "Failed to configure actor with ${vc_constructor_name}"); + check(get_logger(std_cfg1) = logger1, "Failed to configure logger with ${vc_constructor_name}"); + check(get_checker(std_cfg1) = checker1, "Failed to configure checker with ${vc_constructor_name}"); + check(unexpected_msg_type_policy(std_cfg1) = fail, + "Failed to configure unexpected_msg_type_policy = fail with ${vc_constructor_name}"); + +${handle2} + std_cfg2 := get_std_cfg(handle2); + + check(unexpected_msg_type_policy(std_cfg2) = ignore, + "Failed to configure unexpected_msg_type_policy = ignore with ${vc_constructor_name}"); + + elsif run("Test handle independence") then +${handle1} +${handle3} + + std_cfg1 := get_std_cfg(handle1); + std_cfg2 := get_std_cfg(handle2); + check(get_actor(std_cfg1) /= get_actor(std_cfg2), + "Actor shared between handles created by ${vc_constructor_name}"); + check(get_logger(std_cfg1) /= get_logger(std_cfg2), + "Logger shared between handles created by ${vc_constructor_name}"); + check(get_checker(std_cfg1) /= get_checker(std_cfg2), + "Checker shared between handles created by ${vc_constructor_name}"); + check(unexpected_msg_type_policy(std_cfg1) /= unexpected_msg_type_policy(std_cfg2), + "unexpected_msg_type_policy shared between handles created by ${vc_constructor_name}"); + + elsif run("Test default logger") then +${handle4} + std_cfg1 := get_std_cfg(handle1); + check(get_logger(std_cfg1) /= null_logger, + "No valid default logger (null_logger) created by ${vc_constructor_name}"); + check(get_logger(std_cfg1) /= default_logger, + "No valid default logger (default_logger) created by ${vc_constructor_name}"); + +${handle5} + std_cfg2 := get_std_cfg(handle2); + check(get_logger(std_cfg2) /= null_logger, + "No valid default logger (null_logger) created by ${vc_constructor_name}"); + check(get_logger(std_cfg2) /= default_logger, + "No valid default logger (default_logger) created by ${vc_constructor_name}"); + + elsif run("Test default checker") then +${handle6} + std_cfg1 := get_std_cfg(handle1); + check(get_checker(std_cfg1) /= null_checker, + "No valid default checker (null_checker) created by ${vc_constructor_name}"); + check(get_checker(std_cfg1) /= default_checker, + "No valid default checker (default_checker) created by ${vc_constructor_name}"); + +${handle7} + std_cfg2 := get_std_cfg(handle2); + check(get_checker(std_cfg2) /= null_checker, + "No valid default checker (null_checker) created by ${vc_constructor_name}"); + check(get_checker(std_cfg2) /= default_checker, + "No valid default checker (default_checker) created by ${vc_constructor_name}"); + +${handle8} + std_cfg3 := get_std_cfg(handle3); + check(get_checker(std_cfg3) /= null_checker, + "No valid default checker (null_checker) created by ${vc_constructor_name}"); + check(get_checker(std_cfg3) /= default_checker, + "No valid default checker (default_checker) created by ${vc_constructor_name}"); + check(get_logger(get_checker(std_cfg3)) = logger3, + "Default checker not based on logger provided to ${vc_constructor_name}"); + + end if; + end loop; + + test_runner_cleanup(runner); + end process test_runner; +end architecture; +""" +) diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py new file mode 100644 index 000000000..958b420a2 --- /dev/null +++ b/vunit/vc/verification_component.py @@ -0,0 +1,481 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +"""VerificationComponent class.""" + +import sys +import re +from pathlib import Path +from re import subn, MULTILINE, IGNORECASE, DOTALL +from vunit.vc.vc_template import ( + TB_TEMPLATE_TEMPLATE, + ARCHITECTURE_DECLARATIONS_TEMPLATE, + TEST_RUNNER_TEMPLATE, + GENERICS_TEMPLATE, +) +from vunit.vhdl_parser import ( + VHDLDesignFile, + find_closing_delimiter, + remove_comments, +) +from vunit.vc.verification_component_interface import ( + VerificationComponentInterface, + create_context_items, + LOGGER, +) + + +class VerificationComponent: + """Represents a Verification Component (VC).""" + + @classmethod + def find(cls, vc_lib, vc_name, vci): + """ Finds the specified VC if present. + + :param vc_lib: Library object containing the VC. + :param vc_name: Name of VC entity. + :param vci: A VerificationComponentInterface object representing the VCI used by the VC. + + :returns: A VerificationComponent object. + """ + + if not vci: + LOGGER.error("No VCI provided") + sys.exit(1) + + try: + vc_facade = vc_lib.get_entity(vc_name) + except KeyError: + LOGGER.error("Failed to find VC %s", vc_name) + sys.exit(1) + + vc_code = cls.validate(vc_facade.source_file.name) + if not vc_code: + sys.exit(1) + + vc_entity = vc_code.entities[0] + vc_handle_t = vc_entity.generics[0].subtype_indication.type_mark + + if vc_handle_t != vci.vc_constructor.return_type_mark: + LOGGER.error( + "VC handle (%s) doesn't match that of the VCI (%s)", + vc_handle_t, + vci.vc_constructor.return_type_mark, + ) + sys.exit(1) + + return cls(vc_facade, vc_code, vc_entity, vc_handle_t, vci) + + def __init__(self, vc_facade, vc_code, vc_entity, vc_handle_t, vci): + self.vc_facade = vc_facade + self.vc_code = vc_code + self.vc_entity = vc_entity + self.vc_handle_t = vc_handle_t + self.vci = vci + + @staticmethod + def validate(vc_path): + """Validates the existence and contents of the verification component.""" + vc_path = Path(vc_path) + with vc_path.open() as fptr: + vc_code = VHDLDesignFile.parse(fptr.read()) + + if len(vc_code.entities) != 1: + LOGGER.error("%s must contain a single VC entity", vc_path) + return None + + vc_entity = vc_code.entities[0] + + if not ( + (len(vc_entity.generics) == 1) + and (len(vc_entity.generics[0].identifier_list) == 1) + ): + LOGGER.error("%s must have a single generic", vc_entity.identifier) + return None + + return vc_code + + @staticmethod + def create_vhdl_testbench_template(vc_lib_name, vc_path, vci_path): + """ + Creates a template for a VC compliance testbench. + + :param vc_lib_name: Name of the library containing the verification component and its interface. + :param vc_path: Path to the file containing the verification component entity. + :param vci_path: Path to the file containing the verification component interface package. + + :returns: The template string and the name of the verification component entity. + """ + vc_path = Path(vc_path) + vci_path = Path(vci_path) + + def create_constructor(vc_entity, vc_handle_t, vc_constructor): + unspecified_parameters = [] + for parameter in vc_constructor.parameter_list: + if not parameter.init_value: + unspecified_parameters += parameter.identifier_list + + constructor = ( + " -- TODO: Specify a value for all listed parameters. Keep all parameters on separate lines\n" + if unspecified_parameters + else "" + ) + constructor += " constant %s : %s := %s" % ( + vc_entity.generics[0].identifier_list[0], + vc_handle_t, + vc_constructor.identifier, + ) + + if not unspecified_parameters: + constructor += ";\n" + else: + constructor += "(\n" + for parameter in unspecified_parameters: + if parameter in [ + "actor", + "logger", + "checker", + "unexpected_msg_type_policy", + ]: + continue + constructor += " %s => ,\n" % parameter + constructor = constructor[:-2] + "\n );\n" + + return constructor + + def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): + signal_declarations = ( + " -- TODO: Constrain any unconstrained signal connecting to the DUT.\n" + if vc_entity.ports + else "" + ) + port_mappings = "" + for port in vc_entity.ports: + if (port.mode != "out") and port.init_value: + for identifier in port.identifier_list: + port_mappings += " %s => open,\n" % identifier + else: + signal_declarations += " signal %s : %s;\n" % ( + ", ".join(port.identifier_list), + port.subtype_indication, + ) + for identifier in port.identifier_list: + port_mappings += " %s => %s,\n" % (identifier, identifier,) + + vc_instantiation = """ -- DO NOT modify the VC instantiation. + vc_inst: entity %s.%s + generic map(%s)""" % ( + vc_lib_name, + vc_entity.identifier, + vc_entity.generics[0].identifier_list[0], + ) + + if len(vc_entity.ports) > 0: + vc_instantiation = ( + vc_instantiation + + """ + port map( +""" + ) + + vc_instantiation += port_mappings[:-2] + "\n );\n" + else: + vc_instantiation += ";\n" + + return signal_declarations, vc_instantiation + + vc_path = Path(vc_path).resolve() + vci_path = Path(vci_path).resolve() + + vc_code = VerificationComponent.validate(vc_path) + vc_entity = vc_code.entities[0] + vc_handle_t = vc_entity.generics[0].subtype_indication.type_mark + vci_code, vc_constructor = VerificationComponentInterface.validate( + vci_path, vc_handle_t + ) + if (not vci_code) or (not vc_constructor): + return None, None + + ( + signal_declarations, + vc_instantiation, + ) = create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name) + + initial_package_refs = set( + [ + "vunit_lib.sync_pkg.all", + "%s.%s.all" % (vc_lib_name, vci_code.packages[0].identifier), + ] + ) + context_items = create_context_items( + vc_code, + vc_lib_name, + initial_library_names=set(["std", "work", "vunit_lib", vc_lib_name]), + initial_context_refs=set( + ["vunit_lib.vunit_context", "vunit_lib.com_context"] + ), + initial_package_refs=initial_package_refs, + ) + + return ( + TB_TEMPLATE_TEMPLATE.substitute( + context_items=context_items, + vc_name=vc_entity.identifier, + constructor=create_constructor(vc_entity, vc_handle_t, vc_constructor), + signal_declarations=signal_declarations, + vc_instantiation=vc_instantiation, + ), + vc_entity.identifier, + ) + + def create_vhdl_testbench(self, template_path=None): + """ + Creates a VHDL VC compliance testbench. + + :param template_path: Path to template file. If None, a default template is assumed. + + :returns: The testbench code as a string. + """ + template_path = Path(template_path) if template_path is not None else None + + if template_path: + template_path = Path(template_path).resolve() + + def update_architecture_declarations(code): + _constructor_call_start_re = re.compile( + r"\bconstant\s+{vc_handle_name}\s*:\s*{vc_handle_t}\s*:=\s*{vc_constructor_name}".format( + vc_handle_name=self.vc_entity.generics[0].identifier_list[0], + vc_handle_t=self.vc_handle_t, + vc_constructor_name=self.vci.vc_constructor.identifier, + ), + MULTILINE | IGNORECASE | DOTALL, + ) + + constructor_call_start = _constructor_call_start_re.search(code) + if not constructor_call_start: + raise RuntimeError( + "Failed to find call to %s in template_path %s" + % (self.vci.vc_constructor.identifier, template_path) + ) + + parameter_start_re = re.compile(r"\s*\(", MULTILINE | IGNORECASE | DOTALL) + parameter_start = parameter_start_re.match( + code[constructor_call_start.end() :] + ) + + if parameter_start: + closing_parenthesis_pos = find_closing_delimiter( + "\\(", + "\\)", + code[constructor_call_start.end() + parameter_start.end() :], + ) + + specified_parameters = ( + code[ + constructor_call_start.end() + + parameter_start.end() : constructor_call_start.end() + + parameter_start.end() + + closing_parenthesis_pos + - 1 + ].strip() + + "," + ) + + else: + specified_parameters = "" + + _constructor_call_end_re = re.compile( + r"\s*;", MULTILINE | IGNORECASE | DOTALL + ) + if parameter_start: + search_start = ( + constructor_call_start.end() + + parameter_start.end() + + closing_parenthesis_pos + ) + constructor_call_end_match = _constructor_call_end_re.match( + code[search_start:] + ) + else: + search_start = constructor_call_start.end() + constructor_call_end_match = _constructor_call_end_re.match( + code[search_start:] + ) + + if not constructor_call_end_match: + raise RuntimeError( + "Missing trailing semicolon for %s in template_path %s" + % (self.vci.vc_constructor.identifier, template_path) + ) + + constructor_call_end = search_start + constructor_call_end_match.end() + + default_values = {} + for parameter in self.vci.vc_constructor.parameter_list: + for identifier in parameter.identifier_list: + default_values[identifier] = parameter.init_value + + architecture_declarations = ARCHITECTURE_DECLARATIONS_TEMPLATE.substitute( + vc_handle_t=self.vc_handle_t, + vc_constructor_name=self.vci.vc_constructor.identifier, + specified_parameters=specified_parameters, + vc_handle_name=self.vc_entity.generics[0].identifier_list[0], + default_logger=default_values["logger"] + if default_values["logger"] + else 'get_logger("vc_logger")', + default_actor=default_values["actor"] + if default_values["actor"] + else 'new_actor("vc_actor")', + default_checker=default_values["checker"] + if default_values["checker"] + else 'new_checker("vc_checker")', + ) + + return ( + code[: constructor_call_start.start()] + + architecture_declarations + + code[constructor_call_end:] + ) + + def update_test_runner(code): + _test_runner_re = re.compile( + r"\btest_runner\s*:\s*process.*?end\s+process\s+test_runner\s*;", + # r"\btest_runner\s*:\s*process", + MULTILINE | IGNORECASE | DOTALL, + ) + + new_test_runner = TEST_RUNNER_TEMPLATE.substitute( + vc_handle_name=self.vc_entity.generics[0].identifier_list[0] + ) + + code, num_found_test_runners = subn( + _test_runner_re, new_test_runner, code, 1 + ) + if not num_found_test_runners: + raise RuntimeError( + "Failed to find test runner in template_path %s" % template_path + ) + + return code + + def update_generics(code): + _runner_cfg_re = re.compile( + r"\brunner_cfg\s*:\s*string", MULTILINE | IGNORECASE | DOTALL + ) + + code, num_found_runner_cfg = subn( + _runner_cfg_re, GENERICS_TEMPLATE, code, 1 + ) + if not num_found_runner_cfg: + raise RuntimeError( + "Failed to find runner_cfg generic in template_path %s" + % template_path + ) + + return code + + if template_path: + template_code = template_path.read_text().lower() + else: + template_code, _ = self.create_vhdl_testbench_template( + self.vc_facade.library, + self.vc_facade.source_file.name, + self.vci.vci_facade.source_file.name, + ) + if not template_code: + return None + template_code = template_code.lower() + + design_file = VHDLDesignFile.parse(template_code) + if ( + design_file.entities[0].identifier + != "tb_%s_compliance" % self.vc_facade.name + ): + raise RuntimeError( + "%s is not a template_path for %s" + % (template_path, self.vc_facade.name) + ) + + tb_code = update_architecture_declarations(template_code) + tb_code = update_test_runner(tb_code) + tb_code = update_generics(tb_code) + + return remove_comments(tb_code) + + def add_vhdl_testbench(self, vc_test_lib, test_dir, template_path=None): + """ + Adds a VHDL compliance testbench + + :param vc_test_lib: The name of the library to which the testbench is added. + :param test_dir: The name of the directory where the testbench file is stored. + :param template_path: Path to testbench template file. If None, a default template is used. + + :returns: The :class:`.SourceFile` for the added testbench. + + :example: + + .. code-block:: python + + ROOT = Path(__file__).parent() + prj.add_vhdl_testbench("test_lib", ROOT / "test", ROOT / ".vc" /"vc_template.vhd") + + """ + test_dir = Path(test_dir).resolve() + template_path = Path(template_path) if template_path is not None else None + + try: + vc_test_lib.test_bench("tb_%s_compliance" % self.vc_entity.identifier) + raise RuntimeError( + "tb_%s_compliance already exists in %s" + % (self.vc_entity.identifier, vc_test_lib.name) + ) + except KeyError: + pass + + if not test_dir.exists(): + test_dir.mkdir(parents=True) + + tb_path = test_dir / ("tb_%s_compliance.vhd" % self.vc_entity.identifier) + testbench_code = self.create_vhdl_testbench(template_path) + if not testbench_code: + return None + tb_path.write_text(testbench_code) + + tb_file = vc_test_lib.add_source_file(str(tb_path)) + testbench = vc_test_lib.test_bench( + "tb_%s_compliance" % self.vc_entity.identifier + ) + test = testbench.test("Test that the actor can be customised") + test.set_generic("use_custom_actor", True) + + test = testbench.test("Test unexpected message handling") + test.add_config( + name="accept_unexpected_msg_type", + generics=dict( + unexpected_msg_type_policy="ignore", + use_custom_logger=True, + use_custom_actor=True, + ), + ) + test.add_config( + name="fail_unexpected_msg_type_with_null_checker", + generics=dict( + unexpected_msg_type_policy="fail", + use_custom_logger=True, + use_custom_actor=True, + ), + ) + test.add_config( + name="fail_unexpected_msg_type_with_custom_checker", + generics=dict( + unexpected_msg_type_policy="fail", + use_custom_logger=True, + use_custom_checker=True, + use_custom_actor=True, + ), + ) + + return tb_file diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py new file mode 100644 index 000000000..b9072e195 --- /dev/null +++ b/vunit/vc/verification_component_interface.py @@ -0,0 +1,480 @@ +# 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +"""VerificationComponentInterface class.""" + +import sys +import re +import logging +from pathlib import Path +from vunit.vc.vci_template import TB_TEMPLATE_TEMPLATE, TB_EPILOGUE_TEMPLATE +from vunit.vhdl_parser import ( + VHDLDesignFile, + VHDLFunctionSpecification, + remove_comments, + VHDLRecordType, +) + +LOGGER = logging.getLogger(__name__) + + +def create_context_items( + code, lib_name, initial_library_names, initial_context_refs, initial_package_refs +): + """Creates a VHDL snippet with context items found in the provided code and the initial_ arguments.""" + for ref in code.references: + if ref.is_package_reference() or ref.is_context_reference(): + initial_library_names.add(ref.library_name) + + library_name = ref.library_name if ref.library_name != "work" else lib_name + + if ref.is_context_reference(): + initial_context_refs.add("%s.%s" % (library_name, ref.design_unit_name)) + + if ref.is_package_reference(): + initial_package_refs.add( + "%s.%s.%s" % (library_name, ref.design_unit_name, ref.name_within) + ) + + context_items = "" + for library in sorted(initial_library_names): + if library not in ["std", "work"]: + context_items += "library %s;\n" % library + + for context_ref in sorted(initial_context_refs): + context_items += "context %s;\n" % context_ref + + for package_ref in sorted(initial_package_refs): + context_items += "use %s;\n" % package_ref + + return context_items + + +class VerificationComponentInterface: + """Represents a Verification Component Interface (VCI).""" + + @classmethod + def find(cls, vc_lib, vci_name, vc_handle_t): + """ Finds the specified VCI if present. + + :param vc_lib: Library object containing the VCI. + :param vci_name: Name of VCI package. + :param vc_handle_t: Name of VC handle type. + + :returns: A VerificationComponentInterface object. + """ + + try: + vci_facade = vc_lib.package(vci_name) + except KeyError: + LOGGER.error("Failed to find VCI %s", vci_name) + sys.exit(1) + + _, vc_constructor = cls.validate(vci_facade.source_file.name, vc_handle_t) + if not vc_constructor: + sys.exit(1) + + return cls(vci_facade, vc_constructor) + + @classmethod + def validate(cls, vci_path, vc_handle_t): + """Validates the existence and contents of the verification component interface.""" + vci_path = Path(vci_path) + + with vci_path.open() as fptr: + code = remove_comments(fptr.read()) + vci_code = VHDLDesignFile.parse(code) + if len(vci_code.packages) != 1: + LOGGER.error("%s must contain a single VCI package", vci_path) + return None, None + + vc_constructor = cls._validate_constructor(code, vc_handle_t) + if not cls._validate_handle(code, vc_handle_t): + vc_constructor = None + + return vci_code, vc_constructor + + def __init__(self, vci_facade, vc_constructor): + self.vci_facade = vci_facade + self.vc_constructor = vc_constructor + + @staticmethod + def _validate_constructor(code, vc_handle_t): + """Validates the existence and format of the verification component constructor.""" + + def create_messages(required_parameter_types, expected_default_value): + messages = [ + "Failed to find a constructor function%s for %s starting with new_", + "Found constructor function %s but not with the correct return type %s", + ] + + for parameter_name, parameter_type in required_parameter_types.items(): + messages.append( + "Found constructor function %s for %s but the {} parameter is missing".format( + parameter_name + ) + ) + messages.append( + "Found constructor function %s for %s but the {} parameter is not of type {}".format( + parameter_name, parameter_type + ) + ) + messages.append( + "Found constructor function %s for %s but {} is lacking a default value".format( + parameter_name + ) + ) + messages.append( + "Found constructor function %s for %s but {} is the only allowed default " + "value for the {} parameter".format( + expected_default_value[parameter_name], parameter_name + ) + ) + + return messages + + def log_error_message(function_score, messages): + high_score = 0 + best_function = "" + for function_name, score in function_score.items(): + if score > high_score: + high_score = score + best_function = function_name + + error_msg = messages[high_score] % (best_function, vc_handle_t) + LOGGER.error(error_msg) + + required_parameter_types = dict( + logger="logger_t", + actor="actor_t", + checker="checker_t", + unexpected_msg_type_policy="unexpected_msg_type_policy_t", + ) + + expected_default_value = dict( + logger=None, + actor="null_actor", + checker="null_checker", + unexpected_msg_type_policy=None, + ) + + messages = create_messages(required_parameter_types, expected_default_value) + + function_score = {} + for func in VHDLFunctionSpecification.find(code): + function_score[func.identifier] = 0 + + if not func.identifier.startswith("new_"): + continue + function_score[func.identifier] += 1 + + if func.return_type_mark != vc_handle_t: + continue + function_score[func.identifier] += 1 + + parameters = {} + for parameter in func.parameter_list: + for identifier in parameter.identifier_list: + parameters[identifier] = parameter + + for parameter_name, parameter_type in required_parameter_types.items(): + if parameter_name not in parameters: + break + function_score[func.identifier] += 1 + + if ( + parameters[parameter_name].subtype_indication.type_mark + != parameter_type + ): + break + function_score[func.identifier] += 1 + + if not parameters[parameter_name].init_value: + break + function_score[func.identifier] += 1 + + if expected_default_value[parameter_name] and ( + parameters[parameter_name].init_value + != expected_default_value[parameter_name] + ): + break + function_score[func.identifier] += 1 + + if function_score[func.identifier] == len(messages): + return func + + log_error_message(function_score, messages) + + return None + + @staticmethod + def _validate_handle(code, vc_handle_t): + """Validates the existence and format of the verification component handle type.""" + + handle_is_valid = True + for record in VHDLRecordType.find(code): + if record.identifier == vc_handle_t: + for element in record.elements: + for parameter_name in element.identifier_list: + if not parameter_name.lower().startswith("p_"): + handle_is_valid = False + LOGGER.error( + "%s in %s doesn't start with p_", + parameter_name, + vc_handle_t, + ) + return handle_is_valid + + LOGGER.error( + "Failed to find %s record", vc_handle_t, + ) + return False + + @classmethod + def create_vhdl_testbench_template(cls, vci_lib_name, vci_path, vc_handle_t): + """ + Creates a template for a VCI compliance testbench. + + :param vc_lib_name: Name of the library containing the verification component interface. + :param vci_path: Path to the file containing the verification component interface package. + :param vc_handle_t: Name of the VC handle type returned by the VC constructor. + + :returns: The template code as a string and the name of the verification component entity. + """ + vci_path = Path(vci_path) + vci_code, vc_constructor = cls.validate(vci_path, vc_handle_t) + + context_items = create_context_items( + vci_code, + vci_lib_name, + initial_library_names=set(["std", "work", "vunit_lib", vci_lib_name]), + initial_context_refs=set( + ["vunit_lib.vunit_context", "vunit_lib.com_context"] + ), + initial_package_refs=set( + [ + "vunit_lib.vc_pkg.all", + "%s.%s.all" % (vci_lib_name, vci_code.packages[0].identifier), + ] + ), + ) + + unspecified_parameters = [ + parameter + for parameter in vc_constructor.parameter_list + if not parameter.init_value + ] + if unspecified_parameters: + constant_declarations = "" + for parameter in unspecified_parameters: + for identifier in parameter.identifier_list: + if identifier in [ + "actor", + "logger", + "checker", + "unexpected_msg_type_policy", + ]: + continue + constant_declarations += " constant %s : %s := ;\n" % ( + identifier, + parameter.subtype_indication.type_mark, + ) + else: + constant_declarations = "\n" + + template_code = TB_TEMPLATE_TEMPLATE.substitute( + context_items=context_items, + vc_handle_t=vc_handle_t, + constant_declarations=constant_declarations, + ) + + return ( + template_code, + vci_code.packages[0].identifier, + ) + + def create_vhdl_testbench(self, template_path=None): + """ + Creates a VHDL VCI compliance testbench. + + :param template_path: Path to template file. If None, a default template is assumed. + + :returns: The testbench code as a string. + """ + template_path = Path(template_path) if template_path is not None else None + + if not template_path: + template_code, _ = self.create_vhdl_testbench_template( + self.vci_facade.library, + self.vci_facade.source_file.name, + self.vc_constructor.return_type_mark, + ) + else: + with template_path.open() as fptr: + template_code = fptr.read() + + test_runner_body_pattern = re.compile( + r"\s+-- DO NOT modify this line and the lines below." + ) + match = test_runner_body_pattern.search(template_code) + if not match: + LOGGER.error("Failed to find body of test_runner in template code.") + return None + + unspecified_parameters = [ + parameter + for parameter in self.vc_constructor.parameter_list + if not parameter.init_value + ] + + def create_handle_assignment( + handle_name, + actor=None, + logger=None, + checker=None, + unexpected_msg_type_policy="fail", + ): + + handle_assignment = " %s := %s(\n" % ( + handle_name, + self.vc_constructor.identifier, + ) + for parameter in unspecified_parameters: + for identifier in parameter.identifier_list: + if identifier in [ + "actor", + "logger", + "checker", + "unexpected_msg_type_policy", + ]: + continue + handle_assignment += " %s => %s,\n" % ( + identifier, + identifier, + ) + for formal, actual in dict( + actor=actor, + logger=logger, + checker=checker, + unexpected_msg_type_policy=unexpected_msg_type_policy, + ).items(): + if actual: + handle_assignment += " %s => %s,\n" % (formal, actual) + + handle_assignment = handle_assignment[:-2] + "\n );" + + return handle_assignment + + testbench_code = template_code[ + : match.start() + ] + TB_EPILOGUE_TEMPLATE.substitute( + vc_handle_t=self.vc_constructor.return_type_mark, + vc_constructor_name=self.vc_constructor.identifier, + handle1=create_handle_assignment( + "handle1", + actor="actor1", + logger="logger1", + checker="checker1", + unexpected_msg_type_policy="fail", + ), + handle2=create_handle_assignment( + "handle2", + actor="actor2", + logger="logger2", + checker="checker2", + unexpected_msg_type_policy="ignore", + ), + handle3=create_handle_assignment( + "handle2", + actor="actor2", + logger="logger2", + checker="checker2", + unexpected_msg_type_policy="ignore", + ), + handle4=create_handle_assignment( + "handle1", + actor="actor1", + checker="checker1", + unexpected_msg_type_policy="fail", + ), + handle5=create_handle_assignment( + "handle2", + actor="actor2", + logger="null_logger", + checker="checker2", + unexpected_msg_type_policy="fail", + ), + handle6=create_handle_assignment( + "handle1", actor="actor1", unexpected_msg_type_policy="fail", + ), + handle7=create_handle_assignment( + "handle2", + actor="actor2", + checker="null_checker", + unexpected_msg_type_policy="fail", + ), + handle8=create_handle_assignment( + "handle3", + actor="actor3", + logger="logger3", + unexpected_msg_type_policy="fail", + ), + ) + + return testbench_code + + def add_vhdl_testbench(self, vci_test_lib, test_dir, template_path=None): + """ + Adds a VHDL compliance testbench + + :param vci_test_lib: The name of the library to which the testbench is added. + :param test_dir: The name of the directory where the testbench file is stored. + :param template_path: Path to testbench template file. If None, a default template is used. + + :returns: The :class:`.SourceFile` for the added testbench. + + :example: + + .. code-block:: python + + ROOT = Path(__file__).parent + prj.add_vhdl_testbench("test_lib", ROOT / "test", ROOT / ".vc" / "vc_template.vhd") + + """ + test_dir = Path(test_dir) + template_path = Path(template_path) if template_path is not None else None + + test_dir = Path(test_dir).resolve() + if template_path: + template_path = Path(template_path).resolve() + + try: + vci_test_lib.test_bench( + "tb_%s_%s_compliance" + % (self.vci_facade.name, self.vc_constructor.return_type_mark) + ) + raise RuntimeError( + "tb_%s_compliance already exists in %s" + % (self.vci_facade.name, vci_test_lib.name) + ) + except KeyError: + pass + + if not test_dir.exists(): + test_dir.mkdir(parents=True) + + tb_path = test_dir / ( + "tb_%s_%s_compliance.vhd" + % (self.vci_facade.name, self.vc_constructor.return_type_mark) + ) + testbench_code = self.create_vhdl_testbench(template_path) + if not testbench_code: + return None + tb_path.write_text(testbench_code) + + tb_file = vci_test_lib.add_source_file(tb_path) + + return tb_file diff --git a/vunit/vhdl/com/src/com_types.vhd b/vunit/vhdl/com/src/com_types.vhd index a2a4aca42..14087d691 100644 --- a/vunit/vhdl/com/src/com_types.vhd +++ b/vunit/vhdl/com/src/com_types.vhd @@ -20,6 +20,7 @@ use work.integer_vector_ptr_pkg.all; use work.integer_array_pkg.all; use work.string_ptr_pkg.all; use work.logger_pkg.all; +use work.checker_pkg.all; use work.queue_pkg.all; use work.queue_2008p_pkg.all; use work.queue_pool_pkg.all; @@ -188,6 +189,9 @@ package com_types_pkg is procedure unexpected_msg_type(msg_type : msg_type_t; logger : logger_t := com_logger); + procedure unexpected_msg_type(msg_type : msg_type_t; + checker : checker_t); + procedure push_msg_type(msg : msg_t; msg_type : msg_type_t; logger : logger_t := com_logger); alias push is push_msg_type [msg_t, msg_type_t, logger_t]; @@ -445,6 +449,12 @@ package body com_types_pkg is end if; end procedure; + procedure unexpected_msg_type(msg_type : msg_type_t; + checker : checker_t) is + begin + unexpected_msg_type(msg_type, get_logger(checker)); + end; + procedure push_msg_type(msg : msg_t; msg_type : msg_type_t; logger : logger_t := com_logger) is begin push(msg, msg_type.p_code); 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..ce49c6d5e --- /dev/null +++ b/vunit/vhdl/verification_components/src/vc_pkg.vhd @@ -0,0 +1,117 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- +-- This package contains common functionality for VC designers. + +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_actor : actor_t; + p_logger : logger_t; + p_checker : checker_t; + p_unexpected_msg_type_policy : unexpected_msg_type_policy_t; + end record; + + constant null_std_cfg : std_cfg_t := ( + p_actor => null_actor, + p_logger => null_logger, + p_checker => null_checker, + p_unexpected_msg_type_policy => ignore + ); + + -- Creates a standard VC configuration with an actor, a logger, a checker, and the policy for handling unexpected messages + -- + -- * The actor is the actor provided by the actor parameter unless it's the null_actor. In that case a new actor is created + -- * The logger is the logger provided by the logger parameter unless it's the null_logger. In that case the default logger is used which must not be the null_logger. + -- * The checker is the checker provided by the checker parameter unless it's the null_checker. In that case the the default checker is used if the logger is the + -- default logger. Otherwise a new checker is created based on the provided logger. The default checker must not be the null_checker + -- * The policy for handling unexpected messages is according to the unexpected_msg_type_policy parameter. + impure function create_std_cfg( + default_logger : logger_t; + default_checker : checker_t; + actor : actor_t := null_actor; + logger : logger_t := null_logger; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return std_cfg_t; + + -- These functions extracts the different parts of a standard VC configuration + 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_logger : logger_t := get_logger("vunit_lib:vc_pkg"); + constant vc_checker : checker_t := new_checker(vc_logger); + + impure function create_std_cfg( + default_logger : logger_t; + default_checker : checker_t; + actor : actor_t := null_actor; + logger : logger_t := null_logger; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return std_cfg_t is + variable result : std_cfg_t; + begin + check(vc_checker, default_logger /= null_logger, "A default logger must be provided"); + check(vc_checker, default_checker /= null_checker, "A default checker must be provided"); + + result.p_actor := actor when actor /= null_actor else new_actor; + result.p_logger := logger when logger /= null_logger else default_logger; + result.p_unexpected_msg_type_policy := unexpected_msg_type_policy; + + if checker = null_checker then + if logger = default_logger then + result.p_checker := default_checker; + else + result.p_checker := new_checker(logger); + end if; + else + result.p_checker := checker; + end if; + + return result; + end; + + impure function get_actor(std_cfg : std_cfg_t) return actor_t is + begin + return std_cfg.p_actor; + end; + + impure function get_logger(std_cfg : std_cfg_t) return logger_t is + begin + return std_cfg.p_logger; + end; + + impure function get_checker(std_cfg : std_cfg_t) return checker_t is + begin + return std_cfg.p_checker; + end; + + impure function unexpected_msg_type_policy(std_cfg : std_cfg_t) return unexpected_msg_type_policy_t is + begin + return std_cfg.p_unexpected_msg_type_policy; + end; + + procedure unexpected_msg_type(msg_type : msg_type_t; + std_cfg : std_cfg_t) is + begin + if unexpected_msg_type_policy(std_cfg) = fail then + unexpected_msg_type(msg_type, get_checker(std_cfg)); + end if; + end; +end package body; diff --git a/vunit/vhdl_parser.py b/vunit/vhdl_parser.py index 7d5277fea..b7ac04f32 100644 --- a/vunit/vhdl_parser.py +++ b/vunit/vhdl_parser.py @@ -63,7 +63,9 @@ def __init__( # pylint: disable=too-many-arguments self.package_bodies = [] if package_bodies is None else package_bodies self.architectures = [] if architectures is None else architectures self.contexts = [] if contexts is None else contexts - self.component_instantiations = [] if component_instantiations is None else component_instantiations + self.component_instantiations = ( + [] if component_instantiations is None else component_instantiations + ) self.configurations = [] if configurations is None else configurations self.references = [] if references is None else references @@ -244,7 +246,9 @@ def _find_normal_packages(cls, code): if match: yield cls.parse(sub_code[: match.end()]) - _package_instance_re = re.compile("^" + PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE) + _package_instance_re = re.compile( + "^" + PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE + ) @classmethod def _find_package_instances(cls, code): @@ -303,7 +307,8 @@ def add_generic(self, identifier, subtype_code, init_value=None): """ self.generics.append( VHDLInterfaceElement( - identifier, + "constant", + [identifier], VHDLSubtypeIndication.parse(subtype_code), init_value=init_value, ) @@ -315,7 +320,8 @@ def add_port(self, identifier, mode, subtype_code, init_value=None): """ self.ports.append( VHDLInterfaceElement( - identifier, + "signal", + [identifier], VHDLSubtypeIndication.parse(subtype_code), init_value=init_value, mode=mode, @@ -415,7 +421,11 @@ def _find_generic_clause(cls, code): match_semicolon = semicolon.match(code[match.end() + closing_pos :]) if match_semicolon: return cls._parse_generic_clause( - code[match.start() : match.end() + closing_pos + match_semicolon.end()] + code[ + match.start() : match.end() + + closing_pos + + match_semicolon.end() + ] ) return [] @@ -447,7 +457,13 @@ def _find_port_clause(cls, code): ) match_semicolon = semicolon.match(code[match.end() + closing_pos :]) if match_semicolon: - return cls._parse_port_clause(code[match.start() : match.end() + closing_pos + match_semicolon.end()]) + return cls._parse_port_clause( + code[ + match.start() : match.end() + + closing_pos + + match_semicolon.end() + ] + ) return [] @staticmethod @@ -492,7 +508,9 @@ def _split_not_in_par(string, sep): _package_generic_re = re.compile(r"\s*package\s+", re.MULTILINE | re.IGNORECASE) _type_generic_re = re.compile(r"\s*type\s+", re.MULTILINE | re.IGNORECASE) - _function_generic_re = re.compile(r"\s*(impure\s+)?(function|procedure)\s+", re.MULTILINE | re.IGNORECASE) + _function_generic_re = re.compile( + r"\s*(impure\s+)?(function|procedure)\s+", re.MULTILINE | re.IGNORECASE + ) @classmethod def _parse_generic_clause(cls, code): @@ -521,7 +539,11 @@ def _parse_generic_clause(cls, code): # Ignore function generics continue - generic_list.append(VHDLInterfaceElement.parse(interface_element)) + generic_list.append( + VHDLInterfaceElement.parse( + interface_element, default_entity_class="constant" + ) + ) return generic_list @@ -539,7 +561,11 @@ def _parse_port_clause(cls, code): port_list = [] # Add interface elements to the port list for interface_element in interface_elements: - port_list.append(VHDLInterfaceElement.parse(interface_element, is_signal=True)) + port_list.append( + VHDLInterfaceElement.parse( + interface_element, default_entity_class="signal" + ) + ) return port_list @@ -618,8 +644,16 @@ class VHDLInterfaceElement(object): Represents a VHDL interface element """ - def __init__(self, identifier, subtype_indication, mode=None, init_value=None): - self.identifier = identifier + def __init__( + self, + entity_class, + identifier_list, + subtype_indication, + mode=None, + init_value=None, + ): + self.entity_class = entity_class + self.identifier_list = identifier_list self.mode = mode self.subtype_indication = subtype_indication self.init_value = init_value @@ -628,21 +662,32 @@ def without_mode(self): """ @returns A copy of this interface element without a mode """ - return VHDLInterfaceElement(self.identifier, self.subtype_indication, init_value=self.init_value) + return VHDLInterfaceElement( + self.entity_class, + self.identifier_list, + self.subtype_indication, + init_value=self.init_value, + ) @classmethod - def parse(cls, code, is_signal=False): + def parse(cls, code, default_entity_class=None): """ Returns a new instance by parsing the code """ - if is_signal: - # Remove 'signal' string if a signal is beeing parsed - code = code.replace("signal", "") + entity_class_split = code.split(None, 1) + if cls._is_interface_entity_class(entity_class_split[0]): + entity_class = entity_class_split[0] + code = entity_class_split[1] + else: + entity_class = default_entity_class interface_element_string = code - # Extract the identifier - identifier = interface_element_string.split(":")[0].strip() + # Extract the identifier_list + identifier_list_string = interface_element_string.split(":")[0].strip() + identifier_list = [ + identifier.strip() for identifier in identifier_list_string.split(",") + ] # Extract subtype indication and mode (if any) @@ -652,7 +697,9 @@ def parse(cls, code, is_signal=False): subtype_indication = VHDLSubtypeIndication.parse(mode_split[1]) else: mode = None - subtype_indication = VHDLSubtypeIndication.parse(interface_element_string.split(":")[1].strip()) + subtype_indication = VHDLSubtypeIndication.parse( + interface_element_string.split(":")[1].strip() + ) # Extract initial value init_value_split = interface_element_string.split(":=") @@ -661,7 +708,7 @@ def parse(cls, code, is_signal=False): else: init_value = None - return cls(identifier, subtype_indication, mode, init_value) + return cls(entity_class, identifier_list, subtype_indication, mode, init_value) @staticmethod def _is_mode(code): @@ -670,8 +717,15 @@ def _is_mode(code): """ return code in ("in", "out", "inout", "buffer", "linkage") + @staticmethod + def _is_interface_entity_class(code): + """ + Return True if the code is an interface entity class + """ + return code in ("constant", "variable", "signal", "file") + def __str__(self): - code = self.identifier + " : " + code = self.identifier_list + " : " if self.mode is not None: code += self.mode + " " @@ -717,14 +771,6 @@ def find(cls, code): yield cls(identifier, literals) -class VHDLElementDeclaration(object): - """Represents a VHDL element declaration""" - - def __init__(self, identifier_list, subtype_indication): - self.identifier_list = identifier_list - self.subtype_indication = subtype_indication - - class VHDLRecordType(object): """Represents a VHDL record type""" @@ -758,9 +804,16 @@ def find(cls, code): for element in elements: if ":" in element: identifier_list_and_subtype_indication = element.split(":") - identifier_list = [i.strip() for i in identifier_list_and_subtype_indication[0].split(",")] - subtype_indication = VHDLSubtypeIndication.parse(identifier_list_and_subtype_indication[1].strip()) - parsed_elements.append(VHDLElementDeclaration(identifier_list, subtype_indication)) + identifier_list = [ + i.strip() + for i in identifier_list_and_subtype_indication[0].split(",") + ] + subtype_indication = VHDLSubtypeIndication.parse( + identifier_list_and_subtype_indication[1].strip() + ) + parsed_elements.append( + VHDLInterfaceElement(None, identifier_list, subtype_indication) + ) yield cls(identifier, parsed_elements) @@ -854,7 +907,9 @@ def find(cls, code): """Iterate over new instances of VHDLArrayType for all array types within the code""" for array_type in cls._array_declaration_re.finditer(code): identifier = array_type.group("id") - subtype_indication = VHDLSubtypeIndication.parse(array_type.group("subtype_indication")) + subtype_indication = VHDLSubtypeIndication.parse( + array_type.group("subtype_indication") + ) ranges = array_type.group("ranges") range1_str, range2_str = cls._split_ranges(ranges) range1 = cls._parse_range(range1_str) @@ -926,7 +981,9 @@ def find_closing_delimiter(start, end, code): if count == 0: return delimiter.end() - raise ValueError("Failed to find closing delimiter to " + start + " in " + code + ".") + raise ValueError( + "Failed to find closing delimiter to " + start + " in " + code + "." + ) class VHDLReference(object): @@ -934,7 +991,7 @@ class VHDLReference(object): Reference to design unit """ - _reference_types = ("package", "context", "entity", "configuration") + _reference_types = ("package", "context", "entity", "configuration", "library") _uses_re = re.compile( r""" @@ -949,37 +1006,40 @@ class VHDLReference(object): re.MULTILINE | re.IGNORECASE | re.VERBOSE, ) - @classmethod - def _find_uses(cls, code): - """ - Find all the libraries and use clasues within the code + @staticmethod + def get_ids(match): """ + Get all ids found within the match taking the optinal extra ids of + library and use clauses into account such as: - def get_ids(match): - """ - Get all ids found within the match taking the optinal extra ids of - library and use clauses into account such as: + use foo, bar; - use foo, bar; + or - or + library foo, bar; + """ + ids = [match.group("id").strip()] + if match.group("extra"): + ids += [name.strip() for name in match.group("extra").split(",")[1:]] + return ids - library foo, bar; - """ - ids = [match.group("id").strip()] - if match.group("extra"): - ids += [name.strip() for name in match.group("extra").split(",")[1:]] - return ids + @classmethod + def _find_uses(cls, code): + """ + Find all the use and context clauses within the code + """ references = [] for match in cls._uses_re.finditer(code): - for uses in get_ids(match): + for uses in cls.get_ids(match): uses = uses.split(".") names_within = uses[2:] if len(uses) > 2 else (None,) for name_within in names_within: ref = cls( - reference_type="package" if match.group("use_type") == "use" else "context", + reference_type="package" + if match.group("use_type") == "use" + else "context", library=uses[0], design_unit=uses[1], name_within=name_within, @@ -1025,10 +1085,14 @@ def _find_configuration_references(cls, code): """ references = [] for match in cls._configuration_reference_re.finditer(code): - references.append(cls("configuration", match.group("lib"), match.group("cfg"))) + references.append( + cls("configuration", match.group("lib"), match.group("cfg")) + ) return references - _package_instance_re = re.compile(PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE) + _package_instance_re = re.compile( + PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE + ) @classmethod def _find_package_instance_references(cls, code): @@ -1040,6 +1104,33 @@ def _find_package_instance_references(cls, code): references.append(cls("package", match.group("lib"), match.group("name"))) return references + _library_re = re.compile( + r""" + \b # Word boundary + library # library keyword + \s+ # At least one whitespace + (?P[a-zA-Z][\w]*) # First library identifier + (?P(\s*,\s*[a-zA-Z][\w]*)*) # Extra library identifiers + \s* # Potential whitespaces + ; # Semi-colon + """, + re.MULTILINE | re.IGNORECASE | re.VERBOSE, + ) + + @classmethod + def _find_library_references(cls, code): + """ + Finds all library clauses + """ + + references = [] + for match in cls._library_re.finditer(code): + for library in cls.get_ids(match): + ref = cls(reference_type="library", library=library) + references.append(ref) + + return references + @classmethod def find(cls, code): """ @@ -1050,9 +1141,10 @@ def find(cls, code): + cls._find_entity_references(code) + cls._find_configuration_references(code) + cls._find_package_instance_references(code) + + cls._find_library_references(code) ) - def __init__(self, reference_type, library, design_unit, name_within=None): + def __init__(self, reference_type, library, design_unit=None, name_within=None): assert reference_type in self._reference_types self.reference_type = reference_type self.library = library @@ -1061,6 +1153,14 @@ def __init__(self, reference_type, library, design_unit, name_within=None): # String "all" may be used to denote all names within self.name_within = name_within + @property + def library_name(self): + return self.library + + @property + def design_unit_name(self): + return self.design_unit + def __repr__(self): return f"VHDLReference({self.reference_type!r}, {self.library!r}, {self.design_unit!r}, {self.name_within!r})" @@ -1073,7 +1173,9 @@ def __eq__(self, other): ) def copy(self): - return VHDLReference(self.reference_type, self.library, self.design_unit, self.name_within) + return VHDLReference( + self.reference_type, self.library, self.design_unit, self.name_within + ) def is_entity_reference(self): return self.reference_type == "entity" @@ -1081,6 +1183,12 @@ def is_entity_reference(self): def is_package_reference(self): return self.reference_type == "package" + def is_context_reference(self): + return self.reference_type == "context" + + def is_library_reference(self): + return self.reference_type == "library" + def reference_all_names_within(self): return self.name_within == "all" @@ -1089,6 +1197,60 @@ def reference_all_names_within(self): VHDL_REMOVE_COMMENT_COMPILED_RE = re.compile(VHDL_REMOVE_COMMENT_RE, re.MULTILINE) +class VHDLFunctionSpecification(object): + """ + Represents a VHDL function specification. + """ + + def __init__(self, identifier, return_type_mark, parameter_list=None): + self.identifier = identifier + self.return_type_mark = return_type_mark + + self.parameter_list = parameter_list if parameter_list is not None else [] + + _function_specification_re = re.compile( + r""" + \b # Word boundary + function # Function keyword + \s+ # At least one whitespace + (?P[a-zA-Z]\w*) # Function identifier + \s* # Potential whitespaces + (?P\(.*?\))? # Parameter list + \s+ # At least one whitespace + return # Return keyword + \s+ # At least one whitespace + (?P[a-zA-Z]\w*) # Return type mark + \s* # Potential whitespaces + ; # Semi-colon + """, + re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL, + ) + + @classmethod + def find(cls, code): + """ + Iterate over new instances of VHDLFunctionSpecification for all function specifications within the code. + """ + for function_specification in cls._function_specification_re.finditer(code): + identifier = function_specification.group("id") + return_type_mark = function_specification.group("return_type_mark") + + parsed_parameter_list = [] + if function_specification.group("parameter_list"): + for element in function_specification.group("parameter_list")[ + 1:-1 + ].split(";"): + parsed_parameter_list.append( + VHDLInterfaceElement.parse( + element, default_entity_class="constant" + ) + ) + + yield VHDLFunctionSpecification( + identifier, return_type_mark, parsed_parameter_list + ) + + def _comment_repl(match): """ Replace comment with equal amount of whitespace to make From e716d7c3d36a12b5eac84f117761b640295b0bf6 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sun, 31 May 2020 17:27:35 +0200 Subject: [PATCH 02/21] Updated all VCs and VCIs except for Avalon and Wishbone to comply with new standard --- .../tb_axi_slave_t_compliance_template.vhd | 36 + ...xi_stream_master_t_compliance_template.vhd | 37 + ...i_stream_monitor_t_compliance_template.vhd | 37 + ...protocol_checker_t_compliance_template.vhd | 37 + ...axi_stream_slave_t_compliance_template.vhd | 37 + .../tb_bus2memory_t_compliance_template.vhd | 35 + .../tb_bus_master_t_compliance_template.vhd | 35 + .../tb_ram_master_t_compliance_template.vhd | 35 + ...tb_axi_lite_master_compliance_template.vhd | 81 +++ .../tb_axi_read_slave_compliance_template.vhd | 78 +++ ..._axi_stream_master_compliance_template.vhd | 62 ++ ...axi_stream_monitor_compliance_template.vhd | 53 ++ ...m_protocol_checker_compliance_template.vhd | 56 ++ ...b_axi_stream_slave_compliance_template.vhd | 57 ++ ...tb_axi_write_slave_compliance_template.vhd | 83 +++ .../.vc/tb_bus2memory_compliance_template.vhd | 41 ++ .../.vc/tb_ram_master_compliance_template.vhd | 57 ++ ..._std_logic_checker_compliance_template.vhd | 39 ++ vunit/vhdl/verification_components/run.py | 178 ++++- .../src/avalon_master.vhd | 5 +- .../src/avalon_stream_pkg.vhd | 6 +- .../src/axi_lite_master.vhd | 25 +- .../src/axi_lite_master_pkg.vhd | 6 +- .../src/axi_slave_pkg.vhd | 95 ++- .../src/axi_slave_private_pkg.vhd | 57 +- .../src/axi_stream_master.vhd | 97 ++- .../src/axi_stream_monitor.vhd | 27 +- .../src/axi_stream_pkg.vhd | 657 ++++++++++-------- .../src/axi_stream_protocol_checker.vhd | 183 +++-- .../src/axi_stream_slave.vhd | 123 ++-- .../src/bus2memory.vhd | 22 +- .../src/bus2memory_pkg.vhd | 80 +++ .../src/bus_master_pkg-body.vhd | 66 +- .../src/bus_master_pkg.vhd | 23 +- .../src/ram_master.vhd | 25 +- .../src/ram_master_pkg.vhd | 319 +++++++++ .../src/signal_checker_pkg.vhd | 54 +- .../src/std_logic_checker.vhd | 19 +- .../src/stream_master_pkg-body.vhd | 20 +- .../src/stream_master_pkg.vhd | 15 +- .../src/stream_slave_pkg-body.vhd | 21 +- .../src/stream_slave_pkg.vhd | 16 +- .../src/uart_master.vhd | 5 +- .../verification_components/src/uart_pkg.vhd | 95 ++- .../src/uart_slave.vhd | 8 +- .../src/wishbone_master.vhd | 2 +- .../test/tb_axi_lite_master.vhd | 8 +- .../test/tb_axi_stream.vhd | 92 ++- .../test/tb_axi_stream_protocol_checker.vhd | 81 ++- .../test/tb_bus_master_pkg.vhd | 11 +- .../test/tb_ram_master.vhd | 16 +- 51 files changed, 2650 insertions(+), 703 deletions(-) create mode 100644 vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/src/bus2memory_pkg.vhd create mode 100644 vunit/vhdl/verification_components/src/ram_master_pkg.vhd diff --git a/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd new file mode 100644 index 000000000..9f7f8dd3b --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd @@ -0,0 +1,36 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_slave_pkg.all; +use vunit_lib.axi_statistics_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_slave_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_slave_t_compliance is +begin + test_runner : process + constant memory : memory_t := new_memory; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd new file mode 100644 index 000000000..cdc1a03cc --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd @@ -0,0 +1,37 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_master_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_master_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd new file mode 100644 index 000000000..e0e4b20fb --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd @@ -0,0 +1,37 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_monitor_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_monitor_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd new file mode 100644 index 000000000..80f130a2f --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd @@ -0,0 +1,37 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_protocol_checker_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_protocol_checker_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd new file mode 100644 index 000000000..3feadafb0 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd @@ -0,0 +1,37 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_slave_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_slave_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd new file mode 100644 index 000000000..024f6b380 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.bus2memory_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_bus2memory_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_bus2memory_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + constant address_length : natural := 8; + constant memory : memory_t := new_memory; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd new file mode 100644 index 000000000..7c4a0939c --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_bus_master_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_bus_master_t_compliance is +begin + test_runner : process + constant data_length : natural := 32; + constant address_length : natural := 32; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd new file mode 100644 index 000000000..aa69304a5 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.ram_master_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_ram_master_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_ram_master_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + constant address_length : natural := 8; + constant latency : positive := 2; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd new file mode 100644 index 000000000..2e90a898e --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd @@ -0,0 +1,81 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_lite_master_pkg.all; +use vunit_lib.axi_pkg.all; +use vunit_lib.axi_slave_pkg.all; +use vunit_lib.axi_slave_private_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_lite_master_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_lite_master_compliance is + + constant bus_handle : bus_master_t := new_bus( + data_length => 32, + address_length => 32 + ); + + signal aclk : std_logic; + signal arready : std_logic; + signal arvalid : std_logic; + signal araddr : std_logic_vector(address_length(bus_handle) - 1 downto 0); + signal rready : std_logic; + signal rvalid : std_logic; + signal rdata : std_logic_vector(data_length(bus_handle) - 1 downto 0); + signal rresp : axi_resp_t; + signal awready : std_logic; + signal awvalid : std_logic; + signal awaddr : std_logic_vector(address_length(bus_handle) - 1 downto 0); + signal wready : std_logic; + signal wvalid : std_logic; + signal wdata : std_logic_vector(data_length(bus_handle) - 1 downto 0); + signal wstrb : std_logic_vector(byte_enable_length(bus_handle) - 1 downto 0); + signal bvalid : std_logic; + signal bready : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_lite_master + generic map(bus_handle) + port map( + aclk => aclk, + arready => arready, + arvalid => arvalid, + araddr => araddr, + rready => rready, + rvalid => rvalid, + rdata => rdata, + rresp => rresp, + awready => awready, + awvalid => awvalid, + awaddr => awaddr, + wready => wready, + wvalid => wvalid, + wdata => wdata, + wstrb => wstrb, + bvalid => bvalid, + bready => bready, + bresp => open + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd new file mode 100644 index 000000000..0317b4990 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd @@ -0,0 +1,78 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vc_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use vunit_lib.axi_pkg.all; +use vunit_lib.axi_slave_pkg.all; +use vunit_lib.axi_slave_private_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_read_slave_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_read_slave_compliance is + + constant memory : memory_t := new_memory; + constant axi_slave : axi_slave_t := new_axi_slave( + memory => memory + ); + + constant log_data_size : integer := 4; + constant data_size : integer := 2**log_data_size; + + signal aclk : std_logic; + signal arvalid : std_logic; + signal arready : std_logic; + signal arid : std_logic_vector(3 downto 0); + signal araddr : std_logic_vector(31 downto 0); + signal arlen : axi4_len_t; + signal arsize : axi4_size_t; + signal arburst : axi_burst_type_t; + signal rvalid : std_logic; + signal rready : std_logic; + signal rid : std_logic_vector(arid'range); + signal rdata : std_logic_vector(8*data_size-1 downto 0); + signal rresp : axi_resp_t; + signal rlast : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_read_slave + generic map(axi_slave) + + port map( + aclk => aclk, + arvalid => arvalid, + arready => arready, + arid => arid, + araddr => araddr, + arlen => arlen, + arsize => arsize, + arburst => arburst, + rvalid => rvalid, + rready => rready, + rid => rid, + rdata => rdata, + rresp => rresp, + rlast => rlast + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd new file mode 100644 index 000000000..a9257bb76 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd @@ -0,0 +1,62 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_master_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_master_compliance is + + constant master : axi_stream_master_t := new_axi_stream_master( + data_length => 8 + ); + + signal aclk : std_logic; + signal tvalid : std_logic; + signal tdata : std_logic_vector(data_length(master)-1 downto 0); + signal tlast : std_logic; + signal tkeep : std_logic_vector(data_length(master)/8-1 downto 0); + signal tstrb : std_logic_vector(data_length(master)/8-1 downto 0); + signal tid : std_logic_vector(id_length(master)-1 downto 0); + signal tdest : std_logic_vector(dest_length(master)-1 downto 0); + signal tuser : std_logic_vector(user_length(master)-1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_stream_master + generic map(master) + port map( + aclk => aclk, + areset_n => open, + tvalid => tvalid, + tready => open, + tdata => tdata, + tlast => tlast, + tkeep => tkeep, + tstrb => tstrb, + tid => tid, + tdest => tdest, + tuser => tuser + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd new file mode 100644 index 000000000..03551b897 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd @@ -0,0 +1,53 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_monitor_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_monitor_compliance is + + constant monitor : axi_stream_monitor_t := new_axi_stream_monitor( + data_length => 8 + ); + + signal aclk : std_logic; + signal tvalid : std_logic; + signal tdata : std_logic_vector(data_length(monitor) - 1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_stream_monitor + generic map(monitor) + port map( + aclk => aclk, + tvalid => tvalid, + tready => open, + tdata => tdata, + tlast => open, + tkeep => open, + tstrb => open, + tid => open, + tdest => open, + tuser => open + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd new file mode 100644 index 000000000..0375493a0 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd @@ -0,0 +1,56 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std_unsigned.all; +use ieee.std_logic_1164.all; +use std.textio.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_protocol_checker_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_protocol_checker_compliance is + + constant protocol_checker : axi_stream_protocol_checker_t := new_axi_stream_protocol_checker( + data_length => 8 + ); + + signal aclk : std_logic; + signal tvalid : std_logic; + signal tdata : std_logic_vector(data_length(protocol_checker) - 1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_stream_protocol_checker + generic map(protocol_checker) + port map( + aclk => aclk, + areset_n => open, + tvalid => tvalid, + tready => open, + tdata => tdata, + tlast => open, + tkeep => open, + tstrb => open, + tid => open, + tdest => open, + tuser => open + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd new file mode 100644 index 000000000..958198010 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd @@ -0,0 +1,57 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.axi_stream_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.string_ptr_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_stream_slave_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_stream_slave_compliance is + + constant slave : axi_stream_slave_t := new_axi_stream_slave( + data_length => 8 + ); + + signal aclk : std_logic; + signal tvalid : std_logic; + signal tready : std_logic; + signal tdata : std_logic_vector(data_length(slave)-1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_stream_slave + generic map(slave) + port map( + aclk => aclk, + areset_n => open, + tvalid => tvalid, + tready => tready, + tdata => tdata, + tlast => open, + tkeep => open, + tstrb => open, + tid => open, + tdest => open, + tuser => open + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd new file mode 100644 index 000000000..93ea134cf --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd @@ -0,0 +1,83 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use vunit_lib.axi_pkg.all; +use vunit_lib.axi_slave_pkg.all; +use vunit_lib.axi_slave_private_pkg.all; +use vunit_lib.integer_vector_ptr_pkg.all; +use vunit_lib.integer_vector_ptr_pool_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_axi_write_slave_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_axi_write_slave_compliance is + constant axi_slave : axi_slave_t := new_axi_slave( + memory => new_memory + ); + + constant log_data_size : integer := 4; + constant data_size : integer := 2**log_data_size; + + signal aclk : std_logic; + signal awvalid : std_logic; + signal awready : std_logic; + signal awid : std_logic_vector(3 downto 0); + signal awaddr : std_logic_vector(31 downto 0); + signal awlen : std_logic_vector(7 downto 0); + signal awsize : std_logic_vector(2 downto 0); + signal awburst : axi_burst_type_t; + signal wvalid : std_logic; + signal wready : std_logic; + signal wdata : std_logic_vector(8*data_size-1 downto 0); + signal wstrb : std_logic_vector(data_size downto 0); + signal wlast : std_logic; + signal bvalid : std_logic; + signal bready : std_logic; + signal bid : std_logic_vector(awid'range); + signal bresp : axi_resp_t; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.axi_write_slave + generic map(axi_slave) + port map( + aclk => aclk, + awvalid => awvalid, + awready => awready, + awid => awid, + awaddr => awaddr, + awlen => awlen, + awsize => awsize, + awburst => awburst, + wvalid => wvalid, + wready => wready, + wdata => wdata, + wstrb => wstrb, + wlast => wlast, + bvalid => bvalid, + bready => bready, + bid => bid, + bresp => bresp + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd new file mode 100644 index 000000000..5f6eaea47 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd @@ -0,0 +1,41 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use vunit_lib.bus2memory_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_bus2memory_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_bus2memory_compliance is + constant bus2memory_handle : bus2memory_t := new_bus2memory( + data_length => 8, + address_length => 8, + memory => new_memory + ); +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.bus2memory + generic map(bus2memory_handle); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd new file mode 100644 index 000000000..3e171fc5b --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd @@ -0,0 +1,57 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.ram_master_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_ram_master_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_ram_master_compliance is + + constant ram_master : ram_master_t := new_ram_master( + data_length => 32, + address_length => 32, + latency => 2 + ); + + signal clk : std_logic; + signal en : std_logic; + signal we : std_logic_vector(byte_enable_length(as_bus_master(ram_master))-1 downto 0); + signal addr : std_logic_vector(address_length(as_bus_master(ram_master)) - 1 downto 0); + signal wdata : std_logic_vector(data_length(as_bus_master(ram_master)) - 1 downto 0); + signal rdata : std_logic_vector(data_length(as_bus_master(ram_master)) - 1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.ram_master + generic map(ram_master) + port map( + clk => clk, + en => en, + we => we, + addr => addr, + wdata => wdata, + rdata => rdata + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd new file mode 100644 index 000000000..8af208a0b --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd @@ -0,0 +1,39 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.signal_checker_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_std_logic_checker_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_std_logic_checker_compliance is + constant signal_checker : signal_checker_t := new_signal_checker; + + signal value : std_logic_vector(7 downto 0); +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.std_logic_checker + generic map(signal_checker) + port map( + value => value + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 068b209d1..95079792a 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -6,7 +6,11 @@ from pathlib import Path from itertools import product -from vunit import VUnit +from vunit import ( + VUnit, + VerificationComponentInterface, + VerificationComponent, +) ROOT = Path(__file__).parent @@ -158,6 +162,7 @@ def gen_avalon_master_tests(obj, *args): for max_waits in [0, 8]: TEST_FAILING_MAX_WAITS.add_config(name="max_waits=%d" % max_waits, generics=dict(max_waits=max_waits)) + TB_AXI_STREAM.test("test random stall on master").add_config( name="stall_master", generics=dict(g_stall_percentage_master=30) ) @@ -170,4 +175,175 @@ def gen_avalon_master_tests(obj, *args): name="stall_slave", generics=dict(g_stall_percentage_slave=40) ) +TEST_LIB = UI.add_library("test_lib") + +bus_master_vci = VerificationComponentInterface.find( + LIB, "bus_master_pkg", "bus_master_t" +) +bus_master_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "bus_master_pkg" / "tb_bus_master_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "axi_lite_master", bus_master_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_lite_master_compliance_template.vhd", +) + +axi_slave_vci = VerificationComponentInterface.find(LIB, "axi_slave_pkg", "axi_slave_t") +axi_slave_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "axi_slave_pkg" / "tb_axi_slave_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "axi_read_slave", axi_slave_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_read_slave_compliance_template.vhd", +) + +VerificationComponent.find(LIB, "axi_write_slave", axi_slave_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_write_slave_compliance_template.vhd", +) + +axi_stream_master_vci = VerificationComponentInterface.find( + LIB, "axi_stream_pkg", "axi_stream_master_t" +) +axi_stream_master_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_master_t_compliance_template.vhd", +) +VerificationComponent.find( + LIB, "axi_stream_master", axi_stream_master_vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_stream_master_compliance_template.vhd", +) + +axi_stream_slave_vci = VerificationComponentInterface.find( + LIB, "axi_stream_pkg", "axi_stream_slave_t" +) +axi_stream_slave_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_slave_t_compliance_template.vhd", +) +VerificationComponent.find( + LIB, "axi_stream_slave", axi_stream_slave_vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_stream_slave_compliance_template.vhd", +) + +axi_stream_monitor_vci = VerificationComponentInterface.find( + LIB, "axi_stream_pkg", "axi_stream_monitor_t" +) +axi_stream_monitor_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_monitor_t_compliance_template.vhd", +) +VerificationComponent.find( + LIB, "axi_stream_monitor", axi_stream_monitor_vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_stream_monitor_compliance_template.vhd", +) + +axi_stream_protocol_checker_vci = VerificationComponentInterface.find( + LIB, "axi_stream_pkg", "axi_stream_protocol_checker_t" +) +axi_stream_protocol_checker_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT + / ".vc" + / "axi_stream_pkg" + / "tb_axi_stream_protocol_checker_t_compliance_template.vhd", +) +VerificationComponent.find( + LIB, "axi_stream_protocol_checker", axi_stream_protocol_checker_vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_axi_stream_protocol_checker_compliance_template.vhd", +) + +uart_master_vci = VerificationComponentInterface.find(LIB, "uart_pkg", "uart_master_t") +uart_master_vci.add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) +VerificationComponent.find(LIB, "uart_master", uart_master_vci).add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) + +uart_slave_vci = VerificationComponentInterface.find(LIB, "uart_pkg", "uart_slave_t") +uart_slave_vci.add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) +VerificationComponent.find(LIB, "uart_slave", uart_slave_vci).add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) + +std_logic_checker_vci = VerificationComponentInterface.find( + LIB, "signal_checker_pkg", "signal_checker_t" +) +std_logic_checker_vci.add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) +VerificationComponent.find( + LIB, "std_logic_checker", std_logic_checker_vci +).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_std_logic_checker_compliance_template.vhd", +) + +ram_master_vci = VerificationComponentInterface.find( + LIB, "ram_master_pkg", "ram_master_t" +) +ram_master_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "ram_master_pkg" / "tb_ram_master_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "ram_master", ram_master_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_ram_master_compliance_template.vhd", +) + +VerificationComponentInterface.find( + LIB, "stream_master_pkg", "stream_master_t" +).add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) + +VerificationComponentInterface.find( + LIB, "stream_slave_pkg", "stream_slave_t" +).add_vhdl_testbench( + TEST_LIB, ROOT / "compliance_test", +) + +bus2memory_vci = VerificationComponentInterface.find( + LIB, "bus2memory_pkg", "bus2memory_t" +) +bus2memory_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "bus2memory_pkg" / "tb_bus2memory_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "bus2memory", bus2memory_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_bus2memory_compliance_template.vhd", +) + UI.main() diff --git a/vunit/vhdl/verification_components/src/avalon_master.vhd b/vunit/vhdl/verification_components/src/avalon_master.vhd index 1471da0f1..19d67a46b 100644 --- a/vunit/vhdl/verification_components/src/avalon_master.vhd +++ b/vunit/vhdl/verification_components/src/avalon_master.vhd @@ -18,6 +18,7 @@ use work.com_types_pkg.all; use work.logger_pkg.all; use work.check_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; library osvvm; use osvvm.RandomPkg.all; @@ -67,9 +68,9 @@ begin wait until rising_edge(clk); loop request_msg := null_msg; - msgs := num_of_messages(bus_handle.p_actor); + msgs := num_of_messages(get_actor(bus_handle)); if (msgs > 0) then - receive(net, bus_handle.p_actor, request_msg); + receive(net, get_actor(bus_handle), request_msg); msg_type := message_type(request_msg); if msg_type = bus_read_msg then while rnd.Uniform(0.0, 1.0) > read_high_probability loop diff --git a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd index 5871944e3..07036c441 100644 --- a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd @@ -8,8 +8,10 @@ library ieee; use ieee.std_logic_1164.all; use work.logger_pkg.all; +use work.checker_pkg.all; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; +use work.vc_pkg.all; context work.com_context; context work.data_types_context; @@ -125,12 +127,12 @@ package body avalon_stream_pkg is impure function as_stream(source : avalon_source_t) return stream_master_t is begin - return (p_actor => source.p_actor); + return (p_std_cfg => create_std_cfg(source.p_logger, stream_master_checker, source.p_actor)); end; impure function as_stream(sink : avalon_sink_t) return stream_slave_t is begin - return (p_actor => sink.p_actor); + return (p_std_cfg => create_std_cfg(sink.p_logger, stream_slave_checker, sink.p_actor)); end; procedure push_avalon_stream(signal net : inout network_t; diff --git a/vunit/vhdl/verification_components/src/axi_lite_master.vhd b/vunit/vhdl/verification_components/src/axi_lite_master.vhd index 908a5e25b..077983309 100644 --- a/vunit/vhdl/verification_components/src/axi_lite_master.vhd +++ b/vunit/vhdl/verification_components/src/axi_lite_master.vhd @@ -11,6 +11,7 @@ use ieee.std_logic_1164.all; use work.queue_pkg.all; use work.bus_master_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; use work.axi_pkg.all; use work.axi_slave_pkg.all; use work.axi_slave_private_pkg.all; @@ -49,22 +50,27 @@ entity axi_lite_master is end entity; architecture a of axi_lite_master is - constant reply_queue, message_queue : queue_t := new_queue; + constant reply_queue, message_queue, transaction_token_queue : queue_t := new_queue; begin main : process variable request_msg : msg_t; variable msg_type : msg_type_t; begin - receive(net, bus_handle.p_actor, request_msg); + receive(net, get_actor(bus_handle), request_msg); msg_type := message_type(request_msg); + handle_wait_for_time(net, msg_type, request_msg); + if is_read(msg_type) or is_write(msg_type) then push(message_queue, request_msg); + push(transaction_token_queue, true); elsif msg_type = wait_until_idle_msg then - wait until ((bvalid and bready) = '1' or (rvalid and rready) = '1') and is_empty(message_queue) and rising_edge(aclk); + if not is_empty(transaction_token_queue) then + wait until rising_edge(aclk) and is_empty(transaction_token_queue); + end if; handle_wait_until_idle(net, msg_type, request_msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, get_std_cfg(bus_handle)); end if; end process; @@ -74,6 +80,7 @@ begin variable msg_type : msg_type_t; variable w_done, aw_done : boolean; variable expected_resp : axi_resp_t; + variable transaction_token : boolean; begin wait until rising_edge(aclk) and not is_empty(message_queue); @@ -93,9 +100,10 @@ begin wait until (rvalid and rready) = '1' and rising_edge(aclk); rready <= '0'; check_axi_resp(bus_handle, rresp, expected_resp, "rresp"); + transaction_token := pop(transaction_token_queue); - if is_visible(bus_handle.p_logger, debug) then - debug(bus_handle.p_logger, + if is_visible(get_logger(bus_handle), debug) then + debug(get_logger(bus_handle), "Read 0x" & to_hstring(rdata) & " from address 0x" & to_hstring(araddr)); end if; @@ -130,9 +138,10 @@ begin wait until (bvalid and bready) = '1' and rising_edge(aclk); bready <= '0'; check_axi_resp(bus_handle, bresp, expected_resp, "bresp"); + transaction_token := pop(transaction_token_queue); - if is_visible(bus_handle.p_logger, debug) then - debug(bus_handle.p_logger, + if is_visible(get_logger(bus_handle), debug) then + debug(get_logger(bus_handle), "Wrote 0x" & to_hstring(wdata) & " to address 0x" & to_hstring(awaddr)); end if; diff --git a/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd b/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd index f497b0113..39b284ed9 100644 --- a/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd @@ -85,7 +85,7 @@ package body axi_lite_master_pkg is push_std_ulogic_vector(request_msg, expected_bresp); - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure read_axi_lite(signal net : inout network_t; @@ -100,7 +100,7 @@ package body axi_lite_master_pkg is full_address(address'length - 1 downto 0) := address; push_std_ulogic_vector(request_msg, full_address); push_std_ulogic_vector(request_msg, expected_rresp); - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure read_axi_lite(signal net : inout network_t; @@ -142,7 +142,7 @@ package body axi_lite_master_pkg is read_axi_lite(net, bus_handle, address, expected_rresp, data); if not std_match(data, edata) then - failure(bus_handle.p_logger, base_error); + failure(get_logger(bus_handle), base_error); end if; end procedure; diff --git a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd index a6d23455e..ec3b72f3c 100644 --- a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd @@ -9,7 +9,10 @@ use ieee.std_logic_1164.all; use work.queue_pkg.all; use work.logger_pkg.all; +use work.checker_pkg.all; use work.memory_pkg.all; +use work.sync_pkg.all; +use work.vc_pkg.all; context work.com_context; use work.axi_statistics_pkg.all; @@ -18,6 +21,7 @@ package axi_slave_pkg is type axi_slave_t is record -- Private + p_std_cfg : std_cfg_t; p_initial_address_fifo_depth : positive; p_initial_write_response_fifo_depth : positive; p_initial_check_4kbyte_boundary : boolean; @@ -26,12 +30,11 @@ package axi_slave_pkg is p_initial_write_response_stall_probability : probability_t; p_initial_min_response_latency : delay_length; p_initial_max_response_latency : delay_length; - p_actor : actor_t; p_memory : memory_t; - p_logger : logger_t; end record; constant axi_slave_logger : logger_t := get_logger("vunit_lib:axi_slave_pkg"); + constant axi_slave_checker : checker_t := new_checker(axi_slave_logger); impure function new_axi_slave(memory : memory_t; actor : actor_t := null_actor; address_fifo_depth : positive := 1; @@ -42,10 +45,26 @@ package axi_slave_pkg is write_response_stall_probability : probability_t := 0.0; min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger) return axi_slave_t; + logger : logger_t := axi_slave_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t; + + function get_std_cfg(axi_slave : axi_slave_t) return std_cfg_t; + + impure function as_sync(axi_slave : axi_slave_t) return sync_handle_t; + + -- Return the actor used by the axi_slave + impure function get_actor(axi_slave : axi_slave_t) return actor_t; + + -- Return the logger used by the axi_slave + impure function get_logger(axi_slave : axi_slave_t) return logger_t; + + -- Return the checker used by the axi_slave + impure function get_checker(axi_slave : axi_slave_t) return checker_t; - -- Get the logger used by the axi_slave - function get_logger(axi_slave : axi_slave_t) return logger_t; + -- Return policy for handling unexpected messages to the actor + impure function unexpected_msg_type_policy(axi_slave : axi_slave_t) return unexpected_msg_type_policy_t; -- Set the maximum number address channel tokens that can be queued procedure set_address_fifo_depth(signal net : inout network_t; @@ -147,15 +166,15 @@ package body axi_slave_pkg is write_response_stall_probability : probability_t := 0.0; min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger) return axi_slave_t is - variable actor_tmp : actor_t := null_actor; + logger : logger_t := axi_slave_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + axi_slave_logger, axi_slave_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin - if actor = null_actor then - actor_tmp := new_actor; - else - actor_tmp := actor; - end if; - return (p_actor => actor_tmp, + return (p_std_cfg => p_std_cfg, p_initial_address_fifo_depth => address_fifo_depth, p_initial_write_response_fifo_depth => write_response_fifo_depth, p_initial_check_4kbyte_boundary => check_4kbyte_boundary, @@ -164,13 +183,37 @@ package body axi_slave_pkg is p_initial_write_response_stall_probability => write_response_stall_probability, p_initial_min_response_latency => min_response_latency, p_initial_max_response_latency => max_response_latency, - p_memory => to_vc_interface(memory, logger), - p_logger => logger); + p_memory => to_vc_interface(memory, logger)); + end; + + function get_std_cfg(axi_slave : axi_slave_t) return std_cfg_t is + begin + return axi_slave.p_std_cfg; + end; + + impure function as_sync(axi_slave : axi_slave_t) return sync_handle_t is + begin + return get_actor(axi_slave.p_std_cfg); + end; + + impure function get_actor(axi_slave : axi_slave_t) return actor_t is + begin + return get_actor(axi_slave.p_std_cfg); + end; + + impure function get_logger(axi_slave : axi_slave_t) return logger_t is + begin + return get_logger(axi_slave.p_std_cfg); + end; + + impure function get_checker(axi_slave : axi_slave_t) return checker_t is + begin + return get_checker(axi_slave.p_std_cfg); end; - function get_logger(axi_slave : axi_slave_t) return logger_t is + impure function unexpected_msg_type_policy(axi_slave : axi_slave_t) return unexpected_msg_type_policy_t is begin - return axi_slave.p_logger; + return unexpected_msg_type_policy(axi_slave.p_std_cfg); end; procedure set_address_fifo_depth(signal net : inout network_t; @@ -181,7 +224,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_set_address_fifo_depth_msg); push(request_msg, depth); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_address_fifo_depth command"; end; @@ -193,7 +236,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_set_write_response_fifo_depth_msg); push(request_msg, depth); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_write_response_fifo_depth command"; end; @@ -205,7 +248,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_set_address_stall_probability_msg); push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_address_stall_probability command"; end; @@ -217,7 +260,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_set_data_stall_probability_msg); push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_data_stall_probability command"; end; @@ -228,7 +271,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_set_write_response_stall_probability_msg); push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_write_response_stall_probability command"; end; @@ -240,7 +283,7 @@ package body axi_slave_pkg is begin request_msg := new_msg(axi_slave_configure_4kbyte_boundary_check_msg); push_boolean(request_msg, value); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on configure_4kbyte_boundary_check command"; end; @@ -253,7 +296,7 @@ package body axi_slave_pkg is request_msg := new_msg(axi_slave_set_response_latency_msg); push_time(request_msg, min_latency); push_time(request_msg, max_latency); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on set_response_latency command"; end; @@ -287,7 +330,7 @@ package body axi_slave_pkg is deallocate(stat); request_msg := new_msg(axi_slave_get_statistics_msg); push_boolean(request_msg, clear); - send(net, axi_slave.p_actor, request_msg); + send(net, get_actor(axi_slave.p_std_cfg), request_msg); receive_reply(net, request_msg, reply_msg); stat := (p_count_by_burst_length => pop_integer_vector_ptr_ref(reply_msg)); delete(request_msg); @@ -300,7 +343,7 @@ package body axi_slave_pkg is variable ack : boolean; begin request_msg := new_msg(axi_slave_enable_well_behaved_check_msg); - request(net, axi_slave.p_actor, request_msg, ack); + request(net, get_actor(axi_slave.p_std_cfg), request_msg, ack); assert ack report "Failed on msg_enable_well_behaved_check command"; end; end package body; diff --git a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd index 689b94d5b..ccce9dafa 100644 --- a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd @@ -15,6 +15,7 @@ use std.textio.all; use work.axi_pkg.all; use work.queue_pkg.all; use work.integer_vector_ptr_pkg.all; +use work.vc_pkg.all; context work.vunit_context; context work.com_context; context work.vc_context; @@ -47,6 +48,10 @@ package axi_slave_private_pkg is max_id : natural; data : std_logic_vector); impure function get_actor return actor_t; + impure function get_logger return logger_t; + impure function get_checker return checker_t; + impure function unexpected_msg_type_policy return unexpected_msg_type_policy_t; + impure function get_std_cfg return std_cfg_t; procedure set_address_fifo_depth(depth : positive); procedure set_write_response_fifo_depth(depth : positive); @@ -162,7 +167,27 @@ package body axi_slave_private_pkg is impure function get_actor return actor_t is begin - return p_axi_slave.p_actor; + return get_actor(p_axi_slave.p_std_cfg); + end; + + impure function get_logger return logger_t is + begin + return get_logger(p_axi_slave.p_std_cfg); + end; + + impure function get_checker return checker_t is + begin + return get_checker(p_axi_slave.p_std_cfg); + end; + + impure function unexpected_msg_type_policy return unexpected_msg_type_policy_t is + begin + return unexpected_msg_type_policy(p_axi_slave.p_std_cfg); + end; + + impure function get_std_cfg return std_cfg_t is + begin + return p_axi_slave.p_std_cfg; end; procedure set_address_fifo_depth(depth : positive) is @@ -295,8 +320,8 @@ package body axi_slave_private_pkg is burst.index := get(p_id_indexes, burst.id); set(p_id_indexes, burst.id, burst.index + 1); - if is_visible(p_axi_slave.p_logger, debug) then - debug(p_axi_slave.p_logger, + if is_visible(get_logger(p_axi_slave), debug) then + debug(get_logger(p_axi_slave), "Got " & description & " " & describe_burst(burst) & LF & ax & "id = 0x" & to_hstring(axid) & LF & ax & "addr = 0x" & to_hstring(axaddr) & @@ -328,13 +353,13 @@ package body axi_slave_private_pkg is impure function pop_burst return axi_burst_t is constant burst : axi_burst_t := pop_axi_burst(p_burst_queue); begin - if is_visible(p_axi_slave.p_logger, debug) then + if is_visible(get_logger(p_axi_slave), debug) then case p_axi_slave_type is when write_slave => - debug(p_axi_slave.p_logger, + debug(get_logger(p_axi_slave), "Start accepting data for write burst " & describe_burst(burst)); when read_slave => - debug(p_axi_slave.p_logger, + debug(get_logger(p_axi_slave), "Start providing data for read burst " & describe_burst(burst)); end case; end if; @@ -366,8 +391,8 @@ package body axi_slave_private_pkg is impure function pop_resp return axi_burst_t is constant resp_burst : axi_burst_t := pop_axi_burst(p_resp_queue); begin - if is_visible(p_axi_slave.p_logger, debug) then - debug(p_axi_slave.p_logger, + if is_visible(get_logger(p_axi_slave), debug) then + debug(get_logger(p_axi_slave), "Providing write response for burst " & describe_burst(resp_burst)); end if; p_resp_queue_length := p_resp_queue_length - 1; @@ -376,13 +401,13 @@ package body axi_slave_private_pkg is procedure finish_burst(burst : axi_burst_t) is begin - if is_visible(p_axi_slave.p_logger, debug) then + if is_visible(get_logger(p_axi_slave), debug) then case p_axi_slave_type is when write_slave => - debug(p_axi_slave.p_logger, + debug(get_logger(p_axi_slave), "Accepted last data for write burst " & describe_burst(burst)); when read_slave => - debug(p_axi_slave.p_logger, + debug(get_logger(p_axi_slave), "Providing last data for read burst " & describe_burst(burst)); end case; end if; @@ -424,7 +449,7 @@ package body axi_slave_private_pkg is procedure fail(msg : string) is begin - failure(p_axi_slave.p_logger, msg); + check_failed(get_checker(p_axi_slave), msg, failure); end; procedure check_4kbyte_boundary(burst : axi_burst_t) is @@ -503,6 +528,8 @@ package body axi_slave_private_pkg is receive(net, self.get_actor, request_msg); msg_type := message_type(request_msg); + handle_sync_message(net, msg_type, request_msg); + if msg_type = axi_slave_set_address_fifo_depth_msg then self.set_address_fifo_depth(pop(request_msg)); acknowledge(net, request_msg, true); @@ -549,7 +576,7 @@ package body axi_slave_private_pkg is self.enable_well_behaved_check; acknowledge(net, request_msg, true); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, self.get_std_cfg); end if; delete(request_msg); @@ -573,8 +600,6 @@ package body axi_slave_private_pkg is return resp_to_string(resp) & "(" & to_string(resp) & ")"; end; begin - if got /= expected then - failure(bus_handle.p_logger, msg & " - Got AXI response " & describe(got) & " expected " & describe(expected)); - end if; + check(get_checker(bus_handle), got = expected, result("for " & msg & " - Got AXI response " & describe(got) & " expected " & describe(expected)), failure); end; end package body; diff --git a/vunit/vhdl/verification_components/src/axi_stream_master.vhd b/vunit/vhdl/verification_components/src/axi_stream_master.vhd index 21ba42a8d..cd8382c00 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_master.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_master.vhd @@ -14,16 +14,14 @@ use work.axi_stream_pkg.all; use work.axi_stream_private_pkg.all; use work.queue_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; library osvvm; use osvvm.RandomPkg.RandomPType; entity axi_stream_master is generic ( - master : axi_stream_master_t; - drive_invalid : boolean := true; - drive_invalid_val : std_logic := 'X'; - drive_invalid_val_user : std_logic := '0' + master : axi_stream_master_t ); port ( aclk : in std_logic; @@ -41,11 +39,8 @@ entity axi_stream_master is end entity; architecture a of axi_stream_master is - - constant notify_request_msg : msg_type_t := new_msg_type("notify request"); - constant message_queue : queue_t := new_queue; - signal notify_bus_process_done : std_logic := '0'; - + constant message_queue, transaction_token_queue : queue_t := new_queue; + signal notification : boolean := false; procedure drive_invalid_output(signal l_tdata : out std_logic_vector(data_length(master)-1 downto 0); signal l_tkeep : out std_logic_vector(data_length(master)/8-1 downto 0); signal l_tstrb : out std_logic_vector(data_length(master)/8-1 downto 0); @@ -54,51 +49,69 @@ architecture a of axi_stream_master is signal l_tuser : out std_logic_vector(user_length(master)-1 downto 0)) is begin - l_tdata <= (others => drive_invalid_val); - l_tkeep <= (others => drive_invalid_val); - l_tstrb <= (others => drive_invalid_val); - l_tid <= (others => drive_invalid_val); - l_tdest <= (others => drive_invalid_val); - l_tuser <= (others => drive_invalid_val_user); + l_tdata <= (others => master.p_drive_invalid_val); + l_tkeep <= (others => master.p_drive_invalid_val); + l_tstrb <= (others => master.p_drive_invalid_val); + l_tid <= (others => master.p_drive_invalid_val); + l_tdest <= (others => master.p_drive_invalid_val); + l_tuser <= (others => master.p_drive_invalid_val_user); end procedure; begin main : process variable request_msg : msg_t; - variable notify_msg : msg_t; variable msg_type : msg_type_t; + variable timestamp : time; + + procedure wait_on_pending_transactions is begin - receive(net, master.p_actor, request_msg); + if not is_empty(transaction_token_queue) then + wait on notification until is_empty(transaction_token_queue); + end if; + end; + begin + receive(net, get_actor(master.p_std_cfg), request_msg); msg_type := message_type(request_msg); if msg_type = stream_push_msg or msg_type = push_axi_stream_msg then push(message_queue, request_msg); + push(transaction_token_queue, true); elsif msg_type = wait_for_time_msg then - push(message_queue, request_msg); + wait_on_pending_transactions; + handle_wait_for_time(net, msg_type, request_msg); elsif msg_type = wait_until_idle_msg then - notify_msg := new_msg(notify_request_msg); - push(message_queue, notify_msg); - wait on notify_bus_process_done until is_empty(message_queue); + wait_on_pending_transactions; + loop + timestamp := now; + if master.p_monitor /= null_axi_stream_monitor then + wait_until_idle(net, as_sync(master.p_monitor)); + end if; + if master.p_protocol_checker /= null_axi_stream_protocol_checker then + wait_until_idle(net, as_sync(master.p_protocol_checker)); + end if; + exit when now = timestamp; + end loop; handle_wait_until_idle(net, msg_type, request_msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, master.p_std_cfg); end if; end process; bus_process : process variable msg : msg_t; variable msg_type : msg_type_t; + variable not_used : boolean; variable rnd : RandomPType; begin rnd.InitSeed(rnd'instance_name); loop - if drive_invalid then + if master.p_drive_invalid then drive_invalid_output(tdata, tkeep, tstrb, tid, tdest, tuser); end if; -- Wait for messages to arrive on the queue, posted by the process above - wait until rising_edge(aclk) and (not is_empty(message_queue) or areset_n = '0'); + wait until (rising_edge(aclk) and not is_empty(message_queue)) or areset_n = '0'; if (areset_n = '0') then tvalid <= '0'; @@ -107,13 +120,7 @@ begin msg := pop(message_queue); msg_type := message_type(msg); - if msg_type = wait_for_time_msg then - handle_sync_message(net, msg_type, msg); - -- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment. - wait until rising_edge(aclk); - elsif msg_type = notify_request_msg then - -- Ignore this message, but expect it - elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then + if msg_type = stream_push_msg or msg_type = push_axi_stream_msg then drive_invalid_output(tdata, tkeep, tstrb, tid, tdest, tuser); -- stall according to probability configuration probability_stall_axi_stream(aclk, master, rnd); @@ -139,19 +146,19 @@ begin tdest <= (others => '0'); tuser <= (others => '0'); end if; - wait until ((tvalid and tready) = '1' or areset_n = '0') and rising_edge(aclk); + wait until (rising_edge(aclk) and (tvalid and tready) = '1') or areset_n = '0'; tvalid <= '0'; tlast <= '0'; - else - unexpected_msg_type(msg_type); + + not_used := pop(transaction_token_queue); + notification <= not notification; + wait on notification; + else + unexpected_msg_type(msg_type, master.p_std_cfg); end if; delete(msg); end loop; - - notify_bus_process_done <= '1'; - wait until notify_bus_process_done = '1'; - notify_bus_process_done <= '0'; end if; end loop; end process; @@ -173,6 +180,20 @@ begin tdest => tdest, tuser => tuser ); + + repeater : if master.p_use_default_monitor generate + process + constant subscriber : actor_t := new_actor; + variable msg : msg_t; + begin + subscribe(subscriber, get_actor(master.p_monitor.p_std_cfg)); + loop + receive(net, subscriber, msg); + publish(net, get_actor(master.p_std_cfg), msg); + end loop; + end process; + end generate; + end generate axi_stream_monitor_generate; axi_stream_protocol_checker_generate : if master.p_protocol_checker /= null_axi_stream_protocol_checker generate diff --git a/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd b/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd index 5ce59c117..96b57ce99 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd @@ -10,6 +10,8 @@ use ieee.std_logic_1164.all; context work.vunit_context; context work.com_context; use work.axi_stream_pkg.all; +use work.sync_pkg.all; +use work.vc_pkg.all; entity axi_stream_monitor is generic ( @@ -31,6 +33,25 @@ end entity; architecture a of axi_stream_monitor is begin main : process + variable request_msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net,get_actor(monitor.p_std_cfg), request_msg); + msg_type := message_type(request_msg); + + handle_wait_for_time(net, msg_type, request_msg); + + if msg_type = wait_until_idle_msg then + if monitor.p_protocol_checker /= null_axi_stream_protocol_checker then + wait_until_idle(net, as_sync(monitor.p_protocol_checker)); + end if; + handle_wait_until_idle(net, msg_type, request_msg); + else + unexpected_msg_type(msg_type, monitor.p_std_cfg); + end if; + end process; + + publish_transactions : process variable msg : msg_t; variable axi_stream_transaction : axi_stream_transaction_t( tdata(tdata'range), @@ -43,8 +64,8 @@ begin begin wait until (tvalid and tready) = '1' and rising_edge(aclk); - if is_visible(monitor.p_logger, debug) then - debug(monitor.p_logger, "tdata: " & to_nibble_string(tdata) & " (" & to_integer_string(tdata) & ")" & ", tlast: " & to_string(tlast)); + if is_visible(get_logger(monitor.p_std_cfg), debug) then + debug(get_logger(monitor.p_std_cfg), "tdata: " & to_nibble_string(tdata) & " (" & to_integer_string(tdata) & ")" & ", tlast: " & to_string(tlast)); end if; axi_stream_transaction := ( @@ -58,7 +79,7 @@ begin ); msg := new_axi_stream_transaction_msg(axi_stream_transaction); - publish(net, monitor.p_actor, msg); + publish(net, get_actor(monitor.p_std_cfg), msg); end process; axi_stream_protocol_checker_generate : if monitor.p_protocol_checker /= null_axi_stream_protocol_checker generate diff --git a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd index a49ee63c7..f5db7a030 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd @@ -13,12 +13,12 @@ use work.check_pkg.all; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; context work.vunit_context; context work.com_context; context work.data_types_context; package axi_stream_pkg is - type stall_config_t is record stall_probability : real range 0.0 to 1.0; min_stall_cycles : natural; @@ -34,87 +34,84 @@ package axi_stream_pkg is type axi_stream_component_type_t is (null_component, default_component, custom_component); type axi_stream_protocol_checker_t is record + p_std_cfg : std_cfg_t; p_type : axi_stream_component_type_t; - p_actor : actor_t; p_data_length : natural; p_id_length : natural; p_dest_length : natural; p_user_length : natural; - p_logger : logger_t; p_max_waits : natural; end record; constant null_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( + p_std_cfg => null_std_cfg, p_type => null_component, - p_actor => null_actor, p_data_length => 0, p_id_length => 0, p_dest_length => 0, p_user_length => 0, - p_logger => null_logger, p_max_waits => 0 - ); + ); -- The default protocol checker is used to specify that the checker -- configuration is defined by the parent component into which the checker is -- instantiated. constant default_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( + p_std_cfg => null_std_cfg, p_type => default_component, - p_actor => null_actor, p_data_length => 0, p_id_length => 0, p_dest_length => 0, p_user_length => 0, - p_logger => null_logger, p_max_waits => 0 - ); + ); type axi_stream_monitor_t is record + p_std_cfg : std_cfg_t; p_type : axi_stream_component_type_t; - p_actor : actor_t; p_data_length : natural; p_id_length : natural; p_dest_length : natural; p_user_length : natural; - p_logger : logger_t; p_protocol_checker : axi_stream_protocol_checker_t; end record; constant null_axi_stream_monitor : axi_stream_monitor_t := ( + p_std_cfg => null_std_cfg, p_type => null_component, - p_actor => null_actor, p_data_length => 0, p_id_length => 0, p_dest_length => 0, p_user_length => 0, - p_logger => null_logger, p_protocol_checker => null_axi_stream_protocol_checker - ); + ); -- The default monitor is used to specify that the monitor -- configuration is defined by the parent component into which the monitor is -- instantiated. constant default_axi_stream_monitor : axi_stream_monitor_t := ( + p_std_cfg => null_std_cfg, p_type => default_component, - p_actor => null_actor, p_data_length => 0, p_id_length => 0, p_dest_length => 0, p_user_length => 0, - p_logger => null_logger, p_protocol_checker => null_axi_stream_protocol_checker - ); + ); type axi_stream_master_t is record - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_stall_config : stall_config_t; - p_logger : logger_t; - p_monitor : axi_stream_monitor_t; - p_protocol_checker : axi_stream_protocol_checker_t; + p_std_cfg : std_cfg_t; + p_data_length : natural; + p_id_length : natural; + p_dest_length : natural; + p_user_length : natural; + p_stall_config : stall_config_t; + p_drive_invalid : boolean; + p_drive_invalid_val : std_logic; + p_drive_invalid_val_user : std_logic; + p_monitor : axi_stream_monitor_t; + p_use_default_monitor : boolean; + p_protocol_checker : axi_stream_protocol_checker_t; end record; constant null_axi_stream_master : axi_stream_master_t := ( @@ -130,15 +127,15 @@ package axi_stream_pkg is ); type axi_stream_slave_t is record - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_stall_config : stall_config_t; - p_logger : logger_t; - p_monitor : axi_stream_monitor_t; - p_protocol_checker : axi_stream_protocol_checker_t; + p_std_cfg : std_cfg_t; + p_data_length : natural; + p_id_length : natural; + p_dest_length : natural; + p_user_length : natural; + p_stall_config : stall_config_t; + p_monitor : axi_stream_monitor_t; + p_use_default_monitor : boolean; + p_protocol_checker : axi_stream_protocol_checker_t; end record; constant null_axi_stream_slave : axi_stream_slave_t := ( @@ -157,147 +154,164 @@ package axi_stream_pkg is constant axi_stream_checker : checker_t := new_checker(axi_stream_logger); impure function new_axi_stream_master( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_master_t; + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + stall_config : stall_config_t := null_stall_config; + drive_invalid : boolean := true; + drive_invalid_val : std_logic := 'X'; + drive_invalid_val_user : std_logic := '0'; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + monitor : axi_stream_monitor_t := null_axi_stream_monitor; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + ) return axi_stream_master_t; impure function new_axi_stream_slave( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_slave_t; + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + stall_config : stall_config_t := null_stall_config; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + monitor : axi_stream_monitor_t := null_axi_stream_monitor; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + ) return axi_stream_slave_t; impure function new_axi_stream_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_monitor_t; + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + ) return axi_stream_monitor_t; impure function new_axi_stream_protocol_checker( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - max_waits : natural := 16 - ) return axi_stream_protocol_checker_t; - - impure function data_length(master : axi_stream_master_t) return natural; - impure function data_length(slave : axi_stream_slave_t) return natural; - impure function data_length(monitor : axi_stream_monitor_t) return natural; + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + max_waits : natural := 16 + ) return axi_stream_protocol_checker_t; + + impure function data_length(master : axi_stream_master_t) return natural; + impure function data_length(slave : axi_stream_slave_t) return natural; + impure function data_length(monitor : axi_stream_monitor_t) return natural; impure function data_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function id_length(master : axi_stream_master_t) return natural; - impure function id_length(slave : axi_stream_slave_t) return natural; - impure function id_length(monitor : axi_stream_monitor_t) return natural; - impure function id_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function dest_length(master : axi_stream_master_t) return natural; - impure function dest_length(slave : axi_stream_slave_t) return natural; - impure function dest_length(monitor : axi_stream_monitor_t) return natural; + impure function id_length(master : axi_stream_master_t) return natural; + impure function id_length(slave : axi_stream_slave_t) return natural; + impure function id_length(monitor : axi_stream_monitor_t) return natural; + impure function id_length(protocol_checker : axi_stream_protocol_checker_t) return natural; + impure function dest_length(master : axi_stream_master_t) return natural; + impure function dest_length(slave : axi_stream_slave_t) return natural; + impure function dest_length(monitor : axi_stream_monitor_t) return natural; impure function dest_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function user_length(master : axi_stream_master_t) return natural; - impure function user_length(slave : axi_stream_slave_t) return natural; - impure function user_length(monitor : axi_stream_monitor_t) return natural; + impure function user_length(master : axi_stream_master_t) return natural; + impure function user_length(slave : axi_stream_slave_t) return natural; + impure function user_length(monitor : axi_stream_monitor_t) return natural; impure function user_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function as_stream(master : axi_stream_master_t) return stream_master_t; - impure function as_stream(slave : axi_stream_slave_t) return stream_slave_t; - impure function as_sync(master : axi_stream_master_t) return sync_handle_t; - impure function as_sync(slave : axi_stream_slave_t) return sync_handle_t; - - constant push_axi_stream_msg : msg_type_t := new_msg_type("push axi stream"); - constant pop_axi_stream_msg : msg_type_t := new_msg_type("pop axi stream"); - constant check_axi_stream_msg : msg_type_t := new_msg_type("check axi stream"); + impure function as_stream(master : axi_stream_master_t) return stream_master_t; + impure function as_stream(slave : axi_stream_slave_t) return stream_slave_t; + impure function as_sync(master : axi_stream_master_t) return sync_handle_t; + impure function as_sync(slave : axi_stream_slave_t) return sync_handle_t; + impure function as_sync(monitor : axi_stream_monitor_t) return sync_handle_t; + impure function as_sync(protocol_checker : axi_stream_protocol_checker_t) return sync_handle_t; + function get_std_cfg(master : axi_stream_master_t) return std_cfg_t; + function get_std_cfg(slave : axi_stream_slave_t) return std_cfg_t; + function get_std_cfg(monitor : axi_stream_monitor_t) return std_cfg_t; + function get_std_cfg(protocol_checker : axi_stream_protocol_checker_t) return std_cfg_t; + + constant push_axi_stream_msg : msg_type_t := new_msg_type("push axi stream"); + constant pop_axi_stream_msg : msg_type_t := new_msg_type("pop axi stream"); + constant check_axi_stream_msg : msg_type_t := new_msg_type("check axi stream"); constant axi_stream_transaction_msg : msg_type_t := new_msg_type("axi stream transaction"); alias axi_stream_reference_t is msg_t; procedure push_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_master_t; - tdata : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := "" + signal net : inout network_t; + axi_stream : axi_stream_master_t; + tdata : std_logic_vector; + tlast : std_logic := '1'; + tkeep : std_logic_vector := ""; + tstrb : std_logic_vector := ""; + tid : std_logic_vector := ""; + tdest : std_logic_vector := ""; + tuser : std_logic_vector := "" ); -- Blocking: pop a value from the axi stream procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic; + variable tkeep : out std_logic_vector; + variable tstrb : out std_logic_vector; + variable tid : out std_logic_vector; + variable tdest : out std_logic_vector; + variable tuser : out std_logic_vector ); procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic ); -- Non-blocking: pop a value from the axi stream to be read in the future - procedure pop_axi_stream(signal net : inout network_t; - axi_stream : axi_stream_slave_t; + procedure pop_axi_stream(signal net : inout network_t; + axi_stream : axi_stream_slave_t; variable reference : inout axi_stream_reference_t); -- Blocking: Wait for reply to non-blocking pop procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector + signal net : inout network_t; + variable reference : inout axi_stream_reference_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic; + variable tkeep : out std_logic_vector; + variable tstrb : out std_logic_vector; + variable tid : out std_logic_vector; + variable tdest : out std_logic_vector; + variable tuser : out std_logic_vector ); procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic + signal net : inout network_t; + variable reference : inout axi_stream_reference_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic ); -- Blocking: read axi stream and check result against expected value procedure check_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - expected : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := ""; - msg : string := ""; - blocking : boolean := true + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + expected : std_logic_vector; + tlast : std_logic := '1'; + tkeep : std_logic_vector := ""; + tstrb : std_logic_vector := ""; + tid : std_logic_vector := ""; + tdest : std_logic_vector := ""; + tuser : std_logic_vector := ""; + msg : string := ""; + blocking : boolean := true ); type axi_stream_transaction_t is record @@ -312,45 +326,45 @@ package axi_stream_pkg is procedure push_axi_stream_transaction(msg : msg_t; axi_stream_transaction : axi_stream_transaction_t); procedure pop_axi_stream_transaction( - constant msg : in msg_t; + constant msg : in msg_t; variable axi_stream_transaction : out axi_stream_transaction_t - ); + ); impure function new_axi_stream_transaction_msg( axi_stream_transaction : axi_stream_transaction_t - ) return msg_t; + ) return msg_t; procedure handle_axi_stream_transaction( variable msg_type : inout msg_type_t; variable msg : inout msg_t; - variable axi_transaction : out axi_stream_transaction_t); + variable axi_transaction : out axi_stream_transaction_t); function new_stall_config( stall_probability : real range 0.0 to 1.0; min_stall_cycles : natural; max_stall_cycles : natural - ) return stall_config_t; + ) return stall_config_t; end package; package body axi_stream_pkg is - impure function get_valid_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - monitor : axi_stream_monitor_t; - parent_component : string + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + logger : logger_t := axi_stream_logger; + actor : actor_t; + checker : checker_t; + monitor : axi_stream_monitor_t; + parent_component : string ) return axi_stream_monitor_t is begin if monitor = null_axi_stream_monitor then return monitor; elsif monitor = default_axi_stream_monitor then check(actor /= null_actor, "A valid actor is needed to create a default monitor"); - return new_axi_stream_monitor(data_length, id_length, dest_length, user_length, logger, actor); + return new_axi_stream_monitor(data_length, id_length, dest_length, user_length, logger, new_actor(name(actor) & ":monitor"), checker); else check_equal(axi_stream_checker, monitor.p_data_length, data_length, "Data length of monitor doesn't match that of the " & parent_component); check_equal(axi_stream_checker, monitor.p_id_length, id_length, "ID length of monitor doesn't match that of the " & parent_component); @@ -362,19 +376,21 @@ package body axi_stream_pkg is impure function get_valid_protocol_checker( data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; logger : logger_t; actor : actor_t; + checker : checker_t; protocol_checker : axi_stream_protocol_checker_t; parent_component : string - ) return axi_stream_protocol_checker_t is + ) return axi_stream_protocol_checker_t is begin if protocol_checker = null_axi_stream_protocol_checker then return protocol_checker; elsif protocol_checker = default_axi_stream_protocol_checker then - return new_axi_stream_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor); + check(actor /= null_actor, "A valid actor is needed to create a default protocol checker"); + return new_axi_stream_protocol_checker(data_length, id_length, dest_length, user_length, logger, new_actor(name(actor) & ":protocol_checker"), checker); else check_equal(axi_stream_checker, protocol_checker.p_data_length, data_length, "Data length of protocol checker doesn't match that of the " & parent_component); check_equal(axi_stream_checker, protocol_checker.p_id_length, id_length, "ID length of monitor doesn't match that of the " & parent_component); @@ -385,107 +401,130 @@ package body axi_stream_pkg is end; impure function new_axi_stream_master( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_master_t is - variable p_actor : actor_t; + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + stall_config : stall_config_t := null_stall_config; + drive_invalid : boolean := true; + drive_invalid_val : std_logic := 'X'; + drive_invalid_val_user : std_logic := '0'; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + monitor : axi_stream_monitor_t := null_axi_stream_monitor; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + ) return axi_stream_master_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + axi_stream_logger, axi_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); variable p_monitor : axi_stream_monitor_t; variable p_protocol_checker : axi_stream_protocol_checker_t; begin - p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, monitor, "master"); - p_actor := actor when actor /= null_actor else new_actor; - p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "master"); + p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, checker, monitor, "master"); + p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, checker, protocol_checker, "master"); - return (p_actor => p_actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_stall_config => stall_config, - p_logger => logger, - p_monitor => p_monitor, - p_protocol_checker => p_protocol_checker); + + return ( + p_std_cfg => p_std_cfg, + p_data_length => data_length, + p_id_length => id_length, + p_dest_length => dest_length, + p_user_length => user_length, + p_stall_config => stall_config, + p_drive_invalid => drive_invalid, + p_drive_invalid_val => drive_invalid_val, + p_drive_invalid_val_user => drive_invalid_val_user, + p_monitor => p_monitor, + p_use_default_monitor => monitor = default_axi_stream_monitor, + p_protocol_checker => p_protocol_checker); end; impure function new_axi_stream_slave( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + stall_config : stall_config_t := null_stall_config; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + monitor : axi_stream_monitor_t := null_axi_stream_monitor; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker ) return axi_stream_slave_t is - variable p_actor : actor_t; + constant p_std_cfg : std_cfg_t := create_std_cfg( + axi_stream_logger, axi_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); variable p_monitor : axi_stream_monitor_t; variable p_protocol_checker : axi_stream_protocol_checker_t; begin - p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, monitor, "slave"); - p_actor := actor when actor /= null_actor else new_actor; - p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "slave"); + p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, checker, monitor, "slave"); + p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, checker, protocol_checker, "slave"); - return (p_actor => p_actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_stall_config => stall_config, - p_logger => logger, - p_monitor => p_monitor, - p_protocol_checker => p_protocol_checker); + return ( + p_std_cfg => p_std_cfg, + p_data_length => data_length, + p_id_length => id_length, + p_dest_length => dest_length, + p_user_length => user_length, + p_stall_config => stall_config, + p_monitor => p_monitor, + p_use_default_monitor => monitor = default_axi_stream_monitor, + p_protocol_checker => p_protocol_checker); end; impure function new_axi_stream_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker ) return axi_stream_monitor_t is constant p_protocol_checker : axi_stream_protocol_checker_t := get_valid_protocol_checker( - data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "monitor" - ); + data_length, id_length, dest_length, user_length, logger, actor, checker, protocol_checker, "monitor" + ); + constant p_std_cfg : std_cfg_t := create_std_cfg( + axi_stream_logger, axi_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin return ( + p_std_cfg => p_std_cfg, p_type => custom_component, - p_actor => actor, p_data_length => data_length, p_id_length => id_length, p_dest_length => dest_length, p_user_length => user_length, - p_logger => logger, p_protocol_checker => p_protocol_checker); end; impure function new_axi_stream_protocol_checker( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - max_waits : natural := 16 + data_length : natural; + id_length : natural := 0; + dest_length : natural := 0; + user_length : natural := 0; + logger : logger_t := axi_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + max_waits : natural := 16 ) return axi_stream_protocol_checker_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + axi_stream_logger, axi_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin return ( + p_std_cfg => p_std_cfg, p_type => custom_component, - p_actor => actor, p_data_length => data_length, p_id_length => id_length, p_dest_length => dest_length, p_user_length => user_length, - p_logger => logger, p_max_waits => max_waits); end; @@ -524,7 +563,7 @@ package body axi_stream_pkg is return monitor.p_id_length; end; - impure function id_length(protocol_checker: axi_stream_protocol_checker_t) return natural is + impure function id_length(protocol_checker : axi_stream_protocol_checker_t) return natural is begin return protocol_checker.p_id_length; end; @@ -534,7 +573,7 @@ package body axi_stream_pkg is return master.p_dest_length; end; - impure function dest_length(slave: axi_stream_slave_t) return natural is + impure function dest_length(slave : axi_stream_slave_t) return natural is begin return slave.p_dest_length; end; @@ -571,42 +610,72 @@ package body axi_stream_pkg is impure function as_stream(master : axi_stream_master_t) return stream_master_t is begin - return (p_actor => master.p_actor); + return (p_std_cfg => master.p_std_cfg); end; impure function as_stream(slave : axi_stream_slave_t) return stream_slave_t is begin - return (p_actor => slave.p_actor); + return (p_std_cfg => slave.p_std_cfg); end; impure function as_sync(master : axi_stream_master_t) return sync_handle_t is begin - return master.p_actor; + return get_actor(master.p_std_cfg); end; impure function as_sync(slave : axi_stream_slave_t) return sync_handle_t is begin - return slave.p_actor; + return get_actor(slave.p_std_cfg); + end; + + impure function as_sync(monitor : axi_stream_monitor_t) return sync_handle_t is + begin + return get_actor(monitor.p_std_cfg); + end; + + impure function as_sync(protocol_checker : axi_stream_protocol_checker_t) return sync_handle_t is + begin + return get_actor(protocol_checker.p_std_cfg); + end; + + function get_std_cfg(master : axi_stream_master_t) return std_cfg_t is + begin + return master.p_std_cfg; + end; + + function get_std_cfg(slave : axi_stream_slave_t) return std_cfg_t is + begin + return slave.p_std_cfg; + end; + + function get_std_cfg(monitor : axi_stream_monitor_t) return std_cfg_t is + begin + return monitor.p_std_cfg; + end; + + function get_std_cfg(protocol_checker : axi_stream_protocol_checker_t) return std_cfg_t is + begin + return protocol_checker.p_std_cfg; end; procedure push_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_master_t; - tdata : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := "" + signal net : inout network_t; + axi_stream : axi_stream_master_t; + tdata : std_logic_vector; + tlast : std_logic := '1'; + tkeep : std_logic_vector := ""; + tstrb : std_logic_vector := ""; + tid : std_logic_vector := ""; + tdest : std_logic_vector := ""; + tuser : std_logic_vector := "" ) is - variable msg : msg_t := new_msg(push_axi_stream_msg); - variable normalized_data : std_logic_vector(data_length(axi_stream)-1 downto 0) := (others => '0'); + variable msg : msg_t := new_msg(push_axi_stream_msg); + variable normalized_data : std_logic_vector(data_length(axi_stream)-1 downto 0) := (others => '0'); variable normalized_keep : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); variable normalized_strb : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_id : std_logic_vector(id_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_dest : std_logic_vector(dest_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_user : std_logic_vector(user_length(axi_stream)-1 downto 0) := (others => '0'); + variable normalized_id : std_logic_vector(id_length(axi_stream)-1 downto 0) := (others => '0'); + variable normalized_dest : std_logic_vector(dest_length(axi_stream)-1 downto 0) := (others => '0'); + variable normalized_user : std_logic_vector(user_length(axi_stream)-1 downto 0) := (others => '0'); begin normalized_data(tdata'length-1 downto 0) := tdata; push_std_ulogic_vector(msg, normalized_data); @@ -615,33 +684,33 @@ package body axi_stream_pkg is push_std_ulogic_vector(msg, normalized_keep); normalized_strb(tstrb'length-1 downto 0) := tstrb; push_std_ulogic_vector(msg, normalized_strb); - normalized_id(tid'length-1 downto 0) := tid; + normalized_id(tid'length-1 downto 0) := tid; push_std_ulogic_vector(msg, normalized_id); normalized_dest(tdest'length-1 downto 0) := tdest; push_std_ulogic_vector(msg, normalized_dest); normalized_user(tuser'length-1 downto 0) := tuser; push_std_ulogic_vector(msg, normalized_user); - send(net, axi_stream.p_actor, msg); + send(net, get_actor(axi_stream.p_std_cfg), msg); end; - procedure pop_axi_stream(signal net : inout network_t; - axi_stream : axi_stream_slave_t; + procedure pop_axi_stream(signal net : inout network_t; + axi_stream : axi_stream_slave_t; variable reference : inout axi_stream_reference_t) is begin reference := new_msg(pop_axi_stream_msg); - send(net, axi_stream.p_actor, reference); + send(net, get_actor(axi_stream.p_std_cfg), reference); end; procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector + signal net : inout network_t; + variable reference : inout axi_stream_reference_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic; + variable tkeep : out std_logic_vector; + variable tstrb : out std_logic_vector; + variable tid : out std_logic_vector; + variable tdest : out std_logic_vector; + variable tuser : out std_logic_vector ) is variable reply_msg : msg_t; begin @@ -662,10 +731,10 @@ package body axi_stream_pkg is end; procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic + signal net : inout network_t; + variable reference : inout axi_stream_reference_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic ) is variable reply_msg : msg_t; begin @@ -681,15 +750,15 @@ package body axi_stream_pkg is end; procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic; + variable tkeep : out std_logic_vector; + variable tstrb : out std_logic_vector; + variable tid : out std_logic_vector; + variable tdest : out std_logic_vector; + variable tuser : out std_logic_vector ) is variable reference : axi_stream_reference_t; begin @@ -698,10 +767,10 @@ package body axi_stream_pkg is end; procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + variable tdata : out std_logic_vector; + variable tlast : out std_logic ) is variable reference : axi_stream_reference_t; begin @@ -710,17 +779,17 @@ package body axi_stream_pkg is end; procedure check_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - expected : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := ""; - msg : string := ""; - blocking : boolean := true + signal net : inout network_t; + axi_stream : axi_stream_slave_t; + expected : std_logic_vector; + tlast : std_logic := '1'; + tkeep : std_logic_vector := ""; + tstrb : std_logic_vector := ""; + tid : std_logic_vector := ""; + tdest : std_logic_vector := ""; + tuser : std_logic_vector := ""; + msg : string := ""; + blocking : boolean := true ) is variable got_tdata : std_logic_vector(data_length(axi_stream)-1 downto 0); variable got_tlast : std_logic; @@ -759,7 +828,7 @@ package body axi_stream_pkg is push_std_ulogic_vector(check_msg, tid); push_std_ulogic_vector(check_msg, tdest); push_std_ulogic_vector(check_msg, tuser); - send(net, axi_stream.p_actor, check_msg); + send(net, get_actor(axi_stream.p_std_cfg), check_msg); end if; end procedure; @@ -775,9 +844,9 @@ package body axi_stream_pkg is end; procedure pop_axi_stream_transaction( - constant msg : in msg_t; + constant msg : in msg_t; variable axi_stream_transaction : out axi_stream_transaction_t - ) is + ) is begin axi_stream_transaction.tdata := pop_std_ulogic_vector(msg); axi_stream_transaction.tlast := pop_boolean(msg); @@ -790,7 +859,7 @@ package body axi_stream_pkg is impure function new_axi_stream_transaction_msg( axi_stream_transaction : axi_stream_transaction_t - ) return msg_t is + ) return msg_t is variable msg : msg_t; begin msg := new_msg(axi_stream_transaction_msg); @@ -801,7 +870,7 @@ package body axi_stream_pkg is procedure handle_axi_stream_transaction( variable msg_type : inout msg_type_t; variable msg : inout msg_t; - variable axi_transaction : out axi_stream_transaction_t) is + variable axi_transaction : out axi_stream_transaction_t) is begin if msg_type = axi_stream_transaction_msg then handle_message(msg_type); @@ -814,7 +883,7 @@ package body axi_stream_pkg is stall_probability : real range 0.0 to 1.0; min_stall_cycles : natural; max_stall_cycles : natural) return stall_config_t is - variable stall_config : stall_config_t; + variable stall_config : stall_config_t; begin stall_config := ( stall_probability => stall_probability, diff --git a/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd b/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd index e37d0cd58..100859f89 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd @@ -12,84 +12,117 @@ use std.textio.all; context work.vunit_context; context work.com_context; +use work.sync_pkg.all; +use work.vc_pkg.all; use work.axi_stream_pkg.all; entity axi_stream_protocol_checker is - generic ( + generic( protocol_checker : axi_stream_protocol_checker_t); - port ( + port( aclk : in std_logic; - areset_n : in std_logic := '1'; + areset_n : in std_logic := '1'; tvalid : in std_logic; - tready : in std_logic := '1'; + tready : in std_logic := '1'; tdata : in std_logic_vector(data_length(protocol_checker) - 1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(protocol_checker)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(protocol_checker)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(protocol_checker)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(protocol_checker)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(protocol_checker)-1 downto 0) := (others => '0') - ); + tlast : in std_logic := '1'; + tkeep : in std_logic_vector(data_length(protocol_checker) / 8 - 1 downto 0) := (others => '0'); + tstrb : in std_logic_vector(data_length(protocol_checker) / 8 - 1 downto 0) := (others => '0'); + tid : in std_logic_vector(id_length(protocol_checker) - 1 downto 0) := (others => '0'); + tdest : in std_logic_vector(dest_length(protocol_checker) - 1 downto 0) := (others => '0'); + tuser : in std_logic_vector(user_length(protocol_checker) - 1 downto 0) := (others => '0') + ); end entity; architecture a of axi_stream_protocol_checker is - constant rule1_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 1"); - constant rule2_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 2"); - constant rule3_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 3"); - constant rule4_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 4"); - constant rule5_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 5"); - constant rule6_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 6"); - constant rule7_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 7"); - constant rule8_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 8"); - constant rule9_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 9"); - constant rule10_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 10"); - constant rule11_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 11"); - constant rule12_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 12"); - constant rule13_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 13"); - constant rule14_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 14"); - constant rule15_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 15"); - constant rule16_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 16"); - constant rule17_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 17"); - constant rule18_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 18"); - constant rule19_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 19"); - constant rule20_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 20"); - constant rule21_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 21"); - constant rule22_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 22"); - - signal handshake_is_not_x : std_logic; - signal enable_rule1_check : std_logic; - signal enable_rule2_check : std_logic; + type checker_vec_t is array (positive range <>) of checker_t; + + impure function create_checkers(n_rules : positive) return checker_vec_t is + variable checkers : checker_vec_t(1 to n_rules); + begin + for rule in 1 to n_rules loop + checkers(rule) := new_checker(get_name(get_logger(protocol_checker.p_std_cfg)) & ":rule " & to_string(rule)); + end loop; + + return checkers; + end; + + constant n_rules : positive := 23; + constant rule_checkers : checker_vec_t := create_checkers(n_rules); + + constant active_streams : integer_array_t := new_1d(length => 2 ** tid'length); + + signal handshake_is_not_x : std_logic; + signal enable_rule1_check : std_logic; + signal enable_rule2_check : std_logic; signal enable_rule11_check : std_logic; signal enable_rule12_check : std_logic; signal enable_rule13_check : std_logic; signal enable_rule14_check : std_logic; signal enable_rule15_check : std_logic; - signal rule20_check_value : std_logic; + signal rule20_check_value : std_logic; - signal areset_n_d : std_logic := '0'; - signal areset_rose : std_logic; - signal not_tvalid : std_logic; + signal areset_n_d : std_logic := '1'; + signal areset : std_logic; + signal areset_rose : std_logic; + signal tvalid_low, tvalid_not_high : std_logic; begin + + main : process + variable request_msg : msg_t; + variable msg_type : msg_type_t; + + procedure wait_until_all_streams_have_completed is + variable found_active_streams : boolean; + begin + loop + found_active_streams := false; + for i in 0 to length(active_streams) - 1 loop + found_active_streams := get(active_streams, i) /= 0; + exit when found_active_streams; + end loop; + + if not found_active_streams then + return; + end if; + + wait until rising_edge(aclk); + end loop; + end; + begin + receive(net, get_actor(protocol_checker.p_std_cfg), request_msg); + msg_type := message_type(request_msg); + + handle_wait_for_time(net, msg_type, request_msg); + + if msg_type = wait_until_idle_msg then + wait_until_all_streams_have_completed; + handle_wait_until_idle(net, msg_type, request_msg); + else + unexpected_msg_type(msg_type, protocol_checker.p_std_cfg); + end if; + end process; + handshake_is_not_x <= '1' when not is_x(tvalid) and not is_x(tready) else '0'; -- AXI4STREAM_ERRM_TDATA_STABLE TDATA remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule1_check <= '1' when (handshake_is_not_x = '1') and not is_x(tdata) else '0'; check_stable( - rule1_checker, aclk, enable_rule1_check, tvalid, tready, tdata, + rule_checkers(1), aclk, enable_rule1_check, tvalid, tready, tdata, result("for tdata while waiting for tready")); -- AXI4STREAM_ERRM_TLAST_STABLE TLAST remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule2_check <= '1' when (handshake_is_not_x = '1') and not is_x(tlast) else '0'; check_stable( - rule2_checker, aclk, enable_rule2_check, tvalid, tready, tlast, + rule_checkers(2), aclk, enable_rule2_check, tvalid, tready, tlast, result("for tlast while waiting for tready")); -- AXI4STREAM_ERRM_TVALID_STABLE When TVALID is asserted, then it must remain -- asserted until TREADY is HIGH check_stable( - rule3_checker, aclk, handshake_is_not_x, tvalid, tready, tvalid, + rule_checkers(3), aclk, handshake_is_not_x, tvalid, tready, tvalid, result("for tvalid while waiting for tready")); -- AXI4STREAM_RECS_TREADY_MAX_WAIT Recommended that TREADY is asserted within @@ -102,34 +135,32 @@ begin wait until rising_edge(aclk); n_clock_cycles := n_clock_cycles + 1; end loop; - check(rule4_checker, + check(rule_checkers(4), n_clock_cycles <= protocol_checker.p_max_waits, - result("for performance - tready active " & to_string(n_clock_cycles) & - " clock cycles after tvalid. Expected <= " & to_string(protocol_checker.p_max_waits) & " clock cycles."), + result("for performance - tready active " & to_string(n_clock_cycles) & " clock cycles after tvalid. Expected <= " & to_string(protocol_checker.p_max_waits) & " clock cycles."), level => warning); n_clock_cycles := 0; end process; -- AXI4STREAM_ERRM_TDATA_X A value of X on TDATA is not permitted when TVALID -- is HIGH - check_not_unknown(rule5_checker, aclk, tvalid, tdata, result("for tdata when tvalid is high")); + check_not_unknown(rule_checkers(5), aclk, tvalid, tdata, result("for tdata when tvalid is high")); -- AXI4STREAM_ERRM_TLAST_X A value of X on TLAST is not permitted when TVALID -- is HIGH - check_not_unknown(rule6_checker, aclk, tvalid, tlast, result("for tlast when tvalid is high")); + check_not_unknown(rule_checkers(6), aclk, tvalid, tlast, result("for tlast when tvalid is high")); -- AXI4STREAM_ERRM_TVALID_X A value of X on TVALID is not permitted when not -- in reset - check_not_unknown(rule7_checker, aclk, areset_n, tvalid, result("for tvalid when not in reset")); + check_not_unknown(rule_checkers(7), aclk, areset_n, tvalid, result("for tvalid when not in reset")); -- AXI4STREAM_ERRS_TREADY_X A value of X on TREADY is not permitted when not -- in reset - check_not_unknown(rule8_checker, aclk, areset_n, tready, result("for tready when not in reset")); + check_not_unknown(rule_checkers(8), aclk, areset_n, tready, result("for tready when not in reset")); -- AXI4STREAM_ERRM_STREAM_ALL_DONE_EOS At the end of simulation, all streams have had -- their corresponding TLAST transfer check_complete_packets : block is - constant active_streams : integer_array_t := new_1d(length => 2 ** tid'length); begin assert tid'length <= 8 report "tid must not be more than 8 bits (maximum recommendation)" severity failure; @@ -153,9 +184,9 @@ begin wait_until(runner, test_runner_cleanup); if tid'length = 0 then - check(rule9_checker, get(active_streams, 0) = 0, result("for packet completion.")); + check(rule_checkers(9), get(active_streams, 0) = 0, result("for packet completion.")); else - for i in 0 to 2 * tid'length - 1 loop + for i in 0 to 2 ** tid'length - 1 loop if get(active_streams, i) /= 0 then if incomplete_streams = null then write(incomplete_streams, to_string(i)); @@ -166,10 +197,9 @@ begin end loop; if incomplete_streams /= null then - check_failed(rule9_checker, result("for packet completion for the following streams: " & - incomplete_streams.all & ".")); + check_failed(rule_checkers(9), result("for packet completion for the following streams: " & incomplete_streams.all & ".")); else - check_passed(rule9_checker, result("for packet completion.")); + check_passed(rule_checkers(9), result("for packet completion.")); end if; end if; @@ -180,83 +210,88 @@ begin -- AXI4STREAM_ERRM_TUSER_X A value of X on TUSER is not permitted when not in reset -- is HIGH - check_not_unknown(rule10_checker, aclk, areset_n, tuser, result("for tuser when areset_n is high")); + check_not_unknown(rule_checkers(10), aclk, areset_n, tuser, result("for tuser when areset_n is high")); -- AXI4STREAM_ERRM_TUSER_STABLE TUSER payload signals must remain constant while TVALID is asserted, -- and TREADY is de-asserted enable_rule11_check <= '1' when (handshake_is_not_x = '1') and not is_x(tuser) else '0'; check_stable( - rule11_checker, aclk, enable_rule11_check, tvalid, tready, tuser, + rule_checkers(11), aclk, enable_rule11_check, tvalid, tready, tuser, result("for tuser while waiting for tready")); -- AXI4STREAM_ERRM_TID_STABLE TID remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule12_check <= '1' when (handshake_is_not_x = '1') and not is_x(tid) else '0'; check_stable( - rule12_checker, aclk, enable_rule12_check, tvalid, tready, tid, + rule_checkers(12), aclk, enable_rule12_check, tvalid, tready, tid, result("for tid while waiting for tready")); -- AXI4STREAM_ERRM_TDEST_STABLE TDEST remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule13_check <= '1' when (handshake_is_not_x = '1') and not is_x(tdest) else '0'; check_stable( - rule13_checker, aclk, enable_rule13_check, tvalid, tready, tdest, + rule_checkers(13), aclk, enable_rule13_check, tvalid, tready, tdest, result("for tdest while waiting for tready")); -- AXI4STREAM_ERRM_TSTRB_STABLE TSTRB remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule14_check <= '1' when (handshake_is_not_x = '1') and not is_x(tstrb) else '0'; check_stable( - rule14_checker, aclk, enable_rule14_check, tvalid, tready, tstrb, + rule_checkers(14), aclk, enable_rule14_check, tvalid, tready, tstrb, result("for tstrb while waiting for tready")); -- AXI4STREAM_ERRM_TKEEP_STABLE TKEEP remains stable when TVALID is asserted, -- and TREADY is LOW enable_rule15_check <= '1' when (handshake_is_not_x = '1') and not is_x(tkeep) else '0'; check_stable( - rule15_checker, aclk, enable_rule15_check, tvalid, tready, tkeep, + rule_checkers(15), aclk, enable_rule15_check, tvalid, tready, tkeep, result("for tkeep while waiting for tready")); -- AXI4STREAM_ERRM_TID_X A value of X on TID is not permitted when TVALID -- is HIGH - check_not_unknown(rule16_checker, aclk, tvalid, tid, result("for tid when tvalid is high")); + check_not_unknown(rule_checkers(16), aclk, tvalid, tid, result("for tid when tvalid is high")); -- AXI4STREAM_ERRM_TDEST_X A value of X on TDEST is not permitted when TVALID -- is HIGH - check_not_unknown(rule17_checker, aclk, tvalid, tdest, result("for tdest when tvalid is high")); + check_not_unknown(rule_checkers(17), aclk, tvalid, tdest, result("for tdest when tvalid is high")); -- AXI4STREAM_ERRM_TSTRB_X A value of X on TSTRB is not permitted when TVALID -- is HIGH - check_not_unknown(rule18_checker, aclk, tvalid, tstrb, result("for tstrb when tvalid is high")); + check_not_unknown(rule_checkers(18), aclk, tvalid, tstrb, result("for tstrb when tvalid is high")); -- AXI4STREAM_ERRM_TKEEP_X A value of X on TKEEP is not permitted when TVALID -- is HIGH - check_not_unknown(rule19_checker, aclk, tvalid, tkeep, result("for tkeep when tvalid is high")); + check_not_unknown(rule_checkers(19), aclk, tvalid, tkeep, result("for tkeep when tvalid is high")); -- AXI4STREAM_ERRM_TKEEP_TSTRB If TKEEP is de-asserted, then TSTRB must also be de-asserted -- eschmidscs: Binding this to tvalid. ARM does not include that, but makes more sense this way? - rule20_check_value <= not(or(((not tkeep) and tstrb))); - check_true(rule20_checker, aclk, tvalid, rule20_check_value, result("for tstrb de-asserted when tkeep de-asserted")); + rule20_check_value <= not (or(((not tkeep) and tstrb))); + check_true(rule_checkers(20), aclk, tvalid, rule20_check_value, result("for tstrb de-asserted when tkeep de-asserted")); -- AXI4STREAM_AUXM_TID_TDTEST_WIDTH The value of ID_WIDTH + DEST_WIDTH must not exceed 24 -- eschmidscs: Must wait a short while to allow testing of the rule. process begin wait for 1 ps; - check_true(rule21_checker, tid'length + tdest'length <= 24, result("for tid width and tdest width together must be less than 25")); + check_true(rule_checkers(21), tid'length + tdest'length <= 24, result("for tid width and tdest width together must be less than 25")); wait; end process; -- AXI4STREAM_ERRM_TVALID_RESET TVALID is LOW for the first cycle after ARESETn goes HIGH - process (aclk) is + process(aclk) is begin if rising_edge(aclk) then areset_n_d <= areset_n; end if; end process; - areset_rose <= areset_n and not areset_n_d; - not_tvalid <= not tvalid; - check_implication(rule22_checker, aclk, areset_n, areset_rose, not_tvalid, result("for tvalid de-asserted after reset release")); + areset_rose <= to_x01(areset_n and not areset_n_d); + tvalid_low <= not tvalid; + check_implication(rule_checkers(22), aclk, areset_n, areset_rose, tvalid_low, result("for tvalid de-asserted after reset release")); + + -- Check that tvalid stops being asserted asynchronously when areset_n is asserted + areset <= not areset_n; + tvalid_not_high <= '1' when to_x01(tvalid) /= '1' else '0'; + check_implication(rule_checkers(23), aclk, areset, areset, tvalid_not_high, result("for tvalid de-asserted asynchronously when areset_n is asserted")); -- for * being DATA, KEEP, STRB, ID, DEST or USER -- AXI4STREAM_ERRM_T*_TIEOFF T* must be stable while *_WIDTH has been set to zero diff --git a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd index 59451f142..4f8cfe2c2 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd @@ -13,6 +13,7 @@ use work.stream_slave_pkg.all; use work.axi_stream_pkg.all; use work.axi_stream_private_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; use work.string_ptr_pkg.all; library osvvm; @@ -22,49 +23,65 @@ entity axi_stream_slave is generic ( slave : axi_stream_slave_t); port ( - aclk : in std_logic; - areset_n : in std_logic := '1'; - tvalid : in std_logic; - tready : out std_logic := '0'; - tdata : in std_logic_vector(data_length(slave)-1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(slave)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(slave)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(slave)-1 downto 0) := (others => '0') - ); + aclk : in std_logic; + areset_n : in std_logic := '1'; + tvalid : in std_logic; + tready : out std_logic := '0'; + tdata : in std_logic_vector(data_length(slave)-1 downto 0); + tlast : in std_logic := '1'; + tkeep : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); + tstrb : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); + tid : in std_logic_vector(id_length(slave)-1 downto 0) := (others => '0'); + tdest : in std_logic_vector(dest_length(slave)-1 downto 0) := (others => '0'); + tuser : in std_logic_vector(user_length(slave)-1 downto 0) := (others => '0') + ); end entity; architecture a of axi_stream_slave is + constant message_queue, transaction_token_queue : queue_t := new_queue; - constant notify_request_msg : msg_type_t := new_msg_type("notify request"); - constant message_queue : queue_t := new_queue; - signal notify_bus_process_done : std_logic := '0'; - + signal notification : boolean := false; begin main : process - variable request_msg : msg_t; - variable notify_msg : msg_t; - variable msg_type : msg_type_t; + variable request_msg : msg_t; + variable msg_type : msg_type_t; + variable timestamp : time; + + procedure wait_on_pending_transactions is + begin + if not is_empty(transaction_token_queue) then + wait on notification until is_empty(transaction_token_queue); + end if; + end; begin - receive(net, slave.p_actor, request_msg); + receive(net, get_actor(slave.p_std_cfg), request_msg); msg_type := message_type(request_msg); - if msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg then - push(message_queue, request_msg); - elsif msg_type = check_axi_stream_msg then + if msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg or msg_type = check_axi_stream_msg then push(message_queue, request_msg); + push(transaction_token_queue, true); elsif msg_type = wait_for_time_msg then - push(message_queue, request_msg); + wait_on_pending_transactions; + handle_wait_for_time(net, msg_type, request_msg); elsif msg_type = wait_until_idle_msg then - notify_msg := new_msg(notify_request_msg); - push(message_queue, notify_msg); - wait on notify_bus_process_done until is_empty(message_queue); + wait_on_pending_transactions; + loop + timestamp := now; + if slave.p_monitor /= null_axi_stream_monitor then + wait_until_idle(net, as_sync(slave.p_monitor)); + end if; + if slave.p_protocol_checker /= null_axi_stream_protocol_checker then + wait_until_idle(net, as_sync(slave.p_protocol_checker)); + end if; + exit when now = timestamp; + end loop; + if slave.p_monitor /= null_axi_stream_monitor then + wait_until_idle(net, as_sync(slave.p_monitor)); + end if; handle_wait_until_idle(net, msg_type, request_msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, slave.p_std_cfg); end if; end process; @@ -78,8 +95,8 @@ begin end procedure; variable reply_msg, msg : msg_t; - variable msg_type : msg_type_t; - variable report_msg : string_ptr_t; + variable msg_type : msg_type_t; + variable report_msg : string_ptr_t; variable axi_stream_transaction : axi_stream_transaction_t( tdata(tdata'range), tkeep(tkeep'range), @@ -87,25 +104,20 @@ begin tid(tid'range), tdest(tdest'range), tuser(tuser'range) - ); - variable rnd : RandomPType; + ); + variable transaction_token : boolean; + variable rnd : RandomPType; begin rnd.InitSeed(rnd'instance_name); loop - -- Wait for messages to arrive on the queue, posted by the process above + -- Wait for messages to arrive on the queue, posted by the process above wait until rising_edge(aclk) and (not is_empty(message_queue)); while not is_empty(message_queue) loop - msg := pop(message_queue); + msg := pop(message_queue); msg_type := message_type(msg); - if msg_type = wait_for_time_msg then - handle_sync_message(net, msg_type, msg); - wait until rising_edge(aclk); - elsif msg_type = notify_request_msg then - -- Ignore this message, but expect it - elsif msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg or msg_type = check_axi_stream_msg then - + if msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg or msg_type = check_axi_stream_msg then -- stall according to probability configuration probability_stall_axi_stream(aclk, slave, rnd); @@ -137,14 +149,14 @@ begin check_field(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); end if; + transaction_token := pop(transaction_token_queue); + notification <= not notification; + wait on notification; else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, slave.p_std_cfg); end if; - end loop; - notify_bus_process_done <= '1'; - wait until notify_bus_process_done = '1'; - notify_bus_process_done <= '0'; + end loop; end loop; end process; @@ -152,7 +164,7 @@ begin axi_stream_monitor_inst : entity work.axi_stream_monitor generic map( monitor => slave.p_monitor - ) + ) port map( aclk => aclk, tvalid => tvalid, @@ -164,11 +176,24 @@ begin tid => tid, tdest => tdest, tuser => tuser - ); + ); + + repeater : if slave.p_use_default_monitor generate + process + constant subscriber : actor_t := new_actor; + variable msg : msg_t; + begin + subscribe(subscriber, get_actor(slave.p_monitor.p_std_cfg)); + loop + receive(net, subscriber, msg); + publish(net, get_actor(slave.p_std_cfg), msg); + end loop; + end process; + end generate; end generate axi_stream_monitor_generate; axi_stream_protocol_checker_generate : if slave.p_protocol_checker /= null_axi_stream_protocol_checker generate - axi_stream_protocol_checker_inst: entity work.axi_stream_protocol_checker + axi_stream_protocol_checker_inst : entity work.axi_stream_protocol_checker generic map ( protocol_checker => slave.p_protocol_checker) port map ( diff --git a/vunit/vhdl/verification_components/src/bus2memory.vhd b/vunit/vhdl/verification_components/src/bus2memory.vhd index 7b9f1a20a..8bd4bbfb0 100644 --- a/vunit/vhdl/verification_components/src/bus2memory.vhd +++ b/vunit/vhdl/verification_components/src/bus2memory.vhd @@ -12,28 +12,32 @@ context work.com_context; use work.queue_pkg.all; use work.bus_master_pkg.all; use work.memory_pkg.all; +use work.bus2memory_pkg.all; +use work.sync_pkg.all; +use work.vc_pkg.all; entity bus2memory is generic ( - bus_handle : bus_master_t; - memory : memory_t); + bus2memory_handle : bus2memory_t); end entity; architecture a of bus2memory is - constant my_memory : memory_t := to_vc_interface(memory); + constant my_memory : memory_t := to_vc_interface(bus2memory_handle.p_memory); begin main : process variable request_msg, reply_msg : msg_t; variable msg_type : msg_type_t; - variable address : std_logic_vector(address_length(bus_handle)-1 downto 0); - variable byte_enable : std_logic_vector(byte_enable_length(bus_handle)-1 downto 0); - variable data : std_logic_vector(data_length(bus_handle)-1 downto 0); - constant blen : natural := byte_length(bus_handle); + variable address : std_logic_vector(address_length(bus2memory_handle.p_bus_handle)-1 downto 0); + variable byte_enable : std_logic_vector(byte_enable_length(bus2memory_handle.p_bus_handle)-1 downto 0); + variable data : std_logic_vector(data_length(bus2memory_handle.p_bus_handle)-1 downto 0); + constant blen : natural := byte_length(bus2memory_handle.p_bus_handle); begin while true loop - receive(net, bus_handle.p_actor, request_msg); + receive(net, get_actor(bus2memory_handle.p_bus_handle), request_msg); msg_type := message_type(request_msg); + handle_sync_message(net, msg_type, request_msg); + if msg_type = bus_read_msg then address := pop_std_ulogic_vector(request_msg); data := read_word(my_memory, to_integer(unsigned(address)), bytes_per_word => data'length/8); @@ -53,7 +57,7 @@ begin end if; end loop; else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, get_std_cfg(bus2memory_handle.p_bus_handle)); end if; end loop; end process; diff --git a/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd new file mode 100644 index 000000000..99612238d --- /dev/null +++ b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd @@ -0,0 +1,80 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +use ieee.std_logic_1164.all; + +context work.vunit_context; +context work.com_context; +use work.sync_pkg.all; +use work.vc_pkg.all; +use work.bus_master_pkg.all; +use work.memory_pkg.all; + +package bus2memory_pkg is + + type bus2memory_t is record + p_bus_handle : bus_master_t; + p_memory : memory_t; + end record; + + constant bus2memory_logger : logger_t := get_logger("vunit_lib:bus_master_pkg"); + constant bus2memory_checker : checker_t := new_checker(bus2memory_logger); + + impure function new_bus2memory( + data_length : natural; + address_length : natural; + memory : memory_t; + byte_length : natural := 8; + logger : logger_t := bus2memory_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return bus2memory_t; + + impure function get_std_cfg(bus2memory : bus2memory_t) return std_cfg_t; + impure function as_bus_master(bus2memory : bus2memory_t) return bus_master_t; + impure function as_sync(bus2memory : bus2memory_t) return sync_handle_t; + +end package; + +package body bus2memory_pkg is + impure function new_bus2memory( + data_length : natural; + address_length : natural; + memory : memory_t; + byte_length : natural := 8; + logger : logger_t := bus2memory_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return bus2memory_t is + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, checker, + unexpected_msg_type_policy + ); + begin + return (p_bus_handle => p_bus_handle, + p_memory => memory); + end; + + impure function get_std_cfg(bus2memory : bus2memory_t) return std_cfg_t is + begin + return get_std_cfg(bus2memory.p_bus_handle); + end; + + impure function as_bus_master(bus2memory : bus2memory_t) return bus_master_t is + begin + return bus2memory.p_bus_handle; + end; + + impure function as_sync(bus2memory : bus2memory_t) return sync_handle_t is + begin + return as_sync(bus2memory.p_bus_handle); + end; + + + +end package body; diff --git a/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd b/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd index 46d614bc3..97fbc7f6f 100644 --- a/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd @@ -10,30 +10,52 @@ use ieee.numeric_std.all; use work.queue_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; use work.queue_pkg.all; use work.check_pkg.all; package body bus_master_pkg is - impure function new_bus(data_length : natural; - address_length : natural; - byte_length : natural := 8; - logger : logger_t := bus_logger; - actor : actor_t := null_actor) return bus_master_t is - variable p_actor : actor_t; + impure function new_bus(data_length : natural; + address_length : natural; + byte_length : natural := 8; + logger : logger_t := bus_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return bus_master_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + bus_logger, bus_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin - p_actor := actor when actor /= null_actor else new_actor; - - return (p_actor => p_actor, + return (p_std_cfg => p_std_cfg, p_data_length => data_length, p_address_length => address_length, - p_byte_length => byte_length, - p_logger => logger); + p_byte_length => byte_length); + end; + + impure function get_std_cfg(master : bus_master_t) return std_cfg_t is + begin + return master.p_std_cfg; + end; + + impure function get_actor(bus_handle : bus_master_t) return actor_t is + begin + return get_actor(bus_handle.p_std_cfg); + end; + + impure function get_logger(bus_handle : bus_master_t) return logger_t is + begin + return get_logger(bus_handle.p_std_cfg); + end; + + impure function get_checker(bus_handle : bus_master_t) return checker_t is + begin + return get_checker(bus_handle.p_std_cfg); end; - function get_logger(bus_handle : bus_master_t) return logger_t is + impure function unexpected_msg_type_policy(bus_handle : bus_master_t) return unexpected_msg_type_policy_t is begin - return bus_handle.p_logger; + return unexpected_msg_type_policy(bus_handle.p_std_cfg); end; impure function data_length(bus_handle : bus_master_t) return natural is @@ -85,7 +107,7 @@ package body bus_master_pkg is end if; push_std_ulogic_vector(request_msg, full_byte_enable); - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure write_bus(signal net : inout network_t; @@ -114,7 +136,7 @@ package body bus_master_pkg is full_data(bus_handle.p_data_length-1 downto 0) := pop(data); push_std_ulogic_vector(request_msg, full_data); end loop; - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure burst_write_bus(signal net : inout network_t; @@ -153,7 +175,7 @@ package body bus_master_pkg is read_bus(net, bus_handle, address, data); if not std_match(data, edata) then - failure(bus_handle.p_logger, base_error); + failure(get_logger(bus_handle), base_error); end if; end procedure; @@ -177,7 +199,7 @@ package body bus_master_pkg is request_msg := new_msg(bus_read_msg); full_address(address'length-1 downto 0) := address; push_std_ulogic_vector(request_msg, full_address); - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure read_bus(signal net : inout network_t; @@ -200,7 +222,7 @@ package body bus_master_pkg is full_address(address'length-1 downto 0) := address; push_std_ulogic_vector(request_msg, full_address); push_integer(request_msg, burst_length); - send(net, bus_handle.p_actor, request_msg); + send(net, get_actor(bus_handle), request_msg); end procedure; procedure burst_read_bus(signal net : inout network_t; @@ -306,9 +328,9 @@ package body bus_master_pkg is end loop; if msg = "" then - failure(bus_handle.p_logger, "Timeout"); + failure(get_logger(bus_handle), "Timeout"); else - failure(bus_handle.p_logger, msg); + failure(get_logger(bus_handle), msg); end if; end; @@ -329,13 +351,13 @@ package body bus_master_pkg is impure function as_sync(bus_master : bus_master_t) return sync_handle_t is begin - return bus_master.p_actor; + return get_actor(bus_master); end; procedure wait_until_idle(signal net : inout network_t; bus_handle : bus_master_t) is begin - wait_until_idle(net, bus_handle.p_actor); + wait_until_idle(net, get_actor(bus_handle)); end; end package body; diff --git a/vunit/vhdl/verification_components/src/bus_master_pkg.vhd b/vunit/vhdl/verification_components/src/bus_master_pkg.vhd index af486356b..22028016d 100644 --- a/vunit/vhdl/verification_components/src/bus_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/bus_master_pkg.vhd @@ -10,8 +10,10 @@ library ieee; use ieee.std_logic_1164.all; use work.logger_pkg.all; +use work.checker_pkg.all; context work.com_context; use work.sync_pkg.all; +use work.vc_pkg.all; use work.queue_pkg.all; package bus_master_pkg is @@ -19,11 +21,10 @@ package bus_master_pkg is -- Handle to VC instance with bus master VCI type bus_master_t is record -- These fields are private, do not use directly - p_actor : actor_t; + p_std_cfg : std_cfg_t; p_data_length : natural; p_address_length : natural; p_byte_length : natural; - p_logger : logger_t; end record; -- Reference to non-blocking bus command @@ -31,16 +32,30 @@ package bus_master_pkg is -- Default logger object for bus master instances constant bus_logger : logger_t := get_logger("vunit_lib:bus_master_pkg"); + constant bus_checker : checker_t := new_checker(bus_logger); -- Create new handle for bus master VC impure function new_bus(data_length : natural; address_length : natural; byte_length : natural := 8; logger : logger_t := bus_logger; - actor : actor_t := null_actor) return bus_master_t; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return bus_master_t; + + impure function get_std_cfg(master : bus_master_t) return std_cfg_t; + + -- Return the actor used by the bus master + impure function get_actor(bus_handle : bus_master_t) return actor_t; -- Return the logger used by the bus master - function get_logger(bus_handle : bus_master_t) return logger_t; + impure function get_logger(bus_handle : bus_master_t) return logger_t; + + -- Return the checker used by the bus master + impure function get_checker(bus_handle : bus_master_t) return checker_t; + + -- Return true if the bus VC fails on unexpected messages to the actor + impure function unexpected_msg_type_policy(bus_handle : bus_master_t) return unexpected_msg_type_policy_t; -- Return the length of the data on this bus impure function data_length(bus_handle : bus_master_t) return natural; diff --git a/vunit/vhdl/verification_components/src/ram_master.vhd b/vunit/vhdl/verification_components/src/ram_master.vhd index a797f9d8e..740faf625 100644 --- a/vunit/vhdl/verification_components/src/ram_master.vhd +++ b/vunit/vhdl/verification_components/src/ram_master.vhd @@ -11,34 +11,35 @@ use ieee.numeric_std.all; use work.queue_pkg.all; use work.bus_master_pkg.all; +use work.ram_master_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; context work.com_context; entity ram_master is generic ( - bus_handle : bus_master_t; - latency : positive + ram_master : ram_master_t ); port ( clk : in std_logic; en : out std_logic := '0'; - we : out std_logic_vector(byte_enable_length(bus_handle)-1 downto 0); - addr : out std_logic_vector(address_length(bus_handle)-1 downto 0); - wdata : out std_logic_vector(data_length(bus_handle)-1 downto 0); - rdata : in std_logic_vector(data_length(bus_handle)-1 downto 0) + we : out std_logic_vector(byte_enable_length(as_bus_master(ram_master))-1 downto 0); + addr : out std_logic_vector(address_length(as_bus_master(ram_master)) - 1 downto 0); + wdata : out std_logic_vector(data_length(as_bus_master(ram_master)) - 1 downto 0); + rdata : in std_logic_vector(data_length(as_bus_master(ram_master)) - 1 downto 0) ); end entity; architecture a of ram_master is signal rd : std_logic := '0'; - signal rd_pipe : std_logic_vector(0 to latency-1); + signal rd_pipe : std_logic_vector(0 to ram_master.p_latency - 1); constant request_queue : queue_t := new_queue; begin main : process variable request_msg : msg_t; variable msg_type : msg_type_t; begin - receive(net, bus_handle.p_actor, request_msg); + receive(net, get_actor(ram_master), request_msg); msg_type := message_type(request_msg); if msg_type = bus_read_msg then @@ -59,15 +60,15 @@ begin wait until en = '1' and rising_edge(clk); en <= '0'; - elsif msg_type = wait_until_idle_msg then + elsif msg_type = wait_until_idle_msg or msg_type = wait_for_time_msg then while not is_empty(request_queue) loop wait until rising_edge(clk); end loop; - handle_wait_until_idle(net, msg_type, request_msg); + handle_sync_message(net, msg_type, request_msg); + else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, get_std_cfg(ram_master)); end if; - end process; read_return : process diff --git a/vunit/vhdl/verification_components/src/ram_master_pkg.vhd b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd new file mode 100644 index 000000000..5c6882419 --- /dev/null +++ b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd @@ -0,0 +1,319 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Author Slawomir Siluk slaweksiluk@gazeta.pl +library ieee; +use ieee.std_logic_1164.all; + +context work.vunit_context; +context work.com_context; +use work.sync_pkg.all; +use work.vc_pkg.all; +use work.bus_master_pkg.all; +use work.memory_pkg.all; + +package ram_master_pkg is + + type ram_master_t is record + p_bus_handle : bus_master_t; + p_latency : positive; + end record; + + constant ram_master_logger : logger_t := get_logger("vunit_lib:ram_master_pkg"); + constant ram_master_checker : checker_t := new_checker(ram_master_logger); + + impure function new_ram_master( + data_length : natural; + address_length : natural; + latency : positive; + byte_length : natural := 8; + logger : logger_t := ram_master_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return ram_master_t; + + impure function as_sync(ram_master : ram_master_t) return sync_handle_t; + impure function as_bus_master(ram_master : ram_master_t) return bus_master_t; + + -- Return the actor used by the Wishbone master + impure function get_actor(ram_master : ram_master_t) return actor_t; + + -- Return the logger used by the Wishbone master + impure function get_logger(ram_master : ram_master_t) return logger_t; + + -- Return the checker used by the Wishbone master + impure function get_checker(ram_master : ram_master_t) return checker_t; + + -- Return for handling unexpected messages to the actor + impure function unexpected_msg_type_policy(ram_master : ram_master_t) return unexpected_msg_type_policy_t; + + -- Return the length of the data on the Wishbone bus + impure function data_length(ram_master : ram_master_t) return natural; + + -- Return the length of the address on the Wishbone bus + impure function address_length(ram_master : ram_master_t) return natural; + + -- Return the length of a byte on the Wishbone bus + impure function byte_length(ram_master : ram_master_t) return natural; + + -- Return the length of the byte enable signal on the Wishbone bus + impure function byte_enable_length(ram_master : ram_master_t) return natural; + + -- Convert natural address to std_logic_vector using the correct number of bits + impure function to_address(constant ram_master : ram_master_t; address : natural) return std_logic_vector; + + -- Blocking: Write the Wishbone bus + procedure write_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + constant data : std_logic_vector; + -- default byte enable is all bytes + constant byte_enable : std_logic_vector := ""); + procedure write_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + constant data : std_logic_vector; + -- default byte enable is all bytes + constant byte_enable : std_logic_vector := ""); + + -- Non blocking: Read the Wishbone bus returning a reference to the future reply + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + variable reference : inout bus_reference_t); + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + variable reference : inout bus_reference_t); + + -- Blocking: Read the Wishbone bus and check result against expected data + procedure check_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + constant expected : std_logic_vector; + constant msg : string := ""); + procedure check_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + constant expected : std_logic_vector; + constant msg : string := ""); + + -- Blocking: read the Wishbone bus with immediate reply + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + variable data : inout std_logic_vector); + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + variable data : inout std_logic_vector); + + -- Blocking: Wait until a read from address equals the value using + -- std_match If timeout is reached error with msg + procedure wait_until_read_equals( + signal net : inout network_t; + ram_master : ram_master_t; + addr : std_logic_vector; + value : std_logic_vector; + timeout : delay_length := delay_length'high; + msg : string := ""); + + -- Blocking: Wait until a read from address has the bit with this + -- index set to value If timeout is reached error with msg + procedure wait_until_read_bit_equals( + signal net : inout network_t; + ram_master : ram_master_t; + addr : std_logic_vector; + idx : natural; + value : std_logic; + timeout : delay_length := delay_length'high; + msg : string := ""); + + -- Wait until all operations scheduled before this command has finished + procedure wait_until_idle(signal net : inout network_t; + ram_master : ram_master_t); + + impure function get_std_cfg(ram_master : ram_master_t) return std_cfg_t; + +end package; + +package body ram_master_pkg is + impure function new_ram_master( + data_length : natural; + address_length : natural; + latency : positive; + byte_length : natural := 8; + logger : logger_t := ram_master_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return ram_master_t is + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, checker, + unexpected_msg_type_policy + ); + begin + return (p_bus_handle => p_bus_handle, + p_latency => latency); + end; + + impure function as_sync(ram_master : ram_master_t) return sync_handle_t is + begin + return as_sync(ram_master.p_bus_handle); + end; + + impure function as_bus_master(ram_master : ram_master_t) return bus_master_t is + begin + return ram_master.p_bus_handle; + end; + + impure function get_actor(ram_master : ram_master_t) return actor_t is + begin + return get_actor(ram_master.p_bus_handle); + end; + + impure function get_logger(ram_master : ram_master_t) return logger_t is + begin + return get_logger(ram_master.p_bus_handle); + end; + + impure function get_checker(ram_master : ram_master_t) return checker_t is + begin + return get_checker(ram_master.p_bus_handle); + end; + + impure function unexpected_msg_type_policy(ram_master : ram_master_t) return unexpected_msg_type_policy_t is + begin + return unexpected_msg_type_policy(ram_master.p_bus_handle); + end; + + impure function data_length(ram_master : ram_master_t) return natural is + begin + return data_length(ram_master.p_bus_handle); + end; + + impure function address_length(ram_master : ram_master_t) return natural is + begin + return address_length(ram_master.p_bus_handle); + end; + + impure function byte_length(ram_master : ram_master_t) return natural is + begin + return byte_length(ram_master.p_bus_handle); + end; + + impure function byte_enable_length(ram_master : ram_master_t) return natural is + begin + return byte_enable_length(ram_master.p_bus_handle); + end; + + impure function to_address(constant ram_master : ram_master_t; address : natural) return std_logic_vector is + begin + return to_address(ram_master.p_bus_handle, address); + end; + + procedure write_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + constant data : std_logic_vector; + constant byte_enable : std_logic_vector := "") is + begin + write_bus(net, ram_master.p_bus_handle, address, data, byte_enable); + end; + + procedure write_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + constant data : std_logic_vector; + constant byte_enable : std_logic_vector := "") is + begin + write_bus(net, ram_master.p_bus_handle, address, data, byte_enable); + end; + + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + variable reference : inout bus_reference_t) is + begin + read_bus(net, ram_master.p_bus_handle, address, reference); + end; + + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + variable reference : inout bus_reference_t) is + begin + read_bus(net, ram_master.p_bus_handle, address, reference); + end; + + procedure check_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + constant expected : std_logic_vector; + constant msg : string := "") is + begin + check_bus(net, ram_master.p_bus_handle, address, expected, msg); + end; + + procedure check_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + constant expected : std_logic_vector; + constant msg : string := "") is + begin + check_bus(net, ram_master.p_bus_handle, address, expected, msg); + end; + + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : std_logic_vector; + variable data : inout std_logic_vector) is + begin + read_bus(net, ram_master.p_bus_handle, address, data); + end; + + procedure read_bus(signal net : inout network_t; + constant ram_master : ram_master_t; + constant address : natural; + variable data : inout std_logic_vector) is + begin + read_bus(net, ram_master.p_bus_handle, address, data); + end; + + procedure wait_until_read_equals( + signal net : inout network_t; + ram_master : ram_master_t; + addr : std_logic_vector; + value : std_logic_vector; + timeout : delay_length := delay_length'high; + msg : string := "") is + begin + wait_until_read_equals(net, ram_master.p_bus_handle, addr, value, timeout, msg); + end; + + procedure wait_until_read_bit_equals( + signal net : inout network_t; + ram_master : ram_master_t; + addr : std_logic_vector; + idx : natural; + value : std_logic; + timeout : delay_length := delay_length'high; + msg : string := "") is + begin + wait_until_read_bit_equals(net, ram_master.p_bus_handle, addr, idx, value, timeout, msg); + end; + + procedure wait_until_idle(signal net : inout network_t; + ram_master : ram_master_t) is + begin + wait_until_idle(net, ram_master.p_bus_handle); + end; + + impure function get_std_cfg(ram_master : ram_master_t) return std_cfg_t is + begin + return get_std_cfg(ram_master.p_bus_handle); + end; + +end package body; diff --git a/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd b/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd index 124e6ce40..7d16bf02f 100644 --- a/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd +++ b/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd @@ -11,17 +11,23 @@ context work.vunit_context; context work.com_context; use work.sync_pkg.all; +use work.vc_pkg.all; package signal_checker_pkg is type signal_checker_t is record -- Private - p_actor : actor_t; - p_logger : logger_t; + p_std_cfg : std_cfg_t; end record; + constant signal_checker_logger : logger_t := get_logger("vunit_lib:signal_checker_pkg"); + constant signal_checker_checker : checker_t := new_checker(signal_checker_logger); + impure function new_signal_checker( - logger : logger_t := null_logger) - return signal_checker_t; + logger : logger_t := signal_checker_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) + return signal_checker_t; -- Add one value to the expect queue -- Allow event to occur within event_time += margin including end points @@ -33,7 +39,10 @@ package signal_checker_pkg is -- Wait until all expected values have been checked procedure wait_until_idle(signal net : inout network_t; - signal_checker : signal_checker_t); + signal_checker : signal_checker_t); + + impure function as_sync(signal_checker : signal_checker_t) return sync_handle_t; + function get_std_cfg(signal_checker : signal_checker_t) return std_cfg_t; -- Private message type definitions constant expect_msg : msg_type_t := new_msg_type("expect"); @@ -42,15 +51,18 @@ end package; package body signal_checker_pkg is - impure function new_signal_checker(logger : logger_t := null_logger) return signal_checker_t is - variable result : signal_checker_t; + impure function new_signal_checker( + logger : logger_t := signal_checker_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) + return signal_checker_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + signal_checker_logger, signal_checker_checker, actor, logger, checker, unexpected_msg_type_policy + ); + begin - result := (p_actor => new_actor, - p_logger => logger); - if logger = null_logger then - result.p_logger := default_logger; - end if; - return result; + return (p_std_cfg => p_std_cfg); end; procedure expect(signal net : inout network_t; @@ -63,13 +75,25 @@ package body signal_checker_pkg is push_std_ulogic_vector(request_msg, value); push_time(request_msg, event_time); push_time(request_msg, margin); - send(net, signal_checker.p_actor, request_msg); + send(net, get_actor(signal_checker.p_std_cfg), request_msg); end; procedure wait_until_idle(signal net : inout network_t; signal_checker : signal_checker_t) is begin - wait_until_idle(net, signal_checker.p_actor); + wait_until_idle(net, get_actor(signal_checker.p_std_cfg)); + end; + + impure function as_sync(signal_checker : signal_checker_t) return sync_handle_t is + begin + return get_actor(signal_checker.p_std_cfg); + end; + + function get_std_cfg(signal_checker : signal_checker_t) return std_cfg_t is + begin + return signal_checker.p_std_cfg; end; + + end package body; diff --git a/vunit/vhdl/verification_components/src/std_logic_checker.vhd b/vunit/vhdl/verification_components/src/std_logic_checker.vhd index 358621b02..9243811ec 100644 --- a/vunit/vhdl/verification_components/src/std_logic_checker.vhd +++ b/vunit/vhdl/verification_components/src/std_logic_checker.vhd @@ -12,6 +12,7 @@ context work.data_types_context; context work.com_context; use work.signal_checker_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; entity std_logic_checker is generic ( @@ -27,10 +28,9 @@ begin main : process variable request_msg : msg_t; - variable reply_msg : msg_t; variable msg_type : msg_type_t; begin - receive(net, signal_checker.p_actor, request_msg); + receive(net, get_actor(signal_checker.p_std_cfg), request_msg); msg_type := message_type(request_msg); if msg_type = expect_msg then @@ -38,7 +38,7 @@ begin push_time(expect_queue, pop_time(request_msg)); push_time(expect_queue, pop_time(request_msg)); - elsif msg_type = wait_until_idle_msg then + elsif msg_type = wait_until_idle_msg or msg_type = wait_for_time_msg then while not is_empty(expect_queue) loop if value'event then @@ -48,10 +48,9 @@ begin end if; end loop; - reply_msg := new_msg(wait_until_idle_reply_msg); - reply(net, request_msg, reply_msg); + handle_sync_message(net, msg_type, request_msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, signal_checker.p_std_cfg); end if; delete(request_msg); @@ -72,22 +71,22 @@ begin begin wait on value; if is_empty(expect_queue) then - error(signal_checker.p_logger, "Unexpected event with value = " & to_string(value)); + error(get_logger(signal_checker.p_std_cfg), "Unexpected event with value = " & to_string(value)); else expected_value := pop_std_ulogic_vector(expect_queue); event_time := pop_time(expect_queue); margin := pop_time(expect_queue); if value /= expected_value then - error(signal_checker.p_logger, "Got event with wrong value, got " & to_string(value) & + error(get_logger(signal_checker.p_std_cfg), "Got event with wrong value, got " & to_string(value) & " expected " & to_string(expected_value)); elsif now < event_time - margin or now > event_time + margin then - error(signal_checker.p_logger, "Got event at wrong time, occured at " & time'image(now) & + error(get_logger(signal_checker.p_std_cfg), "Got event at wrong time, occured at " & time'image(now) & " expected at " & time'image(event_time) & margin_suffix); else - pass(signal_checker.p_logger, "Got expected event with value = " & to_string(value)); + pass(get_logger(signal_checker.p_std_cfg), "Got expected event with value = " & to_string(value)); end if; end if; end process; diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd index 85a0e6067..f419366be 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd @@ -11,9 +11,23 @@ context work.vunit_context; context work.com_context; package body stream_master_pkg is - impure function new_stream_master return stream_master_t is + impure function new_stream_master( + logger : logger_t := stream_master_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return stream_master_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + stream_master_logger, stream_master_checker, actor, logger, checker, unexpected_msg_type_policy + ); + + begin + return (p_std_cfg => p_std_cfg); + end; + + function get_std_cfg(master : stream_master_t) return std_cfg_t is begin - return (p_actor => new_actor); + return master.p_std_cfg; end; procedure push_stream(signal net : inout network_t; @@ -25,7 +39,7 @@ package body stream_master_pkg is begin push_std_ulogic_vector(msg, normalized_data); push_boolean(msg, last); - send(net, stream.p_actor, msg); + send(net, get_actor(stream.p_std_cfg), msg); end; end package body; diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd index b61e55a27..7505db10b 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd @@ -11,15 +11,26 @@ use ieee.std_logic_1164.all; context work.vunit_context; context work.com_context; +use work.vc_pkg.all; package stream_master_pkg is -- Stream master handle type stream_master_t is record - p_actor : actor_t; + p_std_cfg : std_cfg_t; end record; + constant stream_master_logger : logger_t := get_logger("vunit_lib:stream_master_pkg"); + constant stream_master_checker : checker_t := new_checker(stream_master_logger); + -- Create a new stream master object - impure function new_stream_master return stream_master_t; + impure function new_stream_master( + logger : logger_t := stream_master_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return stream_master_t; + + function get_std_cfg(master : stream_master_t) return std_cfg_t; -- Push a data value to the stream procedure push_stream(signal net : inout network_t; diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd index 5b0ca4660..4de6c4b0f 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd @@ -5,9 +5,24 @@ -- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com package body stream_slave_pkg is - impure function new_stream_slave return stream_slave_t is + + impure function new_stream_slave( + logger : logger_t := stream_slave_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return stream_slave_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + stream_slave_logger, stream_slave_checker, actor, logger, checker, unexpected_msg_type_policy + ); + + begin + return (p_std_cfg => p_std_cfg); + end; + + function get_std_cfg(slave : stream_slave_t) return std_cfg_t is begin - return (p_actor => new_actor); + return slave.p_std_cfg; end; procedure pop_stream(signal net : inout network_t; @@ -15,7 +30,7 @@ package body stream_slave_pkg is variable reference : inout stream_reference_t) is begin reference := new_msg(stream_pop_msg); - send(net, stream.p_actor, reference); + send(net, get_actor(stream.p_std_cfg), reference); end; procedure await_pop_stream_reply(signal net : inout network_t; diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd index fa20b09d9..cd2218cf7 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd @@ -12,14 +12,26 @@ use ieee.std_logic_1164.all; context work.vunit_context; context work.com_context; +use work.vc_pkg.all; + package stream_slave_pkg is -- Stream slave handle type stream_slave_t is record - p_actor : actor_t; + p_std_cfg : std_cfg_t; end record; + constant stream_slave_logger : logger_t := get_logger("vunit_lib:stream_slave_pkg"); + constant stream_slave_checker : checker_t := new_checker(stream_slave_logger); + -- Create a new stream slave object - impure function new_stream_slave return stream_slave_t; + impure function new_stream_slave( + logger : logger_t := stream_slave_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return stream_slave_t; + + function get_std_cfg(slave : stream_slave_t) return std_cfg_t; -- Reference to future stream result alias stream_reference_t is msg_t; diff --git a/vunit/vhdl/verification_components/src/uart_master.vhd b/vunit/vhdl/verification_components/src/uart_master.vhd index 1a4115c1f..910e80d21 100644 --- a/vunit/vhdl/verification_components/src/uart_master.vhd +++ b/vunit/vhdl/verification_components/src/uart_master.vhd @@ -14,6 +14,7 @@ use vunit_lib.stream_master_pkg.all; use vunit_lib.uart_pkg.all; use vunit_lib.queue_pkg.all; use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; entity uart_master is generic ( @@ -50,7 +51,7 @@ begin variable baud_rate : natural := uart.p_baud_rate; variable msg_type : msg_type_t; begin - receive(net, uart.p_actor, msg); + receive(net, get_actor(uart.p_std_cfg), msg); msg_type := message_type(msg); handle_sync_message(net, msg_type, msg); @@ -60,7 +61,7 @@ begin elsif msg_type = uart_set_baud_rate_msg then baud_rate := pop(msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, uart.p_std_cfg); end if; end process; diff --git a/vunit/vhdl/verification_components/src/uart_pkg.vhd b/vunit/vhdl/verification_components/src/uart_pkg.vhd index c1ecb5e96..c223b7ca0 100644 --- a/vunit/vhdl/verification_components/src/uart_pkg.vhd +++ b/vunit/vhdl/verification_components/src/uart_pkg.vhd @@ -11,20 +11,24 @@ context work.com_context; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; use work.integer_vector_ptr_pkg.all; use work.queue_pkg.all; +use work.logger_pkg.all; +use work.checker_pkg.all; +use work.check_pkg.all; package uart_pkg is type uart_master_t is record - p_actor : actor_t; - p_baud_rate : natural; + p_std_cfg : std_cfg_t; + p_baud_rate : natural; p_idle_state : std_logic; end record; type uart_slave_t is record - p_actor : actor_t; - p_baud_rate : natural; - p_idle_state : std_logic; + p_std_cfg : std_cfg_t; + p_baud_rate : natural; + p_idle_state : std_logic; p_data_length : positive; end record; @@ -36,62 +40,101 @@ package uart_pkg is procedure set_baud_rate(signal net : inout network_t; uart_slave : uart_slave_t; baud_rate : natural); + constant uart_logger : logger_t := get_logger("vunit_lib:uart_pkg"); + constant uart_checker : checker_t := new_checker(uart_logger); constant default_baud_rate : natural := 115200; constant default_idle_state : std_logic := '1'; constant default_data_length : positive := 8; - impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state) return uart_master_t; - impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state; - data_length : positive := default_data_length) return uart_slave_t; + impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; + idle_state : std_logic := default_idle_state; + logger : logger_t := uart_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return uart_master_t; + impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; + idle_state : std_logic := default_idle_state; + data_length : positive := default_data_length; + logger : logger_t := uart_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return uart_slave_t; impure function as_stream(uart_master : uart_master_t) return stream_master_t; impure function as_stream(uart_slave : uart_slave_t) return stream_slave_t; impure function as_sync(uart_master : uart_master_t) return sync_handle_t; impure function as_sync(uart_slave : uart_slave_t) return sync_handle_t; + function get_std_cfg(uart_master : uart_master_t) return std_cfg_t; + function get_std_cfg(uart_slave : uart_slave_t) return std_cfg_t; constant uart_set_baud_rate_msg : msg_type_t := new_msg_type("uart set baud rate"); end package; package body uart_pkg is - impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state) return uart_master_t is + impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; + idle_state : std_logic := default_idle_state; + logger : logger_t := uart_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return uart_master_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + uart_logger, uart_checker, actor, logger, checker, unexpected_msg_type_policy + ); + begin - return (p_actor => new_actor, - p_baud_rate => initial_baud_rate, + return (p_std_cfg => p_std_cfg, + p_baud_rate => initial_baud_rate, p_idle_state => idle_state); end; - impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state; - data_length : positive := default_data_length) return uart_slave_t is + impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; + idle_state : std_logic := default_idle_state; + data_length : positive := default_data_length; + logger : logger_t := uart_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return uart_slave_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + uart_logger, uart_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin - return (p_actor => new_actor, - p_baud_rate => initial_baud_rate, - p_idle_state => idle_state, + return (p_std_cfg => p_std_cfg, + p_baud_rate => initial_baud_rate, + p_idle_state => idle_state, p_data_length => data_length); end; impure function as_stream(uart_master : uart_master_t) return stream_master_t is begin - return stream_master_t'(p_actor => uart_master.p_actor); + return stream_master_t'(p_std_cfg => uart_master.p_std_cfg); end; impure function as_stream(uart_slave : uart_slave_t) return stream_slave_t is begin - return stream_slave_t'(p_actor => uart_slave.p_actor); + return (p_std_cfg => uart_slave.p_std_cfg); end; impure function as_sync(uart_master : uart_master_t) return sync_handle_t is begin - return uart_master.p_actor; + return get_actor(uart_master.p_std_cfg); end; impure function as_sync(uart_slave : uart_slave_t) return sync_handle_t is begin - return uart_slave.p_actor; + return get_actor(uart_slave.p_std_cfg); + end; + + function get_std_cfg(uart_master : uart_master_t) return std_cfg_t is + begin + return uart_master.p_std_cfg; + end; + + function get_std_cfg(uart_slave : uart_slave_t) return std_cfg_t is + begin + return uart_slave.p_std_cfg; end; procedure set_baud_rate(signal net : inout network_t; @@ -107,13 +150,13 @@ package body uart_pkg is uart_master : uart_master_t; baud_rate : natural) is begin - set_baud_rate(net, uart_master.p_actor, baud_rate); + set_baud_rate(net, get_actor(uart_master.p_std_cfg), baud_rate); end; procedure set_baud_rate(signal net : inout network_t; uart_slave : uart_slave_t; baud_rate : natural) is begin - set_baud_rate(net, uart_slave.p_actor, baud_rate); + set_baud_rate(net, get_actor(uart_slave.p_std_cfg), baud_rate); end; end package body; diff --git a/vunit/vhdl/verification_components/src/uart_slave.vhd b/vunit/vhdl/verification_components/src/uart_slave.vhd index 8f15359e5..ef127f5eb 100644 --- a/vunit/vhdl/verification_components/src/uart_slave.vhd +++ b/vunit/vhdl/verification_components/src/uart_slave.vhd @@ -13,6 +13,8 @@ context vunit_lib.com_context; use vunit_lib.stream_slave_pkg.all; use vunit_lib.uart_pkg.all; use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; entity uart_slave is generic ( @@ -31,9 +33,11 @@ begin variable reply_msg, msg : msg_t; variable msg_type : msg_type_t; begin - receive(net, uart.p_actor, msg); + receive(net, get_actor(uart.p_std_cfg), msg); msg_type := message_type(msg); + handle_sync_message(net, msg_type, msg); + if msg_type = uart_set_baud_rate_msg then baud_rate <= pop(msg); @@ -47,7 +51,7 @@ begin reply(net, msg, reply_msg); else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, uart.p_std_cfg); end if; end process; diff --git a/vunit/vhdl/verification_components/src/wishbone_master.vhd b/vunit/vhdl/verification_components/src/wishbone_master.vhd index a6c3ff97c..b6b522208 100644 --- a/vunit/vhdl/verification_components/src/wishbone_master.vhd +++ b/vunit/vhdl/verification_components/src/wishbone_master.vhd @@ -65,7 +65,7 @@ begin wait until rising_edge(clk); loop - receive(net, bus_handle.p_actor, request_msg); + receive(net, get_actor(bus_handle), request_msg); msg_type := message_type(request_msg); if msg_type = bus_read_msg or msg_type = bus_write_msg then diff --git a/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd b/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd index 935587b43..44c266a39 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd @@ -192,7 +192,7 @@ begin wait until (bready and bvalid) = '1' and rising_edge(clk); bvalid <= '0'; wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "bresp - Got AXI response SLVERR(10) expected OKAY(00)", failure); + check_only_log(bus_logger, "Check failed for bresp - Got AXI response SLVERR(10) expected OKAY(00)", failure); unmock(bus_logger); done <= true; @@ -234,7 +234,7 @@ begin wait until (bready and bvalid) = '1' and rising_edge(clk); bvalid <= '0'; wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "bresp - Got AXI response EXOKAY(01) expected DECERR(11)", failure); + check_only_log(bus_logger, "Check failed for bresp - Got AXI response EXOKAY(01) expected DECERR(11)", failure); unmock(bus_logger); done <= true; @@ -265,7 +265,7 @@ begin wait until (rready and rvalid) = '1' and rising_edge(clk); rvalid <= '0'; wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "rresp - Got AXI response DECERR(11) expected OKAY(00)", failure); + check_only_log(bus_logger, "Check failed for rresp - Got AXI response DECERR(11) expected OKAY(00)", failure); unmock(bus_logger); done <= true; @@ -297,7 +297,7 @@ begin wait until (rready and rvalid) = '1' and rising_edge(clk); rvalid <= '0'; wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "rresp - Got AXI response DECERR(11) expected EXOKAY(01)", failure); + check_only_log(bus_logger, "Check failed for rresp - Got AXI response DECERR(11) expected EXOKAY(01)", failure); unmock(bus_logger); done <= true; diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index 8181a3a8f..2ce841884 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -166,10 +166,11 @@ begin check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); end loop; elsif run("test reset") then - wait until rising_edge(aclk); + -- The protocol checker does all the checking + push_stream(net, master_stream, x"77", true); + wait until tvalid; areset_n <= '0'; wait until rising_edge(aclk); - check_equal(tvalid, '0', result("for valid low check while in reset")); areset_n <= '1'; wait until rising_edge(aclk); @@ -225,13 +226,13 @@ begin elsif run("test single stalled push and pop") then wait until rising_edge(aclk); - wait_for_time(net, master_sync, 30 ns); + wait_for_time(net, master_sync, 25 ns); timestamp := now; push_stream(net, master_stream, x"77", true); pop_stream(net, slave_stream, data, last_bool); check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 50 ns, result("for push wait time")); -- two extra cycles inserted by alignment + check_equal(now, timestamp + 40 ns, result("for push wait time")); -- two extra cycles inserted by alignment for i in 1 to n_monitors loop get_axi_stream_transaction(axi_stream_transaction); check_equal( @@ -244,33 +245,13 @@ begin elsif run("test single push and stalled pop") then wait until rising_edge(aclk); - wait_for_time(net, slave_sync, 30 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 50 ns, result("for push wait time")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test single push and stalled pop with non-multiple of clock period") then - wait until rising_edge(aclk); - wait_for_time(net, slave_sync, 29 ns); + wait_for_time(net, slave_sync, 25 ns); timestamp := now; push_stream(net, master_stream, x"77", true); pop_stream(net, slave_stream, data, last_bool); check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 40 ns, result("for push wait time")); + check_equal(now, timestamp + 40 ns, result("for push wait time")); for i in 1 to n_monitors loop get_axi_stream_transaction(axi_stream_transaction); @@ -282,25 +263,6 @@ begin check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); end loop; - elsif run("test single stalled push and pop with non-multiple of clock period") then - wait until rising_edge(aclk); - wait_for_time(net, master_sync, 29 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 40 ns, result("for push wait time")); -- Aligned to clock edge again - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - elsif run("test pop before push") then for i in 0 to 7 loop pop_stream(net, slave_stream, reference); @@ -526,6 +488,34 @@ begin check_equal(now, timestamp + 20 ns, " transaction time incorrect"); + elsif run("test that the master waits on its subcomponents to be idle") then + timestamp := now; + wait_for_time(net, as_sync(master_axi_stream.p_monitor), 1 ns); + wait_until_idle(net, as_sync(master_axi_stream)); + check_equal(now, timestamp + 1 ns); + + timestamp := now; + wait_for_time(net, as_sync(master_axi_stream.p_protocol_checker), 2 ns); + wait_until_idle(net, as_sync(master_axi_stream)); + check_equal(now, timestamp + 2 ns); + + elsif run("test that the slave waits on its subcomponents to be idle") then + timestamp := now; + wait_for_time(net, as_sync(slave_axi_stream.p_monitor), 1 ns); + wait_until_idle(net, as_sync(slave_axi_stream)); + check_equal(now, timestamp + 1 ns); + + timestamp := now; + wait_for_time(net, as_sync(slave_axi_stream.p_protocol_checker), 2 ns); + wait_until_idle(net, as_sync(slave_axi_stream)); + check_equal(now, timestamp + 2 ns); + + elsif run("test that the monitor waits on its subcomponents to be idle") then + timestamp := now; + wait_for_time(net, as_sync(monitor.p_protocol_checker), 1 ns); + wait_until_idle(net, as_sync(monitor)); + check_equal(now, timestamp + 1 ns); + elsif run("test random stall on master") or run("test random pop stall on slave") then wait until rising_edge(aclk); for i in 0 to 100 loop @@ -600,22 +590,22 @@ begin not_valid <= not tvalid; not_valid_data <= '1' when tdata = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_data, "Invalid data not X"); + check_true(aclk, not_valid, not_valid_data, "Invalid data not X", active_clock_edge => falling_edge); not_valid_keep <= '1' when tkeep = std_logic_vector'("X") else '0'; - check_true(aclk, not_valid, not_valid_keep, "Invalid keep not X"); + check_true(aclk, not_valid, not_valid_keep, "Invalid keep not X", active_clock_edge => falling_edge); not_valid_strb <= '1' when tstrb = std_logic_vector'("X") else '0'; - check_true(aclk, not_valid, not_valid_strb, "Invalid strb not X"); + check_true(aclk, not_valid, not_valid_strb, "Invalid strb not X", active_clock_edge => falling_edge); GEN_CHECK_INVALID_ID: if g_id_length > 0 generate not_valid_id <= '1' when tid = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_id, "Invalid id not X"); + check_true(aclk, not_valid, not_valid_id, "Invalid id not X", active_clock_edge => falling_edge); end generate; GEN_CHECK_INVALID_DEST: if g_dest_length > 0 generate not_valid_dest <= '1' when tdest = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_dest, "Invalid dest not X"); + check_true(aclk, not_valid, not_valid_dest, "Invalid dest not X", active_clock_edge => falling_edge); end generate; GEN_CHECK_INVALID_USER: if g_user_length > 0 generate not_valid_user <= '1' when tuser = std_logic_vector'("00000000") else '0'; - check_true(aclk, not_valid, not_valid_user, "Invalid user not 0"); + check_true(aclk, not_valid, not_valid_user, "Invalid user not 0", active_clock_edge => falling_edge); end generate; axi_stream_slave_inst : entity work.axi_stream_slave diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd index 0e095953c..137b79947 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd @@ -7,6 +7,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +use ieee.numeric_std_unsigned.all; context work.vunit_context; context work.com_context; @@ -15,6 +16,7 @@ use work.axi_stream_pkg.all; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; use work.runner_pkg.all; +use work.sync_pkg.all; entity tb_axi_stream_protocol_checker is generic( @@ -46,11 +48,12 @@ architecture a of tb_axi_stream_protocol_checker is ); constant meta_values : std_logic_vector(1 to 5) := "-XWZU"; constant valid_values : std_logic_vector(1 to 4) := "01LH"; - + constant clk_period : time := 10 ns; begin main : process variable rule_logger : logger_t; + variable timestamp : time; procedure pass_stable_test (signal d : out std_logic_vector) is constant zeros : std_logic_vector(d'range) := (others => '0'); @@ -387,14 +390,12 @@ begin elsif run("Test passing check of that tready must not be unknown unless in reset") then wait until rising_edge(aclk); areset_n <= '0'; - tvalid <= '1'; for i in meta_values'range loop tready <= meta_values(i); wait until rising_edge(aclk); end loop; areset_n <= '1'; - tvalid <= '0'; - tready <= valid_values(1); + tready <= valid_values(1); wait until rising_edge(aclk); tvalid <= '1'; for i in valid_values'range loop @@ -423,6 +424,12 @@ begin tvalid <= '1'; tlast <= '0'; tready <= '1'; + tid <= (others => '0'); + wait until rising_edge(aclk); + tvalid <= '1'; + tlast <= '0'; + tready <= '1'; + tid <= (others => '1'); wait until rising_edge(aclk); tready <= '0'; wait until rising_edge(aclk); @@ -433,6 +440,12 @@ begin tvalid <= '1'; tlast <= '1'; tready <= '1'; + tid <= (others => '0'); + wait until rising_edge(aclk); + tvalid <= '1'; + tlast <= '1'; + tready <= '1'; + tid <= (others => '1'); wait until rising_edge(aclk); elsif run("Test failing check of that all packets are complete when the simulation ends") then @@ -444,6 +457,12 @@ begin tvalid <= '1'; tlast <= '0'; tready <= '1'; + tid <= (others => '0'); + wait until rising_edge(aclk); + tvalid <= '1'; + tlast <= '0'; + tready <= '1'; + tid <= (others => '1'); wait until rising_edge(aclk); tlast <= '0'; wait until rising_edge(aclk); @@ -452,10 +471,21 @@ begin notify(runner); entry_gate(runner); - check_only_log(rule_logger, "Unconditional check failed for packet completion for the following streams: 0.", error); + check_only_log(rule_logger, "Unconditional check failed for packet completion for the following streams: 0, 15.", error); unmock(rule_logger); + elsif run("Test waiting until idle") then + wait until rising_edge(aclk); + tvalid <= '1'; + tlast <= '0', '1' after 10.5 * clk_period; + tready <= '1'; + tid <= (others => '0'); + wait until rising_edge(aclk); + timestamp := now; + wait_until_idle(net, as_sync(protocol_checker)); + check_equal(now, timestamp + 10 * clk_period); + elsif run("Test passing check of that tuser must not be unknown unless in reset") then pass_unknown_test(tuser, areset_n, areset_n); @@ -599,6 +629,45 @@ begin unmock(rule_logger); + elsif run("Test passing check of that tvalid must go low immediately on assert") then + areset_n <= '1'; + tvalid <= '1'; + tready <= '1'; + wait until rising_edge(aclk); + wait for 0 ns; + areset_n <= '0'; + wait for clk_period * 9 / 10; + tvalid <= '0'; + wait until rising_edge(aclk); + areset_n <= '1'; + wait until rising_edge(aclk); + tvalid <= '1'; + wait until rising_edge(aclk); + + elsif run("Test failing check of that tvalid must go low immediately on assert") then + rule_logger := get_logger(get_name(logger) & ":rule 23"); + mock(rule_logger); + + areset_n <= '1'; + tvalid <= '1'; + tready <= '1'; + wait until rising_edge(aclk); + wait for 0 ns; + areset_n <= '0'; + wait until rising_edge(aclk); + tvalid <= '0'; + areset_n <= '1'; + wait until rising_edge(aclk); + tvalid <= '1'; + wait until rising_edge(aclk); + + check_only_log( + rule_logger, + "Implication check failed for tvalid de-asserted asynchronously when areset_n is asserted", + error); + + unmock(rule_logger); + end if; test_runner_cleanup(runner); @@ -624,5 +693,5 @@ begin tuser => tuser ); - aclk <= not aclk after 5 ns; + aclk <= not aclk after clk_period / 2; end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_bus_master_pkg.vhd b/vunit/vhdl/verification_components/test/tb_bus_master_pkg.vhd index bc9af90d5..577575cd1 100644 --- a/vunit/vhdl/verification_components/test/tb_bus_master_pkg.vhd +++ b/vunit/vhdl/verification_components/test/tb_bus_master_pkg.vhd @@ -16,6 +16,7 @@ use work.queue_pkg.all; use work.bus_master_pkg.all; use work.memory_pkg.all; use work.logger_pkg.all; +use work.bus2memory_pkg.all; entity tb_bus_master_pkg is generic (runner_cfg : string); @@ -23,7 +24,8 @@ end entity; architecture a of tb_bus_master_pkg is constant memory : memory_t := new_memory; - constant bus_handle : bus_master_t := new_bus(data_length => 32, address_length => 32); + constant bus2memory_handle : bus2memory_t := new_bus2memory(data_length => 32, address_length => 32, memory => memory); + constant bus_handle : bus_master_t := as_bus_master(bus2memory_handle); constant logger : logger_t := get_logger("logger"); constant actor : actor_t := new_actor("actor"); constant custom_logger_and_actor_bus_handle : bus_master_t := @@ -92,14 +94,13 @@ begin unmock(bus_logger); elsif run("test custom logger and actor bus master") then - check(custom_logger_and_actor_bus_handle.p_logger = logger); - check(custom_logger_and_actor_bus_handle.p_actor = actor); + check(get_logger(custom_logger_and_actor_bus_handle) = logger); + check(get_actor(custom_logger_and_actor_bus_handle) = actor); end if; test_runner_cleanup(runner); end process; bus2memory_inst : entity work.bus2memory generic map ( - bus_handle => bus_handle, - memory => memory); + bus2memory_handle => bus2memory_handle); end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_ram_master.vhd b/vunit/vhdl/verification_components/test/tb_ram_master.vhd index c16d1ed9c..93ca965c3 100644 --- a/vunit/vhdl/verification_components/test/tb_ram_master.vhd +++ b/vunit/vhdl/verification_components/test/tb_ram_master.vhd @@ -13,6 +13,7 @@ context vunit_lib.vunit_context; context work.com_context; use work.queue_pkg.all; +use work.ram_master_pkg.all; use work.bus_master_pkg.all; entity tb_ram_master is @@ -30,14 +31,14 @@ architecture a of tb_ram_master is signal wdata : std_logic_vector(31 downto 0); signal rdata : std_logic_vector(31 downto 0) := (others => '0'); - constant bus_handle : bus_master_t := new_bus(data_length => wdata'length, address_length => addr'length); + constant ram_master : ram_master_t := new_ram_master(data_length => wdata'length, address_length => addr'length, latency => latency); signal start, done : boolean := false; begin main : process variable reference : bus_reference_t; - variable reference_queue : queue_t := new_queue; + constant reference_queue : queue_t := new_queue; variable tmp : std_logic_vector(rdata'range); begin test_runner_setup(runner, runner_cfg); @@ -45,18 +46,18 @@ begin wait for 0 ns; if run("Test single write") then - write_bus(net, bus_handle, x"77", x"11223344"); + write_bus(net, ram_master, x"77", x"11223344"); elsif run("Test single write with byte enable") then - write_bus(net, bus_handle, x"77", x"11223344", byte_enable => "0101"); + write_bus(net, ram_master, x"77", x"11223344", byte_enable => "0101"); elsif run("Test single read") then - read_bus(net, bus_handle, x"33", tmp); + read_bus(net, ram_master, x"33", tmp); check_equal(tmp, std_logic_vector'(x"55667788"), "read data"); elsif run("Test read back to back") then for i in 1 to num_back_to_back_reads loop - read_bus(net, bus_handle, std_logic_vector(to_unsigned(i, addr'length)), reference); + read_bus(net, ram_master, std_logic_vector(to_unsigned(i, addr'length)), reference); push(reference_queue, reference); end loop; @@ -143,8 +144,7 @@ begin dut : entity work.ram_master generic map ( - bus_handle => bus_handle, - latency => latency) + ram_master => ram_master) port map ( clk => clk, en => en, From aa8196f70e39b1301c7c0d3713f521a9b6e9435e Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sun, 31 May 2020 18:30:09 +0200 Subject: [PATCH 03/21] Updated all Avalon VCs and VCIs to comply with new standard --- ...tb_avalon_master_t_compliance_template.vhd | 36 +++++ .../tb_avalon_slave_t_compliance_template.vhd | 36 +++++ .../tb_avalon_sink_t_compliance_template.vhd | 36 +++++ ...tb_avalon_source_t_compliance_template.vhd | 35 +++++ .../tb_avalon_master_compliance_template.vhd | 70 +++++++++ .../tb_avalon_sink_compliance_template.vhd | 55 +++++++ .../tb_avalon_slave_compliance_template.vhd | 64 ++++++++ .../tb_avalon_source_compliance_template.vhd | 56 +++++++ vunit/vhdl/verification_components/run.py | 56 +++++++ .../src/avalon_master.vhd | 134 ++++++++--------- .../src/avalon_pkg.vhd | 142 +++++++++++++++--- .../src/avalon_sink.vhd | 10 +- .../src/avalon_slave.vhd | 20 ++- .../src/avalon_source.vhd | 7 +- .../src/avalon_stream_pkg.vhd | 119 +++++++++------ .../test/tb_avalon_master.vhd | 17 ++- .../test/tb_avalon_slave.vhd | 2 +- .../test/tb_avalon_stream.vhd | 3 +- 18 files changed, 741 insertions(+), 157 deletions(-) create mode 100644 vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd diff --git a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd new file mode 100644 index 000000000..89aa9d0b5 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd @@ -0,0 +1,36 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.avalon_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_master_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_master_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + constant address_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd new file mode 100644 index 000000000..3954a1169 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd @@ -0,0 +1,36 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.avalon_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_slave_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_slave_t_compliance is +begin + test_runner : process + constant memory : memory_t := new_memory; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd new file mode 100644 index 000000000..2673805c0 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd @@ -0,0 +1,36 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.avalon_stream_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_sink_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_sink_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd new file mode 100644 index 000000000..756d06814 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd @@ -0,0 +1,35 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.data_types_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.avalon_stream_pkg.all; +use vunit_lib.checker_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_source_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_source_t_compliance is +begin + test_runner : process + constant data_length : natural := 8; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd new file mode 100644 index 000000000..3f470bfb4 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd @@ -0,0 +1,70 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.avalon_pkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.com_types_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_master_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_master_compliance is + + -- TODO: Specify a value for all listed parameters. Keep all parameters on separate lines + constant avalon_master_handle : avalon_master_t := new_avalon_master( + data_length => 32, + address_length => 32 + ); + + signal clk : std_logic; + signal address : std_logic_vector(31 downto 0); + signal byteenable : std_logic_vector(3 downto 0); + signal burstcount : std_logic_vector(7 downto 0); + signal waitrequest : std_logic; + signal write : std_logic; + signal writedata : std_logic_vector(31 downto 0); + signal read : std_logic; + signal readdata : std_logic_vector(31 downto 0); + signal readdatavalid : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.avalon_master + generic map(avalon_master_handle) + port map( + clk => clk, + address => address, + byteenable => byteenable, + burstcount => burstcount, + waitrequest => waitrequest, + write => write, + writedata => writedata, + read => read, + readdata => readdata, + readdatavalid => readdatavalid + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd new file mode 100644 index 000000000..ff0c75361 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd @@ -0,0 +1,55 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.avalon_stream_pkg.all; +use vunit_lib.stream_slave_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_sink_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_sink_compliance is + + constant sink : avalon_sink_t := new_avalon_sink( + data_length => 8 + ); + + signal clk : std_logic; + signal ready : std_logic; + signal valid : std_logic; + signal sop : std_logic; + signal eop : std_logic; + signal data : std_logic_vector(data_length(sink)-1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.avalon_sink + generic map(sink) + port map( + clk => clk, + ready => ready, + valid => valid, + sop => sop, + eop => eop, + data => data + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd new file mode 100644 index 000000000..4341e2faa --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd @@ -0,0 +1,64 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.avalon_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_slave_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_slave_compliance is + + constant avalon_slave : avalon_slave_t := new_avalon_slave( + memory => new_memory + ); + + signal clk : std_logic; + signal address : std_logic_vector(31 downto 0); + signal byteenable : std_logic_vector(3 downto 0); + signal burstcount : std_logic_vector(7 downto 0); + signal waitrequest : std_logic; + signal write : std_logic; + signal writedata : std_logic_vector(31 downto 0); + signal read : std_logic; + signal readdata : std_logic_vector(31 downto 0); + signal readdatavalid : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.avalon_slave + generic map(avalon_slave) + port map( + clk => clk, + address => address, + byteenable => byteenable, + burstcount => burstcount, + waitrequest => waitrequest, + write => write, + writedata => writedata, + read => read, + readdata => readdata, + readdatavalid => readdatavalid + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd new file mode 100644 index 000000000..ba3e4e6b7 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd @@ -0,0 +1,56 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.avalon_stream_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.stream_master_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; + +entity tb_avalon_source_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_avalon_source_compliance is + + constant source : avalon_source_t := new_avalon_source( + data_length => 8 + ); + + signal clk : std_logic; + signal ready : std_logic; + signal valid : std_logic; + signal sop : std_logic; + signal eop : std_logic; + signal data : std_logic_vector(data_length(source)-1 downto 0); + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.avalon_source + generic map(source) + port map( + clk => clk, + ready => ready, + valid => valid, + sop => sop, + eop => eop, + data => data + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 95079792a..1e0fdbb08 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -346,4 +346,60 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_bus2memory_compliance_template.vhd", ) +avalon_master_vci = VerificationComponentInterface.find( + LIB, "avalon_pkg", "avalon_master_t" +) +avalon_master_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "avalon_pkg" / "tb_avalon_master_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "avalon_master", avalon_master_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_avalon_master_compliance_template.vhd", +) + +avalon_slave_vci = VerificationComponentInterface.find( + LIB, "avalon_pkg", "avalon_slave_t" +) +avalon_slave_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "avalon_pkg" / "tb_avalon_slave_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "avalon_slave", avalon_slave_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_avalon_slave_compliance_template.vhd", +) + +avalon_source_vci = VerificationComponentInterface.find( + LIB, "avalon_stream_pkg", "avalon_source_t" +) +avalon_source_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "avalon_stream_pkg" / "tb_avalon_source_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "avalon_source", avalon_source_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_avalon_source_compliance_template.vhd", +) + +avalon_sink_vci = VerificationComponentInterface.find( + LIB, "avalon_stream_pkg", "avalon_sink_t" +) +avalon_sink_vci.add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "avalon_stream_pkg" / "tb_avalon_sink_t_compliance_template.vhd", +) +VerificationComponent.find(LIB, "avalon_sink", avalon_sink_vci).add_vhdl_testbench( + TEST_LIB, + ROOT / "compliance_test", + ROOT / ".vc" / "tb_avalon_sink_compliance_template.vhd", +) + UI.main() diff --git a/vunit/vhdl/verification_components/src/avalon_master.vhd b/vunit/vhdl/verification_components/src/avalon_master.vhd index 19d67a46b..b20ca239e 100644 --- a/vunit/vhdl/verification_components/src/avalon_master.vhd +++ b/vunit/vhdl/verification_components/src/avalon_master.vhd @@ -19,19 +19,16 @@ use work.logger_pkg.all; use work.check_pkg.all; use work.sync_pkg.all; use work.vc_pkg.all; +use work.avalon_pkg.all; library osvvm; use osvvm.RandomPkg.all; entity avalon_master is - generic ( - bus_handle : bus_master_t; - use_readdatavalid : boolean := true; - fixed_read_latency : natural := 1; -- (bus cycles). This parameter is ignored when use_readdatavalid is true - write_high_probability : real range 0.0 to 1.0 := 1.0; - read_high_probability : real range 0.0 to 1.0 := 1.0 + generic( + avalon_master_handle : avalon_master_t ); - port ( + port( clk : in std_logic; address : out std_logic_vector; byteenable : out std_logic_vector; @@ -58,85 +55,80 @@ begin variable request_msg : msg_t; variable msg_type : msg_type_t; variable rnd : RandomPType; - variable msgs : natural; variable burst : positive; begin rnd.InitSeed(rnd'instance_name); write <= '0'; read <= '0'; burstcount <= std_logic_vector(to_unsigned(1, burstcount'length)); - wait until rising_edge(clk); loop - request_msg := null_msg; - msgs := num_of_messages(get_actor(bus_handle)); - if (msgs > 0) then - receive(net, get_actor(bus_handle), request_msg); - msg_type := message_type(request_msg); - if msg_type = bus_read_msg then - while rnd.Uniform(0.0, 1.0) > read_high_probability loop - wait until rising_edge(clk); - end loop; - address <= pop_std_ulogic_vector(request_msg); - byteenable(byteenable'range) <= (others => '1'); - read <= '1'; - push(acknowledge_queue, request_msg); - wait until rising_edge(clk) and waitrequest = '0'; - read <= '0'; + receive(net, get_actor(avalon_master_handle.p_bus_handle), request_msg); + msg_type := message_type(request_msg); - elsif msg_type = bus_burst_read_msg then - while rnd.Uniform(0.0, 1.0) > read_high_probability loop - wait until rising_edge(clk); - end loop; - address <= pop_std_ulogic_vector(request_msg); - burstcount <= std_logic_vector(to_unsigned(1, burstcount'length)); - burst := pop_integer(request_msg); - burstcount <= std_logic_vector(to_unsigned(burst, burstcount'length)); - byteenable(byteenable'range) <= (others => '1'); - read <= '1'; - push(burst_acknowledge_queue, request_msg); - wait until rising_edge(clk) and waitrequest = '0'; - read <= '0'; - push(burstlen_queue, burst); + if msg_type = bus_read_msg then + while rnd.Uniform(0.0, 1.0) > avalon_master_handle.p_read_high_probability loop + wait until rising_edge(clk); + end loop; + address <= pop_std_ulogic_vector(request_msg); + byteenable(byteenable'range) <= (others => '1'); + read <= '1'; + push(acknowledge_queue, request_msg); + wait until rising_edge(clk) and waitrequest = '0'; + read <= '0'; - elsif msg_type = bus_write_msg then - while rnd.Uniform(0.0, 1.0) > write_high_probability loop + elsif msg_type = bus_burst_read_msg then + while rnd.Uniform(0.0, 1.0) > avalon_master_handle.p_read_high_probability loop + wait until rising_edge(clk); + end loop; + address <= pop_std_ulogic_vector(request_msg); + burstcount <= std_logic_vector(to_unsigned(1, burstcount'length)); + burst := pop_integer(request_msg); + burstcount <= std_logic_vector(to_unsigned(burst, burstcount'length)); + byteenable(byteenable'range) <= (others => '1'); + read <= '1'; + push(burst_acknowledge_queue, request_msg); + wait until rising_edge(clk) and waitrequest = '0'; + read <= '0'; + push(burstlen_queue, burst); + + elsif msg_type = bus_write_msg then + while rnd.Uniform(0.0, 1.0) > avalon_master_handle.p_write_high_probability loop + wait until rising_edge(clk); + end loop; + address <= pop_std_ulogic_vector(request_msg); + burstcount <= std_logic_vector(to_unsigned(1, burstcount'length)); + writedata <= pop_std_ulogic_vector(request_msg); + byteenable <= pop_std_ulogic_vector(request_msg); + write <= '1'; + wait until rising_edge(clk) and waitrequest = '0'; + write <= '0'; + + elsif msg_type = bus_burst_write_msg then + address <= pop_std_ulogic_vector(request_msg); + burst := pop_integer(request_msg); + burstcount <= std_logic_vector(to_unsigned(burst, burstcount'length)); + for i in 0 to burst-1 loop + while rnd.Uniform(0.0, 1.0) > avalon_master_handle.p_write_high_probability loop wait until rising_edge(clk); end loop; - address <= pop_std_ulogic_vector(request_msg); - burstcount <= std_logic_vector(to_unsigned(1, burstcount'length)); writedata <= pop_std_ulogic_vector(request_msg); - byteenable <= pop_std_ulogic_vector(request_msg); + -- TODO handle byteenable + byteenable(byteenable'range) <= (others => '1'); write <= '1'; wait until rising_edge(clk) and waitrequest = '0'; write <= '0'; + address(address'range) <= (others => 'U'); + burstcount(burstcount'range) <= (others => 'U'); + end loop; - elsif msg_type = bus_burst_write_msg then - address <= pop_std_ulogic_vector(request_msg); - burst := pop_integer(request_msg); - burstcount <= std_logic_vector(to_unsigned(burst, burstcount'length)); - for i in 0 to burst-1 loop - while rnd.Uniform(0.0, 1.0) > write_high_probability loop - wait until rising_edge(clk); - end loop; - writedata <= pop_std_ulogic_vector(request_msg); - -- TODO handle byteenable - byteenable(byteenable'range) <= (others => '1'); - write <= '1'; - wait until rising_edge(clk) and waitrequest = '0'; - write <= '0'; - address(address'range) <= (others => 'U'); - burstcount(burstcount'range) <= (others => 'U'); - end loop; - - elsif msg_type = wait_until_idle_msg then - wait until not burst_read_flag and is_empty(burst_acknowledge_queue) and rising_edge(clk); - handle_wait_until_idle(net, msg_type, request_msg); + elsif msg_type = wait_until_idle_msg or msg_type = wait_for_time_msg then + while burst_read_flag or not is_empty(burst_acknowledge_queue) loop + wait until rising_edge(clk); + end loop; + handle_sync_message(net, msg_type, request_msg); - else - unexpected_msg_type(msg_type); - end if; else - wait until rising_edge(clk); + unexpected_msg_type(msg_type, get_std_cfg(avalon_master_handle.p_bus_handle)); end if; end loop; end process; @@ -144,13 +136,13 @@ begin read_capture : process variable request_msg, reply_msg : msg_t; begin - if use_readdatavalid then + if avalon_master_handle.p_use_readdatavalid then wait until readdatavalid = '1' and not is_empty(acknowledge_queue) and rising_edge(clk); else -- Non-pipelined case: waits for slave to de-assert waitrequest and sample data after fixed_read_latency cycles. wait until rising_edge(clk) and waitrequest = '0' and read = '1'; - if fixed_read_latency > 0 then - for i in 0 to fixed_read_latency - 1 loop + if avalon_master_handle.p_fixed_read_latency > 0 then + for i in 0 to avalon_master_handle.p_fixed_read_latency - 1 loop wait until rising_edge(clk); end loop; end if; diff --git a/vunit/vhdl/verification_components/src/avalon_pkg.vhd b/vunit/vhdl/verification_components/src/avalon_pkg.vhd index b6991f0e1..ded2e5a27 100644 --- a/vunit/vhdl/verification_components/src/avalon_pkg.vhd +++ b/vunit/vhdl/verification_components/src/avalon_pkg.vhd @@ -9,48 +9,140 @@ use ieee.std_logic_1164.all; use work.queue_pkg.all; use work.logger_pkg.all; +use work.checker_pkg.all; use work.memory_pkg.all; +use work.bus_master_pkg.all; +use work.vc_pkg.all; +use work.sync_pkg.all; context work.com_context; package avalon_pkg is + type avalon_master_t is record + p_bus_handle : bus_master_t; + p_use_readdatavalid : boolean; + p_fixed_read_latency : natural; + p_write_high_probability : real range 0.0 to 1.0; + p_read_high_probability : real range 0.0 to 1.0; + end record; + type avalon_slave_t is record - readdatavalid_high_probability : real range 0.0 to 1.0; - waitrequest_high_probability : real range 0.0 to 1.0; - -- Private - p_actor : actor_t; + p_readdatavalid_high_probability : real range 0.0 to 1.0; + p_waitrequest_high_probability : real range 0.0 to 1.0; + p_std_cfg : std_cfg_t; p_ack_actor : actor_t; p_memory : memory_t; - p_logger : logger_t; end record; - constant avalon_slave_logger : logger_t := get_logger("vunit_lib:avalon_pkg"); + constant avalon_logger : logger_t := get_logger("vunit_lib:avalon_pkg"); + constant avalon_checker : checker_t := new_checker(avalon_logger); + + impure function new_avalon_master( + data_length : natural; + address_length : natural; + use_readdatavalid : boolean := true; + fixed_read_latency : natural := 1; -- (bus cycles). This parameter is ignored when use_readdatavalid is true + write_high_probability : real range 0.0 to 1.0 := 1.0; + read_high_probability : real range 0.0 to 1.0 := 1.0; + byte_length : natural := 8; + logger : logger_t := avalon_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return avalon_master_t; + impure function new_avalon_slave( - memory : memory_t; - readdatavalid_high_probability : real := 1.0; - waitrequest_high_probability : real := 0.0; - name : string := ""; - logger : logger_t := avalon_slave_logger) - return avalon_slave_t; + memory : memory_t; + readdatavalid_high_probability : real := 1.0; + waitrequest_high_probability : real := 0.0; + logger : logger_t := avalon_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) + return avalon_slave_t; + + impure function as_sync(avalon_master : avalon_master_t) return sync_handle_t; + impure function as_sync(avalon_slave : avalon_slave_t) return sync_handle_t; + impure function as_bus_master(avalon_master : avalon_master_t) return bus_master_t; + impure function get_std_cfg(avalon_master : avalon_master_t) return std_cfg_t; + impure function get_std_cfg(avalon_slave : avalon_slave_t) return std_cfg_t; end package; package body avalon_pkg is + impure function new_avalon_master( + data_length : natural; + address_length : natural; + use_readdatavalid : boolean := true; + fixed_read_latency : natural := 1; -- (bus cycles). This parameter is ignored when use_readdatavalid is true + write_high_probability : real range 0.0 to 1.0 := 1.0; + read_high_probability : real range 0.0 to 1.0 := 1.0; + byte_length : natural := 8; + logger : logger_t := avalon_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return avalon_master_t is + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, + checker, unexpected_msg_type_policy + ); + begin + return (p_bus_handle => p_bus_handle, + p_use_readdatavalid => use_readdatavalid, + p_fixed_read_latency => fixed_read_latency, + p_write_high_probability => write_high_probability, + p_read_high_probability => read_high_probability + ); + end; + impure function new_avalon_slave( - memory : memory_t; - readdatavalid_high_probability : real := 1.0; - waitrequest_high_probability : real := 0.0; - name : string := ""; - logger : logger_t := avalon_slave_logger) - return avalon_slave_t is + memory : memory_t; + readdatavalid_high_probability : real := 1.0; + waitrequest_high_probability : real := 0.0; + logger : logger_t := avalon_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) + return avalon_slave_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + avalon_logger, avalon_checker, actor, logger, checker, unexpected_msg_type_policy + ); + + begin + return (p_std_cfg => p_std_cfg, + p_ack_actor => new_actor(name(actor) & " read-ack"), + p_memory => to_vc_interface(memory, logger), + p_readdatavalid_high_probability => readdatavalid_high_probability, + p_waitrequest_high_probability => waitrequest_high_probability + ); + end; + + impure function as_sync(avalon_master : avalon_master_t) return sync_handle_t is begin - return (p_actor => new_actor(name), - p_ack_actor => new_actor(name&" read-ack"), - p_memory => to_vc_interface(memory, logger), - p_logger => logger, - readdatavalid_high_probability => readdatavalid_high_probability, - waitrequest_high_probability => waitrequest_high_probability - ); + return as_sync(avalon_master.p_bus_handle); end; + impure function as_sync(avalon_slave : avalon_slave_t) return sync_handle_t is + begin + return get_actor(avalon_slave.p_std_cfg); + end; + + impure function as_bus_master(avalon_master : avalon_master_t) return bus_master_t is + begin + return avalon_master.p_bus_handle; + end; + + impure function get_std_cfg(avalon_master : avalon_master_t) return std_cfg_t is + begin + return get_std_cfg(avalon_master.p_bus_handle); + end; + + impure function get_std_cfg(avalon_slave : avalon_slave_t) return std_cfg_t is + begin + return avalon_slave.p_std_cfg; + end; + + end package body; diff --git a/vunit/vhdl/verification_components/src/avalon_sink.vhd b/vunit/vhdl/verification_components/src/avalon_sink.vhd index be069f642..fff35c68e 100644 --- a/vunit/vhdl/verification_components/src/avalon_sink.vhd +++ b/vunit/vhdl/verification_components/src/avalon_sink.vhd @@ -15,6 +15,8 @@ context work.vunit_context; context work.com_context; use work.stream_slave_pkg.all; use work.avalon_stream_pkg.all; +use work.vc_pkg.all; +use work.sync_pkg.all; library osvvm; use osvvm.RandomPkg.all; @@ -40,13 +42,15 @@ begin variable rnd : RandomPType; variable avalon_stream_transaction : avalon_stream_transaction_t(data(data'range)); begin - receive(net, sink.p_actor, msg); + receive(net, get_actor(sink.p_std_cfg), msg); msg_type := message_type(msg); + handle_sync_message(net, msg_type, msg); + if msg_type = stream_pop_msg or msg_type = pop_avalon_stream_msg then -- Loop till got valid data loop - while rnd.Uniform(0.0, 1.0) > sink.ready_high_probability loop + while rnd.Uniform(0.0, 1.0) > sink.p_ready_high_probability loop wait until rising_edge(clk); end loop; ready <= '1'; @@ -77,7 +81,7 @@ begin end loop; else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, sink.p_std_cfg); end if; end process; diff --git a/vunit/vhdl/verification_components/src/avalon_slave.vhd b/vunit/vhdl/verification_components/src/avalon_slave.vhd index c3c8fcbdf..35ed972c7 100644 --- a/vunit/vhdl/verification_components/src/avalon_slave.vhd +++ b/vunit/vhdl/verification_components/src/avalon_slave.vhd @@ -15,6 +15,8 @@ context work.vunit_context; context work.com_context; use work.memory_pkg.all; use work.avalon_pkg.all; +use work.vc_pkg.all; +use work.sync_pkg.all; library osvvm; use osvvm.RandomPkg.all; @@ -43,6 +45,18 @@ architecture a of avalon_slave is begin + -- TODO: Add interface for updating probability numbers + main : process + variable request_msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(avalon_slave.p_std_cfg), request_msg); + msg_type := message_type(request_msg); + + handle_sync_message(net, msg_type, request_msg); + unexpected_msg_type(msg_type, avalon_slave.p_std_cfg); + end process; + write_handler : process variable pending_writes : positive := 1; variable addr : natural; @@ -67,7 +81,7 @@ begin variable rd_request_msg : msg_t; begin wait until read = '1' and waitrequest = '0' and rising_edge(clk); - rd_request_msg := new_msg(slave_read_msg, avalon_slave.p_actor); + rd_request_msg := new_msg(slave_read_msg); -- For read, only address is passed to ack proc push_integer(rd_request_msg, to_integer(unsigned(burstcount))); push_integer(rd_request_msg, to_integer(unsigned(address))); @@ -89,7 +103,7 @@ begin burst := pop_integer(request_msg); baseaddr := pop_integer(request_msg); for i in 0 to burst-1 loop - while rnd.Uniform(0.0, 1.0) > avalon_slave.readdatavalid_high_probability loop + while rnd.Uniform(0.0, 1.0) > avalon_slave.p_readdatavalid_high_probability loop wait until rising_edge(clk); end loop; readdata <= read_word(avalon_slave.p_memory, baseaddr + byteenable'length*i, byteenable'length); @@ -106,7 +120,7 @@ begin waitrequest_stim: process variable rnd : RandomPType; begin - if rnd.Uniform(0.0, 1.0) < avalon_slave.waitrequest_high_probability then + if rnd.Uniform(0.0, 1.0) < avalon_slave.p_waitrequest_high_probability then waitrequest <= '1'; else waitrequest <= '0'; diff --git a/vunit/vhdl/verification_components/src/avalon_source.vhd b/vunit/vhdl/verification_components/src/avalon_source.vhd index 18cda6fc9..8ae40242e 100644 --- a/vunit/vhdl/verification_components/src/avalon_source.vhd +++ b/vunit/vhdl/verification_components/src/avalon_source.vhd @@ -14,6 +14,7 @@ use work.stream_master_pkg.all; use work.avalon_stream_pkg.all; use work.queue_pkg.all; use work.sync_pkg.all; +use work.vc_pkg.all; library osvvm; use osvvm.RandomPkg.all; @@ -39,13 +40,13 @@ begin variable rnd : RandomPType; variable avalon_stream_transaction : avalon_stream_transaction_t(data(data'range)); begin - receive(net, source.p_actor, msg); + receive(net, get_actor(source.p_std_cfg), msg); msg_type := message_type(msg); handle_sync_message(net, msg_type, msg); if msg_type = stream_push_msg or msg_type = push_avalon_stream_msg then - while rnd.Uniform(0.0, 1.0) > source.valid_high_probability loop + while rnd.Uniform(0.0, 1.0) > source.p_valid_high_probability loop wait until rising_edge(clk); end loop; valid <= '1'; @@ -72,7 +73,7 @@ begin sop <= '0'; eop <= '0'; else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, source.p_std_cfg); end if; end process; diff --git a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd index 07036c441..b563bc5f8 100644 --- a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd @@ -12,39 +12,49 @@ use work.checker_pkg.all; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; use work.vc_pkg.all; +use work.sync_pkg.all; context work.com_context; context work.data_types_context; package avalon_stream_pkg is type avalon_source_t is record - valid_high_probability : real range 0.0 to 1.0; - p_actor : actor_t; - p_data_length : natural; - p_logger : logger_t; + p_std_cfg : std_cfg_t; + p_valid_high_probability : real range 0.0 to 1.0; + p_data_length : natural; end record; type avalon_sink_t is record - ready_high_probability : real range 0.0 to 1.0; - -- Private - p_actor : actor_t; + p_std_cfg : std_cfg_t; + p_ready_high_probability : real range 0.0 to 1.0; p_data_length : natural; - p_logger : logger_t; end record; constant avalon_stream_logger : logger_t := get_logger("vunit_lib:avalon_stream_pkg"); - impure function new_avalon_source(data_length : natural; - valid_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; - actor : actor_t := null_actor) return avalon_source_t; - impure function new_avalon_sink(data_length : natural; - ready_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; - actor : actor_t := null_actor) return avalon_sink_t; + constant avalon_stream_checker : checker_t := new_checker(avalon_stream_logger); + + impure function new_avalon_source(data_length : natural; + valid_high_probability : real := 1.0; + logger : logger_t := avalon_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return avalon_source_t; + impure function new_avalon_sink(data_length : natural; + ready_high_probability : real := 1.0; + logger : logger_t := avalon_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return avalon_sink_t; impure function data_length(source : avalon_source_t) return natural; impure function data_length(source : avalon_sink_t) return natural; + impure function as_sync(source : avalon_source_t) return sync_handle_t; + impure function as_sync(sink : avalon_sink_t) return sync_handle_t; impure function as_stream(source : avalon_source_t) return stream_master_t; impure function as_stream(sink : avalon_sink_t) return stream_slave_t; + function get_std_cfg(source : avalon_source_t) return std_cfg_t; + function get_std_cfg(sink : avalon_sink_t) return std_cfg_t; + constant push_avalon_stream_msg : msg_type_t := new_msg_type("push avalon stream"); constant pop_avalon_stream_msg : msg_type_t := new_msg_type("pop avalon stream"); @@ -87,32 +97,35 @@ end package; package body avalon_stream_pkg is - impure function new_avalon_source(data_length : natural; - valid_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; - actor : actor_t := null_actor) return avalon_source_t is - variable p_actor : actor_t; + impure function new_avalon_source(data_length : natural; + valid_high_probability : real := 1.0; + logger : logger_t := avalon_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return avalon_source_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + avalon_stream_logger, avalon_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin - p_actor := actor when actor /= null_actor else new_actor; - - return (valid_high_probability => valid_high_probability, - p_actor => p_actor, - p_data_length => data_length, - p_logger => logger); + return (p_std_cfg => p_std_cfg, + p_valid_high_probability => valid_high_probability, + p_data_length => data_length); end; - impure function new_avalon_sink(data_length : natural; - ready_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; - actor : actor_t := null_actor) return avalon_sink_t is - variable p_actor : actor_t; + impure function new_avalon_sink(data_length : natural; + ready_high_probability : real := 1.0; + logger : logger_t := avalon_stream_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return avalon_sink_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + avalon_stream_logger, avalon_stream_checker, actor, logger, checker, unexpected_msg_type_policy + ); begin - p_actor := actor when actor /= null_actor else new_actor; - - return (ready_high_probability => ready_high_probability, - p_actor => p_actor, - p_data_length => data_length, - p_logger => logger); + return (p_std_cfg => p_std_cfg, + p_ready_high_probability => ready_high_probability, + p_data_length => data_length); end; impure function data_length(source : avalon_source_t) return natural is @@ -125,15 +138,35 @@ package body avalon_stream_pkg is return source.p_data_length; end; + impure function as_sync(source : avalon_source_t) return sync_handle_t is + begin + return get_actor(source.p_std_cfg); + end; + + impure function as_sync(sink : avalon_sink_t) return sync_handle_t is + begin + return get_actor(sink.p_std_cfg); + end; + impure function as_stream(source : avalon_source_t) return stream_master_t is begin - return (p_std_cfg => create_std_cfg(source.p_logger, stream_master_checker, source.p_actor)); + return (p_std_cfg => source.p_std_cfg); end; impure function as_stream(sink : avalon_sink_t) return stream_slave_t is begin - return (p_std_cfg => create_std_cfg(sink.p_logger, stream_slave_checker, sink.p_actor)); -end; + return (p_std_cfg => sink.p_std_cfg); + end; + + function get_std_cfg(source : avalon_source_t) return std_cfg_t is + begin + return source.p_std_cfg; + end; + + function get_std_cfg(sink : avalon_sink_t) return std_cfg_t is + begin + return sink.p_std_cfg; + end; procedure push_avalon_stream(signal net : inout network_t; avalon_source : avalon_source_t; @@ -155,7 +188,7 @@ end; avalon_stream_transaction.eop := false; end if; push_avalon_stream_transaction(msg, avalon_stream_transaction); - send(net, avalon_source.p_actor, msg); + send(net, get_actor(avalon_source.p_std_cfg), msg); end; procedure pop_avalon_stream(signal net : inout network_t; @@ -167,7 +200,7 @@ end; variable reply_msg : msg_t; variable avalon_stream_transaction : avalon_stream_transaction_t(data(data'length - 1 downto 0)); begin - send(net, avalon_sink.p_actor, reference); + send(net, get_actor(avalon_sink.p_std_cfg), reference); receive_reply(net, reference, reply_msg); pop_avalon_stream_transaction(reply_msg, avalon_stream_transaction); data := avalon_stream_transaction.data; diff --git a/vunit/vhdl/verification_components/test/tb_avalon_master.vhd b/vunit/vhdl/verification_components/test/tb_avalon_master.vhd index e84003042..58b549971 100644 --- a/vunit/vhdl/verification_components/test/tb_avalon_master.vhd +++ b/vunit/vhdl/verification_components/test/tb_avalon_master.vhd @@ -69,9 +69,14 @@ architecture a of tb_avalon_master is constant master_logger : logger_t := get_logger("master"); constant tb_logger : logger_t := get_logger("tb"); constant master_actor : actor_t := new_actor("Avalon-MM Master"); - constant bus_handle : bus_master_t := new_bus(data_length => tb_cfg.data_width, - address_length => tb_cfg.addr_width, logger => master_logger, - actor => master_actor); + constant avalon_master : avalon_master_t := new_avalon_master(data_length => tb_cfg.data_width, + address_length => tb_cfg.addr_width, + logger => master_logger, + actor => master_actor, + write_high_probability => tb_cfg.write_prob, + read_high_probability => tb_cfg.read_prob + ); + constant bus_handle : bus_master_t := as_bus_master(avalon_master); constant memory : memory_t := new_memory; constant buf : buffer_t := allocate(memory, tb_cfg.transfers * byteenable'length); @@ -79,7 +84,7 @@ architecture a of tb_avalon_master is memory => memory, readdatavalid_high_probability => tb_cfg.readdatavalid_prob, waitrequest_high_probability => tb_cfg.waitrequest_prob, - name => "Avalon-MM Slave" + actor => new_actor("Avalon-MM Slave") ); procedure gen_rndburst( @@ -290,9 +295,7 @@ begin dut : entity work.avalon_master generic map ( - bus_handle => bus_handle, - write_high_probability => tb_cfg.write_prob, - read_high_probability => tb_cfg.read_prob + avalon_master_handle => avalon_master ) port map ( clk => clk, diff --git a/vunit/vhdl/verification_components/test/tb_avalon_slave.vhd b/vunit/vhdl/verification_components/test/tb_avalon_slave.vhd index 1c28271c2..27663c719 100644 --- a/vunit/vhdl/verification_components/test/tb_avalon_slave.vhd +++ b/vunit/vhdl/verification_components/test/tb_avalon_slave.vhd @@ -65,7 +65,7 @@ architecture a of tb_avalon_slave is constant buf : buffer_t := allocate(memory, tb_cfg.num_cycles * byteenable'length); constant avalon_slave : avalon_slave_t := new_avalon_slave(memory => memory, - name => "avmm_vc", + actor => new_actor("avmm_vc"), readdatavalid_high_probability => tb_cfg.readdatavalid_prob, waitrequest_high_probability => tb_cfg.waitrequest_prob ); diff --git a/vunit/vhdl/verification_components/test/tb_avalon_stream.vhd b/vunit/vhdl/verification_components/test/tb_avalon_stream.vhd index ae94397cf..7324cd4eb 100644 --- a/vunit/vhdl/verification_components/test/tb_avalon_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_avalon_stream.vhd @@ -15,6 +15,7 @@ context work.data_types_context; use work.avalon_stream_pkg.all; use work.stream_master_pkg.all; use work.stream_slave_pkg.all; +use work.vc_pkg.all; entity tb_avalon_stream is generic (runner_cfg : string); @@ -46,7 +47,7 @@ begin begin test_runner_setup(runner, runner_cfg); set_format(display_handler, verbose, true); - show(avalon_sink_stream.p_logger, display_handler, verbose); + show(get_logger(avalon_sink_stream.p_std_cfg), display_handler, verbose); wait until rising_edge(clk); if run("test single push and pop") then From 775dc8934c84cb5d526df20d73f6af6387dd3fe6 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sun, 31 May 2020 18:51:35 +0200 Subject: [PATCH 04/21] Updated all Wishbone VCs and VCIs to comply with new standard --- ...tb_wishbone_master_compliance_template.vhd | 71 ++++ .../tb_wishbone_slave_compliance_template.vhd | 65 ++++ ..._wishbone_master_t_compliance_template.vhd | 34 ++ ...b_wishbone_slave_t_compliance_template.vhd | 33 ++ .../src/wishbone_master.vhd | 32 +- .../src/wishbone_pkg.vhd | 368 ++++++++++++++++-- .../src/wishbone_slave.vhd | 32 +- .../test/tb_wishbone_master.vhd | 29 +- .../test/tb_wishbone_slave.vhd | 2 - 9 files changed, 600 insertions(+), 66 deletions(-) create mode 100644 vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd create mode 100644 vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd diff --git a/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd new file mode 100644 index 000000000..8df306742 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd @@ -0,0 +1,71 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.com_types_pkg.all; +use vunit_lib.log_levels_pkg.all; +use vunit_lib.logger_pkg.all; +use vunit_lib.queue_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; +use vunit_lib.wishbone_pkg.all; + +entity tb_wishbone_master_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_wishbone_master_compliance is + + constant wishbone_master : wishbone_master_t := new_wishbone_master( + data_length => 32, + address_length => 32 + ); + + signal clk : std_logic; + signal adr : std_logic_vector(31 downto 0); + signal dat_i : std_logic_vector(31 downto 0); + signal dat_o : std_logic_vector(31 downto 0); + signal sel : std_logic_vector(3 downto 0); + signal cyc : std_logic; + signal stb : std_logic; + signal we : std_logic; + signal stall : std_logic; + signal ack : std_logic; + +begin + -- DO NOT modify the test runner process. + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + -- DO NOT modify the VC instantiation. + vc_inst: entity vunit_lib.wishbone_master + generic map(wishbone_master) + port map( + clk => clk, + adr => adr, + dat_i => dat_i, + dat_o => dat_o, + sel => sel, + cyc => cyc, + stb => stb, + we => we, + stall => stall, + ack => ack + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd new file mode 100644 index 000000000..c255b0899 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd @@ -0,0 +1,65 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library osvvm; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; +use osvvm.randompkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; +use vunit_lib.wishbone_pkg.all; + +entity tb_wishbone_slave_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_wishbone_slave_compliance is + + constant memory : memory_t := new_memory; + constant wishbone_slave : wishbone_slave_t := new_wishbone_slave( + memory => memory + ); + + signal clk : std_logic; + signal adr : std_logic_vector(31 downto 0) := (others => '0'); + signal dat_i : std_logic_vector(31 downto 0) := (others => '0'); + signal dat_o : std_logic_vector(31 downto 0) := (others => '0'); + signal sel : std_logic_vector(3 downto 0) := (others => '1'); + signal cyc : std_logic; + signal stb : std_logic; + signal we : std_logic; + signal stall : std_logic; + signal ack : std_logic; + +begin + test_runner : process + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; + + vc_inst: entity vunit_lib.wishbone_slave + generic map(wishbone_slave) + port map( + clk => clk, + adr => adr, + dat_i => dat_i, + dat_o => dat_o, + sel => sel, + cyc => cyc, + stb => stb, + we => we, + stall => stall, + ack => ack + ); + +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd new file mode 100644 index 000000000..f543dcaf0 --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd @@ -0,0 +1,34 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; +use vunit_lib.wishbone_pkg.all; + +entity tb_wishbone_master_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_wishbone_master_t_compliance is +begin + test_runner : process + constant data_length : natural := 32; + constant address_length : natural := 32; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd new file mode 100644 index 000000000..49f0d4bbd --- /dev/null +++ b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd @@ -0,0 +1,33 @@ +-- 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-2020, Lars Asplund lars.anders.asplund@gmail.com + +library ieee; +library vunit_lib; +context vunit_lib.com_context; +context vunit_lib.vunit_context; +use ieee.std_logic_1164.all; +use vunit_lib.bus_master_pkg.all; +use vunit_lib.memory_pkg.all; +use vunit_lib.sync_pkg.all; +use vunit_lib.vc_pkg.all; +use vunit_lib.wishbone_pkg.all; + +entity tb_wishbone_slave_t_compliance is + generic( + runner_cfg : string); +end entity; + +architecture tb of tb_wishbone_slave_t_compliance is +begin + test_runner : process + constant memory : memory_t := new_memory; + + -- DO NOT modify this line and the lines below. + begin + test_runner_setup(runner, runner_cfg); + test_runner_cleanup(runner); + end process test_runner; +end architecture; diff --git a/vunit/vhdl/verification_components/src/wishbone_master.vhd b/vunit/vhdl/verification_components/src/wishbone_master.vhd index b6b522208..8337f986d 100644 --- a/vunit/vhdl/verification_components/src/wishbone_master.vhd +++ b/vunit/vhdl/verification_components/src/wishbone_master.vhd @@ -17,14 +17,15 @@ use work.logger_pkg.all; use work.check_pkg.all; use work.log_levels_pkg.all; use work.sync_pkg.all; +use work.wishbone_pkg.all; +use work.vc_pkg.all; library osvvm; use osvvm.RandomPkg.all; entity wishbone_master is generic ( - bus_handle : bus_master_t; - strobe_high_probability : real range 0.0 to 1.0 := 1.0 + wishbone_master : wishbone_master_t ); port ( clk : in std_logic; @@ -41,10 +42,7 @@ entity wishbone_master is end entity; architecture a of wishbone_master is - constant rd_request_queue : queue_t := new_queue; - constant wr_request_queue : queue_t := new_queue; constant acknowledge_queue : queue_t := new_queue; - constant bus_ack_msg : msg_type_t := new_msg_type("wb master ack msg"); constant wb_master_ack_actor : actor_t := new_actor; signal start_cycle : std_logic := '0'; signal end_cycle : std_logic := '0'; @@ -58,26 +56,25 @@ begin variable rnd : RandomPType; begin rnd.InitSeed(rnd'instance_name); - report rnd'instance_name; + request_msg := null_msg; cycle_type := bus_read_msg; stb <= '0'; - wait until rising_edge(clk); loop - receive(net, get_actor(bus_handle), request_msg); + receive(net, get_actor(wishbone_master), request_msg); msg_type := message_type(request_msg); if msg_type = bus_read_msg or msg_type = bus_write_msg then if msg_type /= cycle_type and cycle then - wait until not cycle; -- todo: is this necessary? the wb spec v4 does not explicitly forbid mixed cycles + wait until not cycle; -- TODO: is this necessary? the wb spec v4 does not explicitly forbid mixed cycles wait until rising_edge(clk); end if; start_cycle <= not start_cycle; cycle_type := msg_type; - while rnd.Uniform(0.0, 1.0) > strobe_high_probability loop + while rnd.Uniform(0.0, 1.0) > wishbone_master.p_strobe_high_probability loop wait until rising_edge(clk); end loop; adr <= pop_std_ulogic_vector(request_msg); @@ -88,31 +85,26 @@ begin sel <= pop_std_ulogic_vector(request_msg); else we <= '0'; - -- TODO why sel is not passed in msg for reading (present for writing)? - --sel <= pop_std_ulogic_vector(request_msg); end if; push(acknowledge_queue, request_msg); wait until rising_edge(clk) and stall = '0'; stb <= '0'; - elsif msg_type = wait_until_idle_msg then + elsif msg_type = wait_until_idle_msg or msg_type = wait_for_time_msg then if cycle then wait until not cycle; end if; - handle_wait_until_idle(net, msg_type, request_msg); + handle_sync_message(net, msg_type, request_msg); else - unexpected_msg_type(msg_type); - + unexpected_msg_type(msg_type, get_std_cfg(wishbone_master)); end if; + end loop; end process; p_cycle : process - variable request_msg : msg_t; - variable ack_msg : msg_t; variable pending : natural := 0; - variable received_acks : natural := 0; begin cyc <= '0'; cycle <= false; @@ -139,7 +131,7 @@ begin end process; acknowledge : process - variable request_msg, reply_msg, ack_msg : msg_t; + variable request_msg, reply_msg : msg_t; begin wait until ack = '1' and rising_edge(clk); request_msg := pop(acknowledge_queue); diff --git a/vunit/vhdl/verification_components/src/wishbone_pkg.vhd b/vunit/vhdl/verification_components/src/wishbone_pkg.vhd index 61263b32a..f2a29ab2a 100644 --- a/vunit/vhdl/verification_components/src/wishbone_pkg.vhd +++ b/vunit/vhdl/verification_components/src/wishbone_pkg.vhd @@ -7,48 +7,368 @@ library ieee; use ieee.std_logic_1164.all; -use work.queue_pkg.all; -use work.logger_pkg.all; -use work.memory_pkg.all; +context work.vunit_context; context work.com_context; +use work.sync_pkg.all; +use work.vc_pkg.all; +use work.bus_master_pkg.all; +use work.memory_pkg.all; package wishbone_pkg is + type wishbone_master_t is record + p_bus_handle : bus_master_t; + p_strobe_high_probability : real range 0.0 to 1.0; + end record; + type wishbone_slave_t is record - ack_high_probability : real range 0.0 to 1.0; - stall_high_probability : real range 0.0 to 1.0; -- Private - p_actor : actor_t; - p_ack_actor : actor_t; - p_memory : memory_t; - p_logger : logger_t; + p_std_cfg : std_cfg_t; + p_ack_high_probability : real range 0.0 to 1.0; + p_stall_high_probability : real range 0.0 to 1.0; + p_ack_actor : actor_t; + p_memory : memory_t; end record; - constant wishbone_slave_logger : logger_t := get_logger("vunit_lib:wishbone_slave_pkg"); + constant wishbone_logger : logger_t := get_logger("vunit_lib:wishbone_pkg"); + constant wishbone_checker : checker_t := new_checker(wishbone_logger); + + impure function new_wishbone_master( + data_length : natural; + address_length : natural; + strobe_high_probability : real range 0.0 to 1.0 := 1.0; + byte_length : natural := 8; + logger : logger_t := wishbone_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return wishbone_master_t; + impure function new_wishbone_slave( - memory : memory_t; - ack_high_probability : real := 1.0; - stall_high_probability : real := 0.0; - logger : logger_t := wishbone_slave_logger) - return wishbone_slave_t; + memory : memory_t; + ack_high_probability : real := 1.0; + stall_high_probability : real := 0.0; + logger : logger_t := wishbone_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return wishbone_slave_t; + + impure function as_sync(master : wishbone_master_t) return sync_handle_t; + impure function as_bus_master(master : wishbone_master_t) return bus_master_t; + impure function as_sync(slave : wishbone_slave_t) return sync_handle_t; + + -- Return the actor used by the Wishbone master + impure function get_actor(wishbone_master : wishbone_master_t) return actor_t; + + -- Return the logger used by the Wishbone master + impure function get_logger(wishbone_master : wishbone_master_t) return logger_t; + + -- Return the checker used by the Wishbone master + impure function get_checker(wishbone_master : wishbone_master_t) return checker_t; + + -- Return policy for handling unexpected messages to the actor + impure function unexpected_msg_type_policy(wishbone_master : wishbone_master_t) return unexpected_msg_type_policy_t; + + -- Return the length of the data on the Wishbone bus + impure function data_length(wishbone_master : wishbone_master_t) return natural; + + -- Return the length of the address on the Wishbone bus + impure function address_length(wishbone_master : wishbone_master_t) return natural; + + -- Return the length of a byte on the Wishbone bus + impure function byte_length(wishbone_master : wishbone_master_t) return natural; + + -- Return the length of the byte enable signal on the Wishbone bus + impure function byte_enable_length(wishbone_master : wishbone_master_t) return natural; + + -- Convert natural address to std_logic_vector using the correct number of bits + impure function to_address(constant wishbone_master : wishbone_master_t; address : natural) return std_logic_vector; + + -- Blocking: Write the Wishbone bus + procedure write_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + constant data : std_logic_vector; + -- default byte enable is all bytes + constant byte_enable : std_logic_vector := ""); + procedure write_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + constant data : std_logic_vector; + -- default byte enable is all bytes + constant byte_enable : std_logic_vector := ""); + + -- Non blocking: Read the Wishbone bus returning a reference to the future reply + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + variable reference : inout bus_reference_t); + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + variable reference : inout bus_reference_t); + + -- Blocking: Read the Wishbone bus and check result against expected data + procedure check_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + constant expected : std_logic_vector; + constant msg : string := ""); + procedure check_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + constant expected : std_logic_vector; + constant msg : string := ""); + + -- Blocking: read the Wishbone bus with immediate reply + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + variable data : inout std_logic_vector); + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + variable data : inout std_logic_vector); + + -- Blocking: Wait until a read from address equals the value using + -- std_match If timeout is reached error with msg + procedure wait_until_read_equals( + signal net : inout network_t; + wishbone_master : wishbone_master_t; + addr : std_logic_vector; + value : std_logic_vector; + timeout : delay_length := delay_length'high; + msg : string := ""); + + -- Blocking: Wait until a read from address has the bit with this + -- index set to value If timeout is reached error with msg + procedure wait_until_read_bit_equals( + signal net : inout network_t; + wishbone_master : wishbone_master_t; + addr : std_logic_vector; + idx : natural; + value : std_logic; + timeout : delay_length := delay_length'high; + msg : string := ""); + + -- Wait until all operations scheduled before this command has finished + procedure wait_until_idle(signal net : inout network_t; + wishbone_master : wishbone_master_t); + + impure function get_std_cfg(wishbone_master : wishbone_master_t) return std_cfg_t; + impure function get_std_cfg(wishbone_slave : wishbone_slave_t) return std_cfg_t; end package; + package body wishbone_pkg is + impure function new_wishbone_master( + data_length : natural; + address_length : natural; + strobe_high_probability : real range 0.0 to 1.0 := 1.0; + byte_length : natural := 8; + logger : logger_t := wishbone_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return wishbone_master_t is + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, checker, + unexpected_msg_type_policy + ); + begin + return (p_bus_handle => p_bus_handle, + p_strobe_high_probability => strobe_high_probability); + end; impure function new_wishbone_slave( - memory : memory_t; - ack_high_probability : real := 1.0; - stall_high_probability : real := 0.0; - logger : logger_t := wishbone_slave_logger) - return wishbone_slave_t is + memory : memory_t; + ack_high_probability : real := 1.0; + stall_high_probability : real := 0.0; + logger : logger_t := wishbone_logger; + actor : actor_t := null_actor; + checker : checker_t := null_checker; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail + ) return wishbone_slave_t is + constant p_std_cfg : std_cfg_t := create_std_cfg( + wishbone_logger, wishbone_checker, actor, logger, checker, unexpected_msg_type_policy + ); + begin - return (p_actor => new_actor, + return (p_std_cfg => p_std_cfg, p_ack_actor => new_actor, p_memory => to_vc_interface(memory, logger), - p_logger => logger, - ack_high_probability => ack_high_probability, - stall_high_probability => stall_high_probability + p_ack_high_probability => ack_high_probability, + p_stall_high_probability => stall_high_probability ); end; + impure function as_sync(master : wishbone_master_t) return sync_handle_t is + begin + return as_sync(master.p_bus_handle); + end; + + impure function as_bus_master(master : wishbone_master_t) return bus_master_t is + begin + return master.p_bus_handle; + end; + + impure function as_sync(slave : wishbone_slave_t) return sync_handle_t is + begin + return get_actor(slave.p_std_cfg); + end; + + impure function get_actor(wishbone_master : wishbone_master_t) return actor_t is + begin + return get_actor(wishbone_master.p_bus_handle); + end; + + impure function get_logger(wishbone_master : wishbone_master_t) return logger_t is + begin + return get_logger(wishbone_master.p_bus_handle); + end; + + impure function get_checker(wishbone_master : wishbone_master_t) return checker_t is + begin + return get_checker(wishbone_master.p_bus_handle); + end; + + impure function unexpected_msg_type_policy(wishbone_master : wishbone_master_t) return unexpected_msg_type_policy_t is + begin + return unexpected_msg_type_policy(wishbone_master.p_bus_handle); + end; + + impure function data_length(wishbone_master : wishbone_master_t) return natural is + begin + return data_length(wishbone_master.p_bus_handle); + end; + + impure function address_length(wishbone_master : wishbone_master_t) return natural is + begin + return address_length(wishbone_master.p_bus_handle); + end; + + impure function byte_length(wishbone_master : wishbone_master_t) return natural is + begin + return byte_length(wishbone_master.p_bus_handle); + end; + + impure function byte_enable_length(wishbone_master : wishbone_master_t) return natural is + begin + return byte_enable_length(wishbone_master.p_bus_handle); + end; + + impure function to_address(constant wishbone_master : wishbone_master_t; address : natural) return std_logic_vector is + begin + return to_address(wishbone_master.p_bus_handle, address); + end; + + procedure write_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + constant data : std_logic_vector; + constant byte_enable : std_logic_vector := "") is + begin + write_bus(net, wishbone_master.p_bus_handle, address, data, byte_enable); + end; + + procedure write_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + constant data : std_logic_vector; + constant byte_enable : std_logic_vector := "") is + begin + write_bus(net, wishbone_master.p_bus_handle, address, data, byte_enable); + end; + + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + variable reference : inout bus_reference_t) is + begin + read_bus(net, wishbone_master.p_bus_handle, address, reference); + end; + + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + variable reference : inout bus_reference_t) is + begin + read_bus(net, wishbone_master.p_bus_handle, address, reference); + end; + + procedure check_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + constant expected : std_logic_vector; + constant msg : string := "") is + begin + check_bus(net, wishbone_master.p_bus_handle, address, expected, msg); + end; + + procedure check_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + constant expected : std_logic_vector; + constant msg : string := "") is + begin + check_bus(net, wishbone_master.p_bus_handle, address, expected, msg); + end; + + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : std_logic_vector; + variable data : inout std_logic_vector) is + begin + read_bus(net, wishbone_master.p_bus_handle, address, data); + end; + + procedure read_bus(signal net : inout network_t; + constant wishbone_master : wishbone_master_t; + constant address : natural; + variable data : inout std_logic_vector) is + begin + read_bus(net, wishbone_master.p_bus_handle, address, data); + end; + + procedure wait_until_read_equals( + signal net : inout network_t; + wishbone_master : wishbone_master_t; + addr : std_logic_vector; + value : std_logic_vector; + timeout : delay_length := delay_length'high; + msg : string := "") is + begin + wait_until_read_equals(net, wishbone_master.p_bus_handle, addr, value, timeout, msg); + end; + + procedure wait_until_read_bit_equals( + signal net : inout network_t; + wishbone_master : wishbone_master_t; + addr : std_logic_vector; + idx : natural; + value : std_logic; + timeout : delay_length := delay_length'high; + msg : string := "") is + begin + wait_until_read_bit_equals(net, wishbone_master.p_bus_handle, addr, idx, value, timeout, msg); + end; + + procedure wait_until_idle(signal net : inout network_t; + wishbone_master : wishbone_master_t) is + begin + wait_until_idle(net, wishbone_master.p_bus_handle); + end; + + impure function get_std_cfg(wishbone_master : wishbone_master_t) return std_cfg_t is + begin + return get_std_cfg(wishbone_master.p_bus_handle); + end; + + impure function get_std_cfg(wishbone_slave : wishbone_slave_t) return std_cfg_t is + begin + return wishbone_slave.p_std_cfg; + end; + + + end package body; diff --git a/vunit/vhdl/verification_components/src/wishbone_slave.vhd b/vunit/vhdl/verification_components/src/wishbone_slave.vhd index 11e15fdb9..e1cd4f60b 100644 --- a/vunit/vhdl/verification_components/src/wishbone_slave.vhd +++ b/vunit/vhdl/verification_components/src/wishbone_slave.vhd @@ -17,6 +17,8 @@ context work.vunit_context; context work.com_context; use work.memory_pkg.all; use work.wishbone_pkg.all; +use work.sync_pkg.all; +use work.vc_pkg.all; library osvvm; use osvvm.RandomPkg.all; @@ -40,11 +42,29 @@ entity wishbone_slave is end entity; architecture a of wishbone_slave is - constant slave_write_msg : msg_type_t := new_msg_type("wb slave write"); constant slave_read_msg : msg_type_t := new_msg_type("wb slave read"); + + signal active_transaction : boolean := false; begin + main : process + variable request_msg : msg_t; + variable msg_type : msg_type_t; + begin + receive(net, get_actor(wishbone_slave.p_std_cfg), request_msg); + msg_type := message_type(request_msg); + + if msg_type = wait_for_time_msg or msg_type = wait_until_idle_msg then + while active_transaction or has_message(wishbone_slave.p_ack_actor) loop + wait until rising_edge(clk); + end loop; + handle_sync_message(net, msg_type, request_msg); + else + unexpected_msg_type(msg_type, wishbone_slave.p_std_cfg); + end if; + end process; + request : process variable wr_request_msg : msg_t; variable rd_request_msg : msg_t; @@ -72,14 +92,16 @@ begin variable rnd : RandomPType; begin ack <= '0'; + active_transaction <= false; receive(net, wishbone_slave.p_ack_actor, request_msg); + active_transaction <= true; msg_type := message_type(request_msg); if msg_type = slave_write_msg then addr := pop_integer(request_msg); data := pop_std_ulogic_vector(request_msg); write_word(wishbone_slave.p_memory, addr, data); - while rnd.Uniform(0.0, 1.0) > wishbone_slave.ack_high_probability loop + while rnd.Uniform(0.0, 1.0) > wishbone_slave.p_ack_high_probability loop wait until rising_edge(clk); end loop; ack <= '1'; @@ -90,7 +112,7 @@ begin data := (others => '0'); addr := pop_integer(request_msg); data := read_word(wishbone_slave.p_memory, addr, sel'length); - while rnd.Uniform(0.0, 1.0) > wishbone_slave.ack_high_probability loop + while rnd.Uniform(0.0, 1.0) > wishbone_slave.p_ack_high_probability loop wait until rising_edge(clk); end loop; dat_o <= data; @@ -99,14 +121,14 @@ begin ack <= '0'; else - unexpected_msg_type(msg_type); + unexpected_msg_type(msg_type, wishbone_slave.p_std_cfg); end if; end process; stall_stim: process variable rnd : RandomPType; begin - if rnd.Uniform(0.0, 1.0) < wishbone_slave.stall_high_probability then + if rnd.Uniform(0.0, 1.0) < wishbone_slave.p_stall_high_probability then stall <= '1'; else stall <= '0'; diff --git a/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd b/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd index 98e7f6886..8ac69adca 100644 --- a/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd +++ b/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd @@ -63,8 +63,8 @@ architecture a of tb_wishbone_master is constant master_logger : logger_t := get_logger("master"); constant tb_logger : logger_t := get_logger("tb"); - constant bus_handle : bus_master_t := new_bus(data_length => tb_cfg.dat_width, - address_length => tb_cfg.adr_width, logger => master_logger); + constant wishbone_master : wishbone_master_t := new_wishbone_master(data_length => tb_cfg.dat_width, + address_length => tb_cfg.adr_width, strobe_high_probability => tb_cfg.strobe_prob, logger => master_logger); constant memory : memory_t := new_memory; constant buf : buffer_t := allocate(memory, tb_cfg.num_cycles * sel'length); @@ -79,7 +79,7 @@ begin main_stim : process variable tmp : std_logic_vector(dat_i'range); variable chk_time : time; - variable value : std_logic_vector(dat_i'range) := (others => '1'); + constant value : std_logic_vector(dat_i'range) := (others => '1'); variable bus_rd_ref1 : bus_reference_t; variable bus_rd_ref2 : bus_reference_t; type bus_reference_arr_t is array (0 to tb_cfg.num_cycles-1) of bus_reference_t; @@ -96,12 +96,12 @@ begin if run("wr single rd single") then info(tb_logger, "Writing..."); - write_bus(net, bus_handle, 0, value); + write_bus(net, wishbone_master, 0, value); wait until ack = '1' and rising_edge(clk); wait until rising_edge(clk); wait for 100 ns; info(tb_logger, "Reading..."); - read_bus(net, bus_handle, 0, tmp); + read_bus(net, wishbone_master, 0, tmp); check_equal(tmp, value, "read data"); -- elsif run("wr block") then -- -- TODO not sure if is allowed to toggle signal we during @@ -112,26 +112,26 @@ begin elsif run("wr block rd single") then info(tb_logger, "Writing..."); for i in 0 to tb_cfg.num_cycles-1 loop - write_bus(net, bus_handle, i*(sel'length), + write_bus(net, wishbone_master, i*(sel'length), std_logic_vector(to_unsigned(i, dat_i'length))); end loop; info(tb_logger, "Reading..."); for i in 0 to tb_cfg.num_cycles-1 loop - read_bus(net, bus_handle, i*(sel'length), tmp); + read_bus(net, wishbone_master, i*(sel'length), tmp); check_equal(tmp, std_logic_vector(to_unsigned(i, dat_i'length)), "read data"); end loop; elsif run("wr block rd block") then info(tb_logger, "Writing..."); for i in 0 to tb_cfg.num_cycles-1 loop - write_bus(net, bus_handle, i*(sel'length), + write_bus(net, wishbone_master, i*(sel'length), std_logic_vector(to_unsigned(i, dat_i'length))); end loop; info(tb_logger, "Reading..."); for i in 0 to tb_cfg.num_cycles-1 loop - read_bus(net, bus_handle, i*(sel'length), rd_ref(i)); + read_bus(net, wishbone_master, i*(sel'length), rd_ref(i)); end loop; info(tb_logger, "Get reads by references..."); @@ -143,11 +143,11 @@ begin elsif run ("wait for idle") then for i in 0 to 5 loop chk_time := now; - read_bus(net, bus_handle, 0, bus_rd_ref1); - write_bus(net, bus_handle, 0, value); - read_bus(net, bus_handle, 0, bus_rd_ref2); + read_bus(net, wishbone_master, 0, bus_rd_ref1); + write_bus(net, wishbone_master, 0, value); + read_bus(net, wishbone_master, 0, bus_rd_ref2); check_equal(chk_time, now, "tb concept broken, command issueing takes time"); - wait_until_idle(net, bus_handle); + wait_until_idle(net, wishbone_master); check_equal(cyc, '0', "bus not idle"); info(tb_logger, "Waited for " & to_string(now-chk_time)); chk_time := now; @@ -174,8 +174,7 @@ begin dut : entity work.wishbone_master generic map ( - bus_handle => bus_handle, - strobe_high_probability => tb_cfg.strobe_prob) + wishbone_master => wishbone_master) port map ( clk => clk, adr => adr, diff --git a/vunit/vhdl/verification_components/test/tb_wishbone_slave.vhd b/vunit/vhdl/verification_components/test/tb_wishbone_slave.vhd index eacfcd03e..7cd86c2ed 100644 --- a/vunit/vhdl/verification_components/test/tb_wishbone_slave.vhd +++ b/vunit/vhdl/verification_components/test/tb_wishbone_slave.vhd @@ -69,8 +69,6 @@ architecture a of tb_wishbone_slave is begin main_stim : process - variable tmp : std_logic_vector(dat_i'range); - variable value : std_logic_vector(dat_i'range) := (others => '1'); begin test_runner_setup(runner, runner_cfg); set_format(display_handler, verbose, true); From 0a576de53951138da57d9d61ae96ecf3781ee5e8 Mon Sep 17 00:00:00 2001 From: umarcor Date: Sat, 20 Mar 2021 15:22:14 +0100 Subject: [PATCH 05/21] doc/verification_components: update user guide --- docs/verification_components/user_guide.rst | 275 +++++++++++--------- 1 file changed, 154 insertions(+), 121 deletions(-) diff --git a/docs/verification_components/user_guide.rst b/docs/verification_components/user_guide.rst index 19fc8bae5..11629b3c3 100644 --- a/docs/verification_components/user_guide.rst +++ b/docs/verification_components/user_guide.rst @@ -1,7 +1,7 @@ .. _vc_library: Verification Component Library -=============================== +############################## .. note:: This library is released as a *BETA* version. This means non-backwards compatible changes are still likely based on @@ -48,7 +48,7 @@ synchronization VCI while also supporting their own bus specific VCIs. interface on the top level. The same testbench code for talking to the submodule can be used in both the submodule test bench as well as the top level test bench regardless of the fact that two different VCs - have been used. Without generic VCIs copy pasting the code and + have been used. Without generic VCIs, copy pasting the code and changing the type of read/write procedure call would be required. Neither a VC or a VCI, there is the :ref:`memory model ` @@ -67,7 +67,7 @@ reading and writing data. .. _verification_components: Verification Components ------------------------ +======================= A verification component (VC) is an entity that is normally connected to the DUT via a bus signal interface such as AXI-Lite. The main test @@ -78,15 +78,15 @@ making it easy to have parallel activity on several bus interfaces. A VC typically has an associated package defining procedures for sending to and receiving messages from the VC. Each VC instance is -associated with a handle that is created by a _constructor_ function +associated with a handle that is created by a *constructor* function in the test bench and set as a generic on the VC instantiation. -The handle is given as an argument to the procedure calls to direct +The handle is given as an argument to the procedure calls for directing messages to the specfic VC instance. .. _verification_component_interfaces: Verification Component Interfaces ---------------------------------- +================================= A verification component interface (VCI) is a procedural interface to a VC. A VCI is defined as procedures in a package file. Several VCs can @@ -95,7 +95,8 @@ and the VC-developers. List of VCIs included in the main repository: -* :ref:`Bus master `: generic read and write of bus with address and byte enable. +* :ref:`Bus master `: generic read and write of bus with + address and byte enable. * :ref:`Stream `: push and pop of data stream without address. * :ref:`Synchronization `: wait for time and events. @@ -106,130 +107,46 @@ List of VCIs included in the main repository: vci VC and VCI Compliance Testing ------------------------------ +============================= -VUnit also provides a set of compliance tests to help VC and VCI developers adhere -to good design principles. These rules aim at creating flexible, reusable, interoperable -and future proof VCs and VCIs. +VUnit also provides a set of compliance tests to help VC and VCI developers +adhere to good design principles. These rules aim at creating flexible, +reusable, interoperable and future proof VCs and VCIs. ----- - -**Rule 1** - The file containing the VC entity shall only contain one entity and the file containing the VCI package shall only contain one package. - -**Rationale** - The VC/VCI can be referenced by file name which makes compliance testing simpler. - ----- - -**Rule 2** - The name of the function used to create a new instance handle for a VC, aka the constructor, shall start with ``new_``. -**Rationale** - Makes it easier for the compliance test to automatically find a constructor and evaluate that with respect to the other applicable rules. - ----- - -**Rule 3** - A VC constructor shall have a ``logger`` parameter giving the user the option to specify the logger to use for VC reporting. -**Rationale** - It enables user control of the logging, for example enabling debug messages. - ----- - -**Rule 4** - A VC constructor shall have a ``checker`` parameter giving the user the option to specify the checker to use for VC checking. -**Rationale** - It enables user control of the checking, for example setting properties like the stop-level (without affecting the logger used above). - ----- - -**Rule 5** - A VC constructor shall have an ``actor`` parameter giving the user the option to specify the actor to use for VC communication. -**Rationale** - It enables user control of the communication, for example setting name for better trace logs. - ----- - -**Rule 6** - A VC constructor shall have an ``unexpected_msg_type_policy`` parameter giving the user the option to specify the action taken when the VC receives an unexpected message type. -**Rationale** - A VC actor setup to subscribe to another actor may receive messages not relevant for its operation. OTOH, VCs just addressed directly should only recieve messages it can handle. - ----- - -**Rule 7** - A VC constructor shall have a default value for all required parameters above. -**Rationale** - Makes it easier for the user if there is no preference on what to use. - ----- - -**Rule 8** - The default value for the logger parameter shall not be ``default_logger``. -**Rationale** - Using a logger more associated with the VC makes the logger output easier to understand. - ----- - -**Rule 9** - The default value for the checker parameter shall not be ``default_checker``. -**Rationale** - Using a checker more associated with the VC makes the checker output easier to understand. - ----- - -**Rule 10** - All fields in the handle returned by the constructor shall start with ``p_``. -**Rationale** - All field shall be considered private and this is a way to emphasize this. Keeping them private makes updates easier without breaking backward compatibility. - ----- - -**Rule 11** - The standard configuration, ``std_cfg_t``, of a VC consisting of the required parameters to the constructor shall be possible to get from the handle using a call to ``get_std_cfg``. -**Rationale** - Makes it possible to reuse operations such as ``get_logger`` between VCs. - ----- - -**Rule 12** - A VC shall only have one generic. -**Rationale** - Representing a VC with a single object makes it easier to handle in code. Since all fields of the handle are private future updates have less risk of breaking backward compatibility. - ----- - -**Rule 13** - All VCs shall support the sync interface. -**Rationale** - Being able to check that a VC is idle and to add a delay between transactions are commonly useful operations for VC users. - ----- - -Compliance testing is done separately for the VC and the VCI and each test consists of two parts. One part tests the code by parsing it and the other part tests the code by running a VHDL testbench. +Compliance testing is done separately for the VC and the VCI. Each test +consists of two parts: one part tests the code by parsing it and the other part +tests the code by running a VHDL testbench. The VHDL testbenches cannot be automatically created because of: -* A VC constructor can have VC specific parameters without default values -* A VC port list can constain unconstrained ports +* A VC constructor can have VC specific parameters without default values. +* A VC port list can constain unconstrained ports. -These issues are solved by creating a templates for the VHDL testbenches. The template is created by calling the compliance_test.py script (--help for instructions). Some rules are checked in this process and any violation is reported. -When all violations have been fixed the script will generate a template file which needs to modified manually according to the instructions in the template file. +These issues are solved by creating templates for the VHDL testbenches. The +template is created by calling the :vunit_file:`compliance_test.py ` +script (see `--help` for instructions). Some rules are checked in this process +and any violation is reported. When all violations have been fixed, the script +will generate a template, which needs to be modified manually according to the +instructions in the file. -The run.py file verifying the VC and the VCI can then add compliance tests by using the VerificationComponentInterface and VerificationComponent classes. These classes provides methods to generate the full VHDL testbenches from the -templates and some extra parameters. +The ``run.py`` file verifying the VC and the VCI can then add compliance tests +by using the ``VerificationComponentInterface`` and ``VerificationComponent`` +classes. These classes provide methods for generating the full VHDL testbenches +from the templates and some extra parameters. For instance: .. code-block:: python - # Find the VCI for the Avalon sink VC located in the avalon_stream_pkg package which has been added - # to library lib (lib.add_source_files). The return type for the VC constructor, avalon_sink_t, which - # allow the constructor to be found analyzed. + # Find the VCI for the Avalon sink VC located in the avalon_stream_pkg package + # which has been added to library lib (lib.add_source_files). The return type + # for the VC constructor, avalon_sink_t, which allow the constructor to be + # found analyzed. avalon_sink_vci = VerificationComponentInterface.find( lib, "avalon_stream_pkg", "avalon_sink_t" ) - # Add a VCI compliance testbench to library test_lib. The generated testbench will be saved in the - # compliance_test directory and the final path identifies the previously generated testbench template + # Add a VCI compliance testbench to library test_lib. The generated testbench + # will be saved in the compliance_test directory and the final path identifies + # the previously generated testbench template avalon_sink_vci.add_vhdl_testbench( test_lib, join(root, "compliance_test"), @@ -239,16 +156,17 @@ templates and some extra parameters. # Find the Avalon_sink VC located in the lib library avalon_sink_vc = VerificationComponent.find(lib, "avalon_sink", avalon_sink_vci) - # Add a VC compliance testbench to library test_lib. The generated testbench will be saved in the - # compliance_test directory and the final path identifies the previously generated testbench template + # Add a VC compliance testbench to library test_lib. The generated testbench + # will be saved in the compliance_test directory and the final path identifies + # the previously generated testbench template avalon_sink_vc.add_vhdl_testbench( test_lib, join(root, "compliance_test"), join(root, ".vc", "tb_avalon_sink_compliance_template.vhd") ) - -The Avalon sink test suite will now have a number of extra test cases verifying that it is compliant +The Avalon sink test suite will now have a number of extra test cases verifying +that it is compliant: .. code-block:: console @@ -269,3 +187,118 @@ The Avalon sink test suite will now have a number of extra test cases verifying Elapsed time was 7.7 seconds ========================================================================================================================================= All passed! + +Rule 1 +------ + +The file containing the VC entity shall only contain one entity and the file +containing the VCI package shall only contain one package. + +**Rationale**: The VC/VCI can be referenced by file name which makes compliance +testing simpler. + +Rule 2 +------ + +The name of the function used to create a new instance handle for a VC, aka the +constructor, shall start with ``new_``. + +**Rationale**: Makes it easier for the compliance test to automatically find a +constructor and evaluate that with respect to the other applicable rules. + +Rule 3 +------ + +A VC constructor shall have a ``logger`` parameter giving the user the option +to specify the logger to use for VC reporting. + +**Rationale**: It enables user control of the logging, for example enabling +debug messages. + +Rule 4 +------ + +A VC constructor shall have a ``checker`` parameter giving the user the option +to specify the checker to use for VC checking. + +**Rationale**: It enables user control of the checking, for example setting +properties like the stop-level (without affecting the logger used above). + +Rule 5 +------ + +A VC constructor shall have an ``actor`` parameter giving the user the option +to specify the actor to use for VC communication. + +**Rationale**: It enables user control of the communication, for example setting +name for better trace logs. + +Rule 6 +------ + +A VC constructor shall have an ``unexpected_msg_type_policy`` parameter giving +the user the option to specify the action taken when the VC receives an unexpected +message type. + +**Rationale**: A VC actor setup to subscribe to another actor may receive messages +not relevant for its operation. OTOH, VCs just addressed directly should only +recieve messages it can handle. + +Rule 7 +------ + +A VC constructor shall have a default value for all required parameters above. + +**Rationale**: Makes it easier for the user if there is no preference on what to +use. + +Rule 8 +------ + +The default value for the logger parameter shall not be ``default_logger``. + +**Rationale**: Using a logger more associated with the VC makes the logger output +easier to understand. + +Rule 9 +------ + +The default value for the checker parameter shall not be ``default_checker``. + +**Rationale**: Using a checker more associated with the VC makes the checker +output easier to understand. + +Rule 10 +------- + +All fields in the handle returned by the constructor shall start with ``p_``. + +**Rationale**: All field shall be considered private and this is a way to +emphasize this. Keeping them private makes updates easier without breaking +backward compatibility. + +Rule 11 +------- + +The standard configuration, ``std_cfg_t``, of a VC consisting of the required +parameters to the constructor shall be possible to get from the handle using a call to ``get_std_cfg``. + +**Rationale**: Makes it possible to reuse operations such as ``get_logger`` +between VCs. + +Rule 12 +------- + +A VC shall only have one generic. + +**Rationale**: Representing a VC with a single object makes it easier to handle +in code. Since all fields of the handle are private future updates have less +risk of breaking backward compatibility. + +Rule 13 +------- + +All VCs shall support the sync interface. + +**Rationale**: Being able to check that a VC is idle and to add a delay between +transactions are commonly useful operations for VC users. From 74dbda97013c0c8e4219921ecc2799eac8025fc8 Mon Sep 17 00:00:00 2001 From: umarcor Date: Sat, 20 Mar 2021 15:33:58 +0100 Subject: [PATCH 06/21] format: run black --- tests/unit/test_compliance_test.py | 3 ++- vunit/vc/verification_component.py | 7 +++++-- vunit/vc/verification_component_interface.py | 9 ++++++--- vunit/vhdl/verification_components/run.py | 21 +++++++++++++------- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py index 0813dad4a..a7a4e9505 100644 --- a/tests/unit/test_compliance_test.py +++ b/tests/unit/test_compliance_test.py @@ -391,7 +391,8 @@ def test_failing_on_missing_handle_record(self, error_mock): "vc_handle_t", ) error_mock.assert_called_once_with( - "Failed to find %s record", "vc_handle_t", + "Failed to find %s record", + "vc_handle_t", ) def test_error_on_missing_default_value(self): diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index 958b420a2..b7176432a 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -33,7 +33,7 @@ class VerificationComponent: @classmethod def find(cls, vc_lib, vc_name, vci): - """ Finds the specified VC if present. + """Finds the specified VC if present. :param vc_lib: Library object containing the VC. :param vc_name: Name of VC entity. @@ -163,7 +163,10 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): port.subtype_indication, ) for identifier in port.identifier_list: - port_mappings += " %s => %s,\n" % (identifier, identifier,) + port_mappings += " %s => %s,\n" % ( + identifier, + identifier, + ) vc_instantiation = """ -- DO NOT modify the VC instantiation. vc_inst: entity %s.%s diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index b9072e195..ed5a83b68 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -58,7 +58,7 @@ class VerificationComponentInterface: @classmethod def find(cls, vc_lib, vci_name, vc_handle_t): - """ Finds the specified VCI if present. + """Finds the specified VCI if present. :param vc_lib: Library object containing the VCI. :param vci_name: Name of VCI package. @@ -229,7 +229,8 @@ def _validate_handle(code, vc_handle_t): return handle_is_valid LOGGER.error( - "Failed to find %s record", vc_handle_t, + "Failed to find %s record", + vc_handle_t, ) return False @@ -408,7 +409,9 @@ def create_handle_assignment( unexpected_msg_type_policy="fail", ), handle6=create_handle_assignment( - "handle1", actor="actor1", unexpected_msg_type_policy="fail", + "handle1", + actor="actor1", + unexpected_msg_type_policy="fail", ), handle7=create_handle_assignment( "handle2", diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 1e0fdbb08..7c7b5681f 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -278,25 +278,30 @@ def gen_avalon_master_tests(obj, *args): uart_master_vci = VerificationComponentInterface.find(LIB, "uart_pkg", "uart_master_t") uart_master_vci.add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) VerificationComponent.find(LIB, "uart_master", uart_master_vci).add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) uart_slave_vci = VerificationComponentInterface.find(LIB, "uart_pkg", "uart_slave_t") uart_slave_vci.add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) VerificationComponent.find(LIB, "uart_slave", uart_slave_vci).add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) std_logic_checker_vci = VerificationComponentInterface.find( LIB, "signal_checker_pkg", "signal_checker_t" ) std_logic_checker_vci.add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) VerificationComponent.find( LIB, "std_logic_checker", std_logic_checker_vci @@ -323,13 +328,15 @@ def gen_avalon_master_tests(obj, *args): VerificationComponentInterface.find( LIB, "stream_master_pkg", "stream_master_t" ).add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) VerificationComponentInterface.find( LIB, "stream_slave_pkg", "stream_slave_t" ).add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test", + TEST_LIB, + ROOT / "compliance_test", ) bus2memory_vci = VerificationComponentInterface.find( From 09cc75a59072697b2910b335f18d3ec59e0848f6 Mon Sep 17 00:00:00 2001 From: umarcor Date: Sat, 20 Mar 2021 15:36:07 +0100 Subject: [PATCH 07/21] doc/verification_components: adapt VCI run.py example to Path --- docs/verification_components/user_guide.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/verification_components/user_guide.rst b/docs/verification_components/user_guide.rst index 11629b3c3..0decf47b7 100644 --- a/docs/verification_components/user_guide.rst +++ b/docs/verification_components/user_guide.rst @@ -149,8 +149,8 @@ from the templates and some extra parameters. For instance: # the previously generated testbench template avalon_sink_vci.add_vhdl_testbench( test_lib, - join(root, "compliance_test"), - join(root, ".vc", "avalon_stream_pkg", "tb_avalon_sink_t_compliance_template.vhd") + ROOT / "compliance_test", + ROOT / ".vc" / "avalon_stream_pkg" / "tb_avalon_sink_t_compliance_template.vhd" ) # Find the Avalon_sink VC located in the lib library @@ -161,8 +161,8 @@ from the templates and some extra parameters. For instance: # the previously generated testbench template avalon_sink_vc.add_vhdl_testbench( test_lib, - join(root, "compliance_test"), - join(root, ".vc", "tb_avalon_sink_compliance_template.vhd") + ROOT / "compliance_test", + ROOT / ".vc" / "tb_avalon_sink_compliance_template.vhd" ) The Avalon sink test suite will now have a number of extra test cases verifying From 517a0f5ed557a14c53c0dce50c1f7e0591d6cf08 Mon Sep 17 00:00:00 2001 From: umarcor Date: Sat, 20 Mar 2021 15:54:42 +0100 Subject: [PATCH 08/21] fix verification components after rebase --- .../src/axi_slave_pkg.vhd | 2 - .../src/axi_stream_pkg.vhd | 79 ++++++++++--------- .../test/tb_avalon.vhd | 15 ++-- .../test/tb_wishbone_master.vhd | 6 +- 4 files changed, 54 insertions(+), 48 deletions(-) diff --git a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd index ec3b72f3c..9c8efda09 100644 --- a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd @@ -46,7 +46,6 @@ package axi_slave_pkg is min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; logger : logger_t := axi_slave_logger; - actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t; @@ -167,7 +166,6 @@ package body axi_slave_pkg is min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; logger : logger_t := axi_slave_logger; - actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t is constant p_std_cfg : std_cfg_t := create_std_cfg( diff --git a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd index f5db7a030..386f2885b 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd @@ -34,7 +34,7 @@ package axi_stream_pkg is type axi_stream_component_type_t is (null_component, default_component, custom_component); type axi_stream_protocol_checker_t is record - p_std_cfg : std_cfg_t; + p_std_cfg : std_cfg_t; p_type : axi_stream_component_type_t; p_data_length : natural; p_id_length : natural; @@ -44,7 +44,7 @@ package axi_stream_pkg is end record; constant null_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( - p_std_cfg => null_std_cfg, + p_std_cfg => null_std_cfg, p_type => null_component, p_data_length => 0, p_id_length => 0, @@ -57,7 +57,7 @@ package axi_stream_pkg is -- configuration is defined by the parent component into which the checker is -- instantiated. constant default_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( - p_std_cfg => null_std_cfg, + p_std_cfg => null_std_cfg, p_type => default_component, p_data_length => 0, p_id_length => 0, @@ -67,7 +67,7 @@ package axi_stream_pkg is ); type axi_stream_monitor_t is record - p_std_cfg : std_cfg_t; + p_std_cfg : std_cfg_t; p_type : axi_stream_component_type_t; p_data_length : natural; p_id_length : natural; @@ -77,7 +77,7 @@ package axi_stream_pkg is end record; constant null_axi_stream_monitor : axi_stream_monitor_t := ( - p_std_cfg => null_std_cfg, + p_std_cfg => null_std_cfg, p_type => null_component, p_data_length => 0, p_id_length => 0, @@ -90,7 +90,7 @@ package axi_stream_pkg is -- configuration is defined by the parent component into which the monitor is -- instantiated. constant default_axi_stream_monitor : axi_stream_monitor_t := ( - p_std_cfg => null_std_cfg, + p_std_cfg => null_std_cfg, p_type => default_component, p_data_length => 0, p_id_length => 0, @@ -115,39 +115,42 @@ package axi_stream_pkg is end record; constant null_axi_stream_master : axi_stream_master_t := ( - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_stall_config => null_stall_config, - p_logger => null_logger, - p_monitor => null_axi_stream_monitor, - p_protocol_checker => null_axi_stream_protocol_checker + p_std_cfg => null_std_cfg, + p_data_length => 0, + p_id_length => 0, + p_dest_length => 0, + p_user_length => 0, + p_stall_config => null_stall_config, + p_drive_invalid => true, + p_drive_invalid_val => 'X', + p_drive_invalid_val_user => '0', + p_monitor => null_axi_stream_monitor, + p_use_default_monitor => true, + p_protocol_checker => null_axi_stream_protocol_checker ); type axi_stream_slave_t is record - p_std_cfg : std_cfg_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_stall_config : stall_config_t; - p_monitor : axi_stream_monitor_t; - p_use_default_monitor : boolean; - p_protocol_checker : axi_stream_protocol_checker_t; + p_std_cfg : std_cfg_t; + p_data_length : natural; + p_id_length : natural; + p_dest_length : natural; + p_user_length : natural; + p_stall_config : stall_config_t; + p_monitor : axi_stream_monitor_t; + p_use_default_monitor : boolean; + p_protocol_checker : axi_stream_protocol_checker_t; end record; constant null_axi_stream_slave : axi_stream_slave_t := ( - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_stall_config => null_stall_config, - p_logger => null_logger, - p_monitor => null_axi_stream_monitor, - p_protocol_checker => null_axi_stream_protocol_checker + p_std_cfg => null_std_cfg, + p_data_length => 0, + p_id_length => 0, + p_dest_length => 0, + p_user_length => 0, + p_stall_config => null_stall_config, + p_monitor => null_axi_stream_monitor, + p_use_default_monitor => true, + p_protocol_checker => null_axi_stream_protocol_checker ); constant axi_stream_logger : logger_t := get_logger("vunit_lib:axi_stream_pkg"); @@ -165,7 +168,7 @@ package axi_stream_pkg is logger : logger_t := axi_stream_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; - unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; monitor : axi_stream_monitor_t := null_axi_stream_monitor; protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker ) return axi_stream_master_t; @@ -179,7 +182,7 @@ package axi_stream_pkg is logger : logger_t := axi_stream_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; - unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; monitor : axi_stream_monitor_t := null_axi_stream_monitor; protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker ) return axi_stream_slave_t; @@ -190,9 +193,9 @@ package axi_stream_pkg is dest_length : natural := 0; user_length : natural := 0; logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; + actor : actor_t := null_actor; checker : checker_t := null_checker; - unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker ) return axi_stream_monitor_t; @@ -204,7 +207,7 @@ package axi_stream_pkg is logger : logger_t := axi_stream_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; - unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; + unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; max_waits : natural := 16 ) return axi_stream_protocol_checker_t; diff --git a/vunit/vhdl/verification_components/test/tb_avalon.vhd b/vunit/vhdl/verification_components/test/tb_avalon.vhd index 497910298..3b24a7748 100644 --- a/vunit/vhdl/verification_components/test/tb_avalon.vhd +++ b/vunit/vhdl/verification_components/test/tb_avalon.vhd @@ -27,7 +27,14 @@ architecture testbench of tb_avalon is signal av_byteenable : std_logic_vector(3 downto 0); signal av_burstcount : std_logic_vector(3 downto 0); - constant avalon_bus : bus_master_t := new_bus(data_length => 32, address_length => av_address'length); + constant avalon_master : avalon_master_t := new_avalon_master( + data_length => 32, + address_length => av_address'length, + use_readdatavalid => false, + fixed_read_latency => 0 + ); + + constant avalon_bus : bus_master_t := as_bus_master(avalon_master); signal clk : std_logic := '0'; @@ -35,11 +42,9 @@ architecture testbench of tb_avalon is begin - avalon_master : entity vunit_lib.avalon_master + dut : entity vunit_lib.avalon_master generic map ( - bus_handle => avalon_bus, - use_readdatavalid => false, - fixed_read_latency => 0 + avalon_master_handle => avalon_master ) port map ( clk => clk, diff --git a/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd b/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd index 8ac69adca..df3774d9f 100644 --- a/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd +++ b/vunit/vhdl/verification_components/test/tb_wishbone_master.vhd @@ -106,8 +106,8 @@ begin -- elsif run("wr block") then -- -- TODO not sure if is allowed to toggle signal we during -- -- wishbone single cycle --- write_bus(net, bus_handle, 0, value); --- read_bus(net, bus_handle, 0, tmp); +-- write_bus(net, wishbone_master, 0, value); +-- read_bus(net, wishbone_master, 0, tmp); -- check_equal(tmp, value, "read data"); elsif run("wr block rd single") then info(tb_logger, "Writing..."); @@ -159,7 +159,7 @@ begin end loop; elsif run("slave comb ack") then - write_bus(net, bus_handle, 0, value); + write_bus(net, wishbone_master, 0, value); wait until ack = '1' and rising_edge(clk); wait for 20 ns; From 4ff8b15337207a4c8c6f3179d6de02f0f003675f Mon Sep 17 00:00:00 2001 From: umarcor Date: Sat, 20 Mar 2021 17:51:33 +0100 Subject: [PATCH 09/21] vc/compliance_test: style --- vunit/vc/compliance_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index b41a0f004..fb8aeb45c 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -12,8 +12,7 @@ import sys import logging from pathlib import Path -from vunit.vc.verification_component import VerificationComponent -from vunit.vc.verification_component_interface import VerificationComponentInterface +from vunit.vc import VerificationComponent, VerificationComponentInterface def _create_vc_template(args): From ecd29edcd590f06bdd9a3bc0de9b5751844c2762 Mon Sep 17 00:00:00 2001 From: umarcor Date: Fri, 21 May 2021 21:06:20 +0200 Subject: [PATCH 10/21] vcs: update license dates to 2021 --- .../vhdl/.vc/tb_vc_with_template_compliance_template.vhd | 2 +- tests/acceptance/artificial/vhdl/vc.vhd | 2 +- .../artificial/vhdl/vc_not_supporting_custom_actor.vhd | 2 +- .../artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd | 2 +- .../artificial/vhdl/vc_not_supporting_custom_logger.vhd | 2 +- .../artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd | 2 +- tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd | 2 +- tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd | 2 +- .../vhdl/vc_not_supporting_unexpected_msg_handling.vhd | 2 +- .../vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd | 2 +- tests/acceptance/artificial/vhdl/vc_pkg.vhd | 2 +- tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd | 2 +- tests/acceptance/artificial/vhdl/vc_with_template.vhd | 2 +- tests/unit/test_compliance_test.py | 2 +- vunit/ui/entity.py | 2 +- vunit/vc/__init__.py | 2 +- vunit/vc/compliance_test.py | 2 +- vunit/vc/vc_template.py | 2 +- vunit/vc/vci_template.py | 2 +- vunit/vc/verification_component.py | 2 +- vunit/vc/verification_component_interface.py | 2 +- .../.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd | 2 +- .../.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd | 2 +- .../avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd | 2 +- .../tb_avalon_source_t_compliance_template.vhd | 2 +- .../.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd | 2 +- .../tb_axi_stream_master_t_compliance_template.vhd | 2 +- .../tb_axi_stream_monitor_t_compliance_template.vhd | 2 +- .../tb_axi_stream_protocol_checker_t_compliance_template.vhd | 2 +- .../tb_axi_stream_slave_t_compliance_template.vhd | 2 +- .../.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd | 2 +- .../.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd | 2 +- .../.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd | 2 +- .../.vc/tb_avalon_master_compliance_template.vhd | 2 +- .../.vc/tb_avalon_sink_compliance_template.vhd | 2 +- .../.vc/tb_avalon_slave_compliance_template.vhd | 2 +- .../.vc/tb_avalon_source_compliance_template.vhd | 2 +- .../.vc/tb_axi_lite_master_compliance_template.vhd | 2 +- .../.vc/tb_axi_read_slave_compliance_template.vhd | 2 +- .../.vc/tb_axi_stream_master_compliance_template.vhd | 2 +- .../.vc/tb_axi_stream_monitor_compliance_template.vhd | 2 +- .../.vc/tb_axi_stream_protocol_checker_compliance_template.vhd | 2 +- .../.vc/tb_axi_stream_slave_compliance_template.vhd | 2 +- .../.vc/tb_axi_write_slave_compliance_template.vhd | 2 +- .../.vc/tb_bus2memory_compliance_template.vhd | 2 +- .../.vc/tb_ram_master_compliance_template.vhd | 2 +- .../.vc/tb_std_logic_checker_compliance_template.vhd | 2 +- .../.vc/tb_wishbone_master_compliance_template.vhd | 2 +- .../.vc/tb_wishbone_slave_compliance_template.vhd | 2 +- .../wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd | 2 +- .../wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd | 2 +- vunit/vhdl/verification_components/src/bus2memory_pkg.vhd | 2 +- vunit/vhdl/verification_components/src/ram_master_pkg.vhd | 2 +- vunit/vhdl/verification_components/src/vc_pkg.vhd | 2 +- 54 files changed, 54 insertions(+), 54 deletions(-) diff --git a/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd b/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd index 88a4d7ab9..7b7936ba1 100644 --- a/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd +++ b/tests/acceptance/artificial/vhdl/.vc/tb_vc_with_template_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library lib; diff --git a/tests/acceptance/artificial/vhdl/vc.vhd b/tests/acceptance/artificial/vhdl/vc.vhd index ab9a7e5eb..8c21ac618 100644 --- a/tests/acceptance/artificial/vhdl/vc.vhd +++ b/tests/acceptance/artificial/vhdl/vc.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd index d02f0f74b..7640e2703 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd index ef3030343..bd70020a7 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd index 7823899bb..83c9a8321 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd index 90a5058a9..fe376e21f 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd index 4329cab3b..ff370318d 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd index dc4bfee40..32a736788 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd index 64f78a581..085c2bfce 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd index 9ccf6231a..00fbf56ec 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_pkg.vhd index 0d5da6d2d..3598f7f61 100644 --- a/tests/acceptance/artificial/vhdl/vc_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd index 733893334..f1d19bd7c 100644 --- a/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd +++ b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/acceptance/artificial/vhdl/vc_with_template.vhd b/tests/acceptance/artificial/vhdl/vc_with_template.vhd index 22e6a85f5..ba50d9094 100644 --- a/tests/acceptance/artificial/vhdl/vc_with_template.vhd +++ b/tests/acceptance/artificial/vhdl/vc_with_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py index a7a4e9505..01bc7956f 100644 --- a/tests/unit/test_compliance_test.py +++ b/tests/unit/test_compliance_test.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """ Test the compliance test. diff --git a/vunit/ui/entity.py b/vunit/ui/entity.py index d5ae9ac9c..8f2475084 100644 --- a/vunit/ui/entity.py +++ b/vunit/ui/entity.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """ UI class Entity diff --git a/vunit/vc/__init__.py b/vunit/vc/__init__.py index 787597729..c00913267 100644 --- a/vunit/vc/__init__.py +++ b/vunit/vc/__init__.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """ Code related to VUnit verification components. diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index fb8aeb45c..d3873d5f5 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """ Module for generating a compliance test for a VUnit verification component diff --git a/vunit/vc/vc_template.py b/vunit/vc/vc_template.py index cace9a997..e8e47bb50 100644 --- a/vunit/vc/vc_template.py +++ b/vunit/vc/vc_template.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """Templates for the verification component testbench.""" diff --git a/vunit/vc/vci_template.py b/vunit/vc/vci_template.py index f25ae9710..57795da44 100644 --- a/vunit/vc/vci_template.py +++ b/vunit/vc/vci_template.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """Templates for the verification component interface testbench""" diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index b7176432a..ef5bc0393 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """VerificationComponent class.""" diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index ed5a83b68..54a025f43 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -2,7 +2,7 @@ # 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-2020, Lars Asplund lars.anders.asplund@gmail.com +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """VerificationComponentInterface class.""" diff --git a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd index 89aa9d0b5..c320f7537 100644 --- a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_master_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd index 3954a1169..365ac9319 100644 --- a/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/avalon_pkg/tb_avalon_slave_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd index 2673805c0..bbfa43824 100644 --- a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_sink_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd index 756d06814..da07aaddd 100644 --- a/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/avalon_stream_pkg/tb_avalon_source_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd index 9f7f8dd3b..e54061f29 100644 --- a/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/axi_slave_pkg/tb_axi_slave_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd index cdc1a03cc..14d57ce7a 100644 --- a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_master_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd index e0e4b20fb..1608a5b22 100644 --- a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_monitor_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd index 80f130a2f..1c929e7e3 100644 --- a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_protocol_checker_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd index 3feadafb0..bb136e697 100644 --- a/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/axi_stream_pkg/tb_axi_stream_slave_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd index 024f6b380..d14049559 100644 --- a/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/bus2memory_pkg/tb_bus2memory_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd index 7c4a0939c..8ec402914 100644 --- a/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/bus_master_pkg/tb_bus_master_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd index aa69304a5..cb67c86c4 100644 --- a/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/ram_master_pkg/tb_ram_master_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd index 3f470bfb4..0b7350461 100644 --- a/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_master_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd index ff0c75361..e4665ac17 100644 --- a/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_sink_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd index 4341e2faa..44a01690c 100644 --- a/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_slave_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd index ba3e4e6b7..3af993522 100644 --- a/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_avalon_source_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd index 2e90a898e..da006f9e5 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_lite_master_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd index 0317b4990..b5fd98139 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_read_slave_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd index a9257bb76..86f9a5fe3 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_master_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd index 03551b897..1fa2e368f 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_monitor_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd index 0375493a0..8fce31136 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_protocol_checker_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd index 958198010..4d6e91de4 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_stream_slave_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd index 93ea134cf..77589778d 100644 --- a/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_axi_write_slave_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd index 5f6eaea47..9d8beb5cc 100644 --- a/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_bus2memory_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd index 3e171fc5b..88c90bbcf 100644 --- a/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_ram_master_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd index 8af208a0b..57bcab7ee 100644 --- a/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_std_logic_checker_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd index 8df306742..2ec0db0bc 100644 --- a/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_wishbone_master_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd index c255b0899..23e4367f5 100644 --- a/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/tb_wishbone_slave_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library osvvm; diff --git a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd index f543dcaf0..4c5f7c173 100644 --- a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_master_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd index 49f0d4bbd..bcfa14161 100644 --- a/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd +++ b/vunit/vhdl/verification_components/.vc/wishbone_pkg/tb_wishbone_slave_t_compliance_template.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; library vunit_lib; diff --git a/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd index 99612238d..8c0d85344 100644 --- a/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd +++ b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com library ieee; use ieee.std_logic_1164.all; diff --git a/vunit/vhdl/verification_components/src/ram_master_pkg.vhd b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd index 5c6882419..38f168475 100644 --- a/vunit/vhdl/verification_components/src/ram_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com -- Author Slawomir Siluk slaweksiluk@gazeta.pl library ieee; use ieee.std_logic_1164.all; diff --git a/vunit/vhdl/verification_components/src/vc_pkg.vhd b/vunit/vhdl/verification_components/src/vc_pkg.vhd index ce49c6d5e..871427e0c 100644 --- a/vunit/vhdl/verification_components/src/vc_pkg.vhd +++ b/vunit/vhdl/verification_components/src/vc_pkg.vhd @@ -2,7 +2,7 @@ -- 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-2020, Lars Asplund lars.anders.asplund@gmail.com +-- Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com -- -- This package contains common functionality for VC designers. From 959d15212b49357c7307ad820590ffd0acbe41e6 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 23 Aug 2021 20:15:23 +0200 Subject: [PATCH 11/21] Improved uart_master --- vunit/vhdl/verification_components/src/uart_master.vhd | 7 +++++-- vunit/vhdl/verification_components/src/uart_pkg.vhd | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vunit/vhdl/verification_components/src/uart_master.vhd b/vunit/vhdl/verification_components/src/uart_master.vhd index 910e80d21..2764576e8 100644 --- a/vunit/vhdl/verification_components/src/uart_master.vhd +++ b/vunit/vhdl/verification_components/src/uart_master.vhd @@ -27,7 +27,8 @@ architecture a of uart_master is begin main : process - procedure uart_send(data : std_logic_vector; + constant logger : logger_t := get_logger(main'path_name, get_logger(uart.p_std_cfg)); + procedure uart_send(data : std_logic_vector := x"00"; signal tx : out std_logic; baud_rate : integer) is constant time_per_bit : time := (10**9 / baud_rate) * 1 ns; @@ -39,7 +40,9 @@ begin end procedure; begin - debug("Sending " & to_string(data)); + if is_visible(logger, display_handler, debug) then + debug(logger, "Sending x""" & to_hstring(data) & """"); + end if; send_bit(not uart.p_idle_state); for i in 0 to data'length-1 loop send_bit(data(i)); diff --git a/vunit/vhdl/verification_components/src/uart_pkg.vhd b/vunit/vhdl/verification_components/src/uart_pkg.vhd index c223b7ca0..afc37940b 100644 --- a/vunit/vhdl/verification_components/src/uart_pkg.vhd +++ b/vunit/vhdl/verification_components/src/uart_pkg.vhd @@ -48,7 +48,7 @@ package uart_pkg is constant default_data_length : positive := 8; impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; idle_state : std_logic := default_idle_state; - logger : logger_t := uart_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -75,7 +75,7 @@ package body uart_pkg is impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; idle_state : std_logic := default_idle_state; - logger : logger_t := uart_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail From fecf8de52dab8584ae49e764242ce69ec6f314a9 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Tue, 31 Aug 2021 22:52:09 +0200 Subject: [PATCH 12/21] Check if the default logger of a VC is used several times and issue a warning if that is so. Using the same default logger for many VC makes it hard to trace the origin of a log entry. --- docs/verification_components/user_guide.rst | 67 ++++++++++------- .../vc_not_supporting_custom_actor_pkg.vhd | 4 +- .../vc_not_supporting_custom_logger_pkg.vhd | 4 +- .../vhdl/vc_not_supporting_sync_pkg.vhd | 4 +- ...supporting_unexpected_msg_handling_pkg.vhd | 4 +- tests/acceptance/artificial/vhdl/vc_pkg.vhd | 4 +- .../artificial/vhdl/vc_pkg_with_template.vhd | 4 +- tests/unit/test_compliance_test.py | 10 +-- vunit/vc/verification_component_interface.py | 2 +- vunit/vhdl/logging/src/logger_pkg.vhd | 3 + .../src/avalon_pkg.vhd | 17 +++-- .../src/avalon_stream_pkg.vhd | 8 +- .../src/axi_slave_pkg.vhd | 6 +- .../src/axi_stream_pkg.vhd | 19 +++-- .../src/bus2memory_pkg.vhd | 9 ++- .../src/bus_master_pkg-body.vhd | 2 +- .../src/bus_master_pkg.vhd | 2 +- .../src/ram_master_pkg.vhd | 9 ++- .../src/signal_checker_pkg.vhd | 4 +- .../src/stream_master_pkg-body.vhd | 2 +- .../src/stream_master_pkg.vhd | 2 +- .../src/stream_slave_pkg-body.vhd | 2 +- .../src/stream_slave_pkg.vhd | 2 +- .../verification_components/src/uart_pkg.vhd | 4 +- .../verification_components/src/vc_pkg.vhd | 34 ++++++++- .../test/tb_vc_pkg.vhd | 74 +++++++++++++++++++ 26 files changed, 212 insertions(+), 90 deletions(-) create mode 100644 vunit/vhdl/verification_components/test/tb_vc_pkg.vhd diff --git a/docs/verification_components/user_guide.rst b/docs/verification_components/user_guide.rst index 0decf47b7..56b6fc51c 100644 --- a/docs/verification_components/user_guide.rst +++ b/docs/verification_components/user_guide.rst @@ -236,69 +236,80 @@ name for better trace logs. Rule 6 ------ -A VC constructor shall have an ``unexpected_msg_type_policy`` parameter giving -the user the option to specify the action taken when the VC receives an unexpected -message type. +A VC constructor shall have an ``unexpected_msg_type_policy`` parameter giving the +user the option to specify the action taken when the VC receives an unexpected message type. -**Rationale**: A VC actor setup to subscribe to another actor may receive messages -not relevant for its operation. OTOH, VCs just addressed directly should only -recieve messages it can handle. +**Rationale**: A VC actor setup to subscribe to another actor may receive messages not +relevant for its operation. OTOH, VCs just addressed directly should only recieve messages it can handle. Rule 7 ------ A VC constructor shall have a default value for all required parameters above. -**Rationale**: Makes it easier for the user if there is no preference on what to -use. +**Rationale**: Makes it easier for the user if there is no preference on what to use. Rule 8 ------ -The default value for the logger parameter shall not be ``default_logger``. +The default value for the logger parameter shall be ``null_logger`` to indicate that the +VC should assign a logger internally. The internally assigned logger shall not be ``default_logger``. -**Rationale**: Using a logger more associated with the VC makes the logger output -easier to understand. +**Rationale**: Using a logger more associated with the VC makes the logger output easier to understand. +Using ``null_logger`` as the default parameter value makes it possible to distinguish between a parameter +not specified and the parameter specified with the intended default value. This can be used to detect +when the user unintendently create two VCs of the same type using the same logger. This is allowed but +deserves a warning if made by mistake. Rule 9 ------ -The default value for the checker parameter shall not be ``default_checker``. +The default value for the checker parameter shall be ``null_checker`` to indicate that the VC should +assign a checker internally. The internally assigned checker shall not be ``default_checker``. -**Rationale**: Using a checker more associated with the VC makes the checker -output easier to understand. +**Rationale**: Using a checker more associated with the VC makes the checker output easier to understand. +Using ``null_checker`` as the default parameter value makes it possible to distinguish between a parameter +not specified and the parameter specified with the intended default value. If no value is specified but +a logger has been provided the VC can create a checker from the provided logger rather than using the default +checker for that VC. Rule 10 ------- -All fields in the handle returned by the constructor shall start with ``p_``. +The default value for the actor parameter shall be ``null_actor`` to indicate that the VC should assign an +actor internally. The internally assigned actor shall be a new actor for each VC. -**Rationale**: All field shall be considered private and this is a way to -emphasize this. Keeping them private makes updates easier without breaking -backward compatibility. +**Rationale**: VCs can never share actors in the same way they can share loggers and checkers. There can be +only one VC serving messages sent to a specific actor. Rule 11 ------- -The standard configuration, ``std_cfg_t``, of a VC consisting of the required -parameters to the constructor shall be possible to get from the handle using a call to ``get_std_cfg``. +All fields in the handle returned by the constructor shall start with ``p_``. -**Rationale**: Makes it possible to reuse operations such as ``get_logger`` -between VCs. +**Rationale**: All field shall be considered private and this is a way to emphasize this. Keeping them private +makes updates easier without breaking backward compatibility. Rule 12 ------- -A VC shall only have one generic. +The standard configuration, ``std_cfg_t``, of a VC consisting of the required parameters to the constructor +shall be possible to get from the handle using a call to ``get_std_cfg``. -**Rationale**: Representing a VC with a single object makes it easier to handle -in code. Since all fields of the handle are private future updates have less -risk of breaking backward compatibility. +**Rationale**: Makes it possible to reuse operations such as ``get_logger`` between VCs. Rule 13 ------- +A VC shall only have one generic. + +**Rationale**: Representing a VC with a single object makes it easier to handle in code. Since all fields of +the handle are private future updates have less risk of breaking backward compatibility. + +Rule 14 +------- + All VCs shall support the sync interface. -**Rationale**: Being able to check that a VC is idle and to add a delay between -transactions are commonly useful operations for VC users. +**Rationale**: Being able to check that a VC is idle and to add a delay between transactions are commonly useful +operations for VC users. diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd index bd70020a7..7611c6138 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_actor_pkg.vhd @@ -22,7 +22,7 @@ package vc_not_supporting_custom_actor_pkg is constant transaction_msg : msg_type_t := new_msg_type("transaction"); impure function new_vc_not_supporting_custom_actor( - logger : logger_t := vc_not_supporting_custom_actor_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -41,7 +41,7 @@ end package; package body vc_not_supporting_custom_actor_pkg is impure function new_vc_not_supporting_custom_actor( - logger : logger_t := vc_not_supporting_custom_actor_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd index fe376e21f..90f4b3b43 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_custom_logger_pkg.vhd @@ -19,7 +19,7 @@ package vc_not_supporting_custom_logger_pkg is constant vc_not_supporting_custom_logger_checker : checker_t := new_checker(vc_not_supporting_custom_logger_logger); impure function new_vc_not_supporting_custom_logger( - logger : logger_t := vc_not_supporting_custom_logger_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -33,7 +33,7 @@ end package; package body vc_not_supporting_custom_logger_pkg is impure function new_vc_not_supporting_custom_logger( - logger : logger_t := vc_not_supporting_custom_logger_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd index 32a736788..19389e862 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_sync_pkg.vhd @@ -19,7 +19,7 @@ package vc_not_supporting_sync_pkg is constant vc_not_supporting_sync_checker : checker_t := new_checker(vc_not_supporting_sync_logger); impure function new_vc_not_supporting_sync( - logger : logger_t := vc_not_supporting_sync_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -33,7 +33,7 @@ end package; package body vc_not_supporting_sync_pkg is impure function new_vc_not_supporting_sync( - logger : logger_t := vc_not_supporting_sync_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd index 00fbf56ec..045987cee 100644 --- a/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_not_supporting_unexpected_msg_handling_pkg.vhd @@ -19,7 +19,7 @@ package vc_not_supporting_unexpected_msg_handling_pkg is constant vc_not_supporting_unexpected_msg_handling_checker : checker_t := new_checker(vc_not_supporting_unexpected_msg_handling_logger); impure function new_vc_not_supporting_unexpected_msg_handling( - logger : logger_t := vc_not_supporting_unexpected_msg_handling_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -33,7 +33,7 @@ end package; package body vc_not_supporting_unexpected_msg_handling_pkg is impure function new_vc_not_supporting_unexpected_msg_handling( - logger : logger_t := vc_not_supporting_unexpected_msg_handling_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/acceptance/artificial/vhdl/vc_pkg.vhd b/tests/acceptance/artificial/vhdl/vc_pkg.vhd index 3598f7f61..d2d05f972 100644 --- a/tests/acceptance/artificial/vhdl/vc_pkg.vhd +++ b/tests/acceptance/artificial/vhdl/vc_pkg.vhd @@ -19,7 +19,7 @@ package vc_pkg is constant vc_checker : checker_t := new_checker(vc_logger); impure function new_vc( - logger : logger_t := vc_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -33,7 +33,7 @@ end package; package body vc_pkg is impure function new_vc( - logger : logger_t := vc_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd index f1d19bd7c..a76f484cd 100644 --- a/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd +++ b/tests/acceptance/artificial/vhdl/vc_pkg_with_template.vhd @@ -20,7 +20,7 @@ package vc_pkg_with_template is impure function new_vc( unspecified : boolean; - logger : logger_t := vc_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -35,7 +35,7 @@ end package; package body vc_pkg_with_template is impure function new_vc( unspecified : boolean; - logger : logger_t := vc_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py index 01bc7956f..5f14516e5 100644 --- a/tests/unit/test_compliance_test.py +++ b/tests/unit/test_compliance_test.py @@ -54,7 +54,7 @@ def setUp(self): end record; impure function new_vc( - logger : logger_t := default_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -248,7 +248,7 @@ def test_failing_with_wrong_constructor_return_type(self, error_mock): @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_failing_on_incorrect_constructor_parameters(self, error_mock): parameters = dict( - logger=("logger_t", "default_logger"), + logger=("logger_t", "null_logger"), actor=("actor_t", "null_actor"), checker=("checker_t", "null_checker"), unexpected_msg_type_policy=("unexpected_msg_type_policy_t", "fail"), @@ -343,7 +343,7 @@ def test_failing_on_non_private_handle_elements(self, error_mock): end record; impure function new_vc( - logger : logger_t := default_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -373,7 +373,7 @@ def test_failing_on_missing_handle_record(self, error_mock): end record; impure function new_vc( - logger : logger_t := default_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -397,7 +397,7 @@ def test_failing_on_missing_handle_record(self, error_mock): def test_error_on_missing_default_value(self): parameters = dict( - logger=("logger_t", "default_logger"), + logger=("logger_t", "null_logger"), actor=("actor_t", "null_actor"), checker=("checker_t", "null_checker"), unexpected_msg_type_policy=("unexpected_msg_type_policy_t", "fail"), diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index 54a025f43..f2e2c34d9 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -155,7 +155,7 @@ def log_error_message(function_score, messages): ) expected_default_value = dict( - logger=None, + logger="null_logger", actor="null_actor", checker="null_checker", unexpected_msg_type_policy=None, diff --git a/vunit/vhdl/logging/src/logger_pkg.vhd b/vunit/vhdl/logging/src/logger_pkg.vhd index 423262924..cbdb8291a 100644 --- a/vunit/vhdl/logging/src/logger_pkg.vhd +++ b/vunit/vhdl/logging/src/logger_pkg.vhd @@ -406,4 +406,7 @@ package logger_pkg is -- Return the number of unchecked messages in the mock queue impure function mock_queue_length return natural; + -- Return an integer reference to the logger + impure function to_integer(logger : logger_t) return integer; + end package; diff --git a/vunit/vhdl/verification_components/src/avalon_pkg.vhd b/vunit/vhdl/verification_components/src/avalon_pkg.vhd index ded2e5a27..7ec8899d2 100644 --- a/vunit/vhdl/verification_components/src/avalon_pkg.vhd +++ b/vunit/vhdl/verification_components/src/avalon_pkg.vhd @@ -45,7 +45,7 @@ package avalon_pkg is write_high_probability : real range 0.0 to 1.0 := 1.0; read_high_probability : real range 0.0 to 1.0 := 1.0; byte_length : natural := 8; - logger : logger_t := avalon_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -55,7 +55,7 @@ package avalon_pkg is memory : memory_t; readdatavalid_high_probability : real := 1.0; waitrequest_high_probability : real := 0.0; - logger : logger_t := avalon_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -79,13 +79,16 @@ package body avalon_pkg is write_high_probability : real range 0.0 to 1.0 := 1.0; read_high_probability : real range 0.0 to 1.0 := 1.0; byte_length : natural := 8; - logger : logger_t := avalon_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return avalon_master_t is - constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, - checker, unexpected_msg_type_policy + constant p_std_cfg : std_cfg_t := create_std_cfg( + avalon_logger, avalon_checker, actor, logger, checker, unexpected_msg_type_policy + ); + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, get_logger(p_std_cfg), get_actor(p_std_cfg), get_checker(p_std_cfg), + unexpected_msg_type_policy ); begin return (p_bus_handle => p_bus_handle, @@ -100,7 +103,7 @@ package body avalon_pkg is memory : memory_t; readdatavalid_high_probability : real := 1.0; waitrequest_high_probability : real := 0.0; - logger : logger_t := avalon_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -113,7 +116,7 @@ package body avalon_pkg is begin return (p_std_cfg => p_std_cfg, p_ack_actor => new_actor(name(actor) & " read-ack"), - p_memory => to_vc_interface(memory, logger), + p_memory => to_vc_interface(memory, get_logger(p_std_cfg)), p_readdatavalid_high_probability => readdatavalid_high_probability, p_waitrequest_high_probability => waitrequest_high_probability ); diff --git a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd index b563bc5f8..2b8b20fda 100644 --- a/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/avalon_stream_pkg.vhd @@ -35,14 +35,14 @@ package avalon_stream_pkg is impure function new_avalon_source(data_length : natural; valid_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return avalon_source_t; impure function new_avalon_sink(data_length : natural; ready_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return avalon_sink_t; @@ -99,7 +99,7 @@ package body avalon_stream_pkg is impure function new_avalon_source(data_length : natural; valid_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -115,7 +115,7 @@ package body avalon_stream_pkg is impure function new_avalon_sink(data_length : natural; ready_high_probability : real := 1.0; - logger : logger_t := avalon_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return avalon_sink_t is diff --git a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd index 9c8efda09..ed7de25fb 100644 --- a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd @@ -45,7 +45,7 @@ package axi_slave_pkg is write_response_stall_probability : probability_t := 0.0; min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger; + logger : logger_t := null_logger; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t; @@ -165,7 +165,7 @@ package body axi_slave_pkg is write_response_stall_probability : probability_t := 0.0; min_response_latency : delay_length := 0 ns; max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger; + logger : logger_t := null_logger; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return axi_slave_t is constant p_std_cfg : std_cfg_t := create_std_cfg( @@ -181,7 +181,7 @@ package body axi_slave_pkg is p_initial_write_response_stall_probability => write_response_stall_probability, p_initial_min_response_latency => min_response_latency, p_initial_max_response_latency => max_response_latency, - p_memory => to_vc_interface(memory, logger)); + p_memory => to_vc_interface(memory, get_logger(p_std_cfg))); end; function get_std_cfg(axi_slave : axi_slave_t) return std_cfg_t is diff --git a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd index 386f2885b..f1683f901 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd @@ -165,7 +165,7 @@ package axi_stream_pkg is drive_invalid : boolean := true; drive_invalid_val : std_logic := 'X'; drive_invalid_val_user : std_logic := '0'; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -179,7 +179,7 @@ package axi_stream_pkg is dest_length : natural := 0; user_length : natural := 0; stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -192,7 +192,7 @@ package axi_stream_pkg is id_length : natural := 0; dest_length : natural := 0; user_length : natural := 0; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -204,7 +204,7 @@ package axi_stream_pkg is id_length : natural := 0; dest_length : natural := 0; user_length : natural := 0; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -356,7 +356,7 @@ package body axi_stream_pkg is id_length : natural := 0; dest_length : natural := 0; user_length : natural := 0; - logger : logger_t := axi_stream_logger; + logger : logger_t; actor : actor_t; checker : checker_t; monitor : axi_stream_monitor_t; @@ -412,7 +412,7 @@ package body axi_stream_pkg is drive_invalid : boolean := true; drive_invalid_val : std_logic := 'X'; drive_invalid_val_user : std_logic := '0'; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -428,7 +428,6 @@ package body axi_stream_pkg is p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, checker, monitor, "master"); p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, checker, protocol_checker, "master"); - return ( p_std_cfg => p_std_cfg, p_data_length => data_length, @@ -450,7 +449,7 @@ package body axi_stream_pkg is dest_length : natural := 0; user_length : natural := 0; stall_config : stall_config_t := null_stall_config; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -483,7 +482,7 @@ package body axi_stream_pkg is id_length : natural := 0; dest_length : natural := 0; user_length : natural := 0; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; @@ -511,7 +510,7 @@ package body axi_stream_pkg is id_length : natural := 0; dest_length : natural := 0; user_length : natural := 0; - logger : logger_t := axi_stream_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail; diff --git a/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd index 8c0d85344..46a3bc97e 100644 --- a/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd +++ b/vunit/vhdl/verification_components/src/bus2memory_pkg.vhd @@ -29,7 +29,7 @@ package bus2memory_pkg is address_length : natural; memory : memory_t; byte_length : natural := 8; - logger : logger_t := bus2memory_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -47,12 +47,15 @@ package body bus2memory_pkg is address_length : natural; memory : memory_t; byte_length : natural := 8; - logger : logger_t := bus2memory_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return bus2memory_t is - constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, checker, + constant p_std_cfg : std_cfg_t := create_std_cfg( + bus2memory_logger, bus2memory_checker, actor, logger, checker, unexpected_msg_type_policy + ); + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, get_logger(p_std_cfg), get_actor(p_std_cfg), get_checker(p_std_cfg), unexpected_msg_type_policy ); begin diff --git a/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd b/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd index 97fbc7f6f..b35ef4638 100644 --- a/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/bus_master_pkg-body.vhd @@ -19,7 +19,7 @@ package body bus_master_pkg is impure function new_bus(data_length : natural; address_length : natural; byte_length : natural := 8; - logger : logger_t := bus_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return bus_master_t is diff --git a/vunit/vhdl/verification_components/src/bus_master_pkg.vhd b/vunit/vhdl/verification_components/src/bus_master_pkg.vhd index 22028016d..7ac6539b1 100644 --- a/vunit/vhdl/verification_components/src/bus_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/bus_master_pkg.vhd @@ -38,7 +38,7 @@ package bus_master_pkg is impure function new_bus(data_length : natural; address_length : natural; byte_length : natural := 8; - logger : logger_t := bus_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return bus_master_t; diff --git a/vunit/vhdl/verification_components/src/ram_master_pkg.vhd b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd index 38f168475..659c9404f 100644 --- a/vunit/vhdl/verification_components/src/ram_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/ram_master_pkg.vhd @@ -29,7 +29,7 @@ package ram_master_pkg is address_length : natural; latency : positive; byte_length : natural := 8; - logger : logger_t := ram_master_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail @@ -146,12 +146,15 @@ package body ram_master_pkg is address_length : natural; latency : positive; byte_length : natural := 8; - logger : logger_t := ram_master_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return ram_master_t is - constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, logger, actor, checker, + constant p_std_cfg : std_cfg_t := create_std_cfg( + ram_master_logger, ram_master_checker, actor, logger, checker, unexpected_msg_type_policy + ); + constant p_bus_handle : bus_master_t := new_bus(data_length, address_length, byte_length, get_logger(p_std_cfg), get_actor(p_std_cfg), get_checker(p_std_cfg), unexpected_msg_type_policy ); begin diff --git a/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd b/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd index 7d16bf02f..5aa1e0bdc 100644 --- a/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd +++ b/vunit/vhdl/verification_components/src/signal_checker_pkg.vhd @@ -23,7 +23,7 @@ package signal_checker_pkg is constant signal_checker_checker : checker_t := new_checker(signal_checker_logger); impure function new_signal_checker( - logger : logger_t := signal_checker_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) @@ -52,7 +52,7 @@ end package; package body signal_checker_pkg is impure function new_signal_checker( - logger : logger_t := signal_checker_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd index f419366be..af9eab9df 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd @@ -12,7 +12,7 @@ context work.com_context; package body stream_master_pkg is impure function new_stream_master( - logger : logger_t := stream_master_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd index 7505db10b..0c28220ee 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd @@ -24,7 +24,7 @@ package stream_master_pkg is -- Create a new stream master object impure function new_stream_master( - logger : logger_t := stream_master_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd index 4de6c4b0f..9af9ccf91 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd @@ -7,7 +7,7 @@ package body stream_slave_pkg is impure function new_stream_slave( - logger : logger_t := stream_slave_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd index cd2218cf7..e27730422 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd @@ -25,7 +25,7 @@ package stream_slave_pkg is -- Create a new stream slave object impure function new_stream_slave( - logger : logger_t := stream_slave_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail diff --git a/vunit/vhdl/verification_components/src/uart_pkg.vhd b/vunit/vhdl/verification_components/src/uart_pkg.vhd index afc37940b..edf14910e 100644 --- a/vunit/vhdl/verification_components/src/uart_pkg.vhd +++ b/vunit/vhdl/verification_components/src/uart_pkg.vhd @@ -56,7 +56,7 @@ package uart_pkg is impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; idle_state : std_logic := default_idle_state; data_length : positive := default_data_length; - logger : logger_t := uart_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return uart_slave_t; @@ -93,7 +93,7 @@ package body uart_pkg is impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; idle_state : std_logic := default_idle_state; data_length : positive := default_data_length; - logger : logger_t := uart_logger; + logger : logger_t := null_logger; actor : actor_t := null_actor; checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail) return uart_slave_t is diff --git a/vunit/vhdl/verification_components/src/vc_pkg.vhd b/vunit/vhdl/verification_components/src/vc_pkg.vhd index 871427e0c..14ba6d77c 100644 --- a/vunit/vhdl/verification_components/src/vc_pkg.vhd +++ b/vunit/vhdl/verification_components/src/vc_pkg.vhd @@ -30,7 +30,7 @@ package vc_pkg is -- -- * The actor is the actor provided by the actor parameter unless it's the null_actor. In that case a new actor is created -- * The logger is the logger provided by the logger parameter unless it's the null_logger. In that case the default logger is used which must not be the null_logger. - -- * The checker is the checker provided by the checker parameter unless it's the null_checker. In that case the the default checker is used if the logger is the + -- * The checker is the checker provided by the checker parameter unless it's the null_checker. In that case the default checker is used if the logger is the -- default logger. Otherwise a new checker is created based on the provided logger. The default checker must not be the null_checker -- * The policy for handling unexpected messages is according to the unexpected_msg_type_policy parameter. impure function create_std_cfg( @@ -56,6 +56,22 @@ end package; package body vc_pkg is constant vc_logger : logger_t := get_logger("vunit_lib:vc_pkg"); constant vc_checker : checker_t := new_checker(vc_logger); + constant used_default_loggers : integer_vector_ptr_t := new_integer_vector_ptr; + + procedure register_if_not_used(default_logger : logger_t) is + constant ref : integer := to_integer(default_logger); + begin + for idx in 0 to length(used_default_loggers) - 1 loop + if get(used_default_loggers, idx) = ref then + warning(default_logger, "This logger is already used by another VC. Source VC for log messages is ambiguous."); + report "This logger is already used by another VC. Source VC for log messages is ambiguous." severity warning; + return; + end if; + end loop; + + resize(used_default_loggers, length(used_default_loggers) + 1); + set(used_default_loggers, length(used_default_loggers) - 1, ref); + end; impure function create_std_cfg( default_logger : logger_t; @@ -70,13 +86,23 @@ package body vc_pkg is check(vc_checker, default_logger /= null_logger, "A default logger must be provided"); check(vc_checker, default_checker /= null_checker, "A default checker must be provided"); - result.p_actor := actor when actor /= null_actor else new_actor; - result.p_logger := logger when logger /= null_logger else default_logger; + result.p_actor := actor when actor /= null_actor else new_actor; + + if logger /= null_logger then + result.p_logger := logger; + else + result.p_logger := default_logger; + register_if_not_used(default_logger); + end if; + result.p_unexpected_msg_type_policy := unexpected_msg_type_policy; if checker = null_checker then - if logger = default_logger then + if logger = null_logger then result.p_checker := default_checker; + if get_logger(default_checker) /= default_logger then + register_if_not_used(get_logger(default_checker)); + end if; else result.p_checker := new_checker(logger); end if; 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..fcad4e53a --- /dev/null +++ b/vunit/vhdl/verification_components/test/tb_vc_pkg.vhd @@ -0,0 +1,74 @@ +-- 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-2021, 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; + constant default_logger1 : logger_t := get_logger("default_logger1"); + constant default_checker1 : checker_t := new_checker(get_logger("default_checker1")); + constant default_checker_based_on_default_checker1 : checker_t := new_checker(default_logger1); + constant default_logger2 : logger_t := get_logger("default_logger2"); + constant default_checker2 : checker_t := new_checker(get_logger("default_checker2")); + begin + test_runner_setup(runner, runner_cfg); + while test_suite loop + if run("Test that no warnings are issued for first std cfg using the default logger") then + mock(default_logger1, warning); + std_cfg := create_std_cfg(default_logger1, default_checker1); + std_cfg := create_std_cfg(default_logger2, default_checker2); + check_no_log; + unmock(default_logger1); + + elsif run("Test that no warnings are issued for when a std cfg use the default logger for the default checker") then + mock(default_logger1, warning); + std_cfg := create_std_cfg(default_logger1, default_checker_based_on_default_checker1); + check_no_log; + unmock(default_logger1); + + elsif run("Test that no warnings are issued for when the input logger to std cfg reuse the default logger") then + mock(default_logger1, warning); + std_cfg := create_std_cfg(default_logger1, default_checker1); + std_cfg := create_std_cfg(default_logger2, default_checker2, logger => default_logger1); + check_no_log; + unmock(default_logger1); + + elsif run("Test that a warning is issued when a std cfg is created with an already used default logger") then + mock(default_logger1, warning); + std_cfg := create_std_cfg(default_logger1, default_checker1); + std_cfg := create_std_cfg(default_logger1, default_checker2); + check_only_log(default_logger1, "This logger is already used by another VC. Source VC for log messages is ambiguous.", warning); + unmock(default_logger1); + + elsif run("Test that a warning is issued when a std cfg is created with a default checker using an already used default logger") then + mock(default_logger1, warning); + std_cfg := create_std_cfg(default_logger1, default_checker1); + std_cfg := create_std_cfg(default_logger2, default_checker_based_on_default_checker1); + check_only_log(default_logger1, "This logger is already used by another VC. Source VC for log messages is ambiguous.", warning); + unmock(default_logger1); + + elsif run("Test that a warning is issued when a std cfg is created with a default checker using an logger already used by a default checker") then + mock(get_logger(default_checker1), warning); + std_cfg := create_std_cfg(default_logger1, default_checker1); + std_cfg := create_std_cfg(default_logger2, default_checker1); + check_only_log(get_logger(default_checker1), "This logger is already used by another VC. Source VC for log messages is ambiguous.", warning); + unmock(get_logger(default_checker1)); + + end if; + end loop; + test_runner_cleanup(runner, fail_on_warning => true); + end process; +end architecture; From d89affcc6c5161df04a800a25b0ebda6ef84ff19 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sun, 5 Sep 2021 12:13:55 +0200 Subject: [PATCH 13/21] Fixed review comments/bugs --- vunit/vc/compliance_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index d3873d5f5..c62704b75 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -52,7 +52,7 @@ def _create_vci_template(args): sys.exit(1) if not args.output_path: - output_dir = args.vc_path.parent / ".vc" / vci_name + output_dir = args.vci_path.parent / ".vc" / vci_name if not output_dir.exists(): output_dir.mkdir(parents=True) @@ -60,7 +60,7 @@ def _create_vci_template(args): elif args.output_path.is_dir(): output_dir = args.output_path / vci_name if not output_dir.exists(): - output_dir.exists(parents=True) + output_dir.mkdir(parents=True) output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) else: output_path = args.output_path From 9b864c42c2b950c9b2a50a9e52bc686153695242 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Sun, 5 Sep 2021 23:39:08 +0200 Subject: [PATCH 14/21] Add support for unconstrained handle fields --- vunit/vc/vc_template.py | 1 - vunit/vc/vci_template.py | 74 ++++++++++++-------- vunit/vc/verification_component_interface.py | 48 ++++++------- 3 files changed, 67 insertions(+), 56 deletions(-) diff --git a/vunit/vc/vc_template.py b/vunit/vc/vc_template.py index e8e47bb50..f243fec93 100644 --- a/vunit/vc/vc_template.py +++ b/vunit/vc/vc_template.py @@ -43,7 +43,6 @@ constant custom_checker : checker_t := new_checker(get_logger("vc_check")); impure function create_handle return ${vc_handle_t} is - variable handle : ${vc_handle_t}; variable logger : logger_t := ${default_logger}; variable actor : actor_t := ${default_actor}; variable checker : checker_t := ${default_checker}; diff --git a/vunit/vc/vci_template.py b/vunit/vc/vci_template.py index 57795da44..0c78e061f 100644 --- a/vunit/vc/vci_template.py +++ b/vunit/vc/vci_template.py @@ -49,14 +49,41 @@ constant checker_logger3 : logger_t := get_logger("checker3"); constant checker3 : checker_t := new_checker(checker_logger3); - variable handle1, handle2, handle3 : ${vc_handle_t}; - variable std_cfg1, std_cfg2, std_cfg3 : std_cfg_t; + constant actor4 : actor_t := new_actor("actor4"); + constant logger4 : logger_t := get_logger("logger4"); + constant checker_logger4 : logger_t := get_logger("checker4"); + constant checker4 : checker_t := new_checker(checker_logger4); + + constant actor5 : actor_t := new_actor("actor5"); + constant logger5 : logger_t := get_logger("logger5"); + constant checker_logger5 : logger_t := get_logger("checker5"); + constant checker5 : checker_t := new_checker(checker_logger5); + + constant actor6 : actor_t := new_actor("actor6"); + constant logger6 : logger_t := get_logger("logger6"); + constant checker_logger6 : logger_t := get_logger("checker6"); + constant checker6 : checker_t := new_checker(checker_logger6); + + constant actor7 : actor_t := new_actor("actor7"); + constant logger7 : logger_t := get_logger("logger7"); + constant checker_logger7 : logger_t := get_logger("checker7"); + constant checker7 : checker_t := new_checker(checker_logger7); + +${handle1} +${handle2} +${handle3} +${handle4} +${handle5} +${handle6} +${handle7} + + variable std_cfg1, std_cfg2, std_cfg3, std_cfg4 : std_cfg_t; + variable std_cfg5, std_cfg6, std_cfg7 : std_cfg_t; begin test_runner_setup(runner, runner_cfg); while test_suite loop if run("Test standard configuration") then -${handle1} std_cfg1 := get_std_cfg(handle1); check(get_actor(std_cfg1) = actor1, "Failed to configure actor with ${vc_constructor_name}"); @@ -65,16 +92,12 @@ check(unexpected_msg_type_policy(std_cfg1) = fail, "Failed to configure unexpected_msg_type_policy = fail with ${vc_constructor_name}"); -${handle2} std_cfg2 := get_std_cfg(handle2); check(unexpected_msg_type_policy(std_cfg2) = ignore, "Failed to configure unexpected_msg_type_policy = ignore with ${vc_constructor_name}"); elsif run("Test handle independence") then -${handle1} -${handle3} - std_cfg1 := get_std_cfg(handle1); std_cfg2 := get_std_cfg(handle2); check(get_actor(std_cfg1) /= get_actor(std_cfg2), @@ -87,42 +110,37 @@ "unexpected_msg_type_policy shared between handles created by ${vc_constructor_name}"); elsif run("Test default logger") then -${handle4} - std_cfg1 := get_std_cfg(handle1); - check(get_logger(std_cfg1) /= null_logger, + std_cfg3 := get_std_cfg(handle3); + check(get_logger(std_cfg3) /= null_logger, "No valid default logger (null_logger) created by ${vc_constructor_name}"); - check(get_logger(std_cfg1) /= default_logger, + check(get_logger(std_cfg3) /= default_logger, "No valid default logger (default_logger) created by ${vc_constructor_name}"); -${handle5} - std_cfg2 := get_std_cfg(handle2); - check(get_logger(std_cfg2) /= null_logger, + std_cfg4 := get_std_cfg(handle4); + check(get_logger(std_cfg4) /= null_logger, "No valid default logger (null_logger) created by ${vc_constructor_name}"); - check(get_logger(std_cfg2) /= default_logger, + check(get_logger(std_cfg4) /= default_logger, "No valid default logger (default_logger) created by ${vc_constructor_name}"); elsif run("Test default checker") then -${handle6} - std_cfg1 := get_std_cfg(handle1); - check(get_checker(std_cfg1) /= null_checker, + std_cfg5 := get_std_cfg(handle5); + check(get_checker(std_cfg5) /= null_checker, "No valid default checker (null_checker) created by ${vc_constructor_name}"); - check(get_checker(std_cfg1) /= default_checker, + check(get_checker(std_cfg5) /= default_checker, "No valid default checker (default_checker) created by ${vc_constructor_name}"); -${handle7} - std_cfg2 := get_std_cfg(handle2); - check(get_checker(std_cfg2) /= null_checker, + std_cfg6 := get_std_cfg(handle6); + check(get_checker(std_cfg6) /= null_checker, "No valid default checker (null_checker) created by ${vc_constructor_name}"); - check(get_checker(std_cfg2) /= default_checker, + check(get_checker(std_cfg6) /= default_checker, "No valid default checker (default_checker) created by ${vc_constructor_name}"); -${handle8} - std_cfg3 := get_std_cfg(handle3); - check(get_checker(std_cfg3) /= null_checker, + std_cfg7 := get_std_cfg(handle7); + check(get_checker(std_cfg7) /= null_checker, "No valid default checker (null_checker) created by ${vc_constructor_name}"); - check(get_checker(std_cfg3) /= default_checker, + check(get_checker(std_cfg7) /= default_checker, "No valid default checker (default_checker) created by ${vc_constructor_name}"); - check(get_logger(get_checker(std_cfg3)) = logger3, + check(get_logger(get_checker(std_cfg7)) = logger6, "Default checker not based on logger provided to ${vc_constructor_name}"); end if; diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index f2e2c34d9..bbdc54645 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -339,8 +339,9 @@ def create_handle_assignment( unexpected_msg_type_policy="fail", ): - handle_assignment = " %s := %s(\n" % ( + handle_assignment = " constant %s : %s := %s(\n" % ( handle_name, + self.vc_constructor.return_type_mark, self.vc_constructor.identifier, ) for parameter in unspecified_parameters: @@ -352,7 +353,7 @@ def create_handle_assignment( "unexpected_msg_type_policy", ]: continue - handle_assignment += " %s => %s,\n" % ( + handle_assignment += " %s => %s,\n" % ( identifier, identifier, ) @@ -363,9 +364,9 @@ def create_handle_assignment( unexpected_msg_type_policy=unexpected_msg_type_policy, ).items(): if actual: - handle_assignment += " %s => %s,\n" % (formal, actual) + handle_assignment += " %s => %s,\n" % (formal, actual) - handle_assignment = handle_assignment[:-2] + "\n );" + handle_assignment = handle_assignment[:-2] + "\n );" return handle_assignment @@ -389,40 +390,33 @@ def create_handle_assignment( unexpected_msg_type_policy="ignore", ), handle3=create_handle_assignment( - "handle2", - actor="actor2", - logger="logger2", - checker="checker2", - unexpected_msg_type_policy="ignore", + "handle3", + actor="actor3", + checker="checker3", + unexpected_msg_type_policy="fail", ), handle4=create_handle_assignment( - "handle1", - actor="actor1", - checker="checker1", + "handle4", + actor="actor4", + logger="null_logger", + checker="checker4", unexpected_msg_type_policy="fail", ), handle5=create_handle_assignment( - "handle2", - actor="actor2", - logger="null_logger", - checker="checker2", + "handle5", + actor="actor5", unexpected_msg_type_policy="fail", ), handle6=create_handle_assignment( - "handle1", - actor="actor1", - unexpected_msg_type_policy="fail", - ), - handle7=create_handle_assignment( - "handle2", - actor="actor2", + "handle6", + actor="actor6", checker="null_checker", unexpected_msg_type_policy="fail", ), - handle8=create_handle_assignment( - "handle3", - actor="actor3", - logger="logger3", + handle7=create_handle_assignment( + "handle7", + actor="actor7", + logger="logger6", unexpected_msg_type_policy="fail", ), ) From 883d9750946dfe4201df692f68f42fbe46e3462f Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Wed, 29 Sep 2021 20:40:10 +0200 Subject: [PATCH 15/21] Added support for VCI and VC belonging to different libraries. Improved compliance tests to detect lack of as_sync function and added missing functions to VUnit VCIs --- tests/unit/test_compliance_test.py | 60 ++++++++++++------- vunit/vc/compliance_test.py | 21 ++++--- vunit/vc/verification_component.py | 9 ++- vunit/vc/verification_component_interface.py | 34 ++++++++++- .../src/stream_master_pkg-body.vhd | 5 ++ .../src/stream_master_pkg.vhd | 2 + .../src/stream_slave_pkg-body.vhd | 5 ++ .../src/stream_slave_pkg.vhd | 2 + 8 files changed, 103 insertions(+), 35 deletions(-) diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py index 5f14516e5..04a23a12d 100644 --- a/tests/unit/test_compliance_test.py +++ b/tests/unit/test_compliance_test.py @@ -29,6 +29,10 @@ class TestComplianceTest(TestCase): # pylint: disable=too-many-public-methods def setUp(self): self.tmp_dir = Path(__file__).parent / "vc_tmp" renew_path(str(self.tmp_dir)) + self.vc_dir = self.tmp_dir / "vc" + renew_path(str(self.vc_dir)) + self.vci_dir = self.tmp_dir / "vci" + renew_path(str(self.vci_dir)) self.vc_contents = """ library ieee use ieee.std_logic_1164.all; @@ -45,7 +49,7 @@ def setUp(self): end entity; """ - self.vc_path = self.make_file("vc.vhd", self.vc_contents) + self.vc_path = self.make_file("vc.vhd", self.vc_contents, self.vc_dir) self.vci_contents = """ package vc_pkg is @@ -59,32 +63,38 @@ def setUp(self): checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return vc_handle_t; + + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ - self.vci_path = self.make_file("vci.vhd", self.vci_contents) + self.vci_path = self.make_file("vci.vhd", self.vci_contents, self.vci_dir) self.ui = VUnit.from_argv([]) self.vc_lib = self.ui.add_library("vc_lib") - self.vc_lib.add_source_files(str(self.tmp_dir / "*.vhd")) + self.vc_lib.add_source_files(str(self.vc_dir / "*.vhd")) + + self.vci_lib = self.ui.add_library("vci_lib") + self.vci_lib.add_source_files(str(self.vci_dir / "*.vhd")) def tearDown(self): if self.tmp_dir.exists(): rmtree(self.tmp_dir) - def make_file(self, file_name, contents): + def make_file(self, file_name, contents, directory=None): """ Create a file in the temporary directory with contents Returns the absolute path to the file. """ - full_file_name = (self.tmp_dir / file_name).resolve() + directory = directory if directory is not None else self.tmp_dir + full_file_name = (directory / file_name).resolve() with full_file_name.open("w") as outfile: outfile.write(contents) return str(full_file_name) @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_not_finding_vc(self, error_mock): - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "other_vc", vci ) @@ -95,7 +105,7 @@ def test_not_finding_vci(self, error_mock): self.assertRaises( SystemExit, VerificationComponentInterface.find, - self.vc_lib, + self.vci_lib, "other_vc_pkg", "vc_handle_t", ) @@ -113,7 +123,7 @@ def test_failing_on_multiple_entities(self, error_mock): end entity; """ self.vc_lib.add_source_file(self.make_file("vc1_2.vhd", vc_contents)) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci ) @@ -121,7 +131,7 @@ def test_failing_on_multiple_entities(self, error_mock): "%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd" ) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci ) @@ -167,7 +177,7 @@ def test_evaluating_vc_generics(self, error_mock): end entity; """ self.vc_lib.add_source_file(self.make_file("vc1.vhd", vc1_contents)) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci ) @@ -179,7 +189,7 @@ def test_evaluating_vc_generics(self, error_mock): end entity; """ self.vc_lib.add_source_file(self.make_file("vc2.vhd", vc2_contents)) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci ) @@ -191,7 +201,7 @@ def test_evaluating_vc_generics(self, error_mock): end entity; """ self.vc_lib.add_source_file(self.make_file("vc3.vhd", vc3_contents)) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") self.assertRaises( SystemExit, VerificationComponent.find, self.vc_lib, "vc3", vci ) @@ -206,6 +216,7 @@ def test_failing_with_no_constructor(self, error_mock): end record; impure function create_vc return vc_handle_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) @@ -230,6 +241,8 @@ def test_failing_with_wrong_constructor_return_type(self, error_mock): end record; impure function new_vc return vc_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; + end package; """ self.vc_lib.add_source_file(self.make_file("other_vci.vhd", vci_contents)) @@ -300,6 +313,7 @@ def test_failing_on_incorrect_constructor_parameters(self, error_mock): vci_contents[:-2] + """ ) return vc_handle_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ ) @@ -348,6 +362,7 @@ def test_failing_on_non_private_handle_elements(self, error_mock): checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return vc_handle_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ @@ -378,6 +393,7 @@ def test_failing_on_missing_handle_record(self, error_mock): checker : checker_t := null_checker; unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail ) return vc_handle_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ @@ -432,6 +448,7 @@ def test_error_on_missing_default_value(self): vci_contents[:-2] + """ ) return vc_handle_t; + function as_sync(handle : vc_handle_t) return sync_handle_t; end package; """ ) @@ -472,11 +489,11 @@ def test_create_vhdl_testbench_template_references(self): vc_path = self.make_file("vc2.vhd", vc_contents) template, _ = VerificationComponent.create_vhdl_testbench_template( - "vc_lib", vc_path, self.vci_path + "vc_lib", "vc_lib", vc_path, self.vci_path ) template = VHDLDesignFile.parse(template) refs = template.references - self.assertEqual(len(refs), 13) + self.assertEqual(len(refs), 14) self.assertIn(VHDLReference("library", "vunit_lib"), refs) self.assertIn(VHDLReference("library", "vc_lib"), refs) self.assertIn(VHDLReference("library", "a_lib"), refs) @@ -485,6 +502,7 @@ def test_create_vhdl_testbench_template_references(self): self.assertIn(VHDLReference("package", "vc_lib", "vc_pkg", "all"), refs) self.assertIn(VHDLReference("package", "a_lib", "x", "y"), refs) self.assertIn(VHDLReference("package", "vunit_lib", "sync_pkg", "all"), refs) + self.assertIn(VHDLReference("package", "vunit_lib", "vc_pkg", "all"), refs) self.assertIn(VHDLReference("context", "vc_lib", "spam"), refs) self.assertIn(VHDLReference("context", "a_lib", "eggs"), refs) self.assertIn(VHDLReference("context", "vunit_lib", "vunit_context"), refs) @@ -510,7 +528,7 @@ def test_template_with_wrong_name(self): template_path = self.make_file("template.vhd", template_contents) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") vc = VerificationComponent.find(self.vc_lib, "vc", vci) self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) @@ -532,7 +550,7 @@ def test_template_missing_contructor(self): template_path = self.make_file("template.vhd", template_contents) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") vc = VerificationComponent.find(self.vc_lib, "vc", vci) self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) @@ -555,7 +573,7 @@ def test_template_missing_runner_cfg(self): template_path = self.make_file("template.vhd", template_contents) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") vc = VerificationComponent.find(self.vc_lib, "vc", vci) self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) @@ -578,7 +596,7 @@ def test_template_missing_test_runner(self): template_path = self.make_file("template.vhd", template_contents) - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") vc = VerificationComponent.find(self.vc_lib, "vc", vci) self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) @@ -667,7 +685,9 @@ def test_creating_template_with_specified_vc_lib(self): [ "compliance_test.py", "create-vc", - "-l", + "--vc-lib-name", + "my_vc_lib", + "--vci-lib-name", "my_vc_lib", self.vc_path, self.vci_path, @@ -688,7 +708,7 @@ def test_creating_template_with_specified_vc_lib(self): def test_adding_vhdl_testbench(self): vc_test_lib = self.ui.add_library("vc_test_lib") - vci = VerificationComponentInterface.find(self.vc_lib, "vc_pkg", "vc_handle_t") + vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") vc = VerificationComponent.find(self.vc_lib, "vc", vci) vc.add_vhdl_testbench(vc_test_lib, str(self.tmp_dir / "compliance_test")) diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index c62704b75..93032e740 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -18,7 +18,7 @@ def _create_vc_template(args): """Creates VC testbench template from args.""" template_code, vc_name = VerificationComponent.create_vhdl_testbench_template( - args.vc_lib_name, args.vc_path, args.vci_path + args.vc_lib_name, args.vci_lib_name, args.vc_path, args.vci_path ) if not template_code or not vc_name: sys.exit(1) @@ -46,13 +46,13 @@ def _create_vci_template(args): template_code, vci_name, ) = VerificationComponentInterface.create_vhdl_testbench_template( - args.vc_lib_name, args.vci_path, args.vc_handle_t + args.vci_lib_name, args.vci_path, args.vc_handle_t ) if not template_code or not vci_name: sys.exit(1) if not args.output_path: - output_dir = args.vci_path.parent / ".vc" / vci_name + output_dir = args.vc_path.parent / ".vc" / vci_name if not output_dir.exists(): output_dir.mkdir(parents=True) @@ -60,7 +60,7 @@ def _create_vci_template(args): elif args.output_path.is_dir(): output_dir = args.output_path / vci_name if not output_dir.exists(): - output_dir.mkdir(parents=True) + output_dir.exists(parents=True) output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) else: output_path = args.output_path @@ -79,9 +79,13 @@ def create_vc_parser(subparsers): "create-vc", help="Creates a VC compliance test template" ) parser.add_argument( - "-l", "--vc-lib-name", - help="Name of library hosting the VC and the VCI (default: vc_lib)", + help="Name of library hosting the VC (default: vc_lib)", + default="vc_lib", + ) + parser.add_argument( + "--vci-lib-name", + help="Name of library hosting the VCI (default: vc_lib)", default="vc_lib", ) parser.add_argument( @@ -102,9 +106,8 @@ def create_vci_parser(subparsers): "create-vci", help="Creates a VCI compliance test template" ) parser.add_argument( - "-l", - "--vc-lib-name", - help="Name of library hosting the VC and the VCI (default: vc_lib)", + "--vci-lib-name", + help="Name of library hosting the VCI (default: vc_lib)", default="vc_lib", ) parser.add_argument( diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index ef5bc0393..9996f00d7 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -99,11 +99,12 @@ def validate(vc_path): return vc_code @staticmethod - def create_vhdl_testbench_template(vc_lib_name, vc_path, vci_path): + def create_vhdl_testbench_template(vc_lib_name, vci_lib_name, vc_path, vci_path): """ Creates a template for a VC compliance testbench. - :param vc_lib_name: Name of the library containing the verification component and its interface. + :param vc_lib_name: Name of the library containing the verification component. + :param vci_lib_name: Name of the library containing the verification component interface. :param vc_path: Path to the file containing the verification component entity. :param vci_path: Path to the file containing the verification component interface package. @@ -209,8 +210,9 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): initial_package_refs = set( [ + "vunit_lib.vc_pkg.all", "vunit_lib.sync_pkg.all", - "%s.%s.all" % (vc_lib_name, vci_code.packages[0].identifier), + "%s.%s.all" % (vci_lib_name, vci_code.packages[0].identifier), ] ) context_items = create_context_items( @@ -385,6 +387,7 @@ def update_generics(code): else: template_code, _ = self.create_vhdl_testbench_template( self.vc_facade.library, + self.vci.vci_facade.library, self.vc_facade.source_file.name, self.vci.vci_facade.source_file.name, ) diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index bbdc54645..7745051ff 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -57,10 +57,10 @@ class VerificationComponentInterface: """Represents a Verification Component Interface (VCI).""" @classmethod - def find(cls, vc_lib, vci_name, vc_handle_t): + def find(cls, vci_lib, vci_name, vc_handle_t): """Finds the specified VCI if present. - :param vc_lib: Library object containing the VCI. + :param vci_lib: Library object containing the VCI. :param vci_name: Name of VCI package. :param vc_handle_t: Name of VC handle type. @@ -68,7 +68,7 @@ def find(cls, vc_lib, vci_name, vc_handle_t): """ try: - vci_facade = vc_lib.package(vci_name) + vci_facade = vci_lib.package(vci_name) except KeyError: LOGGER.error("Failed to find VCI %s", vci_name) sys.exit(1) @@ -91,6 +91,10 @@ def validate(cls, vci_path, vc_handle_t): LOGGER.error("%s must contain a single VCI package", vci_path) return None, None + if not cls._validate_as_sync(code, vc_handle_t): + LOGGER.error("%s must provide an as_sync function", vci_path) + return None, None + vc_constructor = cls._validate_constructor(code, vc_handle_t) if not cls._validate_handle(code, vc_handle_t): vc_constructor = None @@ -101,6 +105,30 @@ def __init__(self, vci_facade, vc_constructor): self.vci_facade = vci_facade self.vc_constructor = vc_constructor + @staticmethod + def _validate_as_sync(code, vc_handle_t): + """Validates the existence and format of the as_sync function.""" + + for func in VHDLFunctionSpecification.find(code): + if not func.identifier.startswith("as_sync"): + continue + + if func.return_type_mark != "sync_handle_t": + continue + + if len(func.parameter_list) != 1: + continue + + if len(func.parameter_list[0].identifier_list) != 1: + continue + + if func.parameter_list[0].subtype_indication.type_mark != vc_handle_t: + continue + + return func + + return None + @staticmethod def _validate_constructor(code, vc_handle_t): """Validates the existence and format of the verification component constructor.""" diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd index af9eab9df..956bb768e 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg-body.vhd @@ -30,6 +30,11 @@ package body stream_master_pkg is return master.p_std_cfg; end; + impure function as_sync(master : stream_master_t) return sync_handle_t is + begin + return get_actor(master.p_std_cfg); + end; + procedure push_stream(signal net : inout network_t; stream : stream_master_t; data : std_logic_vector; diff --git a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd index 0c28220ee..e1eb85fbc 100644 --- a/vunit/vhdl/verification_components/src/stream_master_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_master_pkg.vhd @@ -12,6 +12,7 @@ use ieee.std_logic_1164.all; context work.vunit_context; context work.com_context; use work.vc_pkg.all; +use work.sync_pkg.all; package stream_master_pkg is -- Stream master handle @@ -31,6 +32,7 @@ package stream_master_pkg is ) return stream_master_t; function get_std_cfg(master : stream_master_t) return std_cfg_t; + impure function as_sync(master : stream_master_t) return sync_handle_t; -- Push a data value to the stream procedure push_stream(signal net : inout network_t; diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd index 9af9ccf91..aa285c4aa 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg-body.vhd @@ -25,6 +25,11 @@ package body stream_slave_pkg is return slave.p_std_cfg; end; + impure function as_sync(slave : stream_slave_t) return sync_handle_t is + begin + return get_actor(slave.p_std_cfg); + end; + procedure pop_stream(signal net : inout network_t; stream : stream_slave_t; variable reference : inout stream_reference_t) is diff --git a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd index e27730422..443381e52 100644 --- a/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd +++ b/vunit/vhdl/verification_components/src/stream_slave_pkg.vhd @@ -13,6 +13,7 @@ context work.vunit_context; context work.com_context; use work.vc_pkg.all; +use work.sync_pkg.all; package stream_slave_pkg is -- Stream slave handle @@ -32,6 +33,7 @@ package stream_slave_pkg is ) return stream_slave_t; function get_std_cfg(slave : stream_slave_t) return std_cfg_t; + impure function as_sync(slave : stream_slave_t) return sync_handle_t; -- Reference to future stream result alias stream_reference_t is msg_t; From f8b7433e07616af3e2126acd8bb00435a2ebd8a5 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Fri, 22 Oct 2021 06:47:36 +0200 Subject: [PATCH 16/21] Formatted according to latest black --- tests/acceptance/artificial/vhdl/run.py | 33 ++----- tests/unit/test_compliance_test.py | 93 +++++-------------- tests/unit/test_vhdl_parser.py | 49 +++------- vunit/vc/compliance_test.py | 33 ++----- vunit/vc/verification_component.py | 97 +++++--------------- vunit/vc/verification_component_interface.py | 63 +++---------- vunit/vhdl/verification_components/run.py | 77 ++++------------ vunit/vhdl_parser.py | 97 +++++--------------- 8 files changed, 128 insertions(+), 414 deletions(-) diff --git a/tests/acceptance/artificial/vhdl/run.py b/tests/acceptance/artificial/vhdl/run.py index 5c57c4777..1cdd5a920 100644 --- a/tests/acceptance/artificial/vhdl/run.py +++ b/tests/acceptance/artificial/vhdl/run.py @@ -71,9 +71,7 @@ def configure_tb_set_generic(ui): tb.set_generic("str_quote_val", 'a"b') str_long_num = 512 tb.set_generic("str_long_num", str_long_num) - tb.set_generic( - "str_long_val", "".join(["0123456789abcdef" for x in range(str_long_num)]) - ) + tb.set_generic("str_long_val", "".join(["0123456789abcdef" for x in range(str_long_num)])) def configure_tb_assert_stop_level(ui): @@ -81,10 +79,7 @@ def configure_tb_assert_stop_level(ui): for vhdl_assert_stop_level in ["warning", "error", "failure"]: for report_level in ["warning", "error", "failure"]: - test = tb.test( - "Report %s when VHDL assert stop level = %s" - % (report_level, vhdl_assert_stop_level) - ) + test = tb.test("Report %s when VHDL assert stop level = %s" % (report_level, vhdl_assert_stop_level)) test.set_sim_option("vhdl_assert_stop_level", vhdl_assert_stop_level) @@ -94,16 +89,12 @@ def configure_tb_assert_stop_level(ui): configure_tb_assert_stop_level(VU) LIB.entity("tb_no_generic_override").set_generic("g_val", False) LIB.entity("tb_ieee_warning").test("pass").set_sim_option("disable_ieee_warnings", True) -LIB.entity("tb_other_file_tests").scan_tests_from_file( - str(ROOT / "other_file_tests.vhd") -) +LIB.entity("tb_other_file_tests").scan_tests_from_file(str(ROOT / "other_file_tests.vhd")) TEST_LIB = VU.add_library("test_lib") VCI = VerificationComponentInterface.find(LIB, "vc_pkg", "vc_handle_t") -VerificationComponent.find(LIB, "vc", VCI).add_vhdl_testbench( - TEST_LIB, ROOT / "compliance_test" -) +VerificationComponent.find(LIB, "vc", VCI).add_vhdl_testbench(TEST_LIB, ROOT / "compliance_test") VCI = VerificationComponentInterface.find(LIB, "vc_pkg_with_template", "vc_handle_t") VerificationComponent.find(LIB, "vc_with_template", VCI).add_vhdl_testbench( @@ -113,9 +104,7 @@ def configure_tb_assert_stop_level(ui): ) -vci = VerificationComponentInterface.find( - LIB, "vc_not_supporting_sync_pkg", "vc_not_supporting_sync_handle_t" -) +vci = VerificationComponentInterface.find(LIB, "vc_not_supporting_sync_pkg", "vc_not_supporting_sync_handle_t") VerificationComponent.find(LIB, "vc_not_supporting_sync", vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -124,9 +113,7 @@ def configure_tb_assert_stop_level(ui): vci = VerificationComponentInterface.find( LIB, "vc_not_supporting_custom_actor_pkg", "vc_not_supporting_custom_actor_handle_t" ) -VerificationComponent.find( - LIB, "vc_not_supporting_custom_actor", vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "vc_not_supporting_custom_actor", vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) @@ -136,9 +123,7 @@ def configure_tb_assert_stop_level(ui): "vc_not_supporting_custom_logger_pkg", "vc_not_supporting_custom_logger_handle_t", ) -VerificationComponent.find( - LIB, "vc_not_supporting_custom_logger", vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "vc_not_supporting_custom_logger", vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) @@ -148,9 +133,7 @@ def configure_tb_assert_stop_level(ui): "vc_not_supporting_unexpected_msg_handling_pkg", "vc_not_supporting_unexpected_msg_handling_handle_t", ) -VerificationComponent.find( - LIB, "vc_not_supporting_unexpected_msg_handling", vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "vc_not_supporting_unexpected_msg_handling", vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) diff --git a/tests/unit/test_compliance_test.py b/tests/unit/test_compliance_test.py index 04a23a12d..041a8d553 100644 --- a/tests/unit/test_compliance_test.py +++ b/tests/unit/test_compliance_test.py @@ -95,9 +95,7 @@ def make_file(self, file_name, contents, directory=None): @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_not_finding_vc(self, error_mock): vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "other_vc", vci - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "other_vc", vci) error_mock.assert_called_once_with("Failed to find VC %s", "other_vc") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") @@ -124,20 +122,12 @@ def test_failing_on_multiple_entities(self, error_mock): """ self.vc_lib.add_source_file(self.make_file("vc1_2.vhd", vc_contents)) vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci - ) - error_mock.assert_called_once_with( - "%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd" - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci) + error_mock.assert_called_once_with("%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd") vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci - ) - error_mock.assert_called_with( - "%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd" - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci) + error_mock.assert_called_with("%s must contain a single VC entity", self.tmp_dir / "vc1_2.vhd") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_failing_on_multiple_package(self, error_mock): @@ -156,9 +146,7 @@ def test_failing_on_multiple_package(self, error_mock): "vc_pkg1", "vc_handle_t", ) - error_mock.assert_called_once_with( - "%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd" - ) + error_mock.assert_called_once_with("%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd") self.assertRaises( SystemExit, VerificationComponentInterface.find, @@ -166,9 +154,7 @@ def test_failing_on_multiple_package(self, error_mock): "vc_pkg2", "vc_handle_t", ) - error_mock.assert_called_with( - "%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd" - ) + error_mock.assert_called_with("%s must contain a single VCI package", self.tmp_dir / "vci1_2.vhd") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_evaluating_vc_generics(self, error_mock): @@ -178,9 +164,7 @@ def test_evaluating_vc_generics(self, error_mock): """ self.vc_lib.add_source_file(self.make_file("vc1.vhd", vc1_contents)) vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "vc1", vci) error_mock.assert_called_once_with("%s must have a single generic", "vc1") vc2_contents = """ @@ -190,9 +174,7 @@ def test_evaluating_vc_generics(self, error_mock): """ self.vc_lib.add_source_file(self.make_file("vc2.vhd", vc2_contents)) vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "vc2", vci) error_mock.assert_called_with("%s must have a single generic", "vc2") vc3_contents = """ @@ -202,9 +184,7 @@ def test_evaluating_vc_generics(self, error_mock): """ self.vc_lib.add_source_file(self.make_file("vc3.vhd", vc3_contents)) vci = VerificationComponentInterface.find(self.vci_lib, "vc_pkg", "vc_handle_t") - self.assertRaises( - SystemExit, VerificationComponent.find, self.vc_lib, "vc3", vci - ) + self.assertRaises(SystemExit, VerificationComponent.find, self.vc_lib, "vc3", vci) error_mock.assert_called_with("%s must have a single generic", "vc3") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") @@ -228,9 +208,7 @@ def test_failing_with_no_constructor(self, error_mock): "other_vc_pkg", "vc_handle_t", ) - error_mock.assert_called_once_with( - "Failed to find a constructor function for vc_handle_t starting with new_" - ) + error_mock.assert_called_once_with("Failed to find a constructor function for vc_handle_t starting with new_") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_failing_with_wrong_constructor_return_type(self, error_mock): @@ -272,9 +250,7 @@ def test_failing_on_incorrect_constructor_parameters(self, error_mock): "invalid_default_value", ] - for iteration, (invalid_parameter, invalid_reason) in enumerate( - product(parameters, reasons_for_failure) - ): + for iteration, (invalid_parameter, invalid_reason) in enumerate(product(parameters, reasons_for_failure)): if (invalid_parameter in ["unexpected_msg_type_policy", "logger"]) and ( invalid_reason == "invalid_default_value" ): @@ -317,9 +293,7 @@ def test_failing_on_incorrect_constructor_parameters(self, error_mock): end package; """ ) - self.vc_lib.add_source_file( - self.make_file("other_vci_%d.vhd" % iteration, vci_contents) - ) + self.vc_lib.add_source_file(self.make_file("other_vci_%d.vhd" % iteration, vci_contents)) if invalid_reason == "missing_parameter": error_msg = ( @@ -334,8 +308,7 @@ def test_failing_on_incorrect_constructor_parameters(self, error_mock): elif invalid_reason == "invalid_default_value": error_msg = ( "Found constructor function new_vc for vc_handle_t but null_%s is the only allowed " - "default value for the %s parameter" - % (invalid_parameter, invalid_parameter) + "default value for the %s parameter" % (invalid_parameter, invalid_parameter) ) self.assertRaises( @@ -375,9 +348,7 @@ def test_failing_on_non_private_handle_elements(self, error_mock): "other_vc_pkg", "vc_handle_t", ) - error_mock.assert_called_once_with( - "%s in %s doesn't start with p_", "foo", "vc_handle_t" - ) + error_mock.assert_called_once_with("%s in %s doesn't start with p_", "foo", "vc_handle_t") @mock.patch("vunit.vc.verification_component_interface.LOGGER.error") def test_failing_on_missing_handle_record(self, error_mock): @@ -452,9 +423,7 @@ def test_error_on_missing_default_value(self): end package; """ ) - self.vc_lib.add_source_file( - self.make_file("other_vci_%d.vhd" % iteration, vci_contents) - ) + self.vc_lib.add_source_file(self.make_file("other_vci_%d.vhd" % iteration, vci_contents)) with mock.patch.object(LOGGER, "error") as error_mock: self.assertRaises( @@ -488,9 +457,7 @@ def test_create_vhdl_testbench_template_references(self): """ vc_path = self.make_file("vc2.vhd", vc_contents) - template, _ = VerificationComponent.create_vhdl_testbench_template( - "vc_lib", "vc_lib", vc_path, self.vci_path - ) + template, _ = VerificationComponent.create_vhdl_testbench_template("vc_lib", "vc_lib", vc_path, self.vci_path) template = VHDLDesignFile.parse(template) refs = template.references self.assertEqual(len(refs), 14) @@ -601,16 +568,10 @@ def test_template_missing_test_runner(self): self.assertRaises(RuntimeError, vc.create_vhdl_testbench, template_path) def test_creating_template_without_output_path(self): - with mock.patch( - "sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path] - ): + with mock.patch("sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path]): main() - self.assertTrue( - ( - Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" - ).exists() - ) + self.assertTrue((Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd").exists()) def test_creating_template_with_output_dir(self): output_dir = self.tmp_dir / "template" @@ -664,13 +625,9 @@ def test_creating_template_with_invalid_output_path(self): self.assertRaises(IOError, main) def test_creating_template_with_default_vc_lib(self): - with mock.patch( - "sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path] - ): + with mock.patch("sys.argv", ["compliance_test.py", "create-vc", self.vc_path, self.vci_path]): main() - with ( - Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" - ).open() as fptr: + with (Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd").open() as fptr: self.assertIsNotNone( re.search( r"library\s+vc_lib\s*;", @@ -694,9 +651,7 @@ def test_creating_template_with_specified_vc_lib(self): ], ): main() - with ( - Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd" - ).open() as fptr: + with (Path(self.vc_path).parent / ".vc" / "tb_vc_compliance_template.vhd").open() as fptr: self.assertIsNotNone( re.search( r"library\s+my_vc_lib\s*;", @@ -713,9 +668,7 @@ def test_adding_vhdl_testbench(self): vc.add_vhdl_testbench(vc_test_lib, str(self.tmp_dir / "compliance_test")) - self.assertTrue( - (self.tmp_dir / "compliance_test" / "tb_vc_compliance.vhd").exists() - ) + self.assertTrue((self.tmp_dir / "compliance_test" / "tb_vc_compliance.vhd").exists()) self.assertRaises( RuntimeError, vc.add_vhdl_testbench, diff --git a/tests/unit/test_vhdl_parser.py b/tests/unit/test_vhdl_parser.py index 51caadb95..17be25b75 100644 --- a/tests/unit/test_vhdl_parser.py +++ b/tests/unit/test_vhdl_parser.py @@ -239,9 +239,7 @@ def test_parsing_entity_with_generics(self): self.assertEqual(generics[0].identifier_list, ["max_value"]) self.assertEqual(generics[0].init_value, "(2-19)*4") self.assertEqual(generics[0].mode, None) - self.assertEqual( - generics[0].subtype_indication.code, "integer range 2-2 to 2**10" - ) + self.assertEqual(generics[0].subtype_indication.code, "integer range 2-2 to 2**10") self.assertEqual(generics[0].subtype_indication.type_mark, "integer") # @TODO does not work # self.assertEqual(generics[0].subtypeIndication.constraint, "range 2-2 to 2**10") @@ -329,9 +327,7 @@ def test_parsing_entity_with_ports(self): self.assertEqual(ports[1].identifier_list, ["data"]) self.assertEqual(ports[1].init_value, None) self.assertEqual(ports[1].mode, "out") - self.assertEqual( - ports[1].subtype_indication.code, "std_logic_vector(11-1 downto 0)" - ) + self.assertEqual(ports[1].subtype_indication.code, "std_logic_vector(11-1 downto 0)") self.assertEqual(ports[1].subtype_indication.type_mark, "std_logic_vector") self.assertEqual(ports[1].subtype_indication.constraint, "(11-1 downto 0)") @@ -490,10 +486,7 @@ def test_that_array_type_declarations_are_found(self): type constrained_badgers_array_t is array ( -1 downto 0 ) of badger_t; type unconstrained_natural_array_t is array ( integer range <> ) of natural; """ - arrays = { - e.identifier: e.subtype_indication.type_mark - for e in VHDLArrayType.find(code) - } + arrays = {e.identifier: e.subtype_indication.type_mark for e in VHDLArrayType.find(code)} expect = { "constrained_integer_array_t": "integer", "unconstrained_fish_array_t": "fish_t", @@ -523,13 +516,9 @@ def test_that_record_type_declarations_are_found(self): self.assertIn("space_time_t", records) self.assertEqual(records["space_time_t"][0].identifier_list, ["x", "y", "z"]) - self.assertEqual( - records["space_time_t"][0].subtype_indication.type_mark, "real" - ) + self.assertEqual(records["space_time_t"][0].subtype_indication.type_mark, "real") self.assertEqual(records["space_time_t"][1].identifier_list, ["t"]) - self.assertEqual( - records["space_time_t"][1].subtype_indication.type_mark, "time" - ) + self.assertEqual(records["space_time_t"][1].subtype_indication.type_mark, "time") self.assertIn("complex_t", records) self.assertEqual(records["complex_t"][0].identifier_list, ["im", "re"]) @@ -537,12 +526,8 @@ def test_that_record_type_declarations_are_found(self): self.assertIn("foo", records) self.assertEqual(records["foo"][0].identifier_list, ["bar"]) - self.assertEqual( - records["foo"][0].subtype_indication.type_mark, "std_logic_vector" - ) - self.assertEqual( - records["foo"][0].subtype_indication.constraint, "(7 downto 0)" - ) + self.assertEqual(records["foo"][0].subtype_indication.type_mark, "std_logic_vector") + self.assertEqual(records["foo"][0].subtype_indication.constraint, "(7 downto 0)") self.assertTrue(records["foo"][0].subtype_indication.array_type) def test_parsing_interface_element(self): @@ -560,27 +545,21 @@ def test_parsing_interface_element(self): self.assertEqual(element.mode, "in") self.assertEqual(element.init_value, None) - element = VHDLInterfaceElement.parse( - "a : in bit", default_entity_class="constant" - ) + element = VHDLInterfaceElement.parse("a : in bit", default_entity_class="constant") self.assertEqual(element.identifier_list, ["a"]) self.assertEqual(element.subtype_indication.type_mark, "bit") self.assertEqual(element.entity_class, "constant") self.assertEqual(element.mode, "in") self.assertEqual(element.init_value, None) - element = VHDLInterfaceElement.parse( - "signal a : in bit", default_entity_class="constant" - ) + element = VHDLInterfaceElement.parse("signal a : in bit", default_entity_class="constant") self.assertEqual(element.identifier_list, ["a"]) self.assertEqual(element.subtype_indication.type_mark, "bit") self.assertEqual(element.entity_class, "signal") self.assertEqual(element.mode, "in") self.assertEqual(element.init_value, None) - element = VHDLInterfaceElement.parse( - "signal a : in bit := '1'", default_entity_class="constant" - ) + element = VHDLInterfaceElement.parse("signal a : in bit := '1'", default_entity_class="constant") self.assertEqual(element.identifier_list, ["a"]) self.assertEqual(element.subtype_indication.type_mark, "bit") self.assertEqual(element.entity_class, "signal") @@ -705,13 +684,9 @@ def _create_entity(): """ Helper function to create a VHDLEntity """ - data_width = VHDLInterfaceElement( - "constant", "data_width", VHDLSubtypeIndication.parse("natural := 16") - ) + data_width = VHDLInterfaceElement("constant", "data_width", VHDLSubtypeIndication.parse("natural := 16")) - clk = VHDLInterfaceElement( - "signal", "clk", VHDLSubtypeIndication.parse("std_logic"), "in" - ) + clk = VHDLInterfaceElement("signal", "clk", VHDLSubtypeIndication.parse("std_logic"), "in") data = VHDLInterfaceElement( "signal" "data", VHDLSubtypeIndication.parse("std_logic_vector(data_width-1 downto 0)"), diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index 93032e740..932b06f65 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -35,17 +35,12 @@ def _create_vc_template(args): output_path = args.output_path output_path.write_text(template_code) - print( - "Open %s and read the TODOs to complete the template." % output_path.resolve() - ) + print("Open %s and read the TODOs to complete the template." % output_path.resolve()) def _create_vci_template(args): """Creates VCI testbench template from args.""" - ( - template_code, - vci_name, - ) = VerificationComponentInterface.create_vhdl_testbench_template( + (template_code, vci_name,) = VerificationComponentInterface.create_vhdl_testbench_template( args.vci_lib_name, args.vci_path, args.vc_handle_t ) if not template_code or not vci_name: @@ -66,18 +61,14 @@ def _create_vci_template(args): output_path = args.output_path output_path.write_text(template_code) - print( - "Open %s and read the TODOs to complete the template." % output_path.resolve() - ) + print("Open %s and read the TODOs to complete the template." % output_path.resolve()) def main(): """Parses the command line arguments and acts accordingly.""" def create_vc_parser(subparsers): - parser = subparsers.add_parser( - "create-vc", help="Creates a VC compliance test template" - ) + parser = subparsers.add_parser("create-vc", help="Creates a VC compliance test template") parser.add_argument( "--vc-lib-name", help="Name of library hosting the VC (default: vc_lib)", @@ -94,17 +85,11 @@ def create_vc_parser(subparsers): type=Path, help="Path to the template (default: ./compliance_test/tb__compliance_template.vhd)", ) - parser.add_argument( - "vc_path", type=Path, help="Path to file containing the VC entity" - ) - parser.add_argument( - "vci_path", type=Path, help="Path to file containing the VCI package" - ) + parser.add_argument("vc_path", type=Path, help="Path to file containing the VC entity") + parser.add_argument("vci_path", type=Path, help="Path to file containing the VCI package") def create_vci_parser(subparsers): - parser = subparsers.add_parser( - "create-vci", help="Creates a VCI compliance test template" - ) + parser = subparsers.add_parser("create-vci", help="Creates a VCI compliance test template") parser.add_argument( "--vci-lib-name", help="Name of library hosting the VCI (default: vc_lib)", @@ -116,9 +101,7 @@ def create_vci_parser(subparsers): type=Path, help="Path to the template (default: ./compliance_test/tb__compliance_template.vhd)", ) - parser.add_argument( - "vci_path", type=Path, help="Path to file containing the VCI package" - ) + parser.add_argument("vci_path", type=Path, help="Path to file containing the VCI package") parser.add_argument("vc_handle_t", help="VC handle type") parser = argparse.ArgumentParser(description="Compliance test tool") diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index 9996f00d7..8ecd06d29 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -89,10 +89,7 @@ def validate(vc_path): vc_entity = vc_code.entities[0] - if not ( - (len(vc_entity.generics) == 1) - and (len(vc_entity.generics[0].identifier_list) == 1) - ): + if not ((len(vc_entity.generics) == 1) and (len(vc_entity.generics[0].identifier_list) == 1)): LOGGER.error("%s must have a single generic", vc_entity.identifier) return None @@ -149,9 +146,7 @@ def create_constructor(vc_entity, vc_handle_t, vc_constructor): def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): signal_declarations = ( - " -- TODO: Constrain any unconstrained signal connecting to the DUT.\n" - if vc_entity.ports - else "" + " -- TODO: Constrain any unconstrained signal connecting to the DUT.\n" if vc_entity.ports else "" ) port_mappings = "" for port in vc_entity.ports: @@ -197,9 +192,7 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): vc_code = VerificationComponent.validate(vc_path) vc_entity = vc_code.entities[0] vc_handle_t = vc_entity.generics[0].subtype_indication.type_mark - vci_code, vc_constructor = VerificationComponentInterface.validate( - vci_path, vc_handle_t - ) + vci_code, vc_constructor = VerificationComponentInterface.validate(vci_path, vc_handle_t) if (not vci_code) or (not vc_constructor): return None, None @@ -219,9 +212,7 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): vc_code, vc_lib_name, initial_library_names=set(["std", "work", "vunit_lib", vc_lib_name]), - initial_context_refs=set( - ["vunit_lib.vunit_context", "vunit_lib.com_context"] - ), + initial_context_refs=set(["vunit_lib.vunit_context", "vunit_lib.com_context"]), initial_package_refs=initial_package_refs, ) @@ -267,9 +258,7 @@ def update_architecture_declarations(code): ) parameter_start_re = re.compile(r"\s*\(", MULTILINE | IGNORECASE | DOTALL) - parameter_start = parameter_start_re.match( - code[constructor_call_start.end() :] - ) + parameter_start = parameter_start_re.match(code[constructor_call_start.end() :]) if parameter_start: closing_parenthesis_pos = find_closing_delimiter( @@ -292,23 +281,13 @@ def update_architecture_declarations(code): else: specified_parameters = "" - _constructor_call_end_re = re.compile( - r"\s*;", MULTILINE | IGNORECASE | DOTALL - ) + _constructor_call_end_re = re.compile(r"\s*;", MULTILINE | IGNORECASE | DOTALL) if parameter_start: - search_start = ( - constructor_call_start.end() - + parameter_start.end() - + closing_parenthesis_pos - ) - constructor_call_end_match = _constructor_call_end_re.match( - code[search_start:] - ) + search_start = constructor_call_start.end() + parameter_start.end() + closing_parenthesis_pos + constructor_call_end_match = _constructor_call_end_re.match(code[search_start:]) else: search_start = constructor_call_start.end() - constructor_call_end_match = _constructor_call_end_re.match( - code[search_start:] - ) + constructor_call_end_match = _constructor_call_end_re.match(code[search_start:]) if not constructor_call_end_match: raise RuntimeError( @@ -328,22 +307,12 @@ def update_architecture_declarations(code): vc_constructor_name=self.vci.vc_constructor.identifier, specified_parameters=specified_parameters, vc_handle_name=self.vc_entity.generics[0].identifier_list[0], - default_logger=default_values["logger"] - if default_values["logger"] - else 'get_logger("vc_logger")', - default_actor=default_values["actor"] - if default_values["actor"] - else 'new_actor("vc_actor")', - default_checker=default_values["checker"] - if default_values["checker"] - else 'new_checker("vc_checker")', + default_logger=default_values["logger"] if default_values["logger"] else 'get_logger("vc_logger")', + default_actor=default_values["actor"] if default_values["actor"] else 'new_actor("vc_actor")', + default_checker=default_values["checker"] if default_values["checker"] else 'new_checker("vc_checker")', ) - return ( - code[: constructor_call_start.start()] - + architecture_declarations - + code[constructor_call_end:] - ) + return code[: constructor_call_start.start()] + architecture_declarations + code[constructor_call_end:] def update_test_runner(code): _test_runner_re = re.compile( @@ -356,29 +325,18 @@ def update_test_runner(code): vc_handle_name=self.vc_entity.generics[0].identifier_list[0] ) - code, num_found_test_runners = subn( - _test_runner_re, new_test_runner, code, 1 - ) + code, num_found_test_runners = subn(_test_runner_re, new_test_runner, code, 1) if not num_found_test_runners: - raise RuntimeError( - "Failed to find test runner in template_path %s" % template_path - ) + raise RuntimeError("Failed to find test runner in template_path %s" % template_path) return code def update_generics(code): - _runner_cfg_re = re.compile( - r"\brunner_cfg\s*:\s*string", MULTILINE | IGNORECASE | DOTALL - ) + _runner_cfg_re = re.compile(r"\brunner_cfg\s*:\s*string", MULTILINE | IGNORECASE | DOTALL) - code, num_found_runner_cfg = subn( - _runner_cfg_re, GENERICS_TEMPLATE, code, 1 - ) + code, num_found_runner_cfg = subn(_runner_cfg_re, GENERICS_TEMPLATE, code, 1) if not num_found_runner_cfg: - raise RuntimeError( - "Failed to find runner_cfg generic in template_path %s" - % template_path - ) + raise RuntimeError("Failed to find runner_cfg generic in template_path %s" % template_path) return code @@ -396,14 +354,8 @@ def update_generics(code): template_code = template_code.lower() design_file = VHDLDesignFile.parse(template_code) - if ( - design_file.entities[0].identifier - != "tb_%s_compliance" % self.vc_facade.name - ): - raise RuntimeError( - "%s is not a template_path for %s" - % (template_path, self.vc_facade.name) - ) + if design_file.entities[0].identifier != "tb_%s_compliance" % self.vc_facade.name: + raise RuntimeError("%s is not a template_path for %s" % (template_path, self.vc_facade.name)) tb_code = update_architecture_declarations(template_code) tb_code = update_test_runner(tb_code) @@ -434,10 +386,7 @@ def add_vhdl_testbench(self, vc_test_lib, test_dir, template_path=None): try: vc_test_lib.test_bench("tb_%s_compliance" % self.vc_entity.identifier) - raise RuntimeError( - "tb_%s_compliance already exists in %s" - % (self.vc_entity.identifier, vc_test_lib.name) - ) + raise RuntimeError("tb_%s_compliance already exists in %s" % (self.vc_entity.identifier, vc_test_lib.name)) except KeyError: pass @@ -451,9 +400,7 @@ def add_vhdl_testbench(self, vc_test_lib, test_dir, template_path=None): tb_path.write_text(testbench_code) tb_file = vc_test_lib.add_source_file(str(tb_path)) - testbench = vc_test_lib.test_bench( - "tb_%s_compliance" % self.vc_entity.identifier - ) + testbench = vc_test_lib.test_bench("tb_%s_compliance" % self.vc_entity.identifier) test = testbench.test("Test that the actor can be customised") test.set_generic("use_custom_actor", True) diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index 7745051ff..ed31335b9 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -21,9 +21,7 @@ LOGGER = logging.getLogger(__name__) -def create_context_items( - code, lib_name, initial_library_names, initial_context_refs, initial_package_refs -): +def create_context_items(code, lib_name, initial_library_names, initial_context_refs, initial_package_refs): """Creates a VHDL snippet with context items found in the provided code and the initial_ arguments.""" for ref in code.references: if ref.is_package_reference() or ref.is_context_reference(): @@ -35,9 +33,7 @@ def create_context_items( initial_context_refs.add("%s.%s" % (library_name, ref.design_unit_name)) if ref.is_package_reference(): - initial_package_refs.add( - "%s.%s.%s" % (library_name, ref.design_unit_name, ref.name_within) - ) + initial_package_refs.add("%s.%s.%s" % (library_name, ref.design_unit_name, ref.name_within)) context_items = "" for library in sorted(initial_library_names): @@ -141,9 +137,7 @@ def create_messages(required_parameter_types, expected_default_value): for parameter_name, parameter_type in required_parameter_types.items(): messages.append( - "Found constructor function %s for %s but the {} parameter is missing".format( - parameter_name - ) + "Found constructor function %s for %s but the {} parameter is missing".format(parameter_name) ) messages.append( "Found constructor function %s for %s but the {} parameter is not of type {}".format( @@ -151,15 +145,11 @@ def create_messages(required_parameter_types, expected_default_value): ) ) messages.append( - "Found constructor function %s for %s but {} is lacking a default value".format( - parameter_name - ) + "Found constructor function %s for %s but {} is lacking a default value".format(parameter_name) ) messages.append( "Found constructor function %s for %s but {} is the only allowed default " - "value for the {} parameter".format( - expected_default_value[parameter_name], parameter_name - ) + "value for the {} parameter".format(expected_default_value[parameter_name], parameter_name) ) return messages @@ -213,10 +203,7 @@ def log_error_message(function_score, messages): break function_score[func.identifier] += 1 - if ( - parameters[parameter_name].subtype_indication.type_mark - != parameter_type - ): + if parameters[parameter_name].subtype_indication.type_mark != parameter_type: break function_score[func.identifier] += 1 @@ -225,8 +212,7 @@ def log_error_message(function_score, messages): function_score[func.identifier] += 1 if expected_default_value[parameter_name] and ( - parameters[parameter_name].init_value - != expected_default_value[parameter_name] + parameters[parameter_name].init_value != expected_default_value[parameter_name] ): break function_score[func.identifier] += 1 @@ -280,9 +266,7 @@ def create_vhdl_testbench_template(cls, vci_lib_name, vci_path, vc_handle_t): vci_code, vci_lib_name, initial_library_names=set(["std", "work", "vunit_lib", vci_lib_name]), - initial_context_refs=set( - ["vunit_lib.vunit_context", "vunit_lib.com_context"] - ), + initial_context_refs=set(["vunit_lib.vunit_context", "vunit_lib.com_context"]), initial_package_refs=set( [ "vunit_lib.vc_pkg.all", @@ -291,11 +275,7 @@ def create_vhdl_testbench_template(cls, vci_lib_name, vci_path, vc_handle_t): ), ) - unspecified_parameters = [ - parameter - for parameter in vc_constructor.parameter_list - if not parameter.init_value - ] + unspecified_parameters = [parameter for parameter in vc_constructor.parameter_list if not parameter.init_value] if unspecified_parameters: constant_declarations = "" for parameter in unspecified_parameters: @@ -345,18 +325,14 @@ def create_vhdl_testbench(self, template_path=None): with template_path.open() as fptr: template_code = fptr.read() - test_runner_body_pattern = re.compile( - r"\s+-- DO NOT modify this line and the lines below." - ) + test_runner_body_pattern = re.compile(r"\s+-- DO NOT modify this line and the lines below.") match = test_runner_body_pattern.search(template_code) if not match: LOGGER.error("Failed to find body of test_runner in template code.") return None unspecified_parameters = [ - parameter - for parameter in self.vc_constructor.parameter_list - if not parameter.init_value + parameter for parameter in self.vc_constructor.parameter_list if not parameter.init_value ] def create_handle_assignment( @@ -398,9 +374,7 @@ def create_handle_assignment( return handle_assignment - testbench_code = template_code[ - : match.start() - ] + TB_EPILOGUE_TEMPLATE.substitute( + testbench_code = template_code[: match.start()] + TB_EPILOGUE_TEMPLATE.substitute( vc_handle_t=self.vc_constructor.return_type_mark, vc_constructor_name=self.vc_constructor.identifier, handle1=create_handle_assignment( @@ -478,23 +452,16 @@ def add_vhdl_testbench(self, vci_test_lib, test_dir, template_path=None): try: vci_test_lib.test_bench( - "tb_%s_%s_compliance" - % (self.vci_facade.name, self.vc_constructor.return_type_mark) - ) - raise RuntimeError( - "tb_%s_compliance already exists in %s" - % (self.vci_facade.name, vci_test_lib.name) + "tb_%s_%s_compliance" % (self.vci_facade.name, self.vc_constructor.return_type_mark) ) + raise RuntimeError("tb_%s_compliance already exists in %s" % (self.vci_facade.name, vci_test_lib.name)) except KeyError: pass if not test_dir.exists(): test_dir.mkdir(parents=True) - tb_path = test_dir / ( - "tb_%s_%s_compliance.vhd" - % (self.vci_facade.name, self.vc_constructor.return_type_mark) - ) + tb_path = test_dir / ("tb_%s_%s_compliance.vhd" % (self.vci_facade.name, self.vc_constructor.return_type_mark)) testbench_code = self.create_vhdl_testbench(template_path) if not testbench_code: return None diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 7c7b5681f..ad8df47a2 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -177,9 +177,7 @@ def gen_avalon_master_tests(obj, *args): TEST_LIB = UI.add_library("test_lib") -bus_master_vci = VerificationComponentInterface.find( - LIB, "bus_master_pkg", "bus_master_t" -) +bus_master_vci = VerificationComponentInterface.find(LIB, "bus_master_pkg", "bus_master_t") bus_master_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -209,49 +207,37 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_axi_write_slave_compliance_template.vhd", ) -axi_stream_master_vci = VerificationComponentInterface.find( - LIB, "axi_stream_pkg", "axi_stream_master_t" -) +axi_stream_master_vci = VerificationComponentInterface.find(LIB, "axi_stream_pkg", "axi_stream_master_t") axi_stream_master_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_master_t_compliance_template.vhd", ) -VerificationComponent.find( - LIB, "axi_stream_master", axi_stream_master_vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "axi_stream_master", axi_stream_master_vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "tb_axi_stream_master_compliance_template.vhd", ) -axi_stream_slave_vci = VerificationComponentInterface.find( - LIB, "axi_stream_pkg", "axi_stream_slave_t" -) +axi_stream_slave_vci = VerificationComponentInterface.find(LIB, "axi_stream_pkg", "axi_stream_slave_t") axi_stream_slave_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_slave_t_compliance_template.vhd", ) -VerificationComponent.find( - LIB, "axi_stream_slave", axi_stream_slave_vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "axi_stream_slave", axi_stream_slave_vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "tb_axi_stream_slave_compliance_template.vhd", ) -axi_stream_monitor_vci = VerificationComponentInterface.find( - LIB, "axi_stream_pkg", "axi_stream_monitor_t" -) +axi_stream_monitor_vci = VerificationComponentInterface.find(LIB, "axi_stream_pkg", "axi_stream_monitor_t") axi_stream_monitor_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_monitor_t_compliance_template.vhd", ) -VerificationComponent.find( - LIB, "axi_stream_monitor", axi_stream_monitor_vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "axi_stream_monitor", axi_stream_monitor_vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "tb_axi_stream_monitor_compliance_template.vhd", @@ -263,14 +249,9 @@ def gen_avalon_master_tests(obj, *args): axi_stream_protocol_checker_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", - ROOT - / ".vc" - / "axi_stream_pkg" - / "tb_axi_stream_protocol_checker_t_compliance_template.vhd", + ROOT / ".vc" / "axi_stream_pkg" / "tb_axi_stream_protocol_checker_t_compliance_template.vhd", ) -VerificationComponent.find( - LIB, "axi_stream_protocol_checker", axi_stream_protocol_checker_vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "axi_stream_protocol_checker", axi_stream_protocol_checker_vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "tb_axi_stream_protocol_checker_compliance_template.vhd", @@ -296,24 +277,18 @@ def gen_avalon_master_tests(obj, *args): ROOT / "compliance_test", ) -std_logic_checker_vci = VerificationComponentInterface.find( - LIB, "signal_checker_pkg", "signal_checker_t" -) +std_logic_checker_vci = VerificationComponentInterface.find(LIB, "signal_checker_pkg", "signal_checker_t") std_logic_checker_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) -VerificationComponent.find( - LIB, "std_logic_checker", std_logic_checker_vci -).add_vhdl_testbench( +VerificationComponent.find(LIB, "std_logic_checker", std_logic_checker_vci).add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ROOT / ".vc" / "tb_std_logic_checker_compliance_template.vhd", ) -ram_master_vci = VerificationComponentInterface.find( - LIB, "ram_master_pkg", "ram_master_t" -) +ram_master_vci = VerificationComponentInterface.find(LIB, "ram_master_pkg", "ram_master_t") ram_master_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -325,23 +300,17 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_ram_master_compliance_template.vhd", ) -VerificationComponentInterface.find( - LIB, "stream_master_pkg", "stream_master_t" -).add_vhdl_testbench( +VerificationComponentInterface.find(LIB, "stream_master_pkg", "stream_master_t").add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) -VerificationComponentInterface.find( - LIB, "stream_slave_pkg", "stream_slave_t" -).add_vhdl_testbench( +VerificationComponentInterface.find(LIB, "stream_slave_pkg", "stream_slave_t").add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", ) -bus2memory_vci = VerificationComponentInterface.find( - LIB, "bus2memory_pkg", "bus2memory_t" -) +bus2memory_vci = VerificationComponentInterface.find(LIB, "bus2memory_pkg", "bus2memory_t") bus2memory_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -353,9 +322,7 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_bus2memory_compliance_template.vhd", ) -avalon_master_vci = VerificationComponentInterface.find( - LIB, "avalon_pkg", "avalon_master_t" -) +avalon_master_vci = VerificationComponentInterface.find(LIB, "avalon_pkg", "avalon_master_t") avalon_master_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -367,9 +334,7 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_avalon_master_compliance_template.vhd", ) -avalon_slave_vci = VerificationComponentInterface.find( - LIB, "avalon_pkg", "avalon_slave_t" -) +avalon_slave_vci = VerificationComponentInterface.find(LIB, "avalon_pkg", "avalon_slave_t") avalon_slave_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -381,9 +346,7 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_avalon_slave_compliance_template.vhd", ) -avalon_source_vci = VerificationComponentInterface.find( - LIB, "avalon_stream_pkg", "avalon_source_t" -) +avalon_source_vci = VerificationComponentInterface.find(LIB, "avalon_stream_pkg", "avalon_source_t") avalon_source_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", @@ -395,9 +358,7 @@ def gen_avalon_master_tests(obj, *args): ROOT / ".vc" / "tb_avalon_source_compliance_template.vhd", ) -avalon_sink_vci = VerificationComponentInterface.find( - LIB, "avalon_stream_pkg", "avalon_sink_t" -) +avalon_sink_vci = VerificationComponentInterface.find(LIB, "avalon_stream_pkg", "avalon_sink_t") avalon_sink_vci.add_vhdl_testbench( TEST_LIB, ROOT / "compliance_test", diff --git a/vunit/vhdl_parser.py b/vunit/vhdl_parser.py index b7ac04f32..17b0af866 100644 --- a/vunit/vhdl_parser.py +++ b/vunit/vhdl_parser.py @@ -63,9 +63,7 @@ def __init__( # pylint: disable=too-many-arguments self.package_bodies = [] if package_bodies is None else package_bodies self.architectures = [] if architectures is None else architectures self.contexts = [] if contexts is None else contexts - self.component_instantiations = ( - [] if component_instantiations is None else component_instantiations - ) + self.component_instantiations = [] if component_instantiations is None else component_instantiations self.configurations = [] if configurations is None else configurations self.references = [] if references is None else references @@ -246,9 +244,7 @@ def _find_normal_packages(cls, code): if match: yield cls.parse(sub_code[: match.end()]) - _package_instance_re = re.compile( - "^" + PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE - ) + _package_instance_re = re.compile("^" + PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE) @classmethod def _find_package_instances(cls, code): @@ -421,11 +417,7 @@ def _find_generic_clause(cls, code): match_semicolon = semicolon.match(code[match.end() + closing_pos :]) if match_semicolon: return cls._parse_generic_clause( - code[ - match.start() : match.end() - + closing_pos - + match_semicolon.end() - ] + code[match.start() : match.end() + closing_pos + match_semicolon.end()] ) return [] @@ -457,13 +449,7 @@ def _find_port_clause(cls, code): ) match_semicolon = semicolon.match(code[match.end() + closing_pos :]) if match_semicolon: - return cls._parse_port_clause( - code[ - match.start() : match.end() - + closing_pos - + match_semicolon.end() - ] - ) + return cls._parse_port_clause(code[match.start() : match.end() + closing_pos + match_semicolon.end()]) return [] @staticmethod @@ -508,9 +494,7 @@ def _split_not_in_par(string, sep): _package_generic_re = re.compile(r"\s*package\s+", re.MULTILINE | re.IGNORECASE) _type_generic_re = re.compile(r"\s*type\s+", re.MULTILINE | re.IGNORECASE) - _function_generic_re = re.compile( - r"\s*(impure\s+)?(function|procedure)\s+", re.MULTILINE | re.IGNORECASE - ) + _function_generic_re = re.compile(r"\s*(impure\s+)?(function|procedure)\s+", re.MULTILINE | re.IGNORECASE) @classmethod def _parse_generic_clause(cls, code): @@ -539,11 +523,7 @@ def _parse_generic_clause(cls, code): # Ignore function generics continue - generic_list.append( - VHDLInterfaceElement.parse( - interface_element, default_entity_class="constant" - ) - ) + generic_list.append(VHDLInterfaceElement.parse(interface_element, default_entity_class="constant")) return generic_list @@ -561,11 +541,7 @@ def _parse_port_clause(cls, code): port_list = [] # Add interface elements to the port list for interface_element in interface_elements: - port_list.append( - VHDLInterfaceElement.parse( - interface_element, default_entity_class="signal" - ) - ) + port_list.append(VHDLInterfaceElement.parse(interface_element, default_entity_class="signal")) return port_list @@ -685,9 +661,7 @@ def parse(cls, code, default_entity_class=None): # Extract the identifier_list identifier_list_string = interface_element_string.split(":")[0].strip() - identifier_list = [ - identifier.strip() for identifier in identifier_list_string.split(",") - ] + identifier_list = [identifier.strip() for identifier in identifier_list_string.split(",")] # Extract subtype indication and mode (if any) @@ -697,9 +671,7 @@ def parse(cls, code, default_entity_class=None): subtype_indication = VHDLSubtypeIndication.parse(mode_split[1]) else: mode = None - subtype_indication = VHDLSubtypeIndication.parse( - interface_element_string.split(":")[1].strip() - ) + subtype_indication = VHDLSubtypeIndication.parse(interface_element_string.split(":")[1].strip()) # Extract initial value init_value_split = interface_element_string.split(":=") @@ -804,16 +776,9 @@ def find(cls, code): for element in elements: if ":" in element: identifier_list_and_subtype_indication = element.split(":") - identifier_list = [ - i.strip() - for i in identifier_list_and_subtype_indication[0].split(",") - ] - subtype_indication = VHDLSubtypeIndication.parse( - identifier_list_and_subtype_indication[1].strip() - ) - parsed_elements.append( - VHDLInterfaceElement(None, identifier_list, subtype_indication) - ) + identifier_list = [i.strip() for i in identifier_list_and_subtype_indication[0].split(",")] + subtype_indication = VHDLSubtypeIndication.parse(identifier_list_and_subtype_indication[1].strip()) + parsed_elements.append(VHDLInterfaceElement(None, identifier_list, subtype_indication)) yield cls(identifier, parsed_elements) @@ -907,9 +872,7 @@ def find(cls, code): """Iterate over new instances of VHDLArrayType for all array types within the code""" for array_type in cls._array_declaration_re.finditer(code): identifier = array_type.group("id") - subtype_indication = VHDLSubtypeIndication.parse( - array_type.group("subtype_indication") - ) + subtype_indication = VHDLSubtypeIndication.parse(array_type.group("subtype_indication")) ranges = array_type.group("ranges") range1_str, range2_str = cls._split_ranges(ranges) range1 = cls._parse_range(range1_str) @@ -981,9 +944,7 @@ def find_closing_delimiter(start, end, code): if count == 0: return delimiter.end() - raise ValueError( - "Failed to find closing delimiter to " + start + " in " + code + "." - ) + raise ValueError("Failed to find closing delimiter to " + start + " in " + code + ".") class VHDLReference(object): @@ -1037,9 +998,7 @@ def _find_uses(cls, code): names_within = uses[2:] if len(uses) > 2 else (None,) for name_within in names_within: ref = cls( - reference_type="package" - if match.group("use_type") == "use" - else "context", + reference_type="package" if match.group("use_type") == "use" else "context", library=uses[0], design_unit=uses[1], name_within=name_within, @@ -1085,14 +1044,10 @@ def _find_configuration_references(cls, code): """ references = [] for match in cls._configuration_reference_re.finditer(code): - references.append( - cls("configuration", match.group("lib"), match.group("cfg")) - ) + references.append(cls("configuration", match.group("lib"), match.group("cfg"))) return references - _package_instance_re = re.compile( - PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE - ) + _package_instance_re = re.compile(PACKAGE_INSTANCE_PATTERN, re.MULTILINE | re.IGNORECASE) @classmethod def _find_package_instance_references(cls, code): @@ -1173,9 +1128,7 @@ def __eq__(self, other): ) def copy(self): - return VHDLReference( - self.reference_type, self.library, self.design_unit, self.name_within - ) + return VHDLReference(self.reference_type, self.library, self.design_unit, self.name_within) def is_entity_reference(self): return self.reference_type == "entity" @@ -1237,18 +1190,10 @@ def find(cls, code): parsed_parameter_list = [] if function_specification.group("parameter_list"): - for element in function_specification.group("parameter_list")[ - 1:-1 - ].split(";"): - parsed_parameter_list.append( - VHDLInterfaceElement.parse( - element, default_entity_class="constant" - ) - ) + for element in function_specification.group("parameter_list")[1:-1].split(";"): + parsed_parameter_list.append(VHDLInterfaceElement.parse(element, default_entity_class="constant")) - yield VHDLFunctionSpecification( - identifier, return_type_mark, parsed_parameter_list - ) + yield VHDLFunctionSpecification(identifier, return_type_mark, parsed_parameter_list) def _comment_repl(match): From 565ab6cd13309ef52e6997d46fa1f95d650d32ab Mon Sep 17 00:00:00 2001 From: umarcor Date: Thu, 21 Oct 2021 23:32:16 +0200 Subject: [PATCH 17/21] f-strings: vunit/vc/compliance_test.py --- vunit/vc/compliance_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vunit/vc/compliance_test.py b/vunit/vc/compliance_test.py index 932b06f65..f4052f2db 100644 --- a/vunit/vc/compliance_test.py +++ b/vunit/vc/compliance_test.py @@ -28,14 +28,14 @@ def _create_vc_template(args): if not output_dir.exists(): output_dir.mkdir(parents=True) - output_path = output_dir / ("tb_%s_compliance_template.vhd" % vc_name) + output_path = output_dir / (f"tb_{vc_name!s}_compliance_template.vhd") elif args.output_path.is_dir(): - output_path = args.output_path / ("tb_%s_compliance_template.vhd" % vc_name) + output_path = args.output_path / (f"tb_{vc_name!s}_compliance_template.vhd") else: output_path = args.output_path output_path.write_text(template_code) - print("Open %s and read the TODOs to complete the template." % output_path.resolve()) + print(f"Open {output_path.resolve()!s} and read the TODOs to complete the template.") def _create_vci_template(args): @@ -51,17 +51,17 @@ def _create_vci_template(args): if not output_dir.exists(): output_dir.mkdir(parents=True) - output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) + output_path = output_dir / (f"tb_{args.vc_handle_t!s}_compliance_template.vhd") elif args.output_path.is_dir(): output_dir = args.output_path / vci_name if not output_dir.exists(): output_dir.exists(parents=True) - output_path = output_dir / ("tb_%s_compliance_template.vhd" % args.vc_handle_t) + output_path = output_dir / (f"tb_{args.vc_handle_t!s}_compliance_template.vhd") else: output_path = args.output_path output_path.write_text(template_code) - print("Open %s and read the TODOs to complete the template." % output_path.resolve()) + print(f"Open {output_path.resolve()!s} and read the TODOs to complete the template.") def main(): From 802ebed5d17eedbaef8912410dde5a53b40e21e5 Mon Sep 17 00:00:00 2001 From: umarcor Date: Fri, 22 Oct 2021 02:13:22 +0200 Subject: [PATCH 18/21] f-strings: vunit/vc/verification_component.py --- vunit/vc/verification_component.py | 56 ++++++++++++------------------ 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index 8ecd06d29..19c0b77c4 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -139,7 +139,7 @@ def create_constructor(vc_entity, vc_handle_t, vc_constructor): "unexpected_msg_type_policy", ]: continue - constructor += " %s => ,\n" % parameter + constructor += f" {parameter!s} => ,\n" constructor = constructor[:-2] + "\n );\n" return constructor @@ -152,17 +152,14 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): for port in vc_entity.ports: if (port.mode != "out") and port.init_value: for identifier in port.identifier_list: - port_mappings += " %s => open,\n" % identifier + port_mappings += f" {identifier!s} => open,\n" else: signal_declarations += " signal %s : %s;\n" % ( ", ".join(port.identifier_list), port.subtype_indication, ) for identifier in port.identifier_list: - port_mappings += " %s => %s,\n" % ( - identifier, - identifier, - ) + port_mappings += f" {identifier!s} => {identifier!s},\n" vc_instantiation = """ -- DO NOT modify the VC instantiation. vc_inst: entity %s.%s @@ -201,19 +198,18 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): vc_instantiation, ) = create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name) - initial_package_refs = set( - [ - "vunit_lib.vc_pkg.all", - "vunit_lib.sync_pkg.all", - "%s.%s.all" % (vci_lib_name, vci_code.packages[0].identifier), - ] - ) context_items = create_context_items( vc_code, vc_lib_name, initial_library_names=set(["std", "work", "vunit_lib", vc_lib_name]), initial_context_refs=set(["vunit_lib.vunit_context", "vunit_lib.com_context"]), - initial_package_refs=initial_package_refs, + initial_package_refs=set( + [ + "vunit_lib.vc_pkg.all", + "vunit_lib.sync_pkg.all", + f"{vci_lib_name!s}.{vci_code.packages[0].identifier!s}.all", + ] + ), ) return ( @@ -241,20 +237,16 @@ def create_vhdl_testbench(self, template_path=None): template_path = Path(template_path).resolve() def update_architecture_declarations(code): + constant = rf"\bconstant\s+{self.vc_entity.generics[0].identifier_list[0]}\s*:\s*{self.vc_handle_t}\s*" _constructor_call_start_re = re.compile( - r"\bconstant\s+{vc_handle_name}\s*:\s*{vc_handle_t}\s*:=\s*{vc_constructor_name}".format( - vc_handle_name=self.vc_entity.generics[0].identifier_list[0], - vc_handle_t=self.vc_handle_t, - vc_constructor_name=self.vci.vc_constructor.identifier, - ), + rf"{constant!s}:=\s*{self.vci.vc_constructor.identifier}", MULTILINE | IGNORECASE | DOTALL, ) constructor_call_start = _constructor_call_start_re.search(code) if not constructor_call_start: raise RuntimeError( - "Failed to find call to %s in template_path %s" - % (self.vci.vc_constructor.identifier, template_path) + f"Failed to find call to {self.vci.vc_constructor.identifier!s} in template_path {template_path!s}" ) parameter_start_re = re.compile(r"\s*\(", MULTILINE | IGNORECASE | DOTALL) @@ -290,10 +282,8 @@ def update_architecture_declarations(code): constructor_call_end_match = _constructor_call_end_re.match(code[search_start:]) if not constructor_call_end_match: - raise RuntimeError( - "Missing trailing semicolon for %s in template_path %s" - % (self.vci.vc_constructor.identifier, template_path) - ) + identifier = self.vci.vc_constructor.identifier + raise RuntimeError(f"Missing trailing semicolon for {identifier!s} in template_path {template_path!s}") constructor_call_end = search_start + constructor_call_end_match.end() @@ -327,7 +317,7 @@ def update_test_runner(code): code, num_found_test_runners = subn(_test_runner_re, new_test_runner, code, 1) if not num_found_test_runners: - raise RuntimeError("Failed to find test runner in template_path %s" % template_path) + raise RuntimeError(f"Failed to find test runner in template_path {template_path!s}") return code @@ -336,7 +326,7 @@ def update_generics(code): code, num_found_runner_cfg = subn(_runner_cfg_re, GENERICS_TEMPLATE, code, 1) if not num_found_runner_cfg: - raise RuntimeError("Failed to find runner_cfg generic in template_path %s" % template_path) + raise RuntimeError(f"Failed to find runner_cfg generic in template_path {template_path!s}") return code @@ -354,8 +344,8 @@ def update_generics(code): template_code = template_code.lower() design_file = VHDLDesignFile.parse(template_code) - if design_file.entities[0].identifier != "tb_%s_compliance" % self.vc_facade.name: - raise RuntimeError("%s is not a template_path for %s" % (template_path, self.vc_facade.name)) + if design_file.entities[0].identifier != f"tb_{self.vc_facade.name!s}_compliance": + raise RuntimeError(f"{template_path!s} is not a template_path for {self.vc_facade.name!s}") tb_code = update_architecture_declarations(template_code) tb_code = update_test_runner(tb_code) @@ -385,22 +375,22 @@ def add_vhdl_testbench(self, vc_test_lib, test_dir, template_path=None): template_path = Path(template_path) if template_path is not None else None try: - vc_test_lib.test_bench("tb_%s_compliance" % self.vc_entity.identifier) - raise RuntimeError("tb_%s_compliance already exists in %s" % (self.vc_entity.identifier, vc_test_lib.name)) + vc_test_lib.test_bench(f"tb_{self.vc_entity.identifier!s}_compliance") + raise RuntimeError(f"tb_{self.vc_entity.identifier!s}_compliance already exists in {vc_test_lib.name!s}") except KeyError: pass if not test_dir.exists(): test_dir.mkdir(parents=True) - tb_path = test_dir / ("tb_%s_compliance.vhd" % self.vc_entity.identifier) + tb_path = test_dir / (f"tb_{self.vc_entity.identifier!s}_compliance.vhd") testbench_code = self.create_vhdl_testbench(template_path) if not testbench_code: return None tb_path.write_text(testbench_code) tb_file = vc_test_lib.add_source_file(str(tb_path)) - testbench = vc_test_lib.test_bench("tb_%s_compliance" % self.vc_entity.identifier) + testbench = vc_test_lib.test_bench(f"tb_{self.vc_entity.identifier!s}_compliance") test = testbench.test("Test that the actor can be customised") test.set_generic("use_custom_actor", True) From a32d9b9e5066ea8645f2d6a71c2b7df21e43d3fc Mon Sep 17 00:00:00 2001 From: umarcor Date: Fri, 22 Oct 2021 02:38:51 +0200 Subject: [PATCH 19/21] f-strings: vunit/vc/verification_component_interface.py --- vunit/vc/verification_component_interface.py | 77 ++++++++------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index ed31335b9..005d4e8f4 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -30,21 +30,21 @@ def create_context_items(code, lib_name, initial_library_names, initial_context_ library_name = ref.library_name if ref.library_name != "work" else lib_name if ref.is_context_reference(): - initial_context_refs.add("%s.%s" % (library_name, ref.design_unit_name)) + initial_context_refs.add(f"{library_name!s}.{ref.design_unit_name!s}") if ref.is_package_reference(): - initial_package_refs.add("%s.%s.%s" % (library_name, ref.design_unit_name, ref.name_within)) + initial_package_refs.add(f"{library_name!s}.{ref.design_unit_name!s}.{ref.name_within!s}") context_items = "" for library in sorted(initial_library_names): if library not in ["std", "work"]: - context_items += "library %s;\n" % library + context_items += f"library {library!s};\n" for context_ref in sorted(initial_context_refs): - context_items += "context %s;\n" % context_ref + context_items += f"context {context_ref!s};\n" for package_ref in sorted(initial_package_refs): - context_items += "use %s;\n" % package_ref + context_items += f"use {package_ref!s};\n" return context_items @@ -136,21 +136,18 @@ def create_messages(required_parameter_types, expected_default_value): ] for parameter_name, parameter_type in required_parameter_types.items(): - messages.append( - "Found constructor function %s for %s but the {} parameter is missing".format(parameter_name) - ) - messages.append( - "Found constructor function %s for %s but the {} parameter is not of type {}".format( - parameter_name, parameter_type - ) - ) - messages.append( - "Found constructor function %s for %s but {} is lacking a default value".format(parameter_name) - ) - messages.append( - "Found constructor function %s for %s but {} is the only allowed default " - "value for the {} parameter".format(expected_default_value[parameter_name], parameter_name) - ) + messages += [ + f"Found constructor function %s for %s but the {parameter_name!s} parameter is missing", + ( + f"Found constructor function %s for %s but the {parameter_name} " + f"parameter is not of type {parameter_type}" + ), + f"Found constructor function %s for %s but {parameter_name} is lacking a default value", + ( + f"Found constructor function %s for %s but {expected_default_value[parameter_name]} " + f"is the only allowed default value for the {parameter_name} parameter" + ), + ] return messages @@ -270,7 +267,7 @@ def create_vhdl_testbench_template(cls, vci_lib_name, vci_path, vc_handle_t): initial_package_refs=set( [ "vunit_lib.vc_pkg.all", - "%s.%s.all" % (vci_lib_name, vci_code.packages[0].identifier), + f"{vci_lib_name!s}.{vci_code.packages[0].identifier!s}.all", ] ), ) @@ -287,9 +284,8 @@ def create_vhdl_testbench_template(cls, vci_lib_name, vci_path, vc_handle_t): "unexpected_msg_type_policy", ]: continue - constant_declarations += " constant %s : %s := ;\n" % ( - identifier, - parameter.subtype_indication.type_mark, + constant_declarations += ( + f" constant {identifier!s} : {parameter.subtype_indication.type_mark!s} := ;\n" ) else: constant_declarations = "\n" @@ -342,12 +338,8 @@ def create_handle_assignment( checker=None, unexpected_msg_type_policy="fail", ): - - handle_assignment = " constant %s : %s := %s(\n" % ( - handle_name, - self.vc_constructor.return_type_mark, - self.vc_constructor.identifier, - ) + mark = self.vc_constructor.return_type_mark + handle_assignment = f" constant {handle_name!s} : {mark!s} := {self.vc_constructor.identifier!s}(\n" for parameter in unspecified_parameters: for identifier in parameter.identifier_list: if identifier in [ @@ -357,10 +349,7 @@ def create_handle_assignment( "unexpected_msg_type_policy", ]: continue - handle_assignment += " %s => %s,\n" % ( - identifier, - identifier, - ) + handle_assignment += f" {identifier!s} => {identifier!s},\n" for formal, actual in dict( actor=actor, logger=logger, @@ -368,7 +357,7 @@ def create_handle_assignment( unexpected_msg_type_policy=unexpected_msg_type_policy, ).items(): if actual: - handle_assignment += " %s => %s,\n" % (formal, actual) + handle_assignment += f" {formal!s} => {actual!s},\n" handle_assignment = handle_assignment[:-2] + "\n );" @@ -443,30 +432,22 @@ def add_vhdl_testbench(self, vci_test_lib, test_dir, template_path=None): prj.add_vhdl_testbench("test_lib", ROOT / "test", ROOT / ".vc" / "vc_template.vhd") """ - test_dir = Path(test_dir) - template_path = Path(template_path) if template_path is not None else None - + template_path = Path(template_path).resolve() if template_path is not None else None test_dir = Path(test_dir).resolve() - if template_path: - template_path = Path(template_path).resolve() try: - vci_test_lib.test_bench( - "tb_%s_%s_compliance" % (self.vci_facade.name, self.vc_constructor.return_type_mark) - ) - raise RuntimeError("tb_%s_compliance already exists in %s" % (self.vci_facade.name, vci_test_lib.name)) + vci_test_lib.test_bench(f"tb_{self.vci_facade.name!s}_{self.vc_constructor.return_type_mark!s}_compliance") + raise RuntimeError(f"tb_{self.vci_facade.name!s}_compliance already exists in {vci_test_lib.name!s}") except KeyError: pass if not test_dir.exists(): test_dir.mkdir(parents=True) - tb_path = test_dir / ("tb_%s_%s_compliance.vhd" % (self.vci_facade.name, self.vc_constructor.return_type_mark)) + tb_path = test_dir / (f"tb_{self.vci_facade.name!s}_{self.vc_constructor.return_type_mark!s}_compliance.vhd") testbench_code = self.create_vhdl_testbench(template_path) if not testbench_code: return None tb_path.write_text(testbench_code) - tb_file = vci_test_lib.add_source_file(tb_path) - - return tb_file + return vci_test_lib.add_source_file(tb_path) From bb73b849c160ebfb85525f3f1863faf8cef511c9 Mon Sep 17 00:00:00 2001 From: umarcor Date: Fri, 22 Oct 2021 02:42:49 +0200 Subject: [PATCH 20/21] lint: specify encoding when using 'open' --- vunit/vc/verification_component.py | 4 ++-- vunit/vc/verification_component_interface.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index 19c0b77c4..b160efbd2 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -80,7 +80,7 @@ def __init__(self, vc_facade, vc_code, vc_entity, vc_handle_t, vci): def validate(vc_path): """Validates the existence and contents of the verification component.""" vc_path = Path(vc_path) - with vc_path.open() as fptr: + with vc_path.open("r", encoding="utf-8") as fptr: vc_code = VHDLDesignFile.parse(fptr.read()) if len(vc_code.entities) != 1: @@ -331,7 +331,7 @@ def update_generics(code): return code if template_path: - template_code = template_path.read_text().lower() + template_code = template_path.read_text(encoding="utf-8").lower() else: template_code, _ = self.create_vhdl_testbench_template( self.vc_facade.library, diff --git a/vunit/vc/verification_component_interface.py b/vunit/vc/verification_component_interface.py index 005d4e8f4..0c2f09980 100644 --- a/vunit/vc/verification_component_interface.py +++ b/vunit/vc/verification_component_interface.py @@ -80,7 +80,7 @@ def validate(cls, vci_path, vc_handle_t): """Validates the existence and contents of the verification component interface.""" vci_path = Path(vci_path) - with vci_path.open() as fptr: + with vci_path.open("r", encoding="utf-8") as fptr: code = remove_comments(fptr.read()) vci_code = VHDLDesignFile.parse(code) if len(vci_code.packages) != 1: @@ -318,7 +318,7 @@ def create_vhdl_testbench(self, template_path=None): self.vc_constructor.return_type_mark, ) else: - with template_path.open() as fptr: + with template_path.open("r", encoding="utf-8") as fptr: template_code = fptr.read() test_runner_body_pattern = re.compile(r"\s+-- DO NOT modify this line and the lines below.") From 4d0383d4df42b9b632b64a9d42dea94fa543bbb7 Mon Sep 17 00:00:00 2001 From: umarcor Date: Fri, 22 Oct 2021 02:49:54 +0200 Subject: [PATCH 21/21] vc: refactor --- vunit/vc/verification_component.py | 199 +++++++++++++---------------- 1 file changed, 87 insertions(+), 112 deletions(-) diff --git a/vunit/vc/verification_component.py b/vunit/vc/verification_component.py index b160efbd2..4197a2aac 100644 --- a/vunit/vc/verification_component.py +++ b/vunit/vc/verification_component.py @@ -107,42 +107,37 @@ def create_vhdl_testbench_template(vc_lib_name, vci_lib_name, vc_path, vci_path) :returns: The template string and the name of the verification component entity. """ - vc_path = Path(vc_path) - vci_path = Path(vci_path) + vc_path = Path(vc_path).resolve() + vci_path = Path(vci_path).resolve() def create_constructor(vc_entity, vc_handle_t, vc_constructor): - unspecified_parameters = [] - for parameter in vc_constructor.parameter_list: - if not parameter.init_value: - unspecified_parameters += parameter.identifier_list + unspecified_parameters = [ + parameter.identifier_list for parameter in vc_constructor.parameter_list if not parameter.init_value + ] - constructor = ( - " -- TODO: Specify a value for all listed parameters. Keep all parameters on separate lines\n" - if unspecified_parameters - else "" - ) - constructor += " constant %s : %s := %s" % ( - vc_entity.generics[0].identifier_list[0], - vc_handle_t, - vc_constructor.identifier, + constant = ( + f"{vc_entity.generics[0].identifier_list[0]!s} : {vc_handle_t!s} := {vc_constructor.identifier!s}" ) if not unspecified_parameters: - constructor += ";\n" - else: - constructor += "(\n" - for parameter in unspecified_parameters: - if parameter in [ - "actor", - "logger", - "checker", - "unexpected_msg_type_policy", - ]: - continue - constructor += f" {parameter!s} => ,\n" - constructor = constructor[:-2] + "\n );\n" - - return constructor + return f" constant {constant!s};\n" + return ( + " -- TODO: Specify a value for all listed parameters. Keep all parameters on separate lines\n" + + f" constant {constant!s}(\n" + + "".join( + [ + f" {parameter!s} => ,\n" + for parameter in unspecified_parameters + if parameter + not in [ + "actor", + "logger", + "checker", + "unexpected_msg_type_policy", + ] + ] + ) + )[:-2] + "\n );\n" def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): signal_declarations = ( @@ -151,40 +146,24 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): port_mappings = "" for port in vc_entity.ports: if (port.mode != "out") and port.init_value: - for identifier in port.identifier_list: - port_mappings += f" {identifier!s} => open,\n" + port_mappings += "".join( + [f" {identifier!s} => open,\n" for identifier in port.identifier_list] + ) else: - signal_declarations += " signal %s : %s;\n" % ( - ", ".join(port.identifier_list), - port.subtype_indication, + signal_declarations += ( + f" signal {', '.join(port.identifier_list)!s} : {port.subtype_indication!s};\n" + ) + port_mappings += "".join( + [f" {identifier!s} => {identifier!s},\n" for identifier in port.identifier_list] ) - for identifier in port.identifier_list: - port_mappings += f" {identifier!s} => {identifier!s},\n" - - vc_instantiation = """ -- DO NOT modify the VC instantiation. - vc_inst: entity %s.%s - generic map(%s)""" % ( - vc_lib_name, - vc_entity.identifier, - vc_entity.generics[0].identifier_list[0], - ) - - if len(vc_entity.ports) > 0: - vc_instantiation = ( - vc_instantiation - + """ - port map( -""" - ) - - vc_instantiation += port_mappings[:-2] + "\n );\n" - else: - vc_instantiation += ";\n" - - return signal_declarations, vc_instantiation - vc_path = Path(vc_path).resolve() - vci_path = Path(vci_path).resolve() + return ( + signal_declarations, + f""" -- DO NOT modify the VC instantiation. + vc_inst: entity {vc_lib_name!s}.{vc_entity.identifier!s} + generic map({vc_entity.generics[0].identifier_list[0]!s})""" + + (("\n port map(\n" + port_mappings[:-2] + "\n );\n") if len(vc_entity.ports) > 0 else ";\n"), + ) vc_code = VerificationComponent.validate(vc_path) vc_entity = vc_code.entities[0] @@ -198,23 +177,21 @@ def create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name): vc_instantiation, ) = create_signal_declarations_and_vc_instantiation(vc_entity, vc_lib_name) - context_items = create_context_items( - vc_code, - vc_lib_name, - initial_library_names=set(["std", "work", "vunit_lib", vc_lib_name]), - initial_context_refs=set(["vunit_lib.vunit_context", "vunit_lib.com_context"]), - initial_package_refs=set( - [ - "vunit_lib.vc_pkg.all", - "vunit_lib.sync_pkg.all", - f"{vci_lib_name!s}.{vci_code.packages[0].identifier!s}.all", - ] - ), - ) - return ( TB_TEMPLATE_TEMPLATE.substitute( - context_items=context_items, + context_items=create_context_items( + vc_code, + vc_lib_name, + initial_library_names=set(["std", "work", "vunit_lib", vc_lib_name]), + initial_context_refs=set(["vunit_lib.vunit_context", "vunit_lib.com_context"]), + initial_package_refs=set( + [ + "vunit_lib.vc_pkg.all", + "vunit_lib.sync_pkg.all", + f"{vci_lib_name!s}.{vci_code.packages[0].identifier!s}.all", + ] + ), + ), vc_name=vc_entity.identifier, constructor=create_constructor(vc_entity, vc_handle_t, vc_constructor), signal_declarations=signal_declarations, @@ -231,26 +208,23 @@ def create_vhdl_testbench(self, template_path=None): :returns: The testbench code as a string. """ - template_path = Path(template_path) if template_path is not None else None - - if template_path: - template_path = Path(template_path).resolve() + template_path = Path(template_path).resolve() if template_path is not None else None def update_architecture_declarations(code): - constant = rf"\bconstant\s+{self.vc_entity.generics[0].identifier_list[0]}\s*:\s*{self.vc_handle_t}\s*" - _constructor_call_start_re = re.compile( - rf"{constant!s}:=\s*{self.vci.vc_constructor.identifier}", + releft = rf"\bconstant\s+{self.vc_entity.generics[0].identifier_list[0]}\s*:\s*{self.vc_handle_t}\s*" + constructor_call_start = re.compile( + rf"{releft!s}:=\s*{self.vci.vc_constructor.identifier!s}", MULTILINE | IGNORECASE | DOTALL, - ) + ).search(code) - constructor_call_start = _constructor_call_start_re.search(code) if not constructor_call_start: raise RuntimeError( f"Failed to find call to {self.vci.vc_constructor.identifier!s} in template_path {template_path!s}" ) - parameter_start_re = re.compile(r"\s*\(", MULTILINE | IGNORECASE | DOTALL) - parameter_start = parameter_start_re.match(code[constructor_call_start.end() :]) + parameter_start = re.compile(r"\s*\(", MULTILINE | IGNORECASE | DOTALL).match( + code[constructor_call_start.end() :] + ) if parameter_start: closing_parenthesis_pos = find_closing_delimiter( @@ -292,42 +266,43 @@ def update_architecture_declarations(code): for identifier in parameter.identifier_list: default_values[identifier] = parameter.init_value - architecture_declarations = ARCHITECTURE_DECLARATIONS_TEMPLATE.substitute( - vc_handle_t=self.vc_handle_t, - vc_constructor_name=self.vci.vc_constructor.identifier, - specified_parameters=specified_parameters, - vc_handle_name=self.vc_entity.generics[0].identifier_list[0], - default_logger=default_values["logger"] if default_values["logger"] else 'get_logger("vc_logger")', - default_actor=default_values["actor"] if default_values["actor"] else 'new_actor("vc_actor")', - default_checker=default_values["checker"] if default_values["checker"] else 'new_checker("vc_checker")', + return ( + code[: constructor_call_start.start()] + + ARCHITECTURE_DECLARATIONS_TEMPLATE.substitute( + vc_handle_t=self.vc_handle_t, + vc_constructor_name=self.vci.vc_constructor.identifier, + specified_parameters=specified_parameters, + vc_handle_name=self.vc_entity.generics[0].identifier_list[0], + default_logger=default_values["logger"] if default_values["logger"] else 'get_logger("vc_logger")', + default_actor=default_values["actor"] if default_values["actor"] else 'new_actor("vc_actor")', + default_checker=default_values["checker"] + if default_values["checker"] + else 'new_checker("vc_checker")', + ) + + code[constructor_call_end:] ) - return code[: constructor_call_start.start()] + architecture_declarations + code[constructor_call_end:] - def update_test_runner(code): - _test_runner_re = re.compile( - r"\btest_runner\s*:\s*process.*?end\s+process\s+test_runner\s*;", - # r"\btest_runner\s*:\s*process", - MULTILINE | IGNORECASE | DOTALL, + code, num_found_test_runners = subn( + re.compile( + r"\btest_runner\s*:\s*process.*?end\s+process\s+test_runner\s*;", + # r"\btest_runner\s*:\s*process", + MULTILINE | IGNORECASE | DOTALL, + ), + TEST_RUNNER_TEMPLATE.substitute(vc_handle_name=self.vc_entity.generics[0].identifier_list[0]), + code, + 1, ) - - new_test_runner = TEST_RUNNER_TEMPLATE.substitute( - vc_handle_name=self.vc_entity.generics[0].identifier_list[0] - ) - - code, num_found_test_runners = subn(_test_runner_re, new_test_runner, code, 1) if not num_found_test_runners: raise RuntimeError(f"Failed to find test runner in template_path {template_path!s}") - return code def update_generics(code): - _runner_cfg_re = re.compile(r"\brunner_cfg\s*:\s*string", MULTILINE | IGNORECASE | DOTALL) - - code, num_found_runner_cfg = subn(_runner_cfg_re, GENERICS_TEMPLATE, code, 1) + code, num_found_runner_cfg = subn( + re.compile(r"\brunner_cfg\s*:\s*string", MULTILINE | IGNORECASE | DOTALL), GENERICS_TEMPLATE, code, 1 + ) if not num_found_runner_cfg: raise RuntimeError(f"Failed to find runner_cfg generic in template_path {template_path!s}") - return code if template_path: