Logo

Inheritance in SV

12 Aug 2023
4 mins

In previous article we learnt how to write classes and objects in System Verilog. In this article we will focus on learning about the inheritance of classes in System Verilog. We will learn how to create a child class and add additional functionalities in the child class. We will also see casting of objects from child class to parent class and vice versa.

Subclass or child class

Sub classes or child classes are classes which are derived from other class which are known as parent or super class. In verification, we would come across various scenarios were we want to have some base reference class and then slowly build upon that super/base class.

Child class are known as sub class, derived class.

How to declare a child class?

In System Verilog extend keyword is used to create a child class. We use this keyword in class declaration after the name of the child class.

class <class name> extends <base_class_name>;
endclass

Super Keyword

In previous article we saw about this keyword. super keyword is kind of like this keyword except it is used to access property or method present in parent class.

class abc extends xyz;
	function test();
		super.test1();
	endfunction
endclass

In above code, test method of child class abc will call the test1 method of parent class xyz.

It is not necessary to use the super keyword when method name is unique b/w parent and child class. In the above example, even if we don’t use keyword, it will work as expected. Super keyword is mainly used when method name are common in parent and child or when we do function overriding which we will learn later.

When a constructor of child class is called it automatically calls the new class of parent class, i.e., super.new() is by default the first thing called inside constructor of child class. If the constructor of parent class requires some arg, then we need to explicitly call parent class constructor and pass the arg.

Usage

class parent;
    int a, b;
    function void print();
        $display("a = $-1d, b = %0d", a, b);
    endfunction
endclass

class child extends parent;
    int c;
    function void print();
        super.print();
        $display("c = %-1d", c);
    endfunction
endclass

In the above example, we are creating a child class child from parent class parent. In child class we can access all the properties and methods defined in the parent class and the additional properties which we have declared in child class.

Multi-level inheritance

The example which we saw in previous section was an example of single inheritance, i.e., there was a child class and parent class. But in multi-level inheritance child class can also be the parent of another child. This can be understood from the analogy of family tree.

This concept allows us to create a very complex code structure, where we can create a new level of class hierarchy and add additional functionalities to the class without touching the parent class.

Multi-level inheritance should not be confused with multiple inheritance. In multiple inheritance a child class can have multiple parent class. This is not supported in SV and thus would give error if we try to inherit multiple classes.
In multi-level inheritance it is not allowed to reach class higher than the immediate parent class. This means that super.super.new() or similar are not allowed.

Example

Illustration of multi-level inheritance
Illustration of multi-level inheritance
class c1;
endclass

class c2 extends c1;
endclass

class c3 extends c2;
endclass

Type casting

Type casting refers to casting data of one type to another. In simple terms, it means to covert variable/object of one data type to another. In System Verilog or any other OOP languages, classes are considered as data type and object conversion is allowed b/w parent and child class data types.

These are most often required in scenarios where some component might have args defined in parent class data type and we have an object of child class data type or vice-versa. To deal with these types of scenarios we have to use typecasting.

Object of parent class type can be converted to child class type implicitly by compiler and thus we don’t need to do anything. But vice-versa is not allowed implicitly. We need to do explicit type conversion using $cast() system method.

It is recommended to use $cast() always to cast objects as it returns a bit value to indicate whether cast was successful or not. Thus, it can be used to handle any cast errors properly and avoid any unexpected run-time errors.

We will learn about type casting in detail after few articles. For now, understanding the basic need for type casting would be enough.

Use Case example

class parent;
    int x =5;
    function new();
       $display("inside new of parent class");
    endfunction //new()
    task printf();
        $display("This is parent class");
    endtask
endclass //parent


class subclass extends parent;
    function new();
        $display("inside new of child class");
    endfunction //new()

    task printf();
        $display("This is subclass");
        $display("calling parent's printf method from subclass");
        super.printf();
    endtask
endclass //subclass extends parent

module inheritence;
    initial
    begin
        parent p;
        subclass s;

        p=new();
        s=new();

        s.x = 10;

        $display("Value of x using p: %d", p.x);
        $display("Value of x using s: %d", s.x);

        p.printf();
        s.printf();
    end
endmodule
Output
# inside new of parent class
# inside new of parent class
# inside new of child class
# Value of x using p:           5
# Value of x using s:          10
# This is parent class
# This is subclass
# calling parent's printf method from subclass
# This is parent class

In above example, please note that the constructor of child class automatically called the parent class constructor and thus we are seeing the output from new method of parent class 2 times.

Try this code in EDA Playground

Conclusion

In this article we learnt how to create a child class and how to access the parent class variables/methods from the child class. Also, we learnt about the super keyword which plays a very important role specially in verification frameworks like UVM. In the next article we will learn about polymorphism in System Verilog and how to implement it