Question on Inheritance in SV

Can anyone explain why I am getting a as 0 in the below example:

module top;
class C;                                                 
   int c1 = 1;
   int c2 = 1;
   int c3 = 1;

function new(int a);
   $display("ZAM: a_val: %d",a); // always getting display as 0
   c2 = 2;
   c3 = a;
endfunction
endclass

class D extends C;
   int d1 = 4;
   int d2 = c2;
   int d3 = 6;
function new;
   super.new(d3);
endfunction
endclass


initial  begin
D d1=new();
endmodule

P.S; When I replace int d3=6; with static int d3 =6; then I am able to get value of a as 0 (in base class constructor function)

In reply to soumyarayaprolu:

This is the example in SV LRM 8.7 Constructors chapter. It describes how class construct is executed in order. In this example, when calling super.new(d3), the value of d3 is undefined because d3 variable initialization is done in step 2) after new method executed.

  1. The new method of a derived class shall first call its base class constructor [super.new() as described.
    2)After the base class constructor call (if any) has completed,each property defined in the class shall be initialized to its explicit default value or its uninitialized value if no default is provided.
  2. After the properties are initialized,the remaining code in a user-defined constructor shall be evaluated.

In reply to Lina.Lin:

Thanks for your reply. Cna you also help me understand the below point:

When I replace int d3=6; with static int d3 =6; then I am able to get value of a as 0 (in base class constructor function)

In reply to soumyarayaprolu:

When I replace int d3=6; with static int d3 =6; then I am able to get value ofa as 0 (in base class constructor function)

Your question regarding to a as 0 here is confused. I guess you want to ask that a is 6 when static int d3=6;

static property of the class is shared by all of its instances. it can be accessed by class scope resolution operator :: directly like D::d3 even though no class instance. So I think static variable’s initialization to explicit default value is before the class instance new() construct.

In reply to soumyarayaprolu:
Because all variables with static lifetimes get initialized before any initial or always block processes start.

You actually have a race condition because the order of static variable initialization is not defined. Your d1 variable inside the initial block is also a static variable that gets initialized before the initial block process starts. A simulator that follows the 1800-2012 would have made this an error (Section 6.21). For backward compatibility with Verilog, variables declared inside a procedural block that is not a class method have a default static lifetime. SystemVerilog requires you to remove the static variable initialization, or declare the variable explicitly static to make sure you have the right intent.

In reply to soumyarayaprolu:

Can anyone explain why I am getting a as 0 in the below example:

module top;
class C;                                                 
int c1 = 1;
int c2 = 1;
int c3 = 1;
function new(int a);
$display("ZAM: a_val: %d",a); // always getting display as 0
c2 = 2;
c3 = a;
endfunction
endclass
class D extends C;
int d1 = 4;
int d2 = c2;
int d3 = 6;
function new;
super.new(d3);
endfunction
endclass
initial  begin
D d1=new();
endmodule

P.S; When I replace int d3=6; with static int d3 =6; then I am able to get value of a as 0 (in base class constructor function)

But when running both the cases a is getting value of 6.

In reply to saurabh_3:

I update your code to have d3 as static, d4 as non-static and pass them to new(a,b). The sim result show display message as below. Not sure why you get 0 for both cases.

ZAM: static a_val: 6 non-static b_val:0


module top;
class C;                                                 
   int c1 = 1;
   int c2 = 1;
   int c3 = 1;
 
  function new(int a, int b);
    $display("ZAM: static a_val: %0d non-static b_val:%0d",a,b); // always getting display as 0
   c2 = 2;
   c3 = a;
endfunction
endclass
 
class D extends C;
   int d1 = 4;
   int d2 = c2;
   static int d3 = 6;
          int d4 = 6;
function new;
  super.new(d3,d4);
endfunction
endclass

D d1;
initial  begin
  d1=new();
end
endmodule

In reply to saurabh_3:

Hi could you please clarify the following.

I am assuming that memory for the class properties is created when constructor is called. then how we are able to call super.new(d3) with d3 variable as memory for d3 is not created yet when d3 variable is not declared as static.

  1. when d3 variable is declared as static, what is the order of memory creation and initialization. is memory created first for all static variables and then initialization happens for all static variables . or memory created for one variable and it gets initialized, if this is true ,how d3 variable is accessed even when d3 is declared as static as it is not created still.

In reply to Lina.Lin:

In reply to saurabh_3:
I update your code to have d3 as static, d4 as non-static and pass them to new(a,b). The sim result show display message as below. Not sure why you get 0 for both cases.
ZAM: static a_val: 6 non-static b_val:0


module top;
class C;                                                 
int c1 = 1;
int c2 = 1;
int c3 = 1;
function new(int a, int b);
$display("ZAM: static a_val: %0d non-static b_val:%0d",a,b); // always getting display as 0
c2 = 2;
c3 = a;
endfunction
endclass
class D extends C;
int d1 = 4;
int d2 = c2;
static int d3 = 6;
int d4 = 6;
function new;
super.new(d3,d4);
endfunction
endclass
D d1;
initial  begin
d1=new();
end
endmodule

I am using vcs tool for your updated code ,getting result as
ZAM: static a_val: 6 non-static b_val:6
V C S S i m u l a t i o n R e p o r t

In reply to srbeeram:

The space for any variable, static or non-static, gets allocated and initialized with its default value in time for you to reference it. SV does not allow you to reference a variable that does not exist.

The variable’s lifetime determines when the optional initialization expression gets evaluated.

static: before any initial or always processes begin
automatic: upon entering the procedural block where the variable is declared
dynamic: prior to the body of the class constructor where the variable is declared.

In reply to srbeeram:

The space for any variable, static or non-static, gets allocated and initialized with its default value in time for you to reference it. SV does not allow you to reference a variable that does not exist.

The variable’s lifetime determines when the optional initialization expression gets evaluated.

static: before any initial or always processes begin
automatic: upon entering the procedural block where the variable is declared
dynamic: prior to the body of the class constructor where the variable is declared.

In reply to dave_59:
Hi Dave, could you please clarify the following. in the following code from above example, are d1 ,d2 and d3 get created and assigned with default value of 0 before super.new(d3) , and assigned with the values d1=4, d2=c2 and d3=6 immediately after super.new(d3) in the D class constructor.


class D extends C;
   int d1 = 4;
   int d2 = c2;
   int d3 = 6;
function new;
   super.new(d3);
endfunction
endclass


I am expecting that way as I am getting the value of d3 as 6 in the below code. could you please clarify.



module top;
class C;                                                 
   int c1 = 1;
   int c2 = 1;
   int c3 = 1;
function new(int a);
   $display("ZAM: a_val: %d",a); // always getting display as 0
   c2 = 2;
   c3 = a;
endfunction
endclass
 
class D extends C;
   int d1 = 4;
   int d2 = c2;
   int d3 = 6;
function new;
   super.new(d3);
   $display("value of d3 %d",d3);
endfunction
endclass
 
 
D d1=new();
initial  begin
end
endmodule



In reply to srbeeram:

The explanation is posted above.

In reply to dave_59:

ok Got it. Thanks.