8 OOP技巧
1、 类的继承,如果父类构造函数无参数和返回类型,则子类扩展类不需要构造函数,如只继承变量类和方法
2、 父类的方法定义成虚方法,这样就可以再扩展类中重定义
3、 子程序的原型prototype是指明了参数列表和返回类型的第一行。
4、 当启动扩展类的时候,构造函数new:如果基类里有参数,那么扩展类必须有一个构造函数new(var),并且必须再构造函数第一行调用基类的构造函数super.new(input int var);
5、声明一个虚方法,这样svhi查看存储再tr中的对象类型,并且以此选取恰当的方法或访问正确的对象类型。如果对象是父类类型,那么调用父类方法
6、蓝图模式:想要构建一个事务发生器得时候,不需要知道怎样建立各种类型得事务,只需要能够根据给定得事务建立一个类似的新事务。
构建并使用一个对象:
class generator;
mailbox gen2drv;
Transaction tr;
function new(input mailbox gen2drv);
this.gen2drv = gen2drv;
endfunction
task run;
forever begin
tr=new();
assert(tr.randomize);
gen2drv.put(tr);
end
endtask
endclass
任务run创建了一个书屋并立即随机化该值。这意味着该transaction 使用默认 所有约束。若要修改约束,只能修改transaction类,不符合验证准则;并且gen只使用了transaction对象,因此无法使用扩展对象,所以只能将tr得创建和初始化分开。
先构建一个对象的blueprint,然后修改他的约束,甚至使用一个扩展对象替换它。当随机化这个blueprint的时候,就会赋予想要的随机值。接着赋值这个对象,发给下游transaction。修改bluprint对象就是修改摸具。
class Generator;
mailbox gen2drv;
Transaction blueprint;
function new(input mailbox gen2drv);
this.gen2drv = gen2drv;
blueprint=new();
endfunction
task run;
Transaction tr;
forever begin
assert(blueprint.randomize);
tr=blueprint.copy();
gen2drv.put(tr);
end
endtask
endclass
class Environment;
Generator gen;
Driver drv;
mailbox gen2drv;
function void build();
gen2drv=new();
gen=new(gen2drv);
drv=new(gen2drv);
endfunction
task run();
fork
gen.run();
drv.run();
join_none
endtask
task wrap_up();
..
endtask
endclass
program automatic test;
Environment env;
initial begin
env=new();
env.build();
begin
BadTr=new();
env.gen.blueprint=bad;
end
env.run();
env.wrap_up();//清理内存
end
endprogr
为了注入错误,将tr对象转换为扩展类badtr对象,再创建和运行环境阶段完成,改变蓝图。
7、 类型转换和虚方法
bad=new();构建扩展类对象
tr=bad;子类将句柄赋值给父类,父类句柄指向子类对象可行
tr.src//基类对象成员src可见
tr.display;//BadTr::display
tr=new();
bad=tr;子类句柄指向父类对象;
bad.bad_crc//不可行,基类对象不可见bad_crc
//-------
$cast(bad,tr);//检查tr指向的对象类型,如果是子类独享,那么赋值会成功,
8、 virtual方法
sv会根据对象类型来决定调用什么方法,句柄tr指向子类对象,那么会调用子类的方法。
如果不加virtual,会根据句柄类型调用方法,可能调用出错