Each class instance would normally have a copy of each of its internal variables.
class Packet;
bit [15:0] addr;
bit [7:0] data;
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
$display ("addr=0x%0h data=0x%0h", addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new (16'hdead, 8'h12);
p2 = new (16'hface, 8'hab);
p3 = new (16'hcafe, 8'hfc);
end
endmodule
Each of the class objects p1, p2, p3 will have addr and data variables within it.
ncsim> run addr=0xdead data=0x12 addr=0xface data=0xab addr=0xcafe data=0xfc ncsim: *W,RNQUIE: Simulation is complete.
Static Variables
When a variable inside a class is declared as static
, that variable will be the only copy in all class instances. To demonstrate an example we'll compare a static counter vs a non-static counter. The static counter is declared with static
keyword and named as static_ctr while the normal counter variable is named as ctr. Both counters will be incremented within the new()
function so that they are updated everytime an object is created.
class Packet;
bit [15:0] addr;
bit [7:0] data;
static int static_ctr = 0;
int ctr = 0;
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
static_ctr++;
ctr++;
$display ("static_ctr=%0d ctr=%0d addr=0x%0h data=0x%0h", static_ctr, ctr, addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new (16'hdead, 8'h12);
p2 = new (16'hface, 8'hab);
p3 = new (16'hcafe, 8'hfc);
end
endmodule
You'll see that the static
counter is shared between all class objects p1, p2 and p3 and hence will increment to 3 when three packets are created. On the other hand, the normal counter variable ctr is not declared as static
and hence every class object will have its own copy. This is the reason why ctr is still 1 after all three objects are created.
ncsim> run static_ctr=1 ctr=1 addr=0xdead data=0x12 static_ctr=2 ctr=1 addr=0xface data=0xab static_ctr=3 ctr=1 addr=0xcafe data=0xfc ncsim: *W,RNQUIE: Simulation is complete.
Declaring a variable as static
can be very useful in cases where you want to know the total number of packets generated until a particular time.
Static functions
A static
method follows all class scoping and access rules, but the only difference being that it can be called outside the class even with no class instantiation. A static
method has no access to non-static members but it can directly access static class properties or call static methods of the same class. Also static methods cannot be virtual
. Static function calls using class names need to be made through the scope operator ::
.
class Packet;
static int ctr=0;
function new ();
ctr++;
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d", ctr);
endfunction
endclass
module tb;
Packet pkt [6];
initial begin
for (int i = 0; i < $size(pkt); i++) begin
pkt[i] = new;
end
Packet::get_pkt_ctr(); // Static call using :: operator
pkt[5].get_pkt_ctr(); // Normal call using instance
end
endmodule
ncsim> run ctr=6 ctr=6 ncsim: *W,RNQUIE: Simulation is complete.
Let's add in a non-static member called mode and try to call that from our static function.
class Packet;
static int ctr=0;
bit [1:0] mode;
function new ();
ctr++;
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d mode=%0d", ctr, mode);
endfunction
endclass
It's not allowed and will result in a compilation error.
$display ("ctr=%0d mode=%0d", ctr, mode); | ncvlog: *E,CLSNSU (static-function.sv,10|40): A static class method cannot access non static class members.