{"id":16347,"date":"2021-08-05T11:52:09","date_gmt":"2021-08-05T15:52:09","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=16347"},"modified":"2026-03-27T08:49:52","modified_gmt":"2026-03-27T12:49:52","slug":"class-variables-and-cast","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/08\/05\/class-variables-and-cast\/","title":{"rendered":"Class Variables and $cast"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>My previous <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/07\/12\/class-variables-and-assignments-in-systemverilog\/\">post<\/a> showed how SystemVerilog class variables can refer to base and derived objects. This post shows you how to use the $cast() system task to copy between base and derived class variables. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Classy Cars<\/h2>\n\n\n\n<p>Start with a base class for an automobile with a color property.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class Automobile;\n  string color;\nendclass<\/pre>\n\n\n\n<p>Now extend this to make a Pickup class with a bed in the back to carry big things.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class Pickup extends Automobile;\n  int bed_size;\nendclass<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">A place for everything<\/h2>\n\n\n\n<p>As you create Automobile and Pickup objects, you need a place to hold them. How about a parking lot? This class has an array of Automobile class variables. This can hold handles to base Automobiles and derived Pickups, just like a real parking lot. Include methods to park and retrieve vehicles.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class ParkingLot;\n  Automobile spaces[4];\n\n  function void park(Automobile a, int spot);\n    spaces[spot] = a;\n  endfunction\n\n  function Automobile retrieve(int spot);\n    return spaces[spot];\n  endfunction\nendclass<\/pre>\n\n\n\n<p>Let\u2019s try this out! Declare some class variables, construct the parking lot, then an Automobile object, park it, then retrieve it.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Automobile a1, a2;\nParkingLot lot;\n\ninitial begin\n  lot = new();           \/\/ Construct the parking lot\n  a1 = new();            \/\/ Construct a blue Automobile\n  a1.color = \"blue\";\n  lot.park(a1, 0);       \/\/ Park it in spot 0\n\n  \/\/ Run some errands, then come back to get your car\n\n  <code>a2 = lot.retrieve(0);<\/code>  <code>\/\/ Retrieve automobile with different var<\/code>iable\n  <code>$display(\"Found automobile %p\", a2.color);<\/code>\nend<\/pre>\n\n\n\n<p>Try this code on your favorite simulator. You should see that the blue car was parked in space 0, and was successfully retrieved.<\/p>\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\/2021\/08\/5_3_lot_auto.png\" alt=\"Parking lot with an Automobile in space 0\" class=\"wp-image-16361\" width=\"569\" height=\"186\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_3_lot_auto.png 792w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_3_lot_auto-600x196.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_3_lot_auto-768x251.png 768w\" sizes=\"auto, (max-width: 569px) 100vw, 569px\" \/><figcaption>Parking lot with an Automobile<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Dude, where is my car?<\/h2>\n\n\n\n<p>Construct a red pickup and park it in spot 3.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Pickup p1, p2;\ninitial begin\n  p1 = new();\n  p1.color = \"red\";\n  lot.park(p1, 3);\nend<\/pre>\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\/2021\/08\/5_4_lot_pickup.png\" alt=\"Parking lot with an Automobile and a Pickup\" class=\"wp-image-16362\" width=\"578\" height=\"178\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_4_lot_pickup.png 792w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_4_lot_pickup-600x185.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_4_lot_pickup-768x237.png 768w\" sizes=\"auto, (max-width: 578px) 100vw, 578px\" \/><figcaption>Parking lot with an Automobile and a Pickup<\/figcaption><\/figure>\n\n\n\n<p>Wait, is that legal? The park() method has the formal argument a that is an Automobile class variable. You just tried to assign it a Pickup handle. The previous post showed that a base class variable can hold a handle to base and derived objects.<\/p>\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\/2021\/07\/4_1_venn-1024x428.png\" alt=\"Base and derived classes and their handles\" class=\"wp-image-16329\" width=\"550\" height=\"230\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/4_1_venn-1024x428.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/4_1_venn-600x251.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/4_1_venn-768x321.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/4_1_venn-900x376.png 900w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/4_1_venn.png 1368w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption>Base and derived classes and their handles<\/figcaption><\/figure>\n\n\n\n<p>OK, you\u2019ve now parked the Pickup object in space 3. Can you get it back? Use a different class variable to make sure the assignment worked.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">p2 = lot.retreive(3); \/\/ Won\u2019t compile<\/pre>\n\n\n\n<p>When you compile this code, you get an error that you can\u2019t assign to a Pickup variable from an Automobile variable. This is because retrieve() returns an Automobile variable. The compiler does not know if that variable refers to an Automobile or Pickup object.<\/p>\n\n\n\n<p>Think about this in the real world. Spaces in a parking lot can hold cars, pickups, motorcycles, or might be empty. If you parked your pickup in space 3, you expect to find your vehicle there \u2013 the space better have the same type! But you won&#8217;t know this until you retrieve it at run time.<\/p>\n\n\n\n<p>In SystemVerilog, how do you check the type at run time? Back in <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/06\/28\/runtime-checks-with-the-cast-method\/\">June<\/a> I showed how to do this for enumerated variables. The same $cast() method also works on class variables. Retrieve your pickup from space 3 with the following.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$cast(p2, lot.retreive(3));<\/pre>\n\n\n\n<p>You can check if this was a Pickup object with this extra code.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>if (! $cast(p2, lot.retrieve(3)))<\/code>\n  <code>$fatal(\"The vehicle in space 3 is not a pickup\");<\/code><\/pre>\n\n\n\n<p>Why did I use a $fatal()? If this is not a Pickup object, you have a bug in your code, so stop immediately and fix it. Make your code more reusable with a helpful message. The person who encounters this error may not know why you are parking pickups!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OOP cheat sheet<\/h2>\n\n\n\n<p>Here is your cheat sheet for assignments between base and derived class variables. Print this and put on your wall as a guide while you continue the journey to be a SystemVerilog expert.<\/p>\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\/2021\/08\/5_2_cast.png\" alt=\"\" class=\"wp-image-16356\" width=\"495\" height=\"133\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_2_cast.png 965w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_2_cast-600x162.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_2_cast-768x207.png 768w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_2_cast-900x242.png 900w\" sizes=\"auto, (max-width: 495px) 100vw, 495px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Attack of the (UVM) clones<\/h2>\n\n\n\n<p>A similar pattern occurs when you try to clone an object in UVM. Maybe you want to clone a transaction object before sending its handle to the scoreboard. Here is a transaction class.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class tx_item extends uvm_sequence_item;\n  ...<\/pre>\n\n\n\n<p>The clone() method was declared in uvm_object and returns a handle of type uvm_object. Eventually, everything in UVM is derived from this base class, including uvm_sequence_item.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">class uvm_object;\n  virtual function uvm_object clone();\n    ...<\/pre>\n\n\n\n<p>Declare two txm_item variables and create an object with the name \u201ctx\u201d.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">tx_item t1, t2;\nt1 = tx_item::type_id::create(\u201ctx\u201d); \/\/ Create a tx_item object<\/pre>\n\n\n\n<p>Try to clone the object, and you will get a compile error.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">t2 = t1.clone(); \/\/ Error, won't compile<\/pre>\n\n\n\n<p>Why? t2&#8217;s type is for a derived class, while clone() returns a base uvm_object handle. You can&#8217;t assign a base to a derived. The solution is the $cast() system task to check the type of the object that clone() returns.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$cast(t2, t1.clone());<\/pre>\n\n\n\n<p>Can you rewrite this with a custom error message?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>When you need to assign between two variables of different types, and the source might have a value incompatible with the destination, use $cast() to check the value. The check happens at runtime. This works for class variables, especially when a base variable has a handle to a derived object. If you want to give a helpful message, call $cast() as a function.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction My previous post showed how SystemVerilog class variables can refer to base and derived objects. This post shows you&#8230;<\/p>\n","protected":false},"author":72251,"featured_media":16365,"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],"tags":[300,382,383,585,594,612,614,648,751],"industry":[],"product":[],"coauthors":[942],"class_list":["post-16347","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-systemverilog","category-tips-tricks","tag-cast","tag-class","tag-class-handles","tag-member","tag-method","tag-object-oriented-programming","tag-oop","tag-property","tag-systemverilog"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/08\/5_6_lot_auto2_pickup2.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16347","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\/72251"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=16347"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16347\/revisions"}],"predecessor-version":[{"id":16383,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16347\/revisions\/16383"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/16365"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=16347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=16347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=16347"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=16347"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=16347"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=16347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}