{"id":15321,"date":"2020-11-02T11:21:56","date_gmt":"2020-11-02T16:21:56","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=15321"},"modified":"2026-03-27T08:50:50","modified_gmt":"2026-03-27T12:50:50","slug":"the-uvm-config-db-and-scope","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2020\/11\/02\/the-uvm-config-db-and-scope\/","title":{"rendered":"The UVM Config DB and Scope"},"content":{"rendered":"\n<p class=\"has-medium-font-size\">Introduction<\/p>\n\n\n\n<p>With any large software project, you need to share information and control across widely separated blocks. In the bad old days, this would be done with global variables and routines. In OOP and SystemVerilog, you can do this with classes that have static properties and methods. UVM&#8217;s Configuration Database is a great example. But did you know that the DB has a global space inside its pseudo-global space?<\/p>\n\n\n\n<p>You may be familiar with the RTL passing a virtual handle pointer to the test class through the DB as follows.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">module hdl_top;             \/\/ Holds RTL code\n  import uvm_pkg::*;\n  xbus_ifc xbus_if(...);    \/\/ Instantiate the xbus interface\n\n  initial\n    uvm_config_db #(virtual xbus_ifc)::     \/\/ Pass a virtual ifc\n                 set(null,  \"uvm_test_top\", \/\/ to the test object\n                     \"xbus_if\", xbus_if);   \/\/ Name: \"xbus_if\"\n  ... \/\/ RTL code\nendmodule<\/pre>\n\n\n\n<p>The uvm_config_db call has the 3 parts. Read the statement from right to to left.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The <strong>&#8220;name&#8221;, value<\/strong> pair of what you are accessing in the DB. Your code is easier to understand and understand if you try to make the name string and the variable the same. Here they are both <strong>xbus_if<\/strong>.<\/li><li>The scope, which is a uvm_component handle plus a string. Since the RTL code does not know anything about the test class, it uses a <strong>null <\/strong>handle, and &#8220;<strong>uvm_test_top<\/strong>&#8220;, the instance name of the test object.<\/li><li>Specialization <strong>#(virtual xbus_ifc)<\/strong>  the data type of the value, which here is a virtual Xbus interface handle.<\/li><\/ul>\n\n\n\n<p class=\"has-medium-font-size\">A whole new world<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"468\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-1024x468.png\" alt=\"\" class=\"wp-image-15331\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-1024x468.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-600x274.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-768x351.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-350x160.png 350w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds-1110x507.png 1110w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds.png 1272w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Most calls to the uvm_config_db use scopes made from the UVM testbench hierarchy, such as &#8220;uvm_test_top.env.agt&#8221;, which is an agent&#8217;s instance name. But you can make your own scope and it does not have to start with &#8220;uvm_test_top&#8221;. Under the hood, the uvm_config_db is just an associative array indexed by a string, so make your own global scope with any string.<\/p>\n\n\n\n<p>Maybe a test wants to pass an address to the X-bus agent. It could use the scope &#8220;<strong>uvm_test_top.env.agt<\/strong>&#8221; or it could make up its own scope, such as &#8220;XBUS&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class xbus_test extends uvm_test;\n  virtual function void build_phase(...);\n    uvm_config_db#(int)::          \/\/ Pass an int value\n                 set(null, \"XBUS\", \/\/ in the XBUS global scope\n                     \"addr\", 42);  \/\/ name, value pair\n  endfunction\nendclass<\/pre>\n\n\n\n<p>The agent, or even a sequence can get this value with a nearly identical call.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class xbus_agent extends uvm_agent;\n  int addr = 0;\n  virtual function void build_phase(...);\n    void'(uvm_config_db#(int)::           \/\/ Get an int value\n                 get(null, \"XBUS\",  \/\/ in the XBUS global scope\n                     \"addr\", addr)); \/\/ name, value pair\n  endfunction\nendclass<\/pre>\n\n\n\n<p class=\"has-medium-font-size\">Parallel worlds<\/p>\n\n\n\n<p>These small code examples work great, passing single values to single destinations. What about the real world? One possible problem with this style is expandability: what happens when there are multiple agents? You could replace the &#8220;XBUS&#8221; string with an instance number, such as &#8220;XBUS[1]&#8221;, or pass an array of addresses. Here is the set() call with the $sformatf() call to create the indexed scope.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">uvm_config_db#(int)::set(null, $sformatf(\"XBUS[%0d]\", inst),\n                         \"addr\", addr);<\/pre>\n\n\n\n<p>A more complex case is when making a testbench for a deeply layered system with 3 blocks, each which has an X-bus buried deep inside. The X-bus agent might not know if it is instance 0, 1, or 2, so adding an instance number to the scope string is more difficult.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Summary<\/p>\n\n\n\n<p>With the UVM Config DB, you can pass values around a testbench, following the instance names, or you can make your own global scopes. Make sure you plan ahead. How are you going to reuse those components and sequences if they are surrounded by several layers and instantiated multiple times?<\/p>\n\n\n\n<p><em>Enjoy your verification journey!<\/em><br><em>Chris Spear<\/em><\/p>\n\n\n\n<p>View my recent&nbsp;<a href=\"https:\/\/verificationacademy.com\/seminars\/improving-your-systemverilog-language-and-uvm-methodology-skills\" target=\"_blank\" rel=\"noopener\">webinars&nbsp;<\/a>including an overview of&nbsp;<a href=\"https:\/\/verificationacademy.com\/sessions\/stimulating-simulating-uvm-transactions\" target=\"_blank\" rel=\"noopener\">UVM Transactions<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction With any large software project, you need to share information and control across widely separated blocks. In the bad&#8230;<\/p>\n","protected":false},"author":71586,"featured_media":15331,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1,982,10,983],"tags":[614,751,787,805,838],"industry":[],"product":[],"coauthors":[980],"class_list":["post-15321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-systemverilog","category-tips-tricks","category-uvm","tag-oop","tag-systemverilog","tag-uvm","tag-uvm_config_db","tag-virtual-interface"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/11\/worlds.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/users\/71586"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=15321"}],"version-history":[{"count":6,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15321\/revisions"}],"predecessor-version":[{"id":16041,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15321\/revisions\/16041"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/15331"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=15321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=15321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=15321"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=15321"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=15321"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=15321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}