Thought Leadership

A Short Class on SystemVerilog Classes

By Dave Rich

It is often said that the English language is one of the most difficult languages to learn: inconsistent spelling rules; the same words are used with different meanings in different contexts. “Why does a farmer produce produce?”

Working on the SystemVerilog IEEE 1800 standard, I understand that even more clearly now. The word class is used many times in different contexts to mean slightly different things that the reader is expected to understand. With brevity, but little more attention to clarity, I will explain some of these different contexts.

Class Types

When you declare a class, you are declaring set of members and a set of methods that operate on those members.

class MyClass; bit [7:0] member1;
 bit member2;
 function void method;
   $display("members are %h %b", member1, member2);
 endfunction
endclass

Consider this a user defined type, like a typedef. We are declaring the form and behavior of a type, but nothing is allocated to store the values of this type.

Class Objects

A class object is a particular instance of a class type. Each instance is an allocation of the members defined by the class type. The only way to create an object is to call the class constructor using the built-in new() method of a class. We classify class objects as dynamic objects because executing a procedural statement is the only way to create them.

Class Handles

Each time you call the new() method, it constructs a new class object and the method returns a class handle to the class object. A handle is an indirect reference to a class object, like a pointer to an address in memory. Unlike pointers in other languages such as C/C++, you are very limited in what you can do with a handle in SystemVerilog.

Class Variables

A class variable is where you store the class handle that references a particular class object of a particular class type. Declaring a class variable does not create a class object, only the space to hold the class handles. This contrasts with other data types where the declaration of a variable creates an object of that type and gives you a symbolic name to reference those objects. For example:

typesef struct {bit [7:0] member1; bit member2;} MyStruct;
MyStruct StructVar1, StrucVar2

This creates and allocates the space for two MyStruct type objects and you can use StructVar1.member1 to access one of its members. On the other hand:

MyClass ClassVar1, ClassVar2;

This creates and allocates the space for two MyClass variables, but only allocates the space to hold handles to MyClass objects, not the objects themselves. If you tried to access ClassVar1.member1 now, you would get a null handle reference error because the initial value of a class variable is the special value null. One of the nice things about handles instead of pointers is that they remove the possibility of corrupt object references that access uninitialized or de-allocated memory.

Class Types, Objects, Handles, and Variables

Once you have a class variable, you can call the new() method to construct a class object

ClassVar1 = new();

This calls the constructor of the MyClass type that returns a handle to a MyClass object and then stores that handle in the MyClass variable, ClassVar1. You can now access ClassVar1.member1 because ClassVar1 references an actual object. If you then do:
ClassVar2 = ClassVar1;
Both class variables reference now the same class object – but there is still only one object of MyClass. ClassVar1.member1 and ClassVar2.member1 refer to the same class member.

Class Dismissed

Just remember to add a few extra words when mentioning classes and it will make things much clearer to the reader.

There are whole other classes of class thingy’s I could have explored, but I hope this class on classes will motivate you to learn more of the subtle meanings behind the words.

Comments

9 thoughts about “A Short Class on SystemVerilog Classes
  • I have below query.
    class A;
    int member1 = 1;
    endclass
    class EA extends A;
    int member1 = 2;
    endclass

    Now when I do
    EA =new();
    A=EA;

    ============================================================
    EA = new(); has given handle to object of type EA to class variable EA.
    A=EA; This pass the same handle (pointer value which points to object of EA) to A.
    so , A.member1 should refer to value 2.

    • Not correct. You can only reference class members from a class variable based on the type of the class variable, not on the type of the class object whose handle is stored in the class variable. Virtual class methods are the only way to access extended methods from a base class variable.

  • Hi Dave,
    Thanks for reply. I understood your point.

    But another thought process run on my mind is, As I did A=EA, it assign the handle ,which actually point to EA Object, whose type is EA, to A. Now A contains handle of Object EA, whose type is EA. Now EA has a variable member1, whose value is 2. So A.member1 should point to 2.

    Though I understand your point that value of member1 will reflect the value according to class type.

    But still I want to know where is mismatch in my understanding explained above.

  • Hi Dave,

    Do the usual Verilog timing rules apply to SystemVerilog classes? I am specifically trying to use non-blocking statements in tasks inside my classes.

    • Classes do not have string names associated with them. Methodologies like the UVM defines a class property that represents the class name, but it’s up to the user to make sure they match (the macro `uvm_object_utils does this for you).

Leave a Reply

This article first appeared on the Siemens Digital Industries Software blog at https://blogs.sw.siemens.com/verificationhorizons/2013/07/16/class-on-classes/