Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add APB verification components #1070

Open
wants to merge 23 commits into
base: vc_standard
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions docs/verification_components/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,115 @@ A VC typically has an associated package defining procedures for sending to and
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 an argument to the procedure calls to direct messages to the specific VC instance.


VC and VCI Compliance Testing
=============================

VUnit establishes a standard for VCs and VCIs, designed around a set of rules that promote flexibility,
reusability, interoperability, and future-proofing of VCs and VCIs.

Rule 1
------

The file containing the VC entity shall contain only that entity, and the file containing the VCI package shall
contain only that package.

**Rationale**: This structure simplifies compliance testing, as each VC or VCI can be directly referenced by its
file name.

Rule 2
------

A VC shall have only **one** generic, the *handle*, and it shall be of a record type containing **private** fields.

**Rationale**: Using a record allows future updates to add and/or remove fields in the record without breaking
backward compatibility.

**Recommendation**: Mark the fields as private by using a naming convention and/or including comments. This minimizes
the risk of users accessing fields directly.

Rule 3
------

The VC handle shall be created by a function, the *constructor*, which shall have a name beginning with ``new``.

**Rationale**: Using a constructor removes the need for users to directly access the private fields of the handle
record. The naming convention also enables compliance tests to easily locate the constructor and verify it against
other applicable rules.

Rule 4
------

The VC constructor shall include an ``id`` parameter of type ``id_t`` to enable the user to specify the VC's identity.

**Rationale**: This gives users control over the namespace assigned to the VC.

Rule 5
------

The ``id`` parameter shall default to ``null_id``. If not overridden, ``id`` shall be assigned a value on the format
``<provider>:<VC name>:<n>``, where ``<n>`` starts at 1 for the first instance of the VC and increments with each
additional instance.

**Rationale**: This format ensures clear identification while preventing naming collisions when VCs from different
providers are combined.

Rule 6
------

All identity-supporting objects associated with the VC (such as loggers, actors, and events) shall be assigned an
identity within the namespace defined by the constructor’s ``id`` parameter.

**Rationale**: This gives users control over these objects and simplifies the association of log messages with a
specific VC instance.

Rule 7
------

All logging performed by the VC, including indirect logging (such that error logs from checkers), shall use the
VUnit logging mechanism.

**Rationale**: Using a unified logging mechanism ensures consistency and compatibility across logging outputs
from different VCs.

Rule 8
------

Communication with the VC shall be based on VUnit message passing, and the VC actor’s identity shall match the
``id`` parameter provided to the constructor.

**Rationale**: This ensures a consistent communication framework and enables the reuse of VCIs across multiple VCs.

Rule 9
------

All VCs shall support the sync interface.

**Rationale**: The ability to verify if a VC is idle and to introduce delays between transactions are frequently
needed features for VC users.

Rule 10
-------

The VC constructor shall include an ``unexpected_msg_type_policy`` parameter, allowing users to specify the action
taken when the VC receives an unexpected message type.

**Rationale**: This policy enables flexibility in handling situations where a VC actor, subscribed to another actor,
might receive unsupported messages, while VCs addressed directly should only receive supported messages.

Rule 11
-------

The standard configuration (of type ``std_cfg_t``), which includes the required parameters for the constructor, shall
be accessible by calling ``get_std_cfg`` with the VC handle.

**Rationale**: This enables reuse of common functions across multiple VCs.

Rule 12
-------

A VC shall keep the ``test_runner_cleanup`` phase entry gate locked as long as there are pending operations.

**Rationale**: Locking the gate ensures that the simulation does not terminate prematurely before all operations have
completed.
84 changes: 84 additions & 0 deletions vunit/vhdl/verification_components/src/apb_completer.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2024, Lars Asplund lars.anders.asplund@gmail.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library osvvm;
use osvvm.RandomPkg.RandomPType;

use work.memory_pkg.all;
use work.apb_completer_pkg.all;
use work.logger_pkg.all;

entity apb_completer is
generic (
bus_handle : apb_completer_t
);
port (
clk : in std_logic;
reset : in std_logic;
psel_i : in std_logic;
penable_i : in std_logic;
paddr_i : in std_logic_vector;
pwrite_i : in std_logic;
pwdata_i : in std_logic_vector;
prdata_o : out std_logic_vector;
pready_o : out std_logic
);
end entity;

architecture a of apb_completer is

begin

PROC_MAIN: process
procedure drive_outputs_invalid is
begin
if bus_handle.p_drive_invalid then
prdata_o <= (prdata_o'range => bus_handle.p_drive_invalid_val);
pready_o <= bus_handle.p_drive_invalid_val;
end if;
end procedure;

variable addr : integer;
variable rnd : RandomPType;
begin
drive_outputs_invalid;
wait until rising_edge(clk);

loop
-- IDLE/SETUP state
drive_outputs_invalid;

wait until psel_i = '1' and rising_edge(clk);
-- ACCESS state

while rnd.Uniform(0.0, 1.0) > bus_handle.p_ready_high_probability loop
pready_o <= '0';
wait until rising_edge(clk);
end loop;

pready_o <= '1';

addr := to_integer(unsigned(paddr_i));

if pwrite_i = '1' then
write_word(bus_handle.p_memory, addr, pwdata_i);
else
prdata_o <= read_word(bus_handle.p_memory, addr, prdata_o'length/8);
end if;

wait until rising_edge(clk);

if penable_i = '0' then
failure(bus_handle.p_logger, "penable_i must be active in the ACCESS phase.");
end if;
end loop;
end process;

end architecture;
76 changes: 76 additions & 0 deletions vunit/vhdl/verification_components/src/apb_completer_pkg.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2024, Lars Asplund lars.anders.asplund@gmail.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.bus_master_pkg.all;
use work.com_pkg.all;
use work.com_types_pkg.all;
use work.logger_pkg.all;
use work.memory_pkg.memory_t;
use work.memory_pkg.to_vc_interface;

package apb_completer_pkg is

type apb_completer_t is record
-- Private
p_actor : actor_t;
p_memory : memory_t;
p_logger : logger_t;
p_drive_invalid : boolean;
p_drive_invalid_val : std_logic;
p_ready_high_probability : real range 0.0 to 1.0;
end record;

constant apb_completer_logger : logger_t := get_logger("vunit_lib:apb_completer_pkg");
impure function new_apb_completer(
memory : memory_t;
logger : logger_t := null_logger;
actor : actor_t := null_actor;
drive_invalid : boolean := true;
drive_invalid_val : std_logic := 'X';
ready_high_probability : real := 1.0)
return apb_completer_t;

constant slave_write_msg : msg_type_t := new_msg_type("apb slave write");
constant slave_read_msg : msg_type_t := new_msg_type("apb slave read");
end package;

package body apb_completer_pkg is

impure function new_apb_completer(
memory : memory_t;
logger : logger_t := null_logger;
actor : actor_t := null_actor;
drive_invalid : boolean := true;
drive_invalid_val : std_logic := 'X';
ready_high_probability : real := 1.0)
return apb_completer_t is
variable actor_tmp : actor_t := null_actor;
variable logger_tmp : logger_t := null_logger;
begin
if actor = null_actor then
actor_tmp := new_actor;
else
actor_tmp := actor;
end if;
if logger = null_logger then
logger_tmp := bus_logger;
else
logger_tmp := logger;
end if;
return (
p_memory => to_vc_interface(memory, logger),
p_logger => logger_tmp,
p_actor => actor_tmp,
p_drive_invalid => drive_invalid,
p_drive_invalid_val => drive_invalid_val,
p_ready_high_probability => ready_high_probability
);
end;
end package body;
Loading