GO2UVM Debug 2016
GO2UVM Debug 2016
Given the major adoption of UVM across the globe and Specifically, we will highlight a few hand-picked features in
across the industry, advanced users are looking for tips the UVM factory and provide tips and tricks around them.
and tricks to improve their productivity. UVM does define It is expected that the readers are conversant with the
a structured framework for building complex testbenches. UVM framework to appreciate the tips presented below.
It is built on strong OOP principles and design patterns
using underlying SystemVerilog language features. This
strong OOP nature presents certain challenges to the UVM provides a convenient way to control which
end users. Recall that many Design-Verification (DV) objects get manufactured at run time via the well-known
engineers come from hardware, electronics backgrounds Factory Design pattern. Wikipedia defines factory
and not heavy Software backgrounds. Hence at times it pattern as:
gets tricky for users to debug UVM based testbenches
In class-based programming, the factory method pattern
when things do not work as expected.
is a creational pattern that uses factory methods to deal
In this article the authors share their long experience of with the problem of creating objects without having to
assisting customers with run time debug of common UVM specify the exact class of the object that will be created.
issues and potential solutions to them. During our various This is done by creating objects by calling a factory
training and consulting engagements using UVM we have method rather than by calling a constructor.
seen DV engineers struggling to debug relatively simple
In UVM to use factory, there are three important steps:
UVM issues. It will be unfair to blame the
users as many a times, the error 1. Registration – all classes shall be registered
messages are with a global factory singleton table
2. Use class::type_id::create() instead of new()
3. Use set_type_override functions
41
Figure 1: Sample log with s2p_xactn
TIP: Look at the “Type” column in standard UVM print Figure 5: Pseudo-code to replace existing override
(uvm_object::sprint) to see if your override indeed worked!
If not, no need of waveforms to debug, go back to your This is a handy trick to run a test with a few 100 transactions
UVM code! first with one type and then replace with another derived
type and run another few 100s within the same test!
There are cases when multiple overrides are set on the TIP: Look for UVM log ID “TPREGR” as shown below
same object. There are use cases to “ignore” such to ensure your replacement is guaranteed!
overrides and then other situations where-in it is desired
to “replace”. UVM’s factory override mechanism supports
both requirements. Consider a transaction model derived as
shown in Figure 4, there are two similar error transactions
derived from a base s2p_xactn.
Figure 6: Built-in debug hook in UVM
to display factory replacement
42
Often in a IP to sub-system reuse scenarios the
subsystem engineer is not fully aware of IP level sequence
functionality. It is possible that a factory override was
already set by the IP level sequence. Imagine a scenario
Figure 9: Built-in debug hook in UVM to display
where-in a sub-system verification engineer wants to
factory override behavior
“query” the IP sequence to see if an override exists, if not,
set a new override.
Sometimes the user wants to “undo” an override – i.e.,
a base class has been overridden to be replaced with a
derived class. A little later, with-in the same simulation one
wants to remove/undo the override and revert back to base
class. This makes sense only for transactions/sequence
items as the override plays a role only when the create()
gets called AFTER the override setting.
While the above code will work fine with the latest UVM 1.2
release, in case of UVM 1.1d (which is more prevalent at
many customer designs as of today), the above code will
lead to an error as shown below in Figure 11.
Figure 8: Pseudo-code to query and add a new override
43
A work-around for achieving the same in UVM 1.1d version A code snippet of internal implementation of UVM factory
could be to derive a dummy, new class from the base class is shown in Figure 13 below.
and use it. The new class that is derived should contain no
extra code and is intended to just fool the compiler to treat
it as a derived type, but functionally same as the base type.
Figure 12 shows a possible s2p_undo_xactn UML diagram
to explain this.
When things do not work as expected, the user can add the
following code snippet inside a test:
44
passed to the name argument the same as the handle
In UVM components are built hierarchically and hooked name. There are cases such as AXI fabric environments
up at the top level. The hook-up happens through 2 key where-in the same agent is instantiated many times using
fields – name and parent. Every UVM component in user a dynamic array. Hence the handle name is an array
code implements new() as shown below in Figure 16. variable, where-as the name argument must be created to
be unique for each element in that array. While
doing this, care must be taken to:
Figure 16: Typical constructor in a UVM component For simplicity, let’s consider a case where-in we
change the name to be different than the handle. Figure
For the first-timer the above code looks a bit strange, but 18 shows an AXI fabric UVM setup. The environment is
since the base class (uvm_component to be precise) instantiated with a handle named axi_fabric_env_0.
requires these 2 arguments, it becomes important to
stick to this style (though technically speaking there are
other crude ways with default values, etc.). The parent
argument in the component’s constructor is expected to
be connected to the “testbench” parent component (and
not necessarily a standard OOP parent class). A typical
hierarchy/topology of a UVM testbench looks as shown
in Figure 17. The standard UVM print_topology prints in
a tree format as shown below and every “indentation”
level indicates a layer in the testbench. For instance,
driver is indented inside agent. It indicates that driver’s
parent argument is connected to the agent object.
45
automation brings productivity to the
teams. Debugging UVM issues can
become tricky and painful if users are not
fully aware of many of the built-in debug
hooks in the base class library of UVM.
In this article the authors shared some
Figure 19: Instance specific override for AXI transaction
of the time tested tips with respect to UVM factory. All the
While the above code shall compile, run, it will not produce tips mentioned are tool and vendor independent and comes
the intended overrides! The reason being that the name for free with UVM. Readers are encouraged to see the
of the environment with the handle axi_fabric_env_0 has references section to learn more such tips and tricks.
been set to CRAZY_ENV during the build phase (Refer to
Figure 18).
Figure 20 shows the correct way to get the instance specific • Accellera UVM standard: http://accellera.org/activities/
override working in this case. Please note that this is an working-groups/uvm/
experimental example to demonstrate the impact of name • DVCon US 2016 UVM tutorial, available on request
argument in UVM and the authors do NOT recommend this via http://www.verifnews.org
unless it is really necessary.
46
Editor: Tom Fitzpatrick
Program Manager: Rebecca Granquist
To subscribe visit:
www.mentor.com/horizons