SystemVerilog中的类型向下转换
写在前面:
1、一直以来对这块理解都不是那么清楚,只知道个大概,比如只知道$cast做类型向下转换。今天好好看了下相关的内容,发现自己之前的理解确实有很大的偏差,今天就好好总结下了。
2、难得的六一儿童节,祝各位大龄儿童节日快乐。
//====================================START====================================//
一、对象与句柄
1、对象:对象是类的一个实例。
2、句柄:指向对象的指针。
要理解后面的内容,我们一开始就要明白对象和句柄的区别。对象是真实存在的实体,就像你的女朋友一样(没有的话可以new一个出来),而句柄就是你女朋友的电话号码,通过电话号码,你可以找到你的女朋友,而不是别人的女朋友。
二、静态转换:基类句柄指向派生类对象
规则1:指向基类的句柄可以用来指向派生类的对象。
eg:
句柄tr指向的是Transaction对象,句柄btr指向的是BadTr对象。而类BadTr继承自类Transaction,因此可以直接用句柄tr指向BadTr对象。那么问题来了,当句柄tr指向BadTr对象后:
Q1:通过tr我们可以访问crc变量吗?
A1:不能,由于tr句柄是Transaction类型的,所以看不见crc变量。如果你确实这么做了,编译阶段就会报错。
Q2:调用display函数时,调用的是父类还是派生类的display函数?
A2:调用时,首先通过句柄类型找到该函数,查看有无virtual修饰符,有virtual修饰符,那么就调用实际对象类型的display函数,无virtual修饰符,就调用句柄类型的display函数。
三、动态转换:$cast
由规则1我们可以将指向基类的句柄用来指向派生类的对象。所以下面的场景是经常存在的:
也就是说,为了使验证平台重用性更好,经常会使在各个组件间传递的是数据的基类,而在真正使用的地方再转换为派生类。
那么必然就涉及将基类句柄的对象传递给派生类句柄(上图中的$cast部分)这样一个过程,而显然这个过程是静态转换所不支持的,因为静态转换只检查句柄类型,不看实际的对象类型。因此我们需要用到$cast来做动态转换,$cast转换会检查对象类型,一旦源对象(source_exp)和目的句柄(dest_var)是同一类型或者是目的句柄类型的派生类,转换就是合法的。
$cast既可以当成任务来使用,也可以当成函数来使用。作为任务来使用时,不匹配就会输出错误信息,使仿真中断(如下图)。而作为函数使用时,不匹配仅返回一个 非零值,需要验证人员自己去做处理。
//====================================OVER=====================================//