Hierarchical Testbench Configuration Using Uvm

Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

White Paper

Hierarchal Testbench Configuration


Using uvm_config_db
June 2014

Authors

Abstract

Hannes Nurminen
Professional
Services, Synopsys

SoC designs have become extremely complex as more and more IP blocks are integrated into them. This
increases the verification challenge manifold in terms of configuration and data handling, as well as architecting
and maintaining a large verification environment. Hence it has become very important to create a robust and
reusable testbench using a proven methodology that does not just facilitate but also improves the efficiency in
verifying different configurations of the device under test (DUT).

Satya Durga Ravi


Professional
Services, Synopsys

Accellera Systems Initiatives Universal Verification Methodology (UVM), a stable and widely used methodology
for architecting testbenches for verification of complex designs helps mitigate these verification challenges
to create a scalable, robust and reusable test environment. UVM provides a vast set of macro, policy and
base classes that help facilitate the creation of these testbenches, including an easy way to pass objects and
variables across testbench hierarchy.
For engineers who are new to verification methodologies or are in the process of adopting UVM, this paper
focuses on the UVM configuration mechanism uvm _ config _ db, which helps in passing different class
properties across hierarchy testbench components. Through the use of examples, the usage, techniques, and
limitations of uvm _ config _ db are explained.

Introduction
To address the needs of todays verification architecture, a hierarchical setup of components is necessary to
easily move or share configurations and other parameters across different testbench components. To enable
this, UVM provides the infrastructure to maintain a database of objects and variables that can be populated
and accessed using strings. This is achieved using the UVM syntax uvm _ config _ db.
Using uvm _ config _ db, objects can share the handle to their data members with other objects. Other
testbench components can get access to the object without knowing where it exists in the hierarchy. Its
almost like making some class variables global or public. Any testbench component can place handles and
get handles to objects. In the database, handles are identified by assigned type and name.
Primarily there are two uvm _ config _ db functions, set() and get(). Any verification component using
set() gives others access to the object it has created and controls which components have visibility to the
object it has shared. The object can be shared globally or made available to one or more specific testbench
components. Verification components using get() check if there is a shared handle matching the used
parameters. The get() function defines the object type, the name and hierarchical path to the object
searched for.

How to Use It Different Syntax and Operation


Explicit set() and get() call functions are how you interact with the uvm _ config _ db. The uvm _
config _ db class functions are static, so they must be called using the :: operator.

2 uvm _ config _ db#(<type>)::set(uvm _ component


3
string
4
string
5
<type>
6
7 uvm _ config _ db#(<type>)::get(uvm _ component
8
string
9
string
10
ref

cntxt,
inst _ name,
field _ name,
value)
cntxt,
inst _ name,
field _ name,
value)

Figure 1: set() and get() function syntax

cntxt and inst _ name are used to specify the storage location or address of the object handle. When used
properly these parameters define the hierarchical path to the object data.
field _ name is the name for the object. It does not have to match the objects actual name in the source code.
Objects using set() and get() must use exactly the same name, otherwise the receiving party (get()) will fail to
find the object from uvm _ config _ db.
value is the actual object handle shared through the uvm _ config _ db. Multiple recipients accessing an
object via get(), will access the same object.
<type> is used as a parameter for the uvm _ config _ db class to identify the object from the uvm _
config _ db. <type> which may be either an integral or string, is the class name of the value. The exception
is with enumerated type variables which must use int otherwise the set() wont work as expected.
13 typedef enum {single,incr,wrap4,incr4,wrap8,incr8,wrap16,incr16}hburst _ t
14 hburst _ t
hburst;
15 uvm _ config _ db#(int)::set(this,a,hburst,incr);
Figure 2: config_db for enum type

The set() specifies the address (cntxt & inst _ name) where the object handle is stored to control the
recipient(s) of the object. The get() has the same flexibility, and can freely select from where the information is to
be fetched. In practice get() can be used to fetch an object destined to any component in the hierarchy. Typically
for set() and get(), this is used in the cntxt field to specify the current instance/scope. set() uses
inst _ name to address the object to the appropriate sub-block in the hierarchy. get() often uses empty ()
inst _ name, since it typically is getting the objects destined for itself.
5 uvm _ config _ db#(int)::set(this,my _ subblock _ a,max _ cycles,max _ cycles)
6 uvm _ config _ db#(int)::get(this,, max _ cycles,max _ cycles)
Figure 3: set() and get() typical use

uvm _ config _ db has two additional functions exists() and wait _ modified(). exists() verifies that the
defined variable is found in the uvm _ config _ db. The wait _ modified() function blocks execution until the
defined variable is accessed with the set() call.
2 uvm _ config _ db#(int)::exists(this,my _ subblock _ a,max _ cycles)
3 uvm _ config _ db#(int)::wait _ modified(this,my _ subblock _ a,max _ cycles)
Figure 4: exists() and wait_modified() typical use

Hierarchal Testbench Configuration Using uvm_config_db

Automatic Configuration
UVM also offers build-time configuration of uvm _ component (and extended) classes utilizing uvm _ config _
db. In automatic configuration, it is sufficient to call set() from an upper layer in the hierarchy and the get() will
automatically execute at build time without requiring an explicit call. Automatic configuration utilizes the uvm _
config _ db feature under the hood to pass the configuration values from higher level testbench components in
the hierarchy to its lower level components.
For automatic configuration to work there are two important requirements:
``
The variable or object must have the appropriate FLAG in uvm _ field _ * macros
``
super() must be called in build _ phase()

3 class agents extends uvm _ agent;


4 int i4;
5 `uvm _ component _ utils _ begin (agent)
6
`uvm _ field _ int (i4, UVM _ ALL _ ON)
7 `uvm _ component _ utils _ end
8
9 virtual function void build _ phase(uvm _ phase phase);
10
super.build _ phase(phase);
11

12 endfunction
13
14 endclass
Once the component properties have the uvm _ field _ * declaration(s) in place with the appropriate FLAG(s),
the macro provides the set _ * _ local functionality and super.build _ phase() calls the apply _
config _ settings() method under the hood. The apply _ config _ settings() method searches for all
appropriate config settings matching this components instance and for each match, the appropriate set _ * _
local method is called using the matching uvm _ config _ db settings field _ name and value.
The super.build _ phase() method may be replaced with the apply _ config _ settings() method
however it is recommended to use the super.build _ phase() method.
15 class agent extends uvm _ agent;
16 int i4;
17 uvm _ component _ utils _ begin(agent)
18
`uvm _ field _ int (i4, UVM _ ALL _ ON)
19 uvm _ component _ utiles _ end
20
virtual function void build _ phase(uvm _ phase phase);
21
apply _ config _ settings(1); //No super.build _ phase(phase)
22

23
endfunction
24
25 endclass
The implicit get() method call will not work in the following instances:
``
Missing uvm _ field _ * macro

``
FLAG is set to UVM _ READONLY

``
Missing super.build _ phase() or apply _ config _ settings() in build _ phase()
Below are log messages generated during the simulation phase because of an explicit apply _ config _
settings() function call:
UVM _ INFO @ 0: env.name _ agent _ 1 [CFGAPL] applying configuration settings
UVM _ INFO @ 0: env.name _ agent _ 1 [CFGAPL] applying configuration to field i4
To set the value for i4 of the above agent, env would have the build _ phase() below:
3 function void build _ phase (uvm _ phase phase);
4
agent _ 1 = agent::type _ id::create(name _ agent _ 1, this);
5
uvm _ component _ db#(int)::set(this, name _ agent _ 1, i4, 1111);
6 endfunction
Hierarchal Testbench Configuration Using uvm_config_db

During the build phase of the simulation the agent objects i4 variable would get value 1111. It is important to note
that automatic configuration happens only at build phase.

Command Line
Compilation and simulation time are the major contributors to verification overhead. The ability to change the
configuration or parameters without being forced to recompile is critical. The UVM class uvm _ cmdline _
processor provides a mechanism to capture the command line argument and pass to verification components
the testcase name, verbosity, configuration and other attributes.
Configuration overriding can only be done from the command line for integer and string using the following:
+uvm _ set _ config _ int=<comp>,<filed>,<value>
+uvm _ set _ config _ string=<comp>,<field>,<value>
There is no way to override the object from the command line, because uvm _ object cannot be passed to
the simulation.
When using the command line argument to set the configuration, make sure that the <type> used in
uvm _ config _ db set() and get() functions is uvm _ bitstream _ t for integer and the <type> for
string is as shown below:
2 class env extends uvm _ env;
3
int a;
4
string color;
5

7
function new(string name, uvm _ component parent);
8
super.new(name, parent);
9
endfunction
10
11 virtual function void build _ phase(uvm _ phase parent);
12
super.build _ phase (phase);
13
if(!uvm _ config _ db #(uvm _ bitstream _ t)::get(this, , a, a))
14
`uvm _ fatal(GET _ NOTSUCC, Get is not successful for a .);
15
if(!uvm _ config _ db #(string)::get(this, , color, color))
16
`uvm _ fatal(GET _ NOTSUCC, Get is not successful for color.);
17
`uvm _ info(GET _ VALUE, $psprintf (The value of a = %d and color =

%s,a,color),UVM _ LOW);
18 endfunction
19
20
21 endclass
22
23 class test extends uvm _ test;
24 int a = 2;
25 string color =blue;
26 env env _ i;
27
28
29 virtual function void build _ phase(uvm _ phase phase);
30 super.build _ phase (phase);
31 env _ i = env:type _ id::create(env _ i, this);
32 uvm _ config _ db#(uvm _ bitstream _ t)::set(this, env _ i, a, a);
33 uvm _ config _ db#(string)::set(this, env _ i, color, color);
34 endfunction
35
36 endclass
The command line argument for the example above is:
<simulation command> +UVM _ TESTNAME=test +uvm _ set _ config _ int=uvm _ test _
top.env _ i, a, 6 +uvm _ set _ config _ string=uvm _ test _ top.env _ i, color, red

Hierarchal Testbench Configuration Using uvm_config_db

The log message generated during simulation is:


UVM _ INFO @ 0: reporter [UVM _ CMDLINE _ PROC] Applying config setting from the
command line: +uvm _ set _ config _ int=uvm _ test _ top.env _ i, a, 6
UVM _ INFO @ 0: reporter [UVM _ CMDLINE _ PROC] Applying config setting from the
command line: +uvm _ set _ config _ string=uvm _ test _ top.env _ i, color, red

Cross-Hierarchical Access
The set() and get() parameters cntxt, inst _ name and field _ name make it possible to use a
number of different paths to the same object. cntxt uses actual object hierarchy whereas inst _ name and
field _ name uses the hierarchy path with names given to the objects in create()/new() method. It is good
practice to create the objects with the same name as the object name.
When referencing down in hierarchy, it should be enough to use this in cntxt and then provide the path and/
or names in inst _ name. Field _ name should be used just for the name of the object. When referencing
upwards in hierarchy, utilize the uvm _ root::get() function to get access to the hierarchy root, and then
reference down from there using inst _ name parameter.
Figure 5 below clarifies and provides examples how objects can be referenced in uvm _ config _ db.
To one object

To multiple objects

To everyone

test a

test a

test a

env

env

env

Upwards from one objects

Horizontaly from objects

test a

test a

env

env

agent_1

agent_1

agent_1

agent_1

agent_1

agent_2

agent_2

agent_2

agent_2

agent_2

Figure 5: Options for using cntxt and inst_name parameters in set() and get()

uvm _ config _ db does not actually limit how path field name is shared between cntxt, inst _ name and
field _ name. UVM combines all three of these parameters into one key that is used to access the database.
This feature makes it possible to reference the same object in multiple different ways using the 3 metacharacters
*,+,?. The table below determines the significance of each metacharacter:
Character

Meaning

0 or more characters

1 or more characters

Exactly 1 character

Hierarchal Testbench Configuration Using uvm_config_db

The illustration below shows using these metacharacters for the same object in uvm _ config _ db.
uvm _ config _ db#(<type>)::set( <cntx> , <inst _ name> , <field _ name> , <object>);
uvm _ config _ db#(<type>)::set( <cntx> , <inst _ name> , <field _ name> , <object>);

this env.name _ agen+


this env.name _ agent _ ?
this env.*

i _ of _ env
i _ of _ env
i _ of _ env

Figure 6: Different path notations to the one and same object

Where To UseUsage and Its Benefits


Passing Configuration
uvm _ config _ db is used often to configure agents of the testbench and to pass access to signal interfaces.
Agent is a class encapsulating sequencer, driver and monitor. Agent usually takes care of generating and receiving
data for an interface. The configuration variables or virtual interface are set at agent from top-level and later the
agent is responsible for passing the virtual interface or configuration to other sub-components rather than passing
it from top-level as shown in the figure below. Agents are often reused either as VIP blocks or across projects.
This means that the receiver (get) of the information dictates type and field _ name, and source of the
information (set) must use proper parameters when setting data into uvm _ config _ db. This is also part of the
beauty of uvm _ config _ db: agents can be created without knowing where the parameters or signal interfaces
are coming from, from where in the testbench hierarchy the agent object exists, what name it has, or how many
instances there are in parallel.
test_a

test_a

cfg

env

cfg

env
agent_1

agent_1
set

set

sequncr

sequncr

set
cfg

cfg

set
set

cfg

cfg

set

set
monitor

driver

monitor

driver

cfg

cfg

cfg

cfg

set

Figure 7: Passing configuration to agent and sub-components

Passing Virtual Interface


Passing the virtual interface across the verification component is the most common requirement when creating the
reusable verification environment. The preferred approach of doing this in UVM is to push the virtual interface into the
configuration database from top-level. This is because top-level module is not uvm _ component hence the context
is null and the instance is the absolute hierarchal path of the component where the virtual interface is assigned.
The absolute hierarchal instance of the component starts with uvm _ test _ top. Because the environment is
usually instantiated by test and agent, it can extract the virtual interface from the configuration database as shown
in the example on the next page

Hierarchal Testbench Configuration Using uvm_config_db

2 module tb _ top();
3 svt _ axi _ if vif();
4
5
6 initial begin
7
uvm _ config _ db #(virtual svt _ axi _ if)::set(null, uvm _ test _ top.env.m _
agent _ 0, vif, vif);
8 end
9 endmodule
10
11 class axi _ agent extends uvm _ agent;
12
virtual svt _ axi _ if vif();
13

14
15
virtual function _ void build _ phase(uvm _ phase phase);
16
super.build _ phase(phase);
17

18
if(!uvm _ config _ db#(virtual svt _ axi _ if)::get(this,,vif, vif))
19
`uvm _ fatal(AXI _ AGENT:NOVIF, The virtual interface get is not successful);
20
uvm _ config _ db#(virtual svt _ axi _ if)::set(this, driver,vif,vif);
21
uvm _ config _ db#(virtual svt _ axi _ if)::set(this,monitor,vif,vif);
22
endfunction
23 endclass

Event Synchronization
uvm _ config _ db is used to make the object available for others, it does not create new copies of the object.
Figure 8 below shows how event-object created by Object A is also made available to Objects X, Y and Z through
the uvm _ config _ db. When Object A chooses to use trigger() for the event object, others can detect
it because they have access to exactly the same object. This demonstrates how the same object event is
referenced from four different objects with three different instance names.
Object X
uvm _ event my _ event;
uvm _ config _ db#(uvm _ event)::get(this, , my _ event, my _ event);
Object A
uvm
_ event my _ event;
my _ event = new(my _ event);
uvm _ config _ db#(uvm _ event)::set(this, agent*, my _ event, my _ event);

&

Object Y
uvm _ event my _ event _ also;
uvm _ config _ db#(uvm _ event)::get(this, , my _ event, my _ event _ also);
Object Z

event

uvm _ event my _ event _ too;


uvm _ config _ db#(uvm _ event)::get(this, , my _ event, my _ event _ too);

Figure 8: uvm_config_db shares handles to existing object

Some attention needs to be paid that set() is called before get()for a specific item, otherwise get() will
fail. Values passed through uvm _ config _ db before run _ phase() need to take into account that
build _ phase()constructs objects from top to bottom. This is often the desired order, since settings and
configurations are usually set from higher levels to lower levels via agents. During the simulation, use of set()
and get() need to be synchronized/timed by the normal testbench operation or by using events to create a
synchronization mechanism.

Limitations
uvm _ config _ db can be used anywhere in the hierarchy. The first parameter of set() and get() functions,
cntxt, however needs to be of type class uvm _ component (or extended from that). cntxt parameter
is often given value utilizing class member this. So if set() or get() functions are used outside uvm _
component extended object, cntxt parameter can be given value using uvm _ root::get(), or just
value null.

Hierarchal Testbench Configuration Using uvm_config_db

uvm_sequence
uvm_sequencer

uvm_driver

uvm_scoreboard

uvm_monitor

uvm_agent

uvm_env

uvm_test

uvm_sequence_base

uvm_component

uvm_sequence_item

uvm_report_object

uvm_transaction

uvm_object
uvm_void

Figure 9: set() and get() functions need cntxt parameter of type uvm_component or null

One common usage of uvm _ config _ db outside uvm _ components, is delivering values from hdl _ top to
the testbench, including access to interfaces instantiated on hdl _ top. Though hdl _ top is not extended from
any UVM class, uvm _ config _ db can still be utilized and communication with the UVM part of the testbench
is possible.
If set() or get() function is used with cntxt parameter not pointing to object of uvm _ component extended
classes, there will be a compile error as shown below.
25 Error-[SV-IUOT] Illegal us of this
26
test.sv, 9
27
this can only be used in a class method.
28
29 Error-[ICTTFC] Incompatible complex type usage
30
test.svh, 281
31
Incompatible complex type usage in task or function call.
32
The following expression is incompatible with the formal parameter of the
33
function. The type of the actual is class
34
my _ pkg::bus _ slave, while the type of the formal is class
35
uvm _ pkg::uvm _ component. Expression: this
36
Source info: uvm _ pkg _ uvm _ config _ db _ 2116934237::get(this, \000,
37
this.get _ full _ name(), my _ agent)
Figure 10: Example error messages when trying to use this for non-uvm_component in set/get

Problems, Errors and Debug


Even though operation and use of set() and get() functions with uvm _ config _ db are logical and quite
simple, uvm _ config _ db related debugging is often needed. Some errors may stop the compile or simulation
making them easy to find, as opposed to a coding error that simulates without error even though the get()
function was receiving incorrect objects. Some common types of errors are:
``
Compile time errors
Parameter type does not match provided T value
Trying to use this-pointer from class not extended from uvm _ component

``
Simulation time errors

get() does not find what was set using set() due to misspelling of inst _ name or field value
null object access attributed to get() used before set()

Hierarchal Testbench Configuration Using uvm_config_db

Synopsys VCS Discovery Visualization Environment (DVE) has built-in support for UVM debug. Using the GUI, it is
possible to get list of Set calls without Get and Get calls without Set. These lists help to find and detect errors
in the testbench. Figure 11 below shows the DVE UVM debug dialog window.

Figure 11: Synopys VCS DVE UVM debug dialog window

The UVM command line option +UVM _ CONFIG _ DB _ TRACE makes all set() and get() calls visible in the
simulation log. However doing this makes the log file too verbose and difficult to interpret. For this reason tracing
is typically turned on only when finding a specific uvm _ config _ db problem. Below is an example of log
messages printed out when set() and get() functions are executed.
39 UVM _ INFO /global/apps4/vcs _ 2012.09-3/etc/uvm-1.1/base/uvm _ resource db.svh(129) @ 0:
40 reporter [CFGDB/SET]
41 Configuration uvm _ test _ top.env.name _ agent _ 1.i _ of _ env (type int)
42 set by uvm _ test _ top.env.name _ agent _ 1 = (int) 1
43
44 UVM _ INFO /global/apps4/vcs _ 2012.09-3/etc/uvm-1.1/base/uvm _ resource _ db.svh(129) @ 0;
45 reporter [CFGDB/GET]
46 Configuration uvm _ test _ top.env.name _ agent _ 1.i _ of _ env (type int)
47 read by uvm _ test _ top.env.name _ agent _ 1 = (int) 1
Sometimes it may help just to print out the name of the object. UVM object has functions get _ name() and
get _ full _ name(). By using these, it can be verified manually that names used in the source code and
named objects at runtime match. Below is an example of how to print the objects name.
49 $display(this.get _ name= %0s, this _ get _ full _ name= %0s, this.get _ name(),
this.get _ full _ name());

Conclusion
When using UVM you cant avoid uvm _ config _ db. So its better to get a solid understanding about what the
set() and get() functions of the uvm _ config _ db do and how you can use them more efficiently in building
your testbench. Below are some dos and donts found to be useful when using UVM.
Dos:
``
For simplicity and to avoid confusion, use the field name as the variable name
``
Investigate an upshot warning/error on an unsuccessful get() method call

``
Set the configuration variable needed across the verification component in the agents test environment
to enable the agent to later set its sub-components

Hierarchal Testbench Configuration Using uvm_config_db

Donts:
``
Avoid using the uvm _ config _ db mechanism excessively as it may cause
performance issues
``
Avoid using the automatic configuration or implicit get() method call
Apart from the above recommendations, it is recommended to use a UVM-aware GUI-based debugging tool such
as Synopsys VCS Discovery Visualization Environment (DVE). As part of Synopsys Professional Services we have
used these concepts across multiple customer engagements to successfully deploy UVM. For more information
on these services, see www.synopsys.com/services.

Appendix
Below is a sample UVM environment showcasing the examples presented earlier. set() and get() functions
utilize only integers (int) though classes and interfaces that would normally be used.
1 // Usage
2 // vcs R sverilog ntb _ opts uvm-1.1 debug _ all +vcs+vcdpluson
-1 sim.log
3 // q example.sv +UVM _ TESTNAME=test _ a
4 import uvm _ pkg::*;
5
6 module dut;
7
int dut _ int = 10;
8
initial uvm _ config _ db#(int)::set(uvm _ root::get(),
9
*,
10
from _ dut,
11
dut _ int
12
);
13 endmodule
14
15 module top;
16 initial run _ test();
17 dut i _ dut();
18 endmodule
19
20 class agent extends uvm _ component;
21 int i1 _ agent, i2 _ agent, i3 _ agent; // to receive values from uvm _ config _ db
22 int i4; // to use automatic configuration
23 uvm _ event new _ values; // to signal new step in test (env->agent)
24 `uvm _ component _ utils _ begin (agent)
25 `uvm _ field _ int(i4, UVM _ ALL _ ON)
26 `uvm _ component _ utils _ end
27 function new (string name, uvm _ component parent);
28
super.new(name, parent);
29 endfunction
30 function void build _ phase (uvm _ phase phase);
31
super.build _ phase(phase);
32
uvm _ config _ db#(uvm _ event)::get(this, , new _ values, new _ values);
33
if (new _ values == null)
34
`uvm _ fatal(get _ name(),
35
new _ values must be set in uvm _ config _ db
36 );
37
$display( Agent \%0s\ got Automatic configuration: i4=%0d,
38
get _ name(),
39
i4
40
);
41 endfunction
42 task run _ phase (uvm _ phase phase);
43
while (1)
44
begin
45
uvm _ config _ db#(int)::get(this,
46 ,
47
i _ of _ env,
48 i1 _ agent
49 );
Hierarchal Testbench Configuration Using uvm_config_db

10

50 uvm _ config _ db#(int)::get(uvm _ root::get(),


51
uvm _ test _ top.env.name _ agent _ 1,
52
i _ of _ env,
53
i2 _ agent
54
);
$display( Agent \%0s\ got: %0d (and stole %0d from agent1),
55
56 get _ name(),
57 i1 _ agent,
58 i2 _ agent
59 );
60
uvm _ config _ db#(int)::get(this, , from _ dut, i3 _ agent);
61
$display( Agent \%0s\ got %0d from DUT,
62 get _ name(),
63 i3 _ agent
64 );
65
new _ values.wait _ trigger();
66
67
end
68
endtask
69 endclass
70
71 class env extends uvm _ env;
72 `uvm _ component _ utils(env)
73 agent agent _ 1, agent _ 2, agent _ 3;
74 int i1 _ env=1, i2 _ env=2, i3 _ env=3,
75
i4 _ env=4, i5 _ env=5, i6 _ env=6,
76
i7 _ env=7, i8 _ env=8;
77 uvm _ event new _ values;
78 function new(string name, uvm _ component parent);
79
super.new(name, parent);
80 endfunction
81 function void build _ phase (uvm _ phase phase);
82
agent _ 1 = agent::type _ id::create(name _ agent _ 1, this);
83
agent _ 2 = agent::type _ id::create(name _ agent _ 2, this);
84
agent _ 3 = agent::type _ id::create(name _ agent _ 3, this);
85
set _ config _ int(name _ agent _ 1, i4, 1111);
86
set _ config _ int(name _ agent _ 2, i4, 2222);
87
set _ config _ int(name _ agent _ 3, i4, 3333);
88
new _ values = new(new _ values);
89
//Share event through uvm _ config _ db with agents
90
uvm _ config _ db#(uvm _ event)::set(this,
91 name _ agent _ *,
92
new _ values,
93
new _ values
94
);
95 endfunction
96 task run _ phase (uvm _ phase phase);
97
phase.raise _ objections(this);
98
//uvm _ config: share data with one specific object
99
$display( --- 1, 2, 3 to every agent separately --- );
100
uvm _ config _ db#(int)::set(agent _ 1,
101
,
102
i _ of _ env,
103
i1 _ env
104 );
105
uvm _ config _ db#(int)::set(this,
106 name _ agent _ 2,
107 i _ of _ env,
108 i2 _ env
109 );
110
uvm _ config _ db#(int)::set(uvm _ root::get(),
111 uvm _ test _ top.env.name _ agent _ 3,
112 i _ of _ env,
113 i3 _ env
114 );
115
// uvm _ config _ db: share data with multiple objects using regexp

Hierarchal Testbench Configuration Using uvm_config_db

11

116
new _ values.trigger(); #1;
117 $display( --- 4 to every agent, regexp name _ agent _ ? --- );
118
uvm _ config _ db#(int)::set(this,
119 name _ agent _ ?,
120 i _ of _ env,
121 i4 _ env
122 );
123
new _ values.trigger(); #1;
124
$display( --- 5 to every agent, regexp name _ agent* --- );
125
uvm _ config _ db#(int)::set(this,
126 name _ agent _ *,
127 i _ of _ env,
128 i5 _ env
129 );
130
new _ values.trigger(); #1;
131
$display( --- 6 to every agent, regexp *agent* --- );
132
uvm _ config _ db#(int)::set(uvm _ root::get(),
133 *agent*,
134 i _ of _ env,
135 i6 _ env
136 );
137
// uvm _ config _ db: share data with everyone
138
new _ values.trigger(); #1;
139
$display( --- 7 to everyone, regexp *--- );
140
uvm _ config _ db#(int)::set(uvm _ root::get(),
141 *,
142 i _ of _ env,
143 i7 _ env
144 );
145
new _ values.trigger(); #1;
146
$display( --- 8 to everyone, regexp *--- );
147
uvm _ config _ db#(int)::set(null,
148 *,
149 i _ of _ env,
150 i8 _ env
151 );
152
new _ values.trigger();
153
phase.drop _ objection(this);
154 endtask
155 endclass
156
157 class test _ a extends uvm _ test;
158 `uvm _ component _ utils (test _ a)
159 env env;
160 function new (string name=test _ a, uvm _ component parent=null);
161
super.new (name, parent);
162
env = new(env, this);
163 endfunction
164 function void end _ of _ elaboration();
165
print();
166 endfunction
167 task run _ phase(uvm _ phase phase);
168
#1000; global _ stop _ request();
169 endtask
170 endclass

References
1
2

Accellera Systems Initiative Universal Verification Methodology (UVM) 1.1 Users Guide, May 18, 2011
Accellera Systems Initiative Universal Verification Methodology (UVM) 1.1 Class Reference Manual, June 2011

Synopsys, Inc. 700 East Middlefield Road Mountain View, CA 94043 www.synopsys.com
2014 Synopsys, Inc. All rights reserved. Synopsys is a trademark of Synopsys, Inc. in the United States and other countries. A list of Synopsys trademarks is
available at http://www.synopsys.com/copyright.html. All other names mentioned herein are trademarks or registered trademarks of their respective owners.
06/14.AP.CS3989.

You might also like