SystemVerilog中的类的继承

继承是基于类的面向对象编程(object-oriented pro - gramming)的最重要特性之一。
扩展类,简言之,就是基类的扩展。
扩展类继承了基类的所有属性和方法,并且支持在继承类中重写基类的属性和方法以及新增更多的属性和方法。
所以,继承类的好处是什么?
1、继承类对基类的复用+改进
2、基类的改动能很快地影响到所有继承类,减少公共代码的修改
例如,可以定义一个名为ethernetpacket的基类。然后定义扩展类,如ethererrorpacket、etherlatencypacket等,除了继承基类的属性,还可以根据需要新增更多的新属性和方法。
module class_top( );class base;logic [31:0] data1;logic [31:0] data2;logic [31:0] busx;function void bus;busx = data1 | data2;endfunctionfunction void disp;$display(from base class :: busx or = %h, busx);endfunctionendclass : baseclass ext extends base;logic [31:0] data3; //add a new propertyfunction new ( );$display(call base class method from extended class - super.disp);super.disp;endfunctionfunction void bus; //redefne function 'bus' of class 'base'busx = data1 & data2 & data3;//data1,data2 inherited from class 'base'endfunctionfunction void disp; //redefne function 'disp' of class 'base'$display(from extended class :: busx and = %h,busx);endfunctionendclass : extinitial beginbase b1;ext e1;b1 = new;e1 = new;b1.data1 = 32'h ffff_0000;b1.data2 = 32'h 0000_ffff;b1.bus;b1.disp( );e1.data1 = 32'h 0101_1111;e1.data2 = 32'h 1111_ff;e1.data3 = 32'h 1010_1010;e1.bus;e1.disp( );endendmodule  
仿真log:
call base class method from extended class - super.dispfrom base class :: busx or = xxxxxxxxfrom base class :: busx or = fffffffffrom extended class :: busx and = 00001010 v c s s i m u l a t i o n r e p o r t  
在class “base”中,我们定义了属性data1、 data2和busx,然后又定义了2个functions “bus”和“disp”
由于我们没有显式地定义构造函数new(),所以变量data1, data2和busx都会被初始化成“x”态 。
class “ext”是class “base”的继承类,所以类“ext”自然也会有属性“data1,” “data2,” 和“busx”。
同时我们在类“ext”中额外声明了属性“data3”,并且覆盖了父类中函数“bus”和“disp”的声明。
在上面的例子中,我们在扩展类ext中的构造函数中通过关键字“super.”来调用父类中声明的函数。所以会打印:
from base class :: busx or = xxxxxxxx  
在initial语句块中,我们赋值父类中的属性,然后打印出“busx.”(即data1 | data2)。然后修改扩展类中的属性,然后打印出“busx.”(覆盖过的函数data1 & data2 & data3)
仿真的log也证明了父类的函数被成功地覆盖掉了。
每一个class 都会有一个构造函数new()(隐式或者显式的),在扩展类的构造函数中,第一件事就是要去调用父类的构造函数“super.new( )”。然后如果你忘了在扩展类的构造函数中添加,编译仿真工具也会自动帮你添加的。
一般来说不需要显式地添加super.new(),但是如果构造函数带参数,那么必须要显式地添加supoer.new()
inheritance memory allocation
还是那句话,理解一个语言的很多特性都需要从内存分配的角度去理解。
如果需要完全理解扩展类,就需要理解基类和扩展类中的属性和函数的内存分配。
module class_top( ); class aa; int i1; function funaa; endfunction endclass : aa class bb extends aa; int i1; function funbb; endfunction endclass : bb initial begin bb b; b = new( ); end endmodule
在上面的例子中,虽然我们只是调用了扩展类的构造函数“b = new( ),” ,但是实际上,我们不仅分配的类“bb”的内存空间,还分配了基类“aa”的内存空间,即使变量名称一样。
这个同名的变量需要通过作用域(不同的内存分配)进行区分。


雄安能源积极推动能源转型,碳中和基金会正式成立
天猫魔盒实际性价比怎么样,现在值不值得买
对基于FPGA的高速路由查找算法的研究
‘新基建’提速为推动人工智能发展带来新机遇
华为Mate 20 X石墨烯散热技术大起底:提高竞争门槛
SystemVerilog中的类的继承
工业视觉控制器的工作原理
面对激烈挑战,比亚迪能否持续领跑赢得“智能化”的下半场?
Imagination在AutoSens大会上展示足够精彩,真棒!
如何将PLC设备数据通过物联网网关接入云平台
冷库温湿度物联网监控系统解决方案
【节能学院】故障电弧探测器在分布式光伏电站的应用
非洲猪瘟设备实验室方案
英国政府计划出资帮助安装充电桩等设备
信号放大器会影响到手机的通话吗
固体负离子检测仪有什么作用
TVS二极管的作用和类型 TVS通信接口使用方案举例
如何检测电池内阻?
罗技MX无线蓝牙垂直鼠标体验 疲劳感确实降低了很多
python变量与基本数据类型介绍