{"id":18177,"date":"2023-01-25T16:14:38","date_gmt":"2023-01-25T21:14:38","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=18177"},"modified":"2026-03-27T08:51:19","modified_gmt":"2026-03-27T12:51:19","slug":"the-uvm-factory-revealed-part-2","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/01\/25\/the-uvm-factory-revealed-part-2\/","title":{"rendered":"The UVM Factory Revealed, Part 2"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>This is a follow up to last week\u2019s <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/01\/20\/uvm-factory-revealed-part-1\/\">high-level post on the UVM Factory<\/a>. Now let\u2019s get technical! Here are the SystemVerilog Object-Oriented Programming concepts behind the factory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is a type_id?<\/h2>\n\n\n\n<p>Last week you saw that your verification project will be more stable if you create objects with the UVM Factory instead of calling the class constructor, <code>new()<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>drv = x_driver::type_id::create(\u2026);<\/code><\/pre>\n\n\n\n<p>But what is <code>type_id<\/code>? Is it the UVM Factory? A class? How about a floor polish and a dessert topping? Actually, it is none of the above; it is just a type.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A riddle wrapped in a macro<\/h2>\n\n\n\n<p>What is in the <code>uvm_object_utils <\/code>and <code>uvm_component_utils <\/code>macros? They are almost identical, except the first assumes the class constructor has one argument, and the second assumes there are two. Let\u2019s focus on a transaction class.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Txn extends uvm_sequence_item;\n  `uvm_object_utils(Txn)\n  function new(string name=\u201dTxn\u201d);\n    super.new(name);\n  endfunction\n  \u2026\nendclass<\/code><\/pre>\n\n\n\n<p>For this class, the macro defines <code>type_id<\/code> as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>typedef uvm_object_registry#(Txn,\"Txn\") type_id;<\/code><\/pre>\n\n\n\n<p>You are creating a new object, so the handle is still null, and you can&#8217;t call its methods with <code><em>handle.type_id.create()<\/em><\/code>. The <code>uvm_object_registry <\/code>has static methods, which you call with the <code><em>class::type_id::create()<\/em><\/code> syntax.<\/p>\n\n\n\n<p>The <code>create()<\/code> method essentially just calls <code>uvm_factory::create_object_by_type()<\/code>. That method looks through an array of type overrides to see if you ever called <code>set_type_override()<\/code> for this class, then calls <code>new()<\/code> for the base or override class. For components, where <code>new()<\/code> has two arguments, there is a parallel set of classes and methods such as <code>uvm_component_registry<\/code> and <code>create_component_by_type()<\/code>.<\/p>\n\n\n\n<p>Every class needs a unique identifier, which is its \u201ctype\u201d. The Txn class\u2019s <code>type_id <\/code>proxy creates a single instance of itself, a \u201csingleton instance\u201d, and the \u201ctype\u201d is just a handle to that instance. The following overrides the Txn class with the derived TxnPlus. The call to <code>TxnPlus::get_type()<\/code> returns a handle to the proxy object so that create() can construct a TxnPlus object.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Txn::type_id::set_type_override( TxnPlus::get_type() );<\/code><\/pre>\n\n\n\n<p>The above description is for the UVM type-based factory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s my name?<\/h2>\n\n\n\n<p>When I was first learning UVM, I couldn\u2019t figure out how it constructed the test object from the <code>+UVM_TESTNAME=my_test<\/code> command line switch. In SystemVerilog I can get the string \u201cmy_test\u201d from the switch, but how does UVM turn that into an object?<\/p>\n\n\n\n<p>Did you know that the UVM factory has a parallel, string-based flow? That is why the typedef for <code>type_id <\/code>has a second argument, the class name string.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&nbsp;&nbsp; typedef uvm_object_registry#(Txn,\"Txn\") type_id;<\/code><\/pre>\n\n\n\n<p>If you look up <code>uvm_root::run_test()<\/code>, there is a call to <code>factory.create_component_by_name(\u2026)<\/code>. The string from the command line switch is passed in, and this method constructs that object, or the override one.<\/p>\n\n\n\n<p>Imagine that the factory is a printing press. If you load a drum with a base image, it will print base text. If you load a drum with a derived image, it will print the new text.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"610\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-1024x610.png\" alt=\"The UVM Factory prints objects\" class=\"wp-image-18175\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-1024x610.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-600x357.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-768x457.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-1536x915.png 1536w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-2048x1220.png 2048w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-900x536.png 900w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">The UVM string-based Factory can print base and derived objects<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">You know my name, look up my number<\/h2>\n\n\n\n<p>Why was the type-based factory added? There is a problem with the string-based factory. What if my transaction class is parameterized and I have two specializations?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Txn #(WIDTH) extends uvm_sequence_item;<br>&nbsp; `uvm_object_utils(Txn)<br>&nbsp; rand &#91;WIDTH-1:0] data;<br>endclass<br><br>Txn #(16) txn16;<br>Txn #(32) txn32;<\/code><\/pre>\n\n\n\n<p>This defines two unrelated types, <code>Txn#(16)<\/code> and <code>Txn#(32)<\/code>. If you only have the original class name, \u201cTxn\u201d, you can&#8217;t construct these two types. That is why UVM added the type-based factory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Both UVM Factories allow you to create objects, either the base type or a derived, without changing the call to create(). This keeps your code base stable, reducing the verification time and ultimately the time to market.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Learn More<\/h2>\n\n\n\n<p>You can learn more about this including Oriented Programming with the Siemens SystemVerilog for Verification and UVM courses. They are offered in&nbsp;<a href=\"https:\/\/training.plm.automation.siemens.com\/ilt\/iltdescription.cfm?pID=268489-US_____EDA__2021.4_1199\" target=\"_blank\" rel=\"noreferrer noopener\">instructor led<\/a>&nbsp;format by our industry expert instructors, or in a self-paced&nbsp;<a href=\"https:\/\/training.plm.automation.siemens.com\/mytraining\/viewlibrary.cfm?memTypeID=287545&amp;memID=287545\" target=\"_blank\" rel=\"noreferrer noopener\">on-demand<\/a>&nbsp;format. They can also be tailored to address your specific design goals and show you how to set up an environment for reuse for additional designs.&nbsp; Also, you can now earn a digital badge\/level 1 certificate by taking our&nbsp;<a href=\"https:\/\/training.plm.automation.siemens.com\/mytraining\/viewlibrary.cfm?memTypeID=288054&amp;memID=288054\" target=\"_blank\" rel=\"noreferrer noopener\">Advanced Topics Badging Exam<\/a>. This will enable you to showcase your knowledge of these topics by displaying the badge in your social media and email signature.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction This is a follow up to last week\u2019s high-level post on the UVM Factory. Now let\u2019s get technical! Here&#8230;<\/p>\n","protected":false},"author":71586,"featured_media":18263,"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":[7,1,982,10,983],"tags":[1559,396,397,405,1556,1560,614,1561,1562,707,1558,751,769,1557,787],"industry":[],"product":[],"coauthors":[980],"class_list":["post-18177","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-learning-resources","category-news","category-systemverilog","category-tips-tricks","category-uvm","tag-component","tag-construct","tag-constructor","tag-create","tag-factory","tag-factory-pattern","tag-oop","tag-override","tag-proxy-class","tag-sequence","tag-sequence_item","tag-systemverilog","tag-transaction","tag-type_id","tag-uvm"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/string-rollers-1024x610-1.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18177","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=18177"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18177\/revisions"}],"predecessor-version":[{"id":18190,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18177\/revisions\/18190"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/18263"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=18177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=18177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=18177"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=18177"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=18177"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=18177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}