SystemVerilog-$cast详解

$cast在子类与父类之间的复制

1 子类cast给父类:$cast(father_cls, child_cls)

之前有提到,$cast是将两个类型强制转换,$cast(A,B),将B强制类型转换给A,应用在类上,就是句柄的强制赋值操作,那么在子类和父类之间的赋值呢?其实是原理是一样的,规则也只能是子类的句柄赋值给父类,如下图所示代码块:

1.	program cls_cp;
2.	    class base_cls;
3.	        int a = 100;
4.	        inner_cls i_a;
5.	        function new();
6.	            i_a = new();
7.	        endfunction
8.	    endclass
9.	
10.	    class child_cls extends base_cls;
11.	        int b = 300;
12.	    endclass
13.	
14.	    initial begin
15.	        base_cls base_0;
16.	        child_cls child_0;
17.	        child_0 = new();
18.	        $cast(base_0, child_0);
19.	    end
20.	
21.	endprogram

且经过cast后,等同于赋值操作,即父类的句柄指向子类的对象,且只能访问子类对象的继承类的成员变量。仿一下看看:

       反过来cast,直接报错:

2. 父类cast给子类:$cast(child_cls, father_cls)

       上文提到,父类是不能cast给子类的,那么在什么情况下可以呢?其实很容易想到,就是在父类的句柄指向子类的对象的时候,cast可以生效,如下图所示代码块:

1.	program cls_cp;
2.	    class base_cls;
3.	        int a = 100;
4.	        inner_cls i_a;
5.	        function new();
6.	            i_a = new();
7.	        endfunction
8.	    endclass
9.	
10.	    class child_cls extends base_cls;
11.	        int b = 300;
12.	    endclass
13.	
14.	    initial begin
15.	        base_cls base_0;
16.	        child_cls child_0;
17.	        child_0 = new();
18.	        base_0 = child_0;
19.	        $cast(child_0, base_0);
20.	    end
21.	
22.	endprogram

这样的化,通过父类的cast,其实就是子类的对象,同样的父类也不能访问子类本身的成员变量,父类改变自身的成员变量,子类调用自己父类的成员变量时也会发生改变。仿一下看看:

       修改父类的成员变量,子类也会跟着改:

       实际上,这种赋值是没有意义的,类的赋值要体现在不同的对象之间,用这种方式可以实现父类作为桥梁赋值给另一个子类的对象,在UVM中得到了大量的使用。

改一个,另一个也跟着改变,读者可以自行尝试改变child_1的成员变量,以及改变cls_0的成员变量,看是否另外的两个类成员变量也发生改变。值得注意的是,cls_0依然无法访问child_0和child_1中的成员变量。过程如下图所示:

 

3. 两个不同的子类之间的cast

同一个子类的不同对象之间是可以cast的,那么不同子类直接能否cast?能否通过父类进行cast?这里先给出结论:都是不可以的,原因是cast在对于类进行操作时,认为相同类型的两个句柄,可以cast,那么如果两个不同子类声明的句柄,cast会认为是不同的类型,因此不能转换,即使他们继承自一个父类,同样通过父类的cast也是不可以的。如下图仿真:

        直接报错,通过父类进行不同子类之间的cast,也不可以:

$cast在子类与父类之间深拷贝的用法

在3.2节理解了cast在父类和子类的用法后,本节以一个具体的实例,说明cast在深拷贝中的应用,例如如下代码块:

1.	program cls_cp;
2.	
3.	    class inner_cls;
4.	        int in_a = 200;
5.	        function void copy(inner_cls ii);
6.	            ii.in_a = this.in_a;
7.	        endfunction
8.	    endclass
9.	    class base_cls;
10.	       int a = 100;
11.	        inner_cls i_a;
12.	        function new();
13.	            i_a = new();
14.	        endfunction
15.	        virtual function void copy(base_cls i_c);
16.	            i_c.a = this.a;
17.	            i_c.i_a.copy(this.i_a);
18.	        endfunction
19.	        virtual function void display();
20.	            $display("a in father cls is %d ", a);
21.	        endfunction
22.	    endclass
23.	
24.	    class child_cls extends base_cls;
25.	        int b = 300;
26.	        function void display();
27.	            $display("b in child cls is %d ", b);
28.	        endfunction
29.	
30.	        function void copy(base_cls c);
31.	            child_cls cc;
32.	            super.copy(c);
33.	            $cast(cc, c);
34.	            cc.b = this.b;
35.	        endfunction
36.	
37.	    endclass
38.	
39.	    initial begin
40.	        child_cls child_0;
41.	        child_cls child_1;
42.	        child_0 = new();
43.	        child_1 = new();
44.	        child_1.copy(child_0);
45.	    end
46.	
47.	endprogram

分析:在子类中重载了父类的copy函数,重载的过程是,先声明了一个子类,然后调用父类的copy函数,将父类的成员变量进行深拷贝赋值,包括父类的深层次成员变量inner_cls,然后再通过$cast方法,将父类赋值给子类,这样在子类cc中,就有了父类成员变量的复制本,最后将子类的成员变量进行复制,完成深拷贝。

       此处其实有一个问题,就是之前不是说父类不能够cast给子类吗?为什么这里可以写,因为在实际调用的时候,是两个子类之间的复制,通过调用子类的copy函数,copy函数的参数传递的是子类的句柄,在函数传参的过程中,也就将形式参数父类的句柄指向了实参子类的对象,因此可以cast。

       仿真结果:

 

       读者可以自行尝试注释行的仿真,结果应该是一样的。

       UVM里用到了大量这样的方法,掌握这个原理,对于理解UVM的应用,以及SystemVerilog更高级的建模,都十分有帮助。

  • 3
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值