{"id":18112,"date":"2023-01-20T10:48:41","date_gmt":"2023-01-20T15:48:41","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=18112"},"modified":"2026-03-27T08:51:21","modified_gmt":"2026-03-27T12:51:21","slug":"uvm-factory-revealed-part-1","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/01\/20\/uvm-factory-revealed-part-1\/","title":{"rendered":"UVM Factory Revealed, Part 1"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>When you first learn UVM, most of the concepts make sense, even if you are new to Object-Oriented Programming. Except one, the UVM Factory. Why do you need all that extra code, <code>class::type_id::create()<\/code>, just to make an object? What\u2019s wrong with just calling <code>new()<\/code>? The answer is teamwork!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Small Problem<\/h2>\n\n\n\n<p>Imagine you are trying to verify a design with the X bus protocol. You write UVM testbench components that speak that protocol, including the agent, driver, and monitor. Here is agent code that constructs the driver.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class x_agent extends uvm_agent;\n  x_driver drv;\n\n  function void build_phase(\u2026);\n    drv = new(\"drv\", this); \/\/ Construct the X bus driver\n  endfunction\nendclass<\/code><\/pre>\n\n\n\n<p>In the build phase you call <code>new()<\/code>. SystemVerilog says that this constructs the object based on the type of the handle on the left side, and so you end up with an <code>x_driver<\/code> object. Job done and you didn\u2019t have to type all that <code>type_id::create()<\/code> stuff.<\/p>\n\n\n\n<p>But then halfway through the project, your manager says the design must work with the next generation of the protocol, called the Xplus bus. She even gave you the <code>xplus_driver<\/code> class that extends <code>x_driver<\/code>.<\/p>\n\n\n\n<p>No problem, just add a flag variable and some code and your agent constructs both types. Since the new class extends the original one, you can reuse the <code>drv <\/code>handle. You can even get fancy with the typed constructor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class x_agent extends uvm_agent;\n  x_driver drv;\n  bit use_xbus;&nbsp; \/\/ True: use X bus, False: XPLUS-bus\n\n  function void build_phase(\u2026);\n    if (use_xbus)\n      drv = new(\u2026); \/\/ Contruct the X bus driver\n    else\n      drv = xplus_driver::new(\u2026); \/\/ Typed constructor builds xplus_driver object\n  endfunction\nendclass<\/code><\/pre>\n\n\n\n<p>With this new agent and driver, you write a Xplus test, set the flag <code>use_xbus<\/code>, and it passes. Who needs the factory when you can make a change this easily? Time to commit your changes and release them to the team.<\/p>\n\n\n\n<p>When you come in the next morning, there are several angry people outside your cubicle. There is a bug in your code \u2013 the default value of <code>use_xbus <\/code>is 0, so the agent always constructs <code>xplus_driver<\/code>. Everyone who tried to use your revised agent got the wrong driver and now all their tests fail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Big Problem<\/h2>\n\n\n\n<p>The issue here is not the code bug. You are working in a team, so changes you make affect everyone. Every time you change shared code, adding more control variables, <code>if<\/code>&#8211; and <code>case<\/code>-statement for all the new variants, you potentially cause bugs. How can your tests inject the new <code>xplus_driver <\/code>class without changing the <code>x_agent <\/code>class?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Solution<\/h2>\n\n\n\n<p>Many UVM techniques involve polymorphism. Sounds tricky, but it just means you define a base class with virtual methods. These become \u201chooks\u201d to inject new behavior. How? Define a derived class and replace the base object with the derived one. Now when you call <code>handle.action()<\/code>, you can get the base action or the derived, depending on the object type.<\/p>\n\n\n\n<p>The factory pattern is a little more subtle. 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 one with a derived image, it prints the derived text.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"673\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-1024x673.png\" alt=\"The UVM Factory prints objects\" class=\"wp-image-18174\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-1024x673.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-600x394.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-768x505.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-1536x1009.png 1536w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-2048x1345.png 2048w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/01\/type-rollers-900x591.png 900w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">The UVM type-based Factory can print base and derived objects<\/figcaption><\/figure>\n\n\n\n<p>The UVM Factory prints objects. In the base <code>x_driver <\/code>and derived <code>xplus_driver<\/code>, use the <code>`uvm_component_utils(x_driver)<\/code> macro to define <code>type_id<\/code>. This is a \u201cproxy class\u201d, which means it is a \u201chelper\u201d of these classes, building their objects. Each <code>type_id <\/code>is a unique class that, together, are the UVM Factory. The key is that all these proxy classes share a static array which is lookup table of base and derived types. By default, the following call builds an <code>x_driver <\/code>object.<\/p>\n\n\n\n<p>    <code>drv = x_driver::type_id::create(\"drv\", this);<\/code><\/p>\n\n\n\n<p>The key concept is that from the test class, you can decide which object is built by the agent, without having to modify the agent&#8217;s code. In the test&#8217;s <code>build_phase()<\/code>, add the following call.<\/p>\n\n\n\n<p>    <code>x_driver::type_id::set_type_override(xplus_driver::get_type());<\/code><\/p>\n\n\n\n<p>You can read this as follows. Tell the <code>x_driver<\/code>\u2019s factory that when it is asked to create an object, use the type defined in the <code>xplus_driver<\/code> class, where <code>get_type()<\/code> returns the type <code>xplus_driver::type_id<\/code>.<\/p>\n\n\n\n<p>The OOP hook here to inject new behavior is the virtual method <code>create()<\/code>. The subtle difference is that the method is in the <code>type_id<\/code> proxy class, not in any of the driver classes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>If you write your UVM testbench with the factory create pattern, instead of directly calling the new() constructor, you can inject new behavior by overriding a base class with a derived. Not only can you override components, but you can also extend a sequence item class, override the base type, and now all your sequences will get this new behavior, without changing their code. The factory pattern enables all this, plus a stable code base, so you can inject new features, without affecting your team.<\/p>\n\n\n\n<p>Look for a more <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/01\/25\/the-uvm-factory-revealed-part-2\/\" target=\"_blank\" data-type=\"URL\" data-id=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/01\/25\/the-uvm-factory-revealed-part-2\/\" rel=\"noreferrer noopener\">technical post on the UVM Factory<\/a> next week.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">To learn more<\/h2>\n\n\n\n<p>You can learn more about these topics including Oriented Programming with the Siemens SystemVerilog for Verification course. It is 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. It 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 this topic by displaying the badge in your social media and email signature.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction When you first learn UVM, most of the concepts make sense, even if you are new to Object-Oriented Programming&#8230;.<\/p>\n","protected":false},"author":71586,"featured_media":18265,"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-18112","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\/type-rollers-1024x673-1.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18112","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=18112"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18112\/revisions"}],"predecessor-version":[{"id":18191,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18112\/revisions\/18191"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/18265"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=18112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=18112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=18112"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=18112"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=18112"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=18112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}