Bad.bad_crc = bad_crc; Return bad; Rendfunction endclass
2)优化途径一,创建一个独立的函数copy_data,这样每个类只负责copy其局部变量,即扩展类中的copy函数用super.copy_data(tr),代替了基类中变量的复制。代码的重用性提高。P8.22
$cast(bad,tr); //扩展类句柄指向基类句柄
使用的情况: 因为virtual 函数,在继承中,虚拟函数必须和基类中名称和参数也一致。这样扩展类中copy_data函数参数仍然是transaction类型的tr,这样出现了参数是基类句柄,但是copy_data函数内要作的确实扩展类的成员,就要将基类句柄参数赋值给扩展类句柄,
要将扩展类badtr类型的数据返回,所以必须用$cast(bad,tr)。
2) 优化途径二,最好的。前面的copy子程序都会创建一个新对象,改进的一种方法就是指定复制对象的存放地址。
Virtual function transaction copy(transaction to =null); if(to == null) copy = new(); else copy = to; copy_data(copy); endfunction
l 抽象类和纯虚方法
背景:验证的目标之一是创建多个项目共享的代码。
目的:systemverilog 有两种方法创建共享的基类:抽象类和纯虚方法
Virtual class (抽象类):可以被扩展但是不能被直接例化。
Pure virtual function(纯虚方法):没有实体的方法原型,相当于一个声明。 1) 由抽象类扩展而来的类,只有在所以的虚拟方法都有实体的时候才能被例化, 2) 纯虚方法只能在抽象类中定义。
3)抽象类中,纯虚方法是没实体的,非纯虚方法最好也不写实体。 l 回调
背景:测试平台目的:创建一个不做任何修改就能在所有测试中使用的验证环境。要做到这点的关键是测试平台使用钩子,(什么是钩子?)钩子作用,在不修改原始类的情况下注入新的代码。采用virtual 方法,也可以在扩展类中覆盖基类方法,但是需要重复原方法的所有代码,并且它的修改将传播到它的所有扩展类中。
作用:回调就是一个钩子,在不修改原始类的情况下注入新的代码。
实现:回调任务在顶层中创建,在最低级即驱动器中调用。这样驱动器不需要知道测试的任何信息,它只需要使用一个可以在测试中扩展的通用类。
1) 使用回调注入干扰
回调的一个常见用法就是注入干扰,例如引入一个错误或者延迟。下面测试平台使用回调对象,随机地丢弃数据包。
扩展类是如何作用的?在扩展的回调类中注入错误,如何在驱动器中作用的? 关键是数据队列的作用,驱动器中使用了,回调基类的数据队列
回调基类是抽象类,在扩展的回调类中加入错误注入,而drive驱动类中,是回调基类的数据队列,在环境中将扩展类句柄让入驱动器类,回调基类的数据队列中。
begin // Create error injection callback Driver_cbs_drop dcd = new();
env.drv.cbs.push_back(dcd); // Put into driver end
与前面扩展类作用的差异?
前面代码,要使扩展类中增加代码,需要使基类句柄指向扩展类句柄。
l 驱动器类:
下面的代码如何解释
2)回调也可以想scoreboard 发送数据或收集功能覆盖率。
优点:你可能想过将scoreboard和功能覆盖数据组置于一个事物处理器中,通过邮箱连接到测试平台中,这是一种笨拙的方法,原因如下:测试平台组件几乎都是被动和异步的,组件只有在测试平台给他数据的时候才被唤醒,而且不会主动地向下游事物处理器传递信息。麻烦:1)这样一个需要同时监视多个邮箱的事物处理器复杂了;2)你可能在多个地方采集数据,但是事物处理器设计用来处理单个数据源回调