SystemVerilog: Implicit handles

Introduction

In the last blog post [SC(SECL1] Farmer Ted asked you to keep track of his animals and you wrote some SystemVerilog classes, using public, protected, and local members. This week you are enhancing the code using the implicit handles, this and super.

Quick definition: implicit means the language / tool creates the member for you. If you had to create it yourself, like the weight property, it would be explicit. Also, what I am calling a “handle” is technically called a “class variable” that holds an “object handle”. Everyone I know says “handle” to refer to the variable.

What is this?

How can your routine access a class-level variable when there is a local variable with the same name? This often happens when a set() method or the constructor initializes a class property with an argument. A common style is to give the argument the same name as the class property, such as weight shown here. If the assignment was just “weight = weight”, both names would refer to the closest definition, which is the routine argument. The solution is to use the implicit handle, this, to assign the class property. The code below won’t work without the “this” handle.

class Animal;
int weight; // Class-level property

  virtual function void set_weight_kg(input int weight);
    this.weight = weight;  // class property = routine argument
  endfunction
endclass

This diagram color codes the scope. Members of the Animal class are in blue including the this handle in the upper right, while names associated with the set_weight_kg() method are in purple.

Implicit handle: this

Department of redundant redundancies

Sometimes you might use the handle even when not needed, just to be clear. The function below copies properties from the object that rhs handle (right hand side) points to, into the current object. The code still works without the “this”, but the handle emphasizes what you are trying to do. There is no penalty for being extra careful.

class Animal;
  int weight; // Class-level property

  virtual function void copy(Animal rhs);
    this.weight = rhs.weight; // Copy class member from rhs
  endfunction
endclass

How can you tell if the handle is redundant? You can remove it and see if the code still seems to work, a risky approach. Instead, prove to yourself – is there a weight member in the local scope, the function? No? Then then the handle is redundant.

It’s a bird, it’s a plane

In a derived class, you might want to reference a member of the base class. A common example is a virtual method that overrides a base class method and wants to call that base method. Here is the Animal class with a virtual print() method.

class Animal;
  protected int weight;

  virtual function void print();
    $display("Animal: %0d kg", weight);
  endfunction
endclass

The class Sheep extends Animal and has a property, shorn, to let you know if the sheep had a haircut. The class needs a print() method to display this class property. It also needs to display the base class Animal properties, but you don’t want to hardcode that into the Sheep class. Instead, call the Animal’s print method. Wait, if the Sheep print calls print(), it will call itself! You need a handle to members of Animal. The implicit handle super comes to your rescue!

class Sheep;
  bit shorn;

  virtual function void print();
    $write("Sheep: shorn=%b", shorn);
    super.print();
  endfunction
endclass

The method calls $write() instead of $display()so that the final output is one long line.

Here is a diagram showing the Sheep class in green and the super handle in the upper right.

Super handle to base members

Skipping class

When I show the super handle to students, someone often asks what if you call super.method() and there is no corresponding method in the parent class. When Merino::set_weight_kg() calls super.set_weight_kg(), there is no such method in Sheep, so the compiler keeps looking and finds the method in the base Animal class.

class Merino extends Sheep;
  virtual function void set_weight_kg(int weight);
    super.set_weight_kg(weight); // Ends up in Animal method
  endfunction
endclass

Super-duper handles

The other common question is if a method can call super.super.method(). Maybe my students read too many comics? The answer is that the implicit handles super and this are local members, so they can only be used inside the class. If Merino tried calling super.super.method(), the first super handle is legal, but the second refers to a local property in the Sheep class, which is illegal. Bad news for the fanboys, good news for OOP purists.

Experiment

Try merging the code from this post along with the earlier code. You can then either step through the simulation, line-by-line, or sprinkle the following to trace the execution.

$display("%m");

Learn More

You can learn more about these topics including Oriented Programming with Siemens SystemVerilog for Verification course. It is offered in instructor led format by our industry expert instructors, or in a self-paced on-demand 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.  Also, you can now earn a digital badge/level 1 certificate by taking our Advanced Topics Badging Exam. This will enable you to showcase your knowledge of this topic by displaying the badge in your social media and email signature.


Want to stay up to date on news from Siemens Digital Industries Software? Click here to choose content that's right for you

Leave a Reply

This article first appeared on the Siemens Digital Industries Software blog at https://blogs.sw.siemens.com/verificationhorizons/2022/09/06/systemverilog-implicit-handles/