Last updated: December 20, 2015
In the post, Configurations, we looked at the configuration flow of the jelly bean verification. We also looked at the behind the scenes of the configuration flow in the post, Configuration Database. This post will focus on the syntax and semantics of accessing the configuration database. In Configurations, we stored and retrieved the jelly_bean_if
, jelly_bean_env_config
, and jelly_bean_agent_config
using the configuration database. The following figure depicts the component hierarchy used in Configurations on the left, and the configuration database (shown as clouds) on the right. The code snippets to access the database are shown in the middle.
Storing the jelly_bean_env_config
Let’s look at how to store and retrieve the jb_env_cfg
(shown in gray in the figure) first as this might be the easiest to understand. The jelly_bean_base_test
called set()
function to store the jb_env_cfg
in the database as follows.
uvm_config_db#( jelly_bean_env_config )::set( .cntxt( this ), .inst_name( "*" ), .field_name( "jb_env_cfg" ), .value( jb_env_cfg ) ) |
The uvm_config_db
is a parameterized class. In the above code, the uvm_config_db
is specialized with the jelly_bean_env_config
type. The cntxt
(context) and inst_name
(instance name) are used to create a scope in the database. The scope is created by concatenating the full name of the context and the instance name ({ cntxt.get_full_name(), ".", inst_name }
). In the above example, the scope is { this.get_full_name(), ".", "*" }
, which is evaluated to "uvm_test_top.*"
. Note that the full name of the jelly_bean_base_test
is assigned to be "uvm_test_top"
when the run_test()
task is called in the top-level module (top
). Note also that the "*"
is a wildcard character that matches any components. The object handle of jb_env_cfg
is stored under the name of "jb_env_cfg"
. The picture below conceptually shows how the jb_env_cfg
is tagged in the database.
Retrieving the jelly_bean_env_config
The jb_env
called get()
function to retrieve the jb_env_cfg
from the database as follows.
uvm_config_db#( jelly_bean_env_config )::get( .cntxt( this ), .inst_name( "" ), .field_name( "jb_env_cfg" ), .value( jb_env_cfg ) ) |
The meanings of the arguments of the get()
function are the same as those of the set()
function. Similar to the set()
function, the scope is defined as { cntxt.get_full_name(), ".", inst_name }
. In the above code, the scope is evaluated to "uvm_test_top.jb_env"
. It is typical to use this
as the cntxt
and ""
as the inst_name
. Note that if the inst_name
is empty (""
), the dot ("."
) is also omitted. The get()
function searches the database and tries to find the object that matches the type, scope, and field_name
. Since the scope of the jb_env_cfg
was defined as "uvm_test_top.*"
in the database, the scope, "uvm_test_top.jb_env"
, successfully matches it.
Storing the jelly_bean_agent_config
Now let’s look at another example. This time, the jb_env
stores the jb_agent_cfg
, then the jb_agent1
retrieves it (shown in orange in the figure on the top). The jb_env
called set()
function to store the jb_agent_cfg
in the database 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 ) ) |
The uvm_config_db
is specialized with the jelly_bean_agent_config
type. The scope of the object is { this.get_full_name(), ".", "jb_agent1*" }
, which is evaluated to "uvm_test_top.jb_env.jb_agent1*"
. Note that this scope matches jb_agent1
and any components under it. The jb_env_cfg.jb_agent_cfg1
is stored under the name of "jb_agent_cfg"
. The picture below conceptually shows how the jb_agent_cfg1
is tagged in the database.
Retrieving the jelly_bean_agent_config
The jb_agent1
called get()
function to retrieve the jb_agent_cfg1
as follows.
uvm_config_db#( jelly_bean_agent_config )::get( .cntxt( this ), .inst_name( "" ), .field_name( "jb_agent_cfg" ), .value( jb_agent_cfg ) ) |
The scope is { this.get_full_name(), ".", "" }
, which is evaluated to "uvm_test_top.jb_env.jb_agent1"
. Since the scope of the jb_agent_cfg1
in the database is "uvm_test_top.jb_env.jb_agent1*"
, it successfully matches the scope defined by this get()
function.
Storing the jelly_bean_if
Let’s look at the last example. The top-level module stores a virtual interface (shown in yellow in the figure on the top). The top module called set()
function as follows.
uvm_config_db#( virtual jelly_bean_if )::set( .cntxt( null ), .inst_name( "uvm_test_top" ), .field_name( "jb_if1" ), .value( jb_if1 ) ) |
Two things to note here. The first is that we used null
as the cntxt
. This was because the top-level module is not a uvm_component
and cannot obtain its full name by calling the get_full_name()
. The second is that we used "uvm_test_top"
as the inst_name
. As we have seen, the "uvm_test_top"
is the full name of the top-level test component. Thus, it is important to use this name as a part of the scope.
If the cntxt
is null
, the scope consists of the inst_name
only, which is "uvm_test_top"
. The picture below conceptually shows how the jb_if1
is tagged in the database.
Retrieving the jelly_bean_if
The jelly_bean_base_test
called get()
function to retrieve the jb_if1
as follows.
uvm_config_db#( virtual jelly_bean_if )::get( .cntxt( this ), .inst_name( "" ), .field_name( "jb_if1" ), .value( jb_agent_cfg1.jb_if ) ) |
The scope is { this.get_full_name(), ".", "" }
, which is evaluated to "uvm_test_top"
("."
is not included if the inst_name
is ""
). Since the scope of the jb_if1
in the database is "uvm_test_top"
, it successfully matches the scope defined by this get()
function.
Summary of the scopes
The table below summarizes which component matches the scopes defined in our example assuming get()
function uses this
as the cntxt
and ""
as the inst_name
. Note that the scope "uvm_test_top.*"
matches any components under the uvm_test_top
, but it does not match the scope "uvm_test_top"
(1). On the other hand, the scope "uvm_test_top"
matches "uvm_test_top"
only. It does not match any components under the uvm_test_top
(2).
Component/Scope | uvm_test_top.* | uvm_test_top.jb_env.jb_agent1* | uvm_test_top |
---|---|---|---|
jelly_bean_base_test (uvm_test_top) | (1) | (2) | |
uvm_test_top.jb_env | |||
uvm_test_top.jb_env.jb_agent1 | |||
uvm_test_top.jb_env.jb_agent2 |
I hope this post helped to understand how to access the configuration database.
The picture below conceptually shows how the jb_agent_cfg1 is tagged in the database
Shouldn’t the scope be w wrong the scope should be “uvm_test_top.jb_env.jb_agent1*”, because the picture shows “uvm_test_top.jb_agent1*”
I commented on the earlier post of configuration and asked for more details, Please avoid that comment Isee you added it in this post.
Thanks a lot, the posts are a great learning help, I advised my friends to look at it too.
Moses
I have corrected the picture. Thank you for pointing out this error!
You did write that “the scope “uvm_test_top.*” matches any components under the uvm_test_top, but it does not match the scope “uvm_test_top””. But for agent_config you written that “”uvm_test_top.jb_env.jb_agent1*” will matches jb_agent1 and any components under it.
Why for uvm_test_top wildcard will not match uvm_test_top as explained for jb_agent1.
This is because
"uvm_test_top.*"
has a dot (.
) before the wildcard (*
). If the scope is"uvm_test_top*"
(no dot), it would match any components under theuvm_test_top
as well as theuvm_test_top
itself.uvm_config_db#( virtual jelly_bean_if )::set( .cntxt( null ), .inst_name( “uvm_test_top” ),
.field_name( “jb_if1” ), .value( jb_if1 ) )
If we use * as inst_name, we can get interface anywhere in the hierarchy.
Am I correct?
That is correct.
Hi Keisuke,
I have a question here, would you please take look,
I want to pass the config to clk_seq which is start in a virtual sequence.
If I set config in env , it will show v_seq.clk_clk_seq.m_config could not be gotten.
If I set config in test level, it will show v_seq.clk_clk_seq.m_config could not be gotten.
But if I use uvm_root::get(), in the test level, the config could be gotten.
I just wonder if all the sequence (including virtual sequence) is instantiated in the level of uvm_root. and those objects are paralleled to uvm_test_top?
Or Is there any better way to pass the config to sequence ?
Best,
How did you call
uvm_config_db#(clk_base_config)::get
in the virtual sequence? I want to see thecntxt
andinst_name
arguments.Hi Keisuke,
In the following case:
uvm_test_top.jb_env.jb_agent1*” which is the second case in your example, it would even match uvm_test_top.jb_env.jb_agent11 by the virtue of jb_agent1*.
Is this correct?
That’s correct.