SystemVerilog中不同句柄之间的动态类型转换

多态(polymorphism)是面向对象编程的核心思想之一,指同一个行为具有多个不同表现形式或形态的能力,同一消息可以根据发送对象的不同而采用多种不同的行为方式,在SystemVerilog中指不同的子类在继承父类后分别都重写覆盖了父类的方法,即父类同一个方法,在继承的子类中表现出不同的形式,所以多态和继承是密不可分的,(关于多态可以参考《107】多态和虚方法

因为SystemVerilog中继承和多态特性的存在,父类中的变量和方法(未声明为localprotect时)对于子类是可见的,所以可以将子类句柄复制给父类句柄实现通过父类句柄访问子类对象,如下例所示。

【示例】 

【仿真结果】

示例中,子类句柄c_ahb指向创建对象之后,访问的属性(datasub_data)和方法disp为自身的;当把子类句柄复制给父类句柄后,可以通过父类句柄访问父类句柄类型的所有属性和方法,但是不能访问子类句柄指向的子类对象中的属性和方法,虽然子类中也有属性datastr,但是因为父类句柄的类型为父类,所以其所能访问的属性仍为句柄类型中的属性。示例中的这种将子类句柄复制给父类句柄的过程是一种父类句柄向下类型转换。子类既然继承了父类,就拥有父类的一切属性,除此之外,子类还可以有自己独特的属性,这些是父类没有的进行向类型转换时,相当于父类的句柄指向子类对象,这样的话句柄仍然能对子类对象与父类相同的属性进行访问。

那么,除了上例中将子类句柄复制给父类句柄外,可不可以将父类句柄复制给子类句柄呢?即可以不可以实现子类句柄的向上转换呢?

【示例】 

【仿真结果】 

示例中第37行,通过将父类句柄复制给子类句柄这种子类句柄的向上转换行为会在进行编译时报错,即在SV中不允许直接将父类句柄复制给子类句柄。其实在SystemVerilog中提供了一种系统任务和函数$cast,可以实现父类句柄指向对象和子类句柄指向对象的动态转换,从而实现父类句柄复制给子类句柄的操作,如下例。

【示例】 

【仿真结果】

示例中,虽然代码在编译时通过了,但是在仿真$cast被执行到时因为类型不匹配导致转换错误。同时从这个示例也可以注意到$cast是在仿真执行的过程中执行的,不是在编译阶段完成的,所以使用$cast是一种动态的类型转换。虽然在SystemVerilog中可以使用$cast实现子类句柄的向上转换,但是这种转换并不是不分青红皂白的直接将父类句柄转换成子类句柄,$cast在转换时需要检查要转换的两个句柄指向对象的类型,如果转换源类型与目的类型所指向对象的类型一致或者是目的类型指向的对象是源类型的父类,那么可以使用$cast进行转换。示例中,因为f_ama指向的对象不是目的类型句柄指向的类型,而是目的类型的父类,所以这样的转换将会失败。正确的使用方式如下例所示。

【示例】

【仿真结果】 
示例中,将c_ahb0复制给了f_amba,那么f_amba就指向了c_ahb0指向的对象,c_ahb0在创建对象时,同时初始化了其指向空间中amba的部分,并完成其初始化(调用new函数,未在new函数中出现的属性不会受到影响),即其中的属性str被初始化为了“C_AHB0”。所以在将c_ahb0复制给了f_amba后,通过f_amba访问disp时,其访问的是其指向空间中的父类部分的dispdisp显示的是c_ahb0创建对象时对于str初始化的值,即“C_AHB0”。因为此时f_amba指向的对象与c_ahb1都属于同一类型ahb,所以此时使用$cast系统任务可以实现将f_amba复制给c_ahb1,即实现了子类句柄的向上转换,因为此时c_ahb1指向了和f_amba指向的统一对象空间。同时通过结果,我们可以看到不管是父类中的属性,不会因为指向的对象不同而发生变化,即虽然父类句柄指向了子类对象空间,但是访问的data仍然是父类中的属性data对于类中的属性SV根据句柄handle本身的类型进行判定,父类句柄指访问的仍然是父类句柄类型中的属性。整个示例的执行过程如下图所示。


这里使用到的$castSystemVerilog中存在两种使用方式,一种是任务方式,一种是函数方式。示例中使用的是$cast的任务方式,如果类型不匹配的话仿真将会报错。如果使用$cast的函数方式,那么将不会报错,而是会返回一个int型的数,非零表示转换成功,如下例所示。

【示例】 

【仿真结果】

具体在实际使用过程中,$cast是作为任何还是作为函数使用,仿真时会根据使用的上下文决定具体调用的方式。

通过上面几个示例可以知道如下几点:

如果将子类句柄复制给父类句柄,可以实现父类句柄的向下转换,可以不使用$cast完成,属于一种静态的转换,如果类型不匹配会在编译时报错;

如果将父类句柄复制给子类句柄,可是实现子类句柄的向上转换,但是必须需要使用$cast实现,并且父类句柄指向的对象类型要与子类句柄相同,否则转换失败;

对于类中的属性SV根据句柄handle本身的类型进行判定,父类句柄指访问的仍然是父类句柄类型中的属性;

$cast是作为任务还是作为函数使用,仿真时会根据使用的上下文决定具体调用的方式



全部评论

相关推荐

07-14 13:47
门头沟学院 Java
Lynn012:你评估好自己的位置了吗《顶尖应届》
投递小米集团等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务