SystemVerilog Static Variables & Functions

每个类实例通常都具有其每个内部变量的副本。

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


Simulation Log
ncsim> run
addr=0xdead data=0x12
addr=0xface data=0xab
addr=0xcafe data=0xfc
ncsim: *W,RNQUIE: Simulation is complete.

每个类对象p1,p2,p3都将具有addr和data变量。

静态变量Static Variables

当类中的变量声明为静态时,该变量将是所有类实例中的唯一副本。 为了演示一个示例,我们将比较静态计数器与非静态计数器。 静态计数器使用static关键字声明,并命名为static_ctr,而普通计数器变量命名为ctr。 这两个计数器将在new()函数中递增,以便每次创建对象时更新它们。

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

您会看到静态计数器在所有类对象p1,p2和p3之间共享,因此当创建三个数据包时它将增加到3。 另一方面,普通计数器变量ctr没有声明为静态,因此每个类对象都有其自己的副本。 这就是为什么在创建所有三个对象后ctr仍为1的原因。

Simulation Log
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.

想要知道直到特定时间之前生成的数据包总数的情况下,将变量声明为静态变量可能非常有用。

静态功能

静态方法遵循所有类作用域和访问规则,但是唯一的区别是,即使没有类实例化,也可以在类外部调用它。 静态方法无法访问非静态成员,但可以直接访问静态类的属性或调用同一类的静态方法。 静态方法也不能是虚拟的。 使用类名称的静态函数调用需要通过作用域运算符::进行。

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();   // 使用::操作符进行静态调用
    pkt[5].get_pkt_ctr();   // Normal call using instance
  end
endmodule
 
Simulation Log
ncsim> run
ctr=6
ctr=6
ncsim: *W,RNQUIE: Simulation is complete.

让我们添加一个名为mode的非静态成员,并尝试从我们的静态函数中调用它。

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

不允许这样做,将导致编译错误。

      $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.

参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-static-variables-functions

发布了124 篇原创文章 · 获赞 8 · 访问量 6698

猜你喜欢

转载自blog.csdn.net/qq_43042339/article/details/104494900
今日推荐