8.1 继承
为总线事务创建一个可以注入错误并且带有可变延时的复杂类。
方法1:使用合成(composition),即在类中例化另一种类型的类。有时候很难将功能分成独立部分。如果使用合成,则需要为正确和错误事务分别创建不同的类,正确类的测试平台需要重写以处理错误类的对象。
方法2:使用扩展类,当需要增加事务,而对现有的测试代码修改越少越好,例如增加错误注入功能。
扩展类和类合成的区别:
扩展类解决,增加新事务;使用类合成时,大量修改代码麻烦。
如何使用:
扩展类共享基类的变量和子程序。
1)基本类中的方法,需标记为virtual,这样扩展类中才可以重新定义。扩展类中函数,和基类中函数名一样时,通过super.函数名,调用基类中的函数。System Verilog中不允许super.super.new方式进行多层调用。
2)如果基类构造函数new()有参数,那么扩展类,必须有一个构造函数,并在构造函数的第一行调用基类的构造函数。
例8.3 扩展类中带有参数的构造函数
class Basel;
int var;
function new(input int var);//带有参数的构造函数
this.var=var;
endfunction
endclass
class Extended extends Basel;
function new(input int var); //需要参数
super.new(var);//必须是new构造函数的第一行
//构造函数的其它行为
endfunction
endclass
3)OOP规则指出:基类的句柄,也可以指向扩展类的对象。
8.2 蓝图(Blueprint)模式
1)背景:一个简单的发生器,通过信箱将数据传递给驱动器。
例8.5 发生器类
//使用Transaction对象的发生器类
//第一个尝试…只有有限的功能
class Generator;
mailbox gen2drv;
Transaction tr;
function new(input mailbox gen2drv);
this.gen2drv=gen2drv;//this->类一级变量
endfunction
task run;
forever begin
tr=new();//创建事务
assert(tr.randomize);//随机化
gen2drv.put(tr);//送入驱动器
end
endtask
endclass
存在问题:该例在循环内部而非循环外部创建事务对象,避免常见的测试平台的错误。
New()放在循环外部,错误原因是,mailbox中放入的是句柄,而不能是对象,所有的句柄都指向同一个对象。(1)任务Run创建了一个事物并立即随机化,意味着事务使用了默认的所有约束。要修改,必须要修改transaction类。(2)无法使用扩展
解决办法:将tr的创建和初始化分开,使用蓝图模式。
另一个问题:如果简单的把创建和初始化分开,而放