参数化类 (parameterized class)
systemverilog也支持参数化的类。看下面的实例:
//---- class ----
class packet #(parameter int ADDR_WIDTH = 32,DATA_WIDTH = 32);
bit [ADDR_WIDTH-1:0] address;
bit [DATA_WIDTH-1:0] data ;
function new();
address = 10;
data = 20;
endfunction
endclass
packet pkt;此时声明了一个pkt句柄,其中参数为默认值,即ADDR_WIDTH = 32, DATA_WIDTH= 32。我们可以在这个类被实例化的时候修改默认的参数值。如:packet #(32,64) pkt.
systemVerilog还支持将变量类型进行参数化,在下面的例子中,使用type表示参数化。
class packet #(parameter type T = int);
T address;
T data ;
function new();
address = 10;
data = 20;
endfunction
endclass
packet pkt.表明address 和 data的类型都是Int类型。packet #(bit [31:0] )pkt.表明address 和 data的类型都是bit [31:0]。
继承
继承是一个oop概念,它允许基于一个已经存在的类来创建类。这个新的类有新的特性和方法,但是同时它也可以访问原本类的特性和方法。继承就是继承基类成员衍生到新类中,
既然是继承,谁继承谁,要做区分。被继承者叫基类base,或者父类parent,继承者叫拓展类extended,或者子类subclass。拓展类基于存在的类创建,会继承基类所有的属性和方法,即基类有的,拓展类都有,但拓展类可能会有基类没有的新成员。
class parent_class;
bit [31:0] addr;
endclass
class child_class extends parent_class;
bit [31:0] data;
endclass
module inheritence;
initial begin
child_class c = new();
c.addr = 10;
c.data = 20;
$display("Value of addr = %0d data = %0d", c.addr, c.data);
end
endmodule
其输出结果是:
多态
多态意味着多种形式,在systemverilog中的多态意味一个对象可以展现多种形式。
基类中有方法display,每个子类都定义了自己的display方法。一般,我们父类并不会用它的display方法,更多的是设置为接口,提供api方便调用,具体的实现由子类自己决定。见下面的代码,父类display方法设为虚方法virtual,表示子类可以覆盖掉父类的方法,读写可以尝试删除virtual关键词,体会virtual的效果。然后分别创建了三个子类对象,并把子类对象赋值给父类,然后用父类句柄访问display。如下面的例子所示:
// base class
class base_class;
virtual function void display();
$display("Inside base class");
endfunction
endclass
//extended class 1
class ext_class_1 extends base_class;
function void display();
$display("Inside extended class 1");
endfunction
endclass
//extended class 2
class ext_class_2 extends base_class;
function void display();
$display("Inside extended class 2");
endfunction
endclass
//extended class 3
class ext_class_3 extends base_class;
function void display();
$display("Inside extended class 3");
endfunction
endclass
module class_polymorphism;
initial begin
//declare and create extended class
ext_class_1 ec_1 = new();
ext_class_2 ec_2 = new();
ext_class_3 ec_3 = new();
//base class handle
base_class b_c[3];
//assigning extended class to base class
b_c[0] = ec_1;
b_c[1] = ec_2;
b_c[2] = ec_3;
//accessing extended class methods using base class handle
b_c[0].display();
b_c[1].display();
b_c[2].display();
end
endmodule
其输出结果是:
Overrinding class members
基类或者父类中的性质和方法可能会在子类或者拓展类中被重写,因此此时就存在以谁为准的问题。具体见下面的一个实例:
class parent_class;
bit [31:0] addr ;
function display();
$display("Addr = %0d", addr);
endfunction
endclass
class child_class extends parent_class;
bit [31:0] data;
function display();
$display("Data = %0d", data);
endfunction
endclass
module inheritence;
initial begin
child_class c = new();
c.addr = 10;
c.data = 20;
c.display();
end
endmodule
其输出结果是:
当子类对象调用display方法时,会调用自己定义的方法,即打印data。可以理解为,调用方法遵循就近原则,当成员自己没有的时候,才会去父类寻找。
super
super主要用来是子类访问父类中的成员。如果在子类中一些成员被重写,那么就需要使用super来访问父类中的成员。super关键词,和this一样,内建句柄用于访问父类成员,但仅仅是上一级父类的成员。还是4的代码示例,在子类display方法增加语句。
在上一个例子中添加如下语句:
其输出结果是: