{"id":18333,"date":"2023-04-25T15:28:30","date_gmt":"2023-04-25T19:28:30","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=18333"},"modified":"2026-03-27T08:51:40","modified_gmt":"2026-03-27T12:51:40","slug":"groups-of-class-specializations-in-systemverilog","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2023\/04\/25\/groups-of-class-specializations-in-systemverilog\/","title":{"rendered":"Groups of Class Specializations in SystemVerilog"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p>In a previous <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2022\/10\/17\/dig-a-pool-of-specialized-systemverilog-classes\/\">post<\/a>, I said that in SystemVerilog, once you specialize a class, you can not make a group of them. Oops! Turns out that UVM does this all this time. You just need to know where to start.<\/p>\n\n\n\n<p>Just to be clear, you are making a group of <span style=\"text-decoration: underline;\">handles<\/span>, an array. Every <span style=\"text-decoration: underline;\">object<\/span> is separate, and thus cannot organized into an array.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Where\u2019s my sequencer?<\/h2>\n\n\n\n<p>Here is an example of a group of specialized classes. Your design may speak several protocols, so your UVM testbench needs multiple agents. In UVM, an agent speaks one protocol, such as USB or AXI. Inside the agent, a sequencer picks incoming transactions and sends them to the driver. The uvm_sequencer class is specialized for a single flavor of transactions, like these declarations.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p><code>\/\/ Inside the AXI agent class <\/code><br><code>uvm_sequencer #(axi_txn) axi_sqr; \/\/ A sequencer for AXI transactions <\/code><\/p>\n\n\n\n<p><code>\/\/ Inside the USB agent class <\/code><br><code>uvm_sequencer #(usb_txn) usb_sqr; \/\/ A sequencer for USB transactions<\/code><\/p>\n<\/div><\/div>\n\n\n\n<p>How can your testbench organize all those sequencers? What if your testbench declared an array of handles to hold these? Is the following code legal?<\/p>\n\n\n\n<p>uvm_sequencer sqr_array[string];<\/p>\n\n\n\n<p><code>sqr_array[\"AXI\"] = axi_sqr; \/\/ Compile error<\/code><\/p>\n\n\n\n<p><code>sqr_array[\"USB\"] = usb_sqr;&nbsp;\/\/ Compile error<\/code><\/p>\n\n\n\n<p>This won&#8217;t compile because when you specialized the class uvm_sequencer, it created a new type, and this is not compatible with the base uvm_sequencer, or the USB specialization. The full example requires a lot of support code, so let\u2019s make a smaller example, without UVM.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Back to basics<\/h2>\n\n\n\n<p>There is a solution, which you can see by peeking at the UVM source code where the parameterized class uvm_sequencer is eventually extended from the non-parameterized class, uvm_sequencer base.<\/p>\n\n\n\n<p>Let\u2019s make a simple base class with a name property, and no parameters. The function print() displays the class name.<\/p>\n\n\n\n<p><code>class Base;<br>&nbsp; virtual function void print();<br>&nbsp;&nbsp;&nbsp; $display(\"class Base\");<br>&nbsp; endfunction<br>endclass<\/code><\/p>\n\n\n\n<p>Now make a derived class that has a integer parameter.<\/p>\n\n\n\n<p><code>class Dparm #(int N=42) extends Base;<br>&nbsp; bit [N-1:0] p;<br>&nbsp; function void print();<br>&nbsp;&nbsp;&nbsp; $display(\"Dparm#(%0d)\", N);<br>&nbsp; endfunction<br>endclass<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get organized!<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm-1024x468.png\" alt=\"Pool of parameterized handles in SystemVerilog\" class=\"wp-image-18341\" width=\"644\" height=\"293\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm-1024x468.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm-600x274.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm-768x351.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm-900x411.png 900w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm.png 1518w\" sizes=\"auto, (max-width: 644px) 100vw, 644px\" \/><figcaption class=\"wp-element-caption\">Pool of parameterized handles in SystemVerilog<\/figcaption><\/figure>\n\n\n\n<p>Now you can make a group of handles. Declare them as an associative array of the base type, called a <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2022\/10\/17\/dig-a-pool-of-specialized-systemverilog-classes\/\" target=\"_blank\" rel=\"noreferrer noopener\">pool<\/a>. Also declare another base handle, and a few of the derived type with different specializations.<\/p>\n\n\n\n<p><code>&nbsp; Base bpool[string], b; \/\/ Pool of base handles, and temp<br>&nbsp; Dparm#(1) d1;        &nbsp; \/\/ Derived with #1<br>&nbsp; Dparm#(2) d2;&nbsp;         \/\/ Derived with #2<\/code><\/p>\n\n\n\n<p>Does this work? Can you really make an array of handles that point to different specializations? Try this on your favorite simulator and see what happens.<\/p>\n\n\n\n<p><code>&nbsp; initial begin<br>&nbsp;&nbsp;&nbsp; b = new(\"b\");&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;\/\/ Base handle to base object<br>&nbsp;&nbsp;&nbsp; bpool[\"b\"] = b;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;\/\/ Save in base pool<br>&nbsp;&nbsp;&nbsp; d1 = new(\"d1\");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;\/\/ <code>Dparm<\/code>#(1) object<br>&nbsp;&nbsp;&nbsp; bpool[\"d1\"] = d1; &nbsp;&nbsp;&nbsp;&nbsp;\/\/ Save in base pool<br>&nbsp;&nbsp;&nbsp; d2 = new(\"d2\");&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;\/\/ <code>Dparm<\/code>#(2) object<br>&nbsp;&nbsp;&nbsp; bpool[\"d2\"] = d2; &nbsp;&nbsp;&nbsp;&nbsp;\/\/ Save in base pool<br>&nbsp;&nbsp;&nbsp; $display(\"Print the object types\");<br>&nbsp;&nbsp;&nbsp; foreach (pool[i])&nbsp;&nbsp;&nbsp; \/\/ Wade through pool<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pool[i].print(); &nbsp;&nbsp;\/\/ and print objects<br>&nbsp; end<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Passing and assigning handles<\/h2>\n\n\n\n<p>You can assign a handle of a specialized type to a base handle. Here is a module-level function that calls the print() method.<\/p>\n\n\n\n<p><code>function void print(input Base b_arg);<br>&nbsp; b_arg.print();<br>endfunction<\/code><\/p>\n\n\n\n<p>You can call it as follows.<\/p>\n\n\n\n<p><code>print(b);&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Print base object<br>print(d1);&nbsp;&nbsp;&nbsp; \/\/ Print some specialized types<br>print(d2);&nbsp;&nbsp;&nbsp; \/\/ Equivalent to: b_arg = d2;<\/code><\/p>\n\n\n\n<p>What if you want to assign to a derived specialized handle from a base handle? I\u2019m out of space, so you are going to have to peek at a previous SystemVerilog OOP <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/08\/05\/class-variables-and-cast\/\">post<\/a> and see what works.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p>When you specialize a parameterized class, you are creating a new type, incompatible with other specializations. However, if the parameterized class extends a base class, you can assign a specialized handle to a base handle.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">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\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In a previous post, I said that in SystemVerilog, once you specialize a class, you can not make a&#8230;<\/p>\n","protected":false},"author":71586,"featured_media":18341,"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":[300,345,352,382,383,614,630,631,1488,728,1485,751,787,807],"industry":[],"product":[205],"coauthors":[980],"class_list":["post-18333","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-systemverilog","category-tips-tricks","category-uvm","tag-cast","tag-array","tag-associative-array","tag-class","tag-class-handles","tag-oop","tag-parameter","tag-parameterized-class","tag-pool","tag-specialized-class","tag-specialized-type","tag-systemverilog","tag-uvm","tag-uvm_pool","product-questa"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2023\/04\/dparm.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18333","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=18333"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18333\/revisions"}],"predecessor-version":[{"id":18398,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/18333\/revisions\/18398"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/18341"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=18333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=18333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=18333"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=18333"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=18333"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=18333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}