Last Updated: July 24, 2016
This post will explain how configuration database (uvm_config_db
) works. In Configurations, we used the uvm_config_db
to store a jelly_bean_if
, a jelly_bean_env_config
, and two jelly_bean_agent_config
s. This post will analyze how a configuration data is stored and retrieved. The class diagram related to the configuration database is shown below. Note that we only showed the classes related to the jelly_bean_if
and jelly_bean_agent_config
to avoid clutter. UVM standard library classes are shown in pink, while the UVM classes specialized with the jelly_bean_transaction
type are shown in yellow.
Setting a Virtual Interface
In Configurations, the top
module stored two virtual interfaces (jb_if1
and jb_if2
) into the configuration database as follows:
uvm_config_db#( virtual jelly_bean_if )::set( .cntxt ( null ), .inst_name ( "" ), .field_name( "jb_if1" ), .value ( jb_if1 ) ); uvm_config_db#( virtual jelly_bean_if )::set( .cntxt ( null ), .inst_name ( "" ), .field_name( "jb_if2" ), .value ( jb_if2 ) ); |
The diagram below shows what will be created after these set
functions have been called.
These are the steps involved in this course of action.
- Since the
top
is a module, not auvm_component
,null
is passed as thecntxt
whenset
is called. In this case,uvm_top
, which is the singleton object ofuvm_root
class, will be used as thecntxt
. - An entry of an associative array (
m_rsc
) is created using thecntxt
object as the key, if this entry does not exist. - The entry of the associative array points to a
uvm_pool
, which has another associative array (pool
). - An entry of the associative array is created using the
inst_name
and thefield_name
as the key (lookup
). Note that theinst_name
and thefield_name
are concatenated with a string (“__M_UVM__
“) when thelookup
is created. - If the
lookup
does not exist, auvm_resource
object is created. If theinst_name
is""
, the full name of thecntxt
, which is"uvm_test_top"
, is stored as thescope
. Thevalue
passed to theset()
function is also stored. - The handle to the
uvm_resource
object is stored in two kinds ofuvm_queue
s. The first kind of queues store the handles to theuvm_resource
objects that have the commonfield_name
. Auvm_queue
is created for every uniquefield_name
. In our case, twouvm_queue
s are created; one for the"jb_if1"
and the other for the"jb_if2"
. - The second kind of queues store the handles to the
uvm_resource
objects that have the common type. Auvm_queue
is created for every unique type. In our case, oneuvm_queue
is created for thevirtual jelly_bean_if
type. - The queues are registered in the singleton
uvm_resource_pool
. Theuvm_resouce_pool
has two associative arrays. One array (rtab
) uses thefield_name
as the key. - The other array (
ttab
) uses the type of theuvm_resource
as the key.
Getting a Virtual Interface
In Configurations, the jelly_bean_base_test
retrieved the jelly_bean_if
s as follows:
uvm_config_db#( virtual jelly_bean_if )::get( .cntxt ( this ), .inst_name ( "" ), .field_name( "jb_if1" ), .value( jb_agent_cfg1.jb_if ) ); uvm_config_db#( virtual jelly_bean_if )::get( .cntxt ( this ), .inst_name ( "" ), .field_name( "jb_if2" ), .value( jb_agent_cfg2.jb_if ) ); |
The diagram below shows how the jb_if1
is retrieved.
These are the steps involved in this course of action.
- Look up the name table of the
uvm_resource_pool
with thefield_name
as the key. - If the name matched, get the handle of the
uvm_queue
. - Traverse the entries of the queue.
- If the scope and the type of the object matches, that
uvm_resource
is stored in a newly createduvm_queue
. - The
uvm_resource
with the highest precedence is retrieved. - The value of the resource is returned.
Setting an Agent Configuration
Now let’s look at another example. In Configurations, the jelly_bean_env
stored the jelly-bean-agent configurations (jb_agent_cfg1
and jb_agent_cfg2
) as follows:
uvm_config_db#( jelly_bean_agent_config )::set( .cntxt ( this ), .inst_name ( "jb_agent1*" ), .field_name( "jb_agent_cfg" ), .value( jb_env_cfg.jb_agent_cfg1 ) ); uvm_config_db#( jelly_bean_agent_config )::set( .cntxt ( this ), .inst_name ( "jb_agent2*" ), .field_name( "jb_agent_cfg" ), .value( jb_env_cfg.jb_agent_cfg2 ) ); |
The diagram below shows what will be created after these set
functions have been called.
These are the steps involved in this course of action.
- The
jelly_bean_env
calls theset()
function withthis
(jb_env
) as thecntxt
. - An entry of an associative array (
m_rsc
) is created using thecntxt
object as the key, if this entry does not exist. - The entry of the associative array points to a
uvm_pool
, which has another associative array (pool
). - An entry of the associative array is created using the
inst_name
and thefield_name
as the key (lookup
). Note that theinst_name
and thefield_name
are concatenated with a string (“__M_UVM__
“) when thelookup
is created. - If the
lookup
does not exist, auvm_resource
object is created. Unlike the virtual-interface case, theinst_name
is not""
this time. In this case, the full name of thecntxt
object concatenated with theinst_name
is stored as thescope
. Thevalue
passed to theset()
function is also stored. - The handle to the
uvm_resource
object is stored in two kinds ofuvm_queue
s. The first kind of queues store the handles to theuvm_resource
objects that have the commonfield_name
. Auvm_queue
is created for every uniquefield_name
. In our case, oneuvm_queue
is created for the"jb_agent_cfg"
. - The second kind of queues store the handles to the
uvm_resource
objects that have the common type. Auvm_queue
is created for every unique type. In our case, oneuvm_queue
is created for thejelly_bean_agent_config
type. - The queues are registered in the singleton
uvm_resource_pool
. Theuvm_resouce_pool
has two associative arrays. One array (rtab
) uses thefield_name
as the key. - The other array (
ttab
) uses the type of theuvm_resource
as the key.
One difference from the previous example is that the rtab
has only one entry because both the uvm_agent_cfg1
and the uvm_agent_cfg2
use the same field_name
("uvm_agent_cfg"
).
Getting an Agent Configuration
In Configurations, the jelly_bean_agent
retrieved the jb_agent_cfg
as follows:
uvm_config_db#( jelly_bean_agent_config )::get( .cntxt ( this ), .inst_name ( "" ), .field_name( "jb_agent_cfg" ), .value ( jb_agent_cfg ) ); |
The diagram below shows how the jb_agent_cfg
is retrieved.
These are the steps involved in this course of action.
- Look up the name table of the
uvm_resource_pool
with thefield_name
as the key. - If the name matched, get the handle of the
uvm_queue
. - Traverse the entries of the queue.
- If the scope and the type of the object matches, that
uvm_resource
is stored in a newly createduvm_queue
. Note that there are twouvm_resource
objects, but their scopes are different. The full name of thecntxt
object passed to theget()
function distinguishes between the two. - The
uvm_resource
with the highest precedence is retrieved. - The value of the resource is returned.
Summary
That’s about the configuration database. This diagram shows the main objects involved in this article. I hope this post helped you to understand how the configuration database works.
Its great article to learn uvm_config_db in detail
Hi Keisuke,
What is the diference between uvm_config_db and uvm_resource_db?
How to choose between these two?
Regards,
Siva
Both the
uvm_config_db
and theuvm_resource_db
provide a convenience interface for the resource database. UVM recommends using theuvm_config_db
as it is more robust.As it is correctly said by “Keisuke Shimizu”, Both the uvm_config_db and the uvm_resource_db provide a convenience interface for the resource database. UVM recommends using the uvm_config_db as it is more robust.
uvm_config_db is more robust because with uvm_config_db, we can restrict the db so that it will not be visible to certain components. In other words, while setting up the config_db, we can set a path. So, that this db can be accessed only by the components that are existing in the specified path… But, uvm_resource_db has no such facility (since this db can be accessed by any of the components inTB) uvm_resource_db has global visibility.
It is user’s responsibility to set correct scope when you call
uvm_resource_db#(T)::set( input string scope, input string name, T val, input uvm_object accessor = null )
as thescope
can be any string. On the other hand, when you calluvm_config_db#(T)::set( uvm_component cntxt, string inst_name, string field_name, T value )
, you give auvm_component
for the scope (or context,cntxt
), which is less error-prone.Hi Keisuke,
How is uvm_config_db diffrent from set_inst_override or set_type_override, In which context should we use each of them. Can you please explain, Thanks in advance !!
The
uvm_config_db
is used to share information between components and objects. For example, the top-level test-bench module often stores a virtual interface to theuvm_config_db
. Then auvm_driver
can get the interface from the database for pin wiggling. Please see this and this for how we did it.The
set_inst_override
andset_type_override
are used to substitute a component or an object for another without changing the test-bench code. For example, a user can substitute a transaction for an error transaction. Please see this for how we substituted a jelly bean with a sugar-free jelly bean from a test.Hi
The article is a bit too sophisticated, it explains more about behind the scenes, then about the actual way of using it, as you did in the previous articles. Can you please add some more examples for each field in the set/get of the config_db.
Thanks
This sequel post might help you.
Please ignore my earlier reply, I continued on and saw you elaborated on the issue in another chapter.
Thanks again
great article
Hi Keisuke,
Thanks for the very nice explanation on config db. No I know how to appropriately give the .cntxt, .instname, arguments.
I have a question. I see the configuration object retrieval is only concerned with the associative array in uvm_resource_pool and the handles to uvm_queue they point to. I wanted to know why initially an entry is made in “m_rsc” table and a “uvm_pool” is created with another associative array? Why not start by creating uvm_resource objects for the item and get their handle in uvm_queue and make an entry in the arrays in uvm_resource_pool singleton? What benefit is gained from extra book keeping done initially?
Regards,
Gautam
This is a good question. I don’t know why.
Very good article.
Hi Keisuke,
From where do I read about the internal working of things like you have explained about internal working of a configuration database? What materials do I refer to?
Regards,
Gautam
I read the source code of UVM. Good luck!
Hi shimizu
I want get data from test to testbench is it possible to get by using config db get in test bench
Regards
Ch.siva
You should be able to do like this:
Hi Keisuke,
I have a question regarding to input a name in a interface.
I have a interface like below:
then in my testbench top level, I have declare a instance like below:
However, it compiles with NCSIM successfully. But when I tried to compile with VCS, it gave me error:
I am not sure what the error exactly means? Can you please help me on that?
many thanks
Steve
It seems you cannot use
string
as the interface port type. You could either define thename
as an interface item like this:or use a parameterized interface:
Hi
We have uvm_pool class which is helpful for seting and getting objects, but why still we need config_db ? we can achieve same thing in uvm_pool also but why do we go for uvm_config_db?
You could use
uvm_pool
if simple lookup ofuvm_object
is good enough. However, if you want scope resolution for example,uvm_resource
needs to be involved. Look at the diagram in Summary section and see how many objects are involved to resolve the scope. Theuvm_config_db
provides simple API for this.hi
below code iam using config db set and get
but in this line error is pointing like this
can u plz help me out
If
apb_reg_seq
calls theget()
, you cannot usethis
as the first argument becauseapb_reg_seq
is not auvm_component
. Try to usem_sequencer
instead ofthis
.