UVM Framework Users Guide PDF
UVM Framework Users Guide PDF
Users Guide
Revision 2020.1
The steep learning curve of UVM often prevents product teams from realizing the
productivity and quality benefits of using advanced verification methodology. The UVM
Framework (UVMF) provides a jump-start for learning UVM and building UVM verification
environments. It defines an architecture and reuse methodology upon UVM, enabling
teams new to UVM to be productive from the beginning while coming up the UVM learning
curve. The UVM code generator provided by UVMF automates the creation of the files,
infrastructure and interconnect for interface packages, environment packages and project
benches. Interface packages, environment packages, and project benches are characterized
using YAML or a python API. The UVMF generator uses these characterizations to create
UVM source. Once generated, developers can promptly focus on adding functionality
specific to the design and interfaces used.
The UVM Framework is a reuse methodology that verification teams can leverage. It
supports component level verification reuse across projects and environment reuse from
block through chip to system level simulation. The UVM Framework is an established UVM
use model that is in use at many companies in multiple industries across North America
and Europe.
The UVM Framework provides an architecture that supports pure simulation and
accelerated simulation using emulation. This enables the creation of a single unified
environment that supports block, subsystem, chip and system level tests, and with the
choice of running on a pure simulation platform (e.g. Questa) or a hardware-assisted
acceleration platform using emulation (e.g. Veloce and Strato).
1.1.3 Coverage within UVMF
1 Coverage components: Create the class definition for this component using the
UVMF generator and connect it to other components in the environment using the
generator. The coverage component will likely only have analysis exports for
receiving transactions and no analysis ports.
2 Predictors: Manually add required cover groups to the predictor that was
generated.
3 Scoreboard: Extend UVMF scoreboards on a per-environment basis to define cover
It is important to collect coverage on data that has been validated. In order to avoid
agent coverage being confused with coverage of scoreboard validated data the default
value of the has_coverage bit in the uvmf_parameterzed_agent is 0. This will prevent the
coverage component within the agent from being constructed. Users will have to manually
change this bit to enable agents to record transaction coverage at the interface agent.
The UVMF scoreboards contain features that help avoid the falsely optimistic level
of coverage:
1 end_of_test_activity_check: This flag is set by default. It generates a uvm error if no
transactions were received. This will help avoid mistakes that result in the
scoreboard not being attached to prediction or prediction not sending expected
transactions. This flag can be set for specific scoreboards in the build_phase of the
environment.
2 end_of_test_empty_check: This flag is set by default. It generates a uvm error if
transactions remain in the scoreboard in the check_phase. This will help avoid
mistakes that result in no transactions being received for comparison against
expected transactions. This flag can be set for specific scoreboards in the
build_phase of the environment.
3 wait_for_scoreboard_empty: This flag is clear by default. It postpones the
termination of run_phase until there are no transactions in the scoreboard. The
UVM based timeout, UVM_DEFAULT_TIMEOUT, is used to prevent simulations
from hanging.
4 The uvm messaging ID field of UVMF scoreboards contain the scoreboard
hierarchy. A cursory view of the message summary at the end of the transcript
will identify the absence of a scoreboard.
The project_benches directory contains bench level code that is not reuable. The
simulation bench is composed of top level elements that are not generally intended to be
reusable horizontally nor vertically. It defines test level parameters, the top level modules,
top level sequence and top level UVM test. It also includes derived sequences and tests
used to implement additional test scenarios.
1.3.2.1 uvmf_transaction_base.svh
This is the base class for all sequence items, i.e. transactions, within UVMF. It
provides a unique transaction ID variable and associated functions useful for debug. It also
provides variables used for transaction viewing and a unique key for storing the
transaction in associative arrays.
1.3.2.2 uvmf_sequence_base.svh
This is the base class for all sequences within UVMF. It extends uvm_sequence but
provides no additional functionality. It provides a location where functionality common to
all UVMF sequences can be added.
1.3.3.1 uvmf_monitor_base.svh
This is the base class for all UVMF monitors. Only monitors extended from
uvmf_monitor_base should be used as specialization of the MONITOR_T parameter of the
uvmf_parameterized_agent base class. When extending the uvmf_monitor_base, only the
monitor task must be defined. The monitor task either observes and captures bus activity
directly or calls a task in the monitor BFM which captures bus activity. It is recommended
that signal level bus monitoring be done in the monitor BFM for optimal run-time
performance, especially with emulation.
1.3.3.2 uvmf_driver_base.svh
This is the base class for all UVMF drivers. Only drivers extended from
uvmf_driver_base should be used as specialization of the DRIVER_T parameter of the
uvmf_parameterized_agent base class. When extending uvmf_driver_base, only the access
task must be defined. The access task either drives bus activity directly or calls a task in
1.3.3.3 uvmf_parameterized_agent_configuration_base.svh
This is the base class for all interface agent configurations. Only configurations
extended from uvmf_parameterized_agent_configuration_base should be used as
specialization of the CONFIG_T parameter of the uvmf_parameterized_agent base class.
Variables common to all agents and specific to the uvmf_parameterized_agent are in the
uvmf_parameterized_agent_configuration_base. Add protocol specific configuration
variables to an extension of uvmf_parameterized_agent_configuration class.
1.3.3.4 uvmf_parameterized_agent.svh
This class implements an interface agent. This agent can be used with any protocol.
The protocol specific features reside in the configuration, driver, monitor, coverage and
transaction class types used as parameters to this class. If the agent is active then it
automatically places its sequencer within the uvm_config_db and within the agent
configuration object for retrieval and use by the top level sequence.
Prior to constructing a monitor, the parameterized agent checks the uvm_config_db
for a monitor of the required type. If one is returned then it is used instead of constructing
a local monitor. This is to support construction of a shared monitor in an upper level
environment. The shared monitor is created in an upper level environment where lower
level environments monitor common interfaces.
Coverage
(COVERAGE_T) Monitor
(MONITOR_T)
The UVMF environment generator provides a way for users to specify analysis components
with any combination of analysis_exports and analysis_ports. This allows the user to
automatically generate any analysis component required. One type of analysis component
that can be generated are predictors. Predictor specification for the UVMF code generator
includes the number and type of analysis_exports required as well as the number and type
of analysis_ports required. Another type of analysis component that can be generated are
coverage components. Coverage component specification for the UVMF code generator
includes the number and type of analysis_exports required. Coverage components typically
do not have analysis_ports so the list of analysis_port type and names would be empty.
Another type of analysis component that can be generated are scoreboards. Scoreboard
specification for the UVMF code generator includes the number and type of
analysis_exports required as well as the number and type of analysis_ports required. The
scoreboard specification for an analysis component is for defining and instantiating custom
1.3.6.1 uvmf_scoreboard_base.svh
This is the base class for all scoreboards within the UVM Framework. It provides
the two analysis exports for receiving transactions, expected_analysis_export and
actual_analysis_export. It also provides basic end of test use checks and reporting.
extends uvm_scoreboard
uvmf_scoreboard_base
1.3.6.2 uvmf_in_order_scoreboard.svh
This scoreboard is used in circumstances where the data order through the DUT is
preserved.
The in order scoreboard extends the scoreboard base. It adds an analysis FIFO for
storing expected results. Transactions received through the expected_export are placed
into the analysis FIFO. Transactions observed on the DUT output are sent to the actual
export for comparison. The arrival of a transaction on the actual export causes the next
transaction to be removed from the analysis FIFO and compared to the actual transaction.
An error is generated if the FIFO is empty.
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_in_order_scoreboard
try_put()
try_get()
1.3.6.3 uvmf_in_order_scoreboard_array.svh
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_in_order_scoreboard_array
.
.
.
1.3.6.4 uvmf_out_of_order_scoreboard.svh
The out of order scoreboard is used in circumstances where data order through the
DUT is not guaranteed or not predictable.
The out of order scoreboard extends the scoreboard base. It adds a SystemVerilog
associative array for storing expected results. Transactions received through the
expected_export are placed into the associative array using the value returned from the
get_key function as the key of the entry. Transactions observed on the DUT output are sent
to the actual export for comparison. The arrival of a transaction on the actual export
causes a transaction to be removed from the associative array and compared to the actual
transaction. The get_key function of the actual transaction is used to identify a matching
transaction in the associative array. An error is generated if the associative array does not
have an entry that matches the key returned from the actual transactions get_key function.
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_out_of_order_scoreboard
t.get_key() used to
index into Hash
T expected_hash[integer]
1.3.6.5 uvmf_in_order_race_scoreboard.svh
The in order race scoreboard is used in circumstances where data order through the
DUT is preserved and the DUT can send output transactions before input transactions are
received.
The in order race scoreboard extends the scoreboard base. It adds an analysis FIFO
for the expected_export and actual_export. When a transaction arrives on either port the
other port is checked for an entry to compare against. If an entry exists in the FIFO for the
other port then the entry is pulled from the FIFO for comparison. If an entry does not exist
in the FIFO for the other port then the entry is queued for later comparison.
1.3.7.1 uvmf_environment_configuration_base.svh
The uvmf_environment_configuration_base is the base environment configuration
class for all UVMF environments. It provides flags used for register model integration. It
also provides debug features for the initialize call and its handling of agent interface name
and agent activity arrays.
1.3.7.2 uvmf_environment_base.svh
The uvmf_environment_base is the base class for all UVMF based environments. It
provides a handle to the environments configuration class.
1.3.8.1 uvmf_test_base.svh
This is the base class for the base test for all simulation benches. The
uvmf_test_base instantiates the top level configuration, top level environment and top level
sequence. The test class directly extended from uvmf_test_base is named test_top and must
define the parameters for the top level configuration, environment and sequence and calls
the initialize function of the configuration class. Test top is then extended to create
additional test cases by specifying factory overrides.
https://verificationacademy.com/courses/UVM-Framework-One-Bite-at-a-Time
The diagram below shows a block level environment. It is from the WB2SPI
example. Block level environments include agents, predictors, scoreboards, coverage
collectors and other components that are connected based on design data flow.
wb2spi_environment
wb2spi_scoreboard
(expected) (actual)
wb2spipredictor spi_mem_slave_coverage
spi_mem_slave_viewer
The diagram below shows a chip level environment. It is from the AHB2SPI
example. Chip level environments include other environments. This is true for all
environments other than block level environments. Environments are structured in a
hierarchical manner similar to how RTL blocks are composed hierarchically. This allows
for environment reuse as RTL components are reused.
ahb2spi_environment
ahb2wb_environment wb2spi_environment
The structure of the simulation bench is shown below. It is from the AHB2WB
simulation bench.
The three top level elements in every UVMF simulation bench are hdl_top, hvl_top and
test_top.
Synthesizable content that may be run in emulation is placed in hdl_top. This
includes the DUT, driver BFMs, monitor BFMs, signal bundle interfaces and any other logic
required by the DUT.
The non-synthesizable elements that must be in a module are placed in hvl_top. This
includes the test package import and the call to UVM’s run_test to start the UVM phases.
The top level configuration, top level environment and top level sequence are placed
in test_top. This defines the base test from which all other tests are derived.
ahb2wb_environment
Module: hvl_top
A specification for the ahb2wb DUT can be found in the doc folder of the example.
UVM Framework Users Guide 21
AHB2WB Example: Test Bench
ahb2wb_environment
Module: hvl_top
As with all UVMF test benches, the AHB2WB test bench is composed of three top
levels: hdl_top, hvl_top and test_top. The module named hdl_top contains the DUT, BFMs
and signal bundle interfaces that tie them together. All content in hdl_top is synthesizable
to support emulation. The module named hvl_top contains all content that must reside
within a module but is not synthesizable. This includes importing the test package and
calling run_test to start the UVM phases. The class named test_top is the top level UVM test
class. It is selected using the +UVM_TESTNAME argument on the command line and
constructed by the UVM factory.
Module: hdl_top
ahb_mon_bfm wb_mon_bfm
ahb_bus wb_bus
initial begin
uvm_config_db #( virtual ahb_monitor_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , AHB_BFM , ahb_mon_bfm );
uvm_config_db #( virtual ahb_driver_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , AHB_BFM , ahb_drv_bfm );
The hdl_top module contains the DUT and BFMs used to drive and monitor bus
activity. The _drv_bfm interfaces provide signal stimulus. The _mon_bfm interfaces
observe signal activity and capture transaction information for broadcasting to the
environment for prediction, scoreboarding and coverage collection. An interface
containing all of the signals for the bus ties the monitor BFM, driver BFM and DUT signal
ports together. Protocol signals are separated into an interface to enable block to top reuse
of environments and monitor BFMs. All BFMs are placed into the uvm_config_db by hdl_top
for retrieval by the appropriate agent configuration. This mechanism is described in the
section on resource sharing and initialization within the UVM Framework.
ahb2wb_configuration
ahb_config
wb_config
uvmf_parameterized_2agent_environment
port_0_ap a2b_scoreboard port_0_ap
port_1_ap port_1_ap
b2a_scoreboard
(B2A_SCOREBOARD_T) (expected)
(actual)
a2b_predictor b2a_predictor
(A2B_PREDICTOR_T) (B2A_PREDICTOR_T)
wb2spi_configuration
wb2spi_environment
Module: hvl_top
As with all UVMF test benches, the WB2SPI test bench is composed of three top
levels: hdl_top, hvl_top and test_top. The module named hdl_top contains the DUT, BFMs
and signal bundle interfaces that tie them together. All content in hdl_top is synthesizable
to support emulation. The module named hvl_top contains all content that must reside
within a module but is not synthesizable. This includes importing the test package and
calling run_test to start the UVM phases. The class named test_top is the top level UVM test
class. It is selected using the +UVM_TESTNAME argument on the command line and
constructed by the UVM factory.
Module: hdl_top
wb_mon_bfm spi_mon_bfm
wb_bus spi_bus
initial begin
uvm_config_db #( virtual spi_monitor_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , SPI_BFM , spi_mon_bfm );
uvm_config_db #( virtual spi_driver_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , SPI_BFM , spi_drv_bfm );
The hdl_top module contains the DUT and BFMs used to drive and monitor bus
activity. The _drv_bfm interfaces provide signal stimulus. The _mon_bfm interfaces
observe signal activity and capture signal information for broadcasting to the environment
for prediction, scoreboarding and coverage collection. An interface containing all of the
signals for the bus ties the monitor BFM, driver BFM and DUT signal ports together.
Protocol signals are separated into an interface to enable block to top reuse of
environments and monitor BFMs. All BFMs are placed into the uvm_config_db by hdl_top
for retrieval by the appropriate agent configuration. This mechanism is described in the
section on resource sharing and initialization within UVM Framework.
wb2spi_configuration
reg_model
spi_config
wb_config
wb2spi_environment
wb2spi_scoreboard
(expected) (actual)
wb2spipredictor spi_mem_slave_coverage
spi_mem_slave_viewer
The wb2spi environment contains the agents, predictor, scoreboard, coverage and
transaction viewing components shown in the above diagram. The wishbone agent
interacts with the wb_drv_bfm and wb_mon_bfm. It receives stimulus information from
sequences in the top level sequence. Bus operations are observed and broadcasted to the
wb2spi predictor. The predictor creates an expected SPI transaction based on DUT
configuration and input from the wishbone bus. Output from the wb2spi predictor are sent
to the scoreboard to be queued until DUT activity is received for comparison. The SPI
agent interacts with the spi_drv_bfm and spi_mon_bfm. It receives stimulus information
from sequences in the top level sequence. Bus operations are observed and broadcasted to
the wb2spi scoreboard, coverage component and transaction viewing component. The
coverage component records functional coverage of SPI operations. The transaction
viewing component provides a transaction viewing stream of SPI memory slave
transactions. The monitor within the SPI agent provides transaction viewing of the base
SPI transfer. This allows for viewing of raw SPI transfers as well as the functional meaning
of each bit within the raw SPI transfer.
spi_enable_sequence
spi_write_via_wb_sequence
spi_write_via_wb_sequence
spi_read_via_wb_sequence
spi_read_via_wb_sequence
spi_write_via_wb_sequence
The top level sequence, named wb2spi_sequence_base, orchestrates and controls all
stimulus within the simulation. The stimulus flow is shown in the diagram above. The first
sequence to be started is the SPI memory slave sequence. This sequence is forked off at the
beginning because it will remain active throughout the simulation. This is because a slave
device is always active and ready to respond to activity initiated by the master. Once the
slave sequence is forked the wishbone reset sequence is started. This causes the
wb_drv_bfm to assert and then release reset. Once the reset sequence has completed a
series of writes and reads are performed on the wb2spi DUT. The format of the SPI
transfer as a memory slave is shown in the table below.
ahb2spi_configuration
ahb2spi_environment
Module: hvl_top
As with all UVMF test benches, the AHB2SPI test bench is composed of three top
levels: hdl_top, hvl_top and test_top. The module named hdl_top contains the DUT, BFMs
and signal bundle interfaces that tie them together. All content in hdl_top is synthesizable
to support emulation. The module named hvl_top contains all content that must reside
within a module but is not synthesizable. This includes importing the test package and
calling run_test to start the UVM phases. The class named test_top is the top level UVM test
class. It is selected using the +UVM_TESTNAME argument on the command line and
constructed by the UVM factory.
Module: hdl_top
wb_mon_bfm
ahb_mon_bfm spi_mon_bfm
wb_bus
ahb_bus spi_bus
DUT
ahb_drv_bfm spi_drv_bfm
ahb2wb wb2spi
initial begin
uvm_config_db #( virtual ahb_monitor_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , AHB_BFM , ahb_mon_bfm );
uvm_config_db #( virtual ahb_driver_bfm )::set( null , UVMF_VIRTUAL_INTERFACES , AHB_BFM , ahb_drv_bfm );
The hdl_top module contains the DUT and BFMs used to drive and monitor bus
activity. The _drv_bfm interfaces provide signal stimulus. The _mon_bfm interfaces
observe signal activity and capture signal information for broadcasting to the environment
for prediction, scoreboarding and coverage collection. An interface containing all of the
signals for the bus ties the monitor BFM, driver BFM and DUT signal ports together.
Protocol signals are separated into an interface to enable block to top reuse of
environments and monitor BFMs. All BFMs are placed into the uvm_config_db by hdl_top
for retrieval by the appropriate agent configuration. This mechanism is described in the
section on resource sharing and initialization within UVM Framework.
In this example the wishbone bus is internal to the DUT and driven by RTL within
the DUT. A wishbone signal bundle interface, wb_bus, is connected to the wishbone bus in
the DUT in order to observe bus activity. This can be done using either the SystemVerilog
bind construct or hierarchically connecting the signal bundle into the DUT. This wishbone
signal bundle is connected to two wishbone monitor BFM. This is to provide the wishbone
agent within each of the block level environments a wishbone monitor BFM virtual
interface handle. This allows independent prediction, scoreboarding and coverage for each
block level environment.
ahb2spi_configuration
reg_model
ahb2wb_config
wb2spi_config
ahb2spi_environment
Shared
wb_monitor
ahb2wb_environment wb2spi_environment
The ahb2spi environment contains the ahb2wb environment and the wb2spi
environment. These two block level environments perform the same prediction,
scoreboarding and coverage provided when run in the block level bench. Stimulus is
driven into the design via the ahb interface. The wishbone interface is now buried in the
DUT. It is observed by both environments for prediction, scoreboarding and coverage.
Data is sent out through the SPI interface of the DUT. The ahb2wb_environment is
configured by the ahb2spi_configuration. The ahb2wb_environment is configured by the
ahb2wb_configuration. The wb2spi_environment is configured by the
wb2spi_configuration.
The ahb2spi environment creates a wb_monitor to be shared between the two
environments that need to observe the wb bus. This wb monitor is constructed by the
ahb2spi environment and placed into the uvm_config_db for retrieval by the wb agent
within each block level environment. The shared wb_monitor is connected to the single
wb_monitor_bfm. WB transactions observed by the wb_monitor_bfm are sent to the shared
wb_monitor and broadcasted within each environment.
The top level sequence, named ahb2spi_sequence_base, orchestrates and controls all
stimulus within the simulation. The stimulus flow is shown in the diagram above. The first
sequence to be started is the ahb reset sequence. This causes the ahb_drv_bfm to assert
and then release reset. Once the reset sequence has completed then the SPI memory slave
sequence is started. This sequence is forked off because it will remain active throughout
the simulation. This is because a slave device is always active and ready to respond to
activity initiated by the master. Once the slave sequence is forked a series of writes and
reads are performed on the DUT through the ahb port. These operations write and read
the SPI memory slave attached to the SPI port of the DUT.
gpio_example_configuration
gpio_example_environment
Module: hvl_top
As with all UVMF test benches, the GPIO test bench is composed of three top levels:
hdl_top, hvl_top and test_top. The module named hdl_top contains the DUT, BFMs and
signal bundle interfaces that tie them together. All content in hdl_top is synthesizable to
support emulation. The module named hvl_top contains all content that must reside within
a module but is not synthesizable. This includes importing the test package and calling
run_test to start the UVM phases. The class named test_top is the top level UVM test class.
It is selected using the +UVM_TESTNAME argument on the command line and constructed
by the UVM factory.
Module: hdl_top
gpio_mon_bfm
write_port read_port_
gpio_bus
clk
gpio_drv_bfm
read_port
initial begin
uvm_config_db #( virtual gpio_monitor_bfm #(TEST_GPIO_READ_PORT_WIDTH,
TEST_GPIO_WRITE_PORT_WIDTH))::set( null , UVMF_VIRTUAL_INTERFACES , "gpio_bfm" ,gpio_mon_bfm );
The hdl_top module contains the DUT and BFMs used to drive and monitor bus
activity. The _drv_bfm interfaces provide signal stimulus. The _mon_bfm interfaces
observe signal activity and capture signal information for broadcasting to the environment
for prediction, scoreboarding and coverage collection. An interface containing all of the
signals for the bus ties the monitor BFM, driver BFM and DUT signal ports together.
Protocol signals are separated into an interface to enable block to top reuse of
environments and monitor BFMs. All BFMs are placed into the uvm_config_db by hdl_top
for retrieval by the appropriate agent configuration. This mechanism is described in the
section on resource sharing and initialization within UVM Framework.
In this example the DUT is a simple register named read_port_. The input to the
register is the write_port of the gpio_bus. On each clock edge the value on write_port is
output on read_port_. The read_port_ value is then assigned to the read_port of the
gpio_bus. This inserts a one clock delay between the write_port output and read_port
input. This loopback delay is only for demonstration purposes.
gpio_example_configuration
gpio_config
gpio_example_environment
gpio_agent
The sequence used in this example is different from most sequences in that it is
started at the beginning of the simulation and remains throughout the simulation. Writing
values to the GPIO write_port and reading values from the GPIO read_port are done
through tasks in this sequence. The sequence, named gpio_seq, is an extension to the
gpio_sequence located in the gpio_pkg. This extension defines bit assignments to the
write_port and read_port. In this case bus_a and bus_b are assigned to the write_port, bus_c
and bus_d are assigned from the read_port. The flow of the top level sequence is outlined
below:
Initialization:
Line 61: Construct the gpio_seq sequence.
Line 62: Start the gpio_seq sequence. This sequence remains resident throughout
the simulation.
Line 63: Wait for two clocks using the wait_for_num_clocks task within the
gpio_agents configuration class.
Write operation:
Line 64 and 65: Set the values of bus_a and bus_b variables.
Line 66: Display the variable values in the sequence item within gpio_seq.
Line 67: Write the new values of bus_a and bus_b to the GPIO write_port
Line 68: Wait for two clocks using the wait_for_num_clocks task within the
gpio_agents configuration class.
This example demonstrates the various features of the QVIP AXI4 as listed below.
This example can be used as a production environment by substituting a design for either
axi4_master, axi4_slave or both.
The table below lists the interfaces and classes used from the QVIP Library and
where they are located in the environment.
Module: hdl_top
QVIP: axi4_monitor
The UVMF examples all use the same VRM configuration file (RMDB). That common
default.rmdb file resides in $UVMF_HOME/scripts. A test list control file resides in each
bench’s ./sim directory to specify which tests are associated with the given bench. To
invoke a VRM regression simply invoke the “make vrun” Makefile target or issue the “vrun”
command yourself in a bench’s sim directory, as shown:
Refer to section 43.5 for details on how to invoke UVMF regression test runs with
VRM.
To run a simulation with Visualizer enabled for the purposes of post-sim debug, set the
USE_VIS or USE_VIS_UVM variables to 1 when running “make cli” for a given test. Setting
USE_VIS to 1 will log all signals and memories for a given run whereas USE_VIS_UVM will
also log SV and UVM constructs. Once a simulation is complete, invoke Visualizer in post-
sim debug mode by running “make vis”.
44 UVM Framework Users Guide
To run a simulation using Visualizer as the interactive debugger execute “make debug
USE_VIS=1”.
Visualizer wave files can also be produced during a VRM-based regression run. See
section 3.5 for details.
3 Makefiles
The UVMF uses a two level makefile structure. Individual packages have a makefile
that contains make targets for compiling the package and associated modules. The
simulation bench makefile includes the makefiles for all packages used by the bench as well
as the uvmf_base_pkg makefile. This gives the bench makefile access to the make targets
needed to compile required packages located under verification_ip. The bench makefile
also contains make targets for all packages located under the project’s tb directory.
UVMF_HOME : This variable points to the home directory of UVMF core code. This
represents released, non-user modified, code. This directory should contain the
4.2 Invocation
The simplest way to invoke a VRM regression for a given bench is to use the makefile
target “make vrun”. Information about how to compile the given bench as well as which
tests to invoke is pulled from a test list file. The default location and name for the test list
file is “./sim/testlist”. Information on the content and format of the test list file can
be found in a subsequent subsection. By default, the following RMDB behavior is invoked
by UVMF:
Advanced test list file
o Per-test extra arguments
o Nested test list files
o Repeat of tests
o Control of random seeds on per-test basis
Parallel build of separate testbenches
Parallel run of simulations on per-bench basis
Automatic parallel merge of UCDB output
Automatic generation of HTML coverage report
Random test seed generation and control
Automatic integration of Questa test plan file, if specified
Automatic email notifications
Use the initialization file by setting the environment variable $UVMF_VRM_INI to the full
path to the desired file. An example file can be found in
$UVMF_HOME/scripts/uvmf_vrm_ini.tcl but the file can and should be located
elsewhere.
This file, if pointed to, will be sourced prior to running VRM and can be used to both
initialize parameters as well as specify Tcl procedures for overriding default VRM behavior
or specifying how to invoke non-standard grid management systems.
Parameter overrides take place by specifying a Tcl proc called “vrmSetup”. From within
this proc use calls to the pre-defined routine “setIniVar” to specify the desired value for
a given parameter. For example, one can more widely enable support for Visualizer with
the following Tcl content:
proc vrmSetup {} {
setIniVar use_vis 1
}
UVM Framework Users Guide 55
Attempts to use setIniVar to initialize parameters not in the list above will result in a
fatal error. It is legal to have the initialization file source other Tcl files and this mechanism
can be used to specify project-level preferences along with user-level preferences.
The build arguments will be applied to the ‘make’ command that is used to both compile
and optimize the testbench environment. Any runtime arguments will be applied to all
invocations of vsim for simulations against the given testbench environment.
4.2.3.2 TB Keyword
The TB keyword specifies which test bench should be used for all following tests. The
format is as follows:
TB <bench_name>
After a given TB keyword is found, all subsequent tests will target this testbench. If another
TB keyword is used with a different bench name, all subsequent tests after that will utilize
the new bench.
INCLUDE <file_name>
All operations and output take place under the ./sim/VRMDATA directory. The VRMDATA
directory is created when VRM is invoked. Individual bench builds take place in
subdirectories, as do individual simulation runs. This allows for a high degree of parallel
operation.
Individual bench compiles take place in
VRMDATA/top/each_top~<bench_name>/build_group/build_task
Individual simulations run in
VRMDATA/top/each_top~<bench_name>/build_group/run_fork/run~
<bench_name>-<test_name>-<iteration_number>-<random_seed>
If a build or simulation fails, look in the execScript.log underneath the given directory for
information on what went wrong.
4.4 Timeouts
All meaningful actions that the UVMF VRM process can invoke have the potential to take
too much time to complete and, in some cases, could be misconfigured in such a way as to
hang the entire VRM process. In order to avoid this situation, timeouts are in place that will
terminate any processes that have taken too long.
There are two timeouts associated with each activity – a “runtime” timeout that tracks the
amount of time a process has taken while running and a “queue” timeout that is associated
with how long a given process has been waiting to begin. The “queue” timeout is only
meaningful when using a grid management system like LSF or SunGrid.
All values are given in seconds. By default, all processes’ runtime timeouts default to 3600s
(1 hour) and queue timeouts default to 60s. Timeouts can be disabled via a VRM command-
line argument (controllable via the “make vrun” makefile target) and individual timeouts
can be increased or decreased via VRM INI variables. These can all be found in the table of
INI variables in section 4.2.1 of this document.
For more detail on how VRM handles timeouts please refer to the VRM User Guide.
For more detail on how to properly set these variables please refer to the VRM User Guide.
The following switches are supported by the yaml2uvmf.py command for YAML-based
generation of code. All of these switches can be viewed from the command through the ‘-h’
or ‘--help’ switches of the script.
Option Description
--version Show script version number and exit
--help | -h Show help message and exit
--clean | -c Clean up generated code instead of
generating code
--quiet | -q Suppress output while running
--dest_dir=DEST_DIR | -d DEST_DIR Override default destination directory of
‘./uvmf_template_output’
--template_dir=TEMPLATE_DIR | -t Override the template source directory to
TEMPLATE_DIR utilize, overriding default directory
‘template_files’ relative to location of
the uvmf_gen.py script.
--overwrite | -o Overwrite existing output. Default is to skip
any existing output.
--file=FILE | -f FILE Specify a list of YAML configuration files as
an input file
--generate=GEN_NAME | -g GEN_NAME Specify which elements to generate. Default
is to generate everything.
--merge_source=DIR | -m DIR Enable auto-merge flow, pulling information
from the specified directory.
--merge_output=DIR | -e DIR Specify output directory for auto-merge.
Default is ‘uvmf_template_merged’
--merge_skip_missing_blocks | -s Continue merge if unable to locate a labeled
block in new output that was defined in old
source and produce a list of issues at the
end. Default behavior is to raise an error
and quit.
The UVM Framework includes example environment templates. They are located under
the templates/python/examples directory. The names of the example
environment templates are block_a_env, block_b_env, chip_env, and block_c_env. The
template requires the following information: environment name, agents contained in the
environment, analysis components contained in the environment, scoreboards contained in
the environment and the connections between agents, analysis components and
scoreboards. The format can be viewed in the examples. The docs directory contains
reference guides for the YAML and Python API template generators.
Block_a is an example of an environment and bench without parameters. Block_b is
an example of an environment and bench that uses parameters, has a UVM register model,
and uses DPI-C. Chip_env is an example of a chip level environment that instantiates a
block_a sub environment and a block_b sub environment. The block_c example
demonstrates use of Questa VIP for standard protocols in an environment that also
contains custom protocols, predictors, and scoreboards. These examples are provided in
both API and YAML formats within the api_files and yaml_files directories respectively.
Block diagrams of these examples are shown below.
block_a_pred
control_plane_sb
0 2 4
control_plane_in A S A control_plane_out
P secure_data_plane_sb
1
secure_data_plane_in A 3 5
S A secure_data_plane_out
block_a_cov
6
C
7
control_plane_pred control_plane_sb
0 3 5
control_plane_in A P S A control_plane_out
unsecure_data_plane_pred unsecure_data_plane_sb
1
4 6
2 P S A unsecure_data_plane_out
unsecure_data_plane_in A
block_a Block_b
Environment Environment
control_plane_in
control_plane_out
block_a
secure_data_plane_in secure_data_plane_out
Environment
mem_monitor_bfm
internal_control_plane_out_mon_bfm(internal_control_plane_out_bus);
mem_monitor_bfm
internal_control_plane_in_mon_bfm(internal_control_plane_in_bus);
This code must be converted to the following to connect the internal interfaces between the
two block levels. The two signal bundles of type abc_if are combined into one named
mem_monitor_bfm
internal_control_plane_out_mon_bfm(internal_control_plane_bus);
mem_monitor_bfm
internal_control_plane_in_mon_bfm(internal_control_plane_bus);
Further optimization can be achieved by having the two environments share the same UVM
based mem_monitor using the mechanism shown in the ahb2spi environment example.
control_plane_in
secure_data_plane_out
block_a
secure_data_plane_in internal_control_plane_out
Environment
control_plane_out
internal_control_plane_in Block_b
Environment unsecure_data_plane_out
unsecure_data_plane_in
5.7 Using the Questa VIP Configurator in tandem with UVMF code generators
The Questa VIP Configurator is used to generate UVMF based environments containing
standard protocols. The UVMF environment generated by the configurator contain the
agents and configuration policies for each standard protocol selected by the user. This
Class: qvip_agents_environment 9
1
axi4_master_1 AXI4 Inst: qvip_env AXI4 axi4_slave
2 10
axi4_master_0 AXI4 APB3 apb3_config_master
pcie_ep PCIe
The standard protocol agents generated by the QVIP configurator are contained by
the UVMF environment named qvip_agents_environment. This environment is integrated
into the block_c_environment using the qvip_subenv label in YAML or the addQvipSubEnv()
Python API in the environment code generator. The numbers on the diagram are used to
identify the UVM connections and the generator constructs used to create the connections.
YAML format:
qvip_connections :
- driver: “qvip_env.axi4_master_0”
ap_key: “trans_ap”
receiver: “blk_c_pred.axi4_master_0_ae”
The analysis ports within QVIP are located within an associative array of analysis
ports named ap. This associative array is indexed using a string. In the above example the
trans_ap argument is used as a string to index into the associative array of analysis ports
within the QVIP agent to select the desired analysis port within the array. All analysis ports
within ap broadcast transactions that are casted to the base class type named
mvc_sequence_item_base. These analysis ports must be connected to analysis exports
parameterized to receive transactions of type mvc_sequence_item_base. Transactions
received through the analysis export must be casted to the expected transaction type.
QVIP agents contain default analysis ports. The Users Guide for each protocol
within the QVIP installation describes the analysis port name and transaction type
broadcasted for each protocol. Remember that the analysis export must be parameterized
to receive mvc_sequence_item_base and the received transaction must be casted to the type
listed in the protocol specific users guide in the QVIP installation docs directory.
UVM Framework Users Guide 71
5.7.3 Clock generation within QVIP Configurator generated UVMF module
The QVIP configurator generates a module that contains all of the QVIP interface
BFM’s. The name of this module is based on the test bench name: hdl_benchName.sv. This
module contains a default clock and reset generator. There is no interaction between this
clock/reset generator and the clock/reset generator used in hdl_top.sv created by UVMF. If
a single clock/reset generator is required then ports can be added to the hdl_benchName
module to bring in clock and reset from hdl_top.sv.
When using the YAML-based generation flow you can point to a previous iteration of your
generated code when producing a new version of the code. In doing so, the script will
attempt to extract any hand-edits from the old version and place them into the new output.
This is accomplished through the use of labeled blocks within the source - all hand edits
should be made within these blocks in order to ensure everything is reliably transferred.
The “yaml2uvmf.py --merge_source” switch enables this capability. An older generated
output directory that underwent hand edits should be pointed to with this switch.
The user can search for these pragma blocks in addition to “UVMF_CHANGE_ME” in order
to track down areas of code that will require hand edits.
All blocks must begin with a “begin” pragma and end with an “end” pragma using the same
label name. Blocks may not be nested, and all label names must be unique within a given
file.
do_monitor()
do_monitor()
do_monitor() snoops transfer information
notify_transaction()
notify_transaction() places transfer variables into
transaction object then broadcasts transaction
start_item/finish_item 1
get_next_item()
2
3
access() initiate_and_get_response()
5 4
Process response item_done()
start_item/finish_item
get_next_item()
access() initiate_and_get_response()
start_item/finish_item S1
get_next_item()
Initial pass through start_item/finish_item/get_next_item
gives the driver class a handle to the responder sequence S2
so that it can send initiator data back to the sequence.
S3
access() respond_and_wait_for_next_transfer()
1
Process data from initiator 2 item_done()
to determine response 3
start_item/finish_item 4
get_next_item()
5
6
access() respond_and_wait_for_next_transfer()
start_item/finish_item
get_next_item()
access() respond_and_wait_for_next_transfer()
The agent configuration object is located in the environment configuration object. The
agent configuration contains a handle to the agent’s sequencer, driver BFM virtual interface
handle, and monitor BFM virtual interface handle.
The agent configuration places itself in the uvm_config_db using null for the cntxt
and “UVMF_CONFIGURATIONS” as the inst_name arguments. The interface_name
argument in the agent configuration is used for the field_name argument.
The top level virtual sequence base retrieves the agent configuration handles from
the uvm_config_db. Through the agent configurations, the top level virtual sequence base
has access to all agent configurations for starting sequences on any sequencer.
The monitor and driver BFM virtual interface handles are available through the
uvm_config_db. The virtual interface handles are placed into the uvm_config_db by
hdl_top.sv. The cntxt argument is null, the inst_name argument is
UVMF_VIRTUAL_INTERFACES, the field_name argument is the interface_name variable in
the agent configuration class. The monitor and driver BFM virtual interface handles are
retrieved by the agent configuration in the initialize function of the
uvmf_parameterized_agent_configuration_base. The agent configuration initialize function
receives the interface_name as an argument. This argument is used to retrieve the monitor
and driver BFM handles from the uvm_config_db.
7.2.3 Sequencer Handles
The sequencer handle is made available to the top level virtual sequence through
the agent configuration handle.
The sequencer handle is also available for retrieval from the uvm_config_db. The
cntxt argument is null, the inst_name argument is UVMF_SEQUENCERS, the field_name
argument is the interface_name variable in the agent configuration object. Though the
sequencer handle is available in the uvm_config_db, it is not retrieved from the
uvm_config_db by the UVMF or any generated code. This is to avoid simulation
performance impact caused by uvmf_config_db:: get calls.
The UVM Framework is architected for reuse. One key characteristic of reuse is self-
containment. Reusable components automatically get needed resources, construct and
configure children components and make internal resources available to other
components. The two mechanisms for applying this are the initialize function and
set_config function.
The initialize function passes information down through the configuration object
hierarchy. This information configures environments and agents in a simulation. It begins
at the top level UVM test and ends at agent configurations. It is the mechanism by which all
agents are initialized.
The set_config function passes configuration object handles down through the
environment hierarchy.
It is important to note that the code listed below is automatically generated when
generating an interface package, environment package and project bench.
The initialize function passes information down through the configuration hierarchy.
It starts at the top level UVM test and ends at the agent configurations. The configuration
class for each agent in a simulation is initialized using this mechanism. At the top level
UVM test and environment level the initialize function passes the following information:
simulation level, hierarchical path down to the configurations environment and an array of
string names that uniquely identify each interface in the design. At the agent level the
initialize function passes the following information: active/passive state of the agent,
hierarchical path to the configurations agent and unique string identifying the agents
handle to the interface BFMs (driver BFM and monitor BFM).
The following initialize flow is from the ahb2wb example.
The code below is from test_top.svh. Keep in mind that the build_phase function of
this component completes before the environment build_function is executed. This allows
Lines 30-33: Create an array of strings that contains the unique names of each
interface BFMs in the simulation. These values are parameters defined in tb/parameters
Lines 35-38: Create an array of agent activity settings. The order matches the
interface name order. Since this is a block level simulation, all agents are passive. The
bench generator creates this code and assumes all agents are active. The user must specify
which agents are passive.
Line 70: Pass the array of agent interface names to the environment,
uvm_test_top.environment. Each environment will distribute these names to sub-
environemnts. Ultimately, each agent configuration will receive its own unique interface
name. The agent configuration uses this name to retrieve interface BFM handles from the
uvm_config_db. This name is also used by the agent to place its sequencer in the
uvm_config_db for retrieval by the top level sequence.
Liine 97: The initialize function is called to pass the ahb agent configuration
information required for setup. This call includes the active/passive setting, full path to the
agent in the environment hierarchy, and the unique string name of this interface.
Line 98: The activity setting determines the ACTIVE or PASSIVE setting of this agent.
Line 99: The full path to the agent in the environment hierarchy that this agent
configuration is paired with. Each agent has its own corresponding agent configuration.
This path is used by the agent configuration to place itself in the uvm_config_db. The path
Line 100: The interface name uniquely identifying this agent. This variable is used
by the agent configuration to retrieve the monitor BFM and driver BFM if the agent is
configured as ACTIVE.
Lines 103-107: These lines are used to pass initialization information to the wb
agent.
Line 82: This configuration object places itself in the uvm_config_db using the string
that identifies the interface BFMs used for this agent. This creates an automatic association
between an interface and its configuration.
Lines 110-111: Set the local activity level and interface string name variables from
the arguments to the function call.
Lines 114-115: Check the uvm_config_db for command line setting of the
enable_transaction_viewing flag for this interface.
Lines 117-120: Retrieve the handle to the monitor BFM. Generate an error if the get
function fails.
Lines 122-126: If the agent is configured as active then retrieve the handle to the
driver BFM. Generate an error if the get function fails.
The code below is from uvmf_test_base.svh. This call is made in the build_phase and
happens automatically for any test_top derived from uvmf_test_base. This call is performed
on the top level environment. If the environment is not a block level, i.e. chip level or
The code below is from ahb2spi_environment.svh. The build phase of this chip level
environment uses set_config to pass configuration handles into lower level environments.
Line 60: Pass the ahb2wb_config handle into the ahb2wb environment using
set_config.
Line 63: Pass the wb2spi_config handle into the wb2spi environment using
set_config.
The add_to_wave function of the wb_transaction class of the wb_pkg is shown below.
Line 63: This line executes the add_to_wave function in the base class. It adds
variables in the base class, uvmf_transaction_base, to the waveform viewer.
Lines 64-67: The add_attribute system function adds transaction variables to the
waveform viewer. The second argument is the data variable to be added. The third
argument identifies the variable value.
Line 68: The end_transaction system function call sets the end time of the transaction
in the waveform viewer.
Line 69: The free_transaction system function call closes the transaction viewing
handle on the stream and completes the process of adding the transaction.
The UVM recording detail of the simulation can be set in either of the two
mechanisms listed below:
Add the following line to the UVM test case in any phase prior to and including the
run_phase:
set_config_int(“*”,”recording_detail”,UVM_FULL);
The line below adds the transaction viewing stream, txn_stream, in the wishbone
agent monitor component with the hierarchical path listed. The transaction stream of any
UVMF based monitor can be added to the waveform in the same manner.
Lines 48 and 52 instantiate the alu_in_if and alu_out_if signal bundles respectively.
Lines 49 and 53 instantiate the alu_in_if and alu_out_if monitor BFMs. Lines 50 and 54
instantiate the alu_in_if and alu_out_if driver BFMs. The monitor and driver BFM port lists
require a reference to the signal bundle. This allows the monitor BFM to observe signals in
the signal bundle and the driver BFM to drive signals in the signal bundle.
Line 59 defines the module type, alu, and instance name, DUT. Parameters for the
module are defined in the parenthesis following the #. Lines 60 through 68 list the ports of
the alu module. The parenthesis following each port name identify the signal to be
connected to the port. For each port connection the interface signal bundle and signal
within the signal bundle is identified using hierarchical notation.
10.1.2 Hvl_top
The module named hvl_top, located in tb/test bench directory, imports the test
package and contains the call to run_test which executes the UVM phases. The UVMF uses a
two top architecture, hdl_top and hvl_top, to support emulation. Hdl_top is synthesized
into the emulator. Hvl_top is run on the host simulator.
The code below is from hvl_top from the ALU example.
Line 42 imports the alu test package which contains all alu tests. The call to run_test
in line 46 starts execution of all UVM phases.
An example sequence derived from the top level sequence base is generated by the
bench generator. It is named example_derived_test_sequence and is located in
project_benches/<bench_name>/tb/sequences/src.
13.6 Makefile
A makefile named Makefile should be created for compiling the interface and package
for the VIP. The makefile should contain a make target named comp_xyz_pkg where xyz is
the protocol name. If this recommendation is not followed then the test bench makefile
must be modified accordingly. The makefile from an interface package generated using the
UVMF code generator can be used as a template for creating the interface makefile.
extends uvm_driver
uvmf_driver_base
Sequencer
Connection
virtual task access(inout REQ txn); Pin level interface
(BFM_BIND_T)
Coverage
(COVERAGE_T) Monitor
(MONITOR_T)
extends uvm_scoreboard
uvmf_scoreboard_base
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_in_order_scoreboard
try_put()
try_get()
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_in_order_scoreboard_array
extends uvm_scoreboard
extends uvmf_scoreboard_base
uvmf_out_of_order_scoreboard
t.get_key() used to
index into Hash
T expected_hash[integer]