Systemverilog作为面向对象的编程语言,很多特性参考Java,CPP。
作用域解析运算符(Class scope resolution operator) ::
:用于显式的对标识符identifier
的命名空间namespace
做出解析。
Systemverilog中的形式:class_type :: { class_type :: } identifier
常见归类如下:
包packet
的使用,如import packets::*
内建类调用函数,如process::self
;内建packet调用函数,如std::randomize()
class
endclass
内部声明,外部定义function
constraint
,需要通过class_name::
指定。
在class外部,对常量parameter
localparam
的引用。(parameter
localparam
为elaboration-time
赋值,const
为run-time
赋值,常量constans
为 read only)
对 静态变量static variable
静态方法static method
的调用
对静态成员static member
的调用,如typedef
创建新类型,enmu
枚举变量
调用randomize with {}
时使用local::identifier
对重名的标识符做出区分
派生类内部访问父类的public变量和方法
covergroup
coverpoint
cross
的使用
如下示例:
package SEASONS_PKG;
typedef enum {SPRING,SUMMER,AUTUMN,WINTER} seasons_t;
endpackage
package TEST_PKG;
import SEASONS_PKG::*;
class SEED;
rand int seed;
constraint seed_value;
endclass
constraint SEED::seed_value {
seed inside {[0:100]};
}
//class Packet #(localparam NAME = "DEFAULT_PKT"); // not work
class Packet #(parameter NAME = "DEFAULT_PKT");
localparam NUMBER = 100;
localparam WIDTH = 32;
static string id;
enum {RED,BLUE,GREEN} COLOR_e;
typedef bit [15:0] b16;
const int seed;
bit [WIDTH-1:0] value = 1;
struct packed {
bit [31:16] head;
bit [15: 0] data;
} frame_s;
SEED m_seed;
function new();
seed = 100;
m_seed = new();
void'(std::randomize(frame_s) with {frame_s.head inside{1,3,5};frame_s.data inside {2,4,6};});
endfunction
extern static function void show_id();
extern function int get_seed();
extern function bit [WIDTH-1:0] get_value();
endclass
static function void Packet::show_id();
$display("class Packet ID:%s",id);
endfunction
function int Packet::get_seed();
void'(m_seed.randomize() with {seed == local::seed;});
return m_seed.seed;
endfunction
function bit [Packet::WIDTH-1:0] Packet::get_value();
return value;
endfunction
class Packet_e extends Packet;
static function void get_number();
$display("Packet number:%0d",Packet::NUMBER);
endfunction
function void get_value();
//$display("Packet value:%0d",value);
$display("Packet value:%0d",Packet::value);
endfunction
function void get_seed();
//$display("Packet_e seed:%0d",get_seed());
$display("Packet_e seed:%0d",Packet::get_seed());
endfunction
endclass
endpackage
module test();
import TEST_PKG::*;
Packet#("DATA_PKT") pkt;
initial begin
Packet#()::id = "PKT_1";
Packet#()::show_id(); // class Packet ID:PKT_1
Packet#("DATA_PKT")::show_id(); // class Packet ID:
pkt = new();
$display("frame_s : %p",pkt.frame_s); // frame_s : '{head:'h3, data:'h6}
$display("name:%s",pkt.NAME); // name:DATA_PKT
$display("name:%s",Packet#("CTRL_PKT")::NAME); // name:CTRL_PKT
$display("number:%0d",Packet#()::NUMBER); // number:100
$display("COLOR_e:%s",Packet#()::GREEN); // COLOR_e:GREEN
$display("seed:%0d",pkt.get_seed()); // seed:100
$display("value:%0d",pkt.get_value()); // value:1
end
initial begin
SEASONS_PKG::seasons_t seasons_e;
#1ns;
$display("seasons_e:%s",seasons_e.name()); // seasons_e:SPRING
seasons_e = SEASONS_PKG::WINTER;
$display("seasons_e:%s",seasons_e.name()); // seasons_e:WINTER
end
initial begin
Packet#()::b16 val = 16'hABCD;
#2ns;
$display("val:%0h,type:%s,bits:%0d",val,$typename(val),$bits(val)); // val:abcd,type:bit[15:0],bits:16
end
initial begin
Packet_e pkt_e;
#3ns;
Packet_e::get_number(); // Packet number:100
pkt_e = new();
pkt_e.get_value(); // Packet value:1
pkt_e.get_seed(); // Packet_e seed:100
end
process proc;
initial begin
proc = process::self();
$display("process status:%s",proc.status()); // process status:RUNNING
end
endmodule
参数化的类
class Packet
是一个参数化的类parameterized class
,使用时需要调用#
对generic class
进行specialization
获得一个concrete type
的类 ,否则报warning。Packet#()
使用default值。
每一个concrete type
的类,内部的静态成员都是相互独立的。如上述示例的 line 94,打印为空。
localparamlocalparam
相比parameter
,只能用于class
module
内部。而parameter
可以用于class
module
的参数化声明。
new()