SystemVerilog学习笔记(七)


1. 类的继承

1.1 实例1 子类没有定义new函数,会调用父类new函数

**仿真结果**: >p.i = 2; >lp.i = 2;

1.2 实例2

**仿真结果**: >lp.i = 3;
## 1.3 实例3 如果子类定义function new,仍会默认调用父类的new函数
**仿真结果**: >p.i = 2; >lp.i = 2;

1.4 实例4

子类和父类出现同名函数function,如果子类没有使用supper.(functionname),不会调用父类的此函数。如果子类里使用supper.(functionname),即调用父类的此函数。 ## 1.5 实例5
  1. 子类带参数,父类不带参数,仍会调用父类new函数。
  2. 只要父类new没有参数,就可以默认调用
  3. 子类必须调动父类的new函数,否则编译无法通过。
  4. 如果父类new函数没有参数,直接调用;如果父类new函数有参数,子类里面需要严格用supper.new

1.6 实例6

仿真结果

p.i = 4;
lp.i = 3;
after shift p.i = 8;
after shift lp.i = 12;

设置断点分析

**注意**: 1. 子类和父类出现同名的函数或者同名的函数或者任务(同名方法),子类想要继承,需要方法名一致参数一致,调用一定写supper 2. 子类的方法名称可以与父类同名,但子类的变量最好不要跟父类的变量同名

1.7 实例7 子类的句柄能够赋值给父类的句柄,父类的句柄不能赋值给子类的句柄

  1. 子类的句柄能够赋值给父类的句柄( ==能够访问区域缩小==),父类的句柄不能直接赋值给子类的句柄。(注意这里是不能直接赋值,在编译时父类句柄赋值给子类句柄会报错,但是在仿真运行时,若一个父类句柄指向子类对象,此时就可以将其赋值给子类句柄,采用系统函数$cast)
  2. lp.i只能指向子类中的i,无法指向父类的i(子类的变量跟父类的变量同名,i被覆盖);tmp.i可以指向父类的i
  3. lp能访问子类的i、k、m,无法访问父类的i;tmp能访问父类的i、m,但找不到子类的i、k

2. 包的使用

2.1 包的概念

为了使得可以在多个模块(硬件)或者类(软件)之间共享用户定义的类型,SV添加了包(package) 。包的概念参考于VHDL,用户自定义的类型譬如==类、方法、变量、结构体、枚举类==(==偏软件类,Module、inteface偏硬件就不能定义在包里面==)等都可以在package…endpackage中定义。

2.2 包的使用方法

  1. module、interface、class等可以使用包中定义或者声明的内容。

  2. 导出:可以通过域的==索引符::号==直接引用。

  3. 可以==指定索引==一些需要的包中定义的类型到指定的容器中(module/class/…) 。

  4. 通过通配符$*$来将包中==所有类别导入==到指定容器中。

2.3 实例1

3. 问答题

1.在packet和linkedpacket有关类的继承的例子中(如图),tb中的句柄p是否可以访问父类的成员i?lp是否可以访问父类的成员i?句柄tmp是否可以访问子类的成员i?

代码:

/*Problem1
在packet和linkedpacket有关类的继承的例子中(如图),
tb中的句柄p是否可以访问父类的成员i?
lp是否可以访问父类的成员i?
句柄tmp是否可以访问子类的成员i?
*/
class packet;
    integer i = 1;
    integer m = 2;
    function new(int val);
        i = val + 1;
    endfunction
    function shift();
        i = i << 1;
    endfunction
    endclass
    
class linkedpacket extends packet;
    integer i = 3;
    integer k = 5;
    function new (val);
        super.new(val);
        if (val >= 2)
            i = val;
    endfunction
    function shift();
        super.shift();
        i = i << 2;
    endfunction
endclass

module tb;
    initial begin
        packet p = new(3);
        linkedpacket lp = new(1);
        packet tmp;
        tmp = lp;
        
//tb中的句柄p是否可以访问父类的成员i?
    $display("p.i = %0d",p.i);
    
//lp是否可以访问父类的成员i? 
    $display("lp.i = %0d",lp.i);//lp.i只能指向子类中的i,无法指向父类的i(子类的变量跟父类的变量同名,i被覆盖)	
    $display("lp.m = %0d",lp.m);//但lp可以访问父类的其他成员
    
//句柄tmp是否可以访问子类的成员i?
    $display("tmp.i = %0d",tmp.i);
    //$display("tmp.k = %0d",tmp.k); //ERROR:Could not find member 'k' in class 'packet', at "class_test.sv", 7.
    
    end
endmodule

仿真结果:

p.i = 4 tb中的句柄p是否可以访问父类的成员i
lp.i = 3 lp.i只能指向子类中的i,无法指向父类的i(子类的变量跟父类的变量同名,i被覆盖)
lp.m = 2 但lp可以访问父类的其他成员
tmp.i = 2 tmp能访问父类的i、m,但找不到子类的i、k

2.试着在对应的位置填入代码,即如何导入pkg_a中的类型packet_a,从pkg_b中导入packet_b,以及从pkg_b中导入静态变量shared?

代码:

package pkt_a;
    class packet_a;
        int pkg_a;
    endclass
    typedef struct{
        int data;
        int command;
        }struct_a;
        int va = 1;
        int shared = 10;
endpackage

package pkt_b;
    class packet_b;
        int pkg_b;
    endclass
    typedef struct{
        int data;
        int command;
        }struct_b;
        int vb = 2;
        int shared = 20;
endpackage		
                
module tb;
    class packet_tb;
    endclass
    typedef struct{
        int data;
        int command;
    }struct_tb;
    
    class packet_a;
        int tb_a;
    endclass
    class packet_b;
        int tb_b;
    endclass
    
//how to import type from packages can be seen as follows
    //精确导出
    import pkt_a::va;
    import pkt_b::vb;
    //import pkt_a::shared;//从pkt_a取出shared
    import pkg_b::shared;//从pkt_b取出shared
    
    ////全部导出
    //import pkt_a::*;
    //import pkt_b::*;
    
    initial begin 
        packet_a pa = new();
        packet_b pb = new();
        packet_tb ptb = new();
        $display("pkg_a::va = %0d,pkg_b:: = %0d",va ,vb);
        $display("shared = %0d", shared);
        //$display("shared = %0d", pkt_b::shared);
    end
    endmodule

仿真结果:

pkg_a::va = 1,pkg_b:: = 2
shared = 20


文章作者: DPH
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 DPH !
  目录