Skip to content

Commit

Permalink
Merge pull request #1 from c-thaler/apb_vc
Browse files Browse the repository at this point in the history
Apb vc
  • Loading branch information
DavidMartinPhios authored Nov 26, 2024
2 parents 07f2f9f + 2eb5409 commit b5ecdc8
Show file tree
Hide file tree
Showing 8 changed files with 1,238 additions and 0 deletions.
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 [email protected]

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 [email protected]

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

0 comments on commit b5ecdc8

Please sign in to comment.