UVM Tutorial for Candy Lovers – 13. Configuration Database

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_configs. 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.

                                                     Class Diagram Related to the Configuration Database

 

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  ) );

                                                                                  Storing the Virtual Interfaces

These are the steps involved in this course of action.

  1. Since the top is a module, not a uvm_componentnull is passed as the cntxt when set is called. In this case, uvm_top, which is the singleton object of uvm_root class, will be used as the cntxt.
  2. An entry of an associative array (m_rsc) is created using the cntxt object as the key, if this entry does not exist.
  3. The entry of the associative array points to a uvm_pool, which has another associative array (pool).
  4. An entry of the associative array is created using the inst_name and the field_name as the key (lookup). Note that the inst_name and the field_name are concatenated with a string (“__M_UVM__“) when the lookup is created.
  5. If the lookup does not exist, a uvm_resource object is created. If the inst_name is "", the full name of the cntxt, which is "uvm_test_top", is stored as the scope. The value passed to the set() function is also stored.
  6. The handle to the uvm_resource object is stored in two kinds of uvm_queues. The first kind of queues store the handles to the uvm_resource objects that have the common field_name. A uvm_queue is created for every unique field_name. In our case, two uvm_queues are created; one for the "jb_if1" and the other for the "jb_if2".
  7. The second kind of queues store the handles to the uvm_resource objects that have the common type. A uvm_queue is created for every unique type. In our case, one uvm_queue is created for the virtual jelly_bean_if type.
  8. The queues are registered in the singleton uvm_resource_pool. The uvm_resouce_pool has two associative arrays. One array (rtab) uses the field_name as the key.
  9. The other array (ttab) uses the type of the uvm_resource as the key.

Getting a Virtual Interface

In Configurations, the jelly_bean_base_test retrieved the jelly_bean_ifs 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 ) );

                                                                        Retrieving the Virtual Interface

These are the steps involved in this course of action.

  1. Look up the name table of the uvm_resource_pool with the field_name as the key.
  2. If the name matched, get the handle of the uvm_queue.
  3. Traverse the entries of the queue.
  4. If the scope and the type of the object matches, that uvm_resource is stored in a newly created uvm_queue.
  5. The uvm_resource with the highest precedence is retrieved.
  6. 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.

                                                                    Storing the Agent Configurations

These are the steps involved in this course of action.

  1. The jelly_bean_env calls the set() function with this (jb_env) as the cntxt.
  2. An entry of an associative array (m_rsc) is created using the cntxt object as the key, if this entry does not exist.
  3. The entry of the associative array points to a uvm_pool, which has another associative array (pool).
  4. An entry of the associative array is created using the inst_name and the field_name as the key (lookup). Note that the inst_name and the field_name are concatenated with a string (“__M_UVM__“) when the lookup is created.
  5. If the lookup does not exist, a uvm_resource object is created. Unlike the virtual-interface case, the inst_name is not "" this time. In this case, the full name of the cntxt object concatenated with the inst_name is stored as the scope. The value passed to the set() function is also stored.
  6. The handle to the uvm_resource object is stored in two kinds of uvm_queues. The first kind of queues store the handles to the uvm_resource objects that have the common field_name. A uvm_queue is created for every unique field_name. In our case, one uvm_queue is created for the "jb_agent_cfg".
  7. The second kind of queues store the handles to the uvm_resource objects that have the common type. A uvm_queue is created for every unique type. In our case, one uvm_queue is created for the jelly_bean_agent_config type.
  8. The queues are registered in the singleton uvm_resource_pool. The uvm_resouce_pool has two associative arrays. One array (rtab) uses the field_name as the key.
  9. The other array (ttab) uses the type of the uvm_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.

                                                                  Retrieving the Agent Configuration

These are the steps involved in this course of action.

  1. Look up the name table of the uvm_resource_pool with the field_name as the key.
  2. If the name matched, get the handle of the uvm_queue.
  3. Traverse the entries of the queue.
  4. If the scope and the type of the object matches, that uvm_resource is stored in a newly created uvm_queue. Note that there are two uvm_resource objects, but their scopes are different. The full name of the cntxt object passed to the get() function distinguishes between the two.
  5. The uvm_resource with the highest precedence is retrieved.
  6. 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.

UVM Objects Involved in This Article

                                                                        UVM Objects Involved in This Article

發佈了68 篇原創文章 · 獲贊 440 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章