systemverilog学习 ---- 类(完结)

抽象类

在systemverilog中,可以使用关键字virtual来声明一个类,说明这个类是抽象类。

  • 抽象类为子类设置prototype
  • 抽象类不可以被实例化,只可以被继承
  • 在抽象类中,可以只包含方法的原型,可以没有实现,就是一个方法的声明。
    在这里插入图片描述
    抽象类的声明如下:
virtual class abc;
	//Class defination
endclass

接下来展示一个抽象类的例子:

//abstract class
virtual class packet;
    bit [31:0]  addr;
endclass

module virtual_address;
    initial begin
        packet p;
        p = new();
    end
endmodule

在上面这个例子中,创建了一个虚拟类的对象,但是一个虚拟类只可以被继承,不可以被实例化,因此编译器会报错。
在这里插入图片描述
因此需要对虚拟类进行继承才可以。

//abstract class
virtual class packet;
    bit [31:0]  addr;
endclass

class extended_packet extends packet;
    function void display;
        $display("Value of addr is %0d", addr);
    endfunction
endclass

module virtual_address;
    initial begin
        extended_packet p;
        p = new();
        p.addr = 10;
        p.display();
    end
endmodule

其输出结果是:
在这里插入图片描述

抽象方法(abstract method)

在systemverilog中方法也可以被抽象,可以在方法的前面加上virtual的关键字,,因为方法分为任务和函数两类,因此抽象方法也分为两类:

  • Virtual Functions
  • VIrtual Tasks

在虚拟化的方法中,如果基类的句柄指向子类。那么子类的方法句柄将会被赋值给基类句柄。如下所示:

base_class b_c;
extended_class e_c;

假设这两个类都有display的方法,此时我们把b_c = e_c。
那么当我们访问b_c.display()

  • 若在基类中display的方法是抽象的,那么将会访问子类中的display方法
  • 若在基类中的display方法不是抽象的,那么将会访问基类中的方法。

虚方法体现在当我们把子类句柄赋值给父类句柄时,通过给父类句柄就可以访问子类中重名的方法。
虚拟函数和虚拟任务的声明形式如下:

//vitural function
virtual function function_name;
	//function definition
endfunction

//virtual task
virtual task task_namel
	// task definition
endtask

下面举一个例子:

class base_class;
    function void display;
        $display("Inside base_class");
    endfunction
endclass

class extended_class extends base_class;

    function void display();
        $display("Inside extended class");
    endfunction
endclass

module virtual_address;
    initial begin
        base_class b_c;
        extended_class e_c;

        e_c = new();
        b_c = e_c;

        b_c.display();
    end

endmodule

在上面这个例子中,我们发现在基类中的dispaly方法并没有用virtual关键字修饰,因此尽管父类对象已经指向了子类,但是调用的让然是父类的方法。
在这里插入图片描述
但是若是如下代码:

在这里插入图片描述
其输出结果是:
在这里插入图片描述

(域解析操作符)scope resolution Operator ::

程序设计中,不可避免出现重名方法,sv也可以通过域控制不同版本的重名方法。域解析操作符由两个冒号组成,即::
我们通过类域解析操作符,可以在类外访问静态成员,也可以在子类中访问父类的公有public成员和保护protected成员。

//class
class packet;
    bit [31:0]  addr;
    static bit [31:0]   id;

    function display(bit[31:0] a, b);
        $display("Values are %0d %0d", a, b);
    endfunction
endclass

//module
module sro_class;
    int id = 10;
    initial begin
        packet p;
        packet::id = 20;
        p.display(packet::id, id);
    end
endmodule

在上面的例子中,一个类中的静态成员被使用::来进行访问。
其输出结果是:
在这里插入图片描述

class external methods

如果一个方法的定义卸载类的外面,那么这个方法就做external method。但是,类内部还是要留个位置,即需要声明该方法,和c++类似,我们要在类内给出该方法的修饰(local/protected/virtual)以及完整的参数列表。在类外实现方法时,我们还要加上域操作符,说明这是哪个类的方法。

//class with extern function

class packet;

    bit [31:0]  addr;
    bit [31:0]  data;

    //function declaration - extern indicates out of body declaration
    extern virtual function void display();

endclass

//function implementation outside class body
function void packet::display();
    $display("Addr = %0d Data = %0d", addr, data);
endfunction

module extern_method;
    initial begin
        packet p;
        p = new();
        p.addr = 10;
        p.data = 20;
        p.display();
    end
endmodule

其模拟输出结果是:
在这里插入图片描述
此外类中和类外的函数声明应该时一样的。否则编译器会报错。
在这里插入图片描述
即:

Error-[ECMDSMPD] Mismatched method definition
testbench.sv, 11
External class method definition should match prototype declaration.
Argument names do not match. The signature of function 'packet::display'
should match the corresponding prototype declaration at: "testbench.sv", 7.

typedef class

typedef被用来为一个类提供前向声明。在一些情况下,这个类需要在类声明前被实例化。其声明形式如下:

typedef class class_name;

如下面一个例子:

//class - 1
class c1;
    //using class c2 handle before declaring it
    c2 c;
endclass

//class - 2
class c2;
    c1 c;
endclass

module typedef_class;
    initial begin
        c1 class1;
        c2 class2;
        $display("Inside typedef_class");
    end
endmodule

在上面这个例子中,c2 在c1中被实例化,c1在c2中被实例化。因此会导致编译器错误:
在这里插入图片描述
可以发现,类c1和c2,成员变量有对方的示例,不可避免出现未声明就实例化。解决办法使用typedef,通过typedeg我们可以声明一个实例化可以在声明前的类。
在这里插入图片描述
其仿真结果是:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值