一、蓝图模式
蓝图模式是OOP中一种非常有用的技术。如果你用一台机器来生产标记,那么并不需要预先知道每一个可能的标记形状,你所需要的只是一个压印机然后变换金属模子以剪裁出不同的形状。同样的。当你想要构建一个事务发生器的时候,不需要知道怎样建立各种类型的事务,只需要能够根据给定的事务建立一个类似的新的事务即可。
蓝图模式发生器:
我们先构建一个对象的蓝图(建材金属模),然后修改它的约束,甚至使用一个扩展对象替换它。然后随机化这个蓝图的时候,它就会具有你想赋予的随机值,接着复制这个对象,并将拷贝值发送给下游的事务处理器。此技术出色的地方在于如果你改变了蓝图对象,你的发生器就会创建一个不同类型的对象。在生产标志的那个比方中,相对于你使用了一个三角形金属模子取代了正确性金属模子来制作。这个蓝图是一个“钩子”,它允许你改变发生器类的行为而无需改变其类代码,但是在使用时你需要创建一个复制方法来复制蓝图以便传送,这样最原始的蓝图对象在循环中的下一轮调用时就可以随时使用了。
使用新模式的蓝图发生器:
使用蓝图模式的发生器类
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
二、Environment类
测试平台要执行的三个阶段:build、run、wrap_up,而Environment类例化了测试平台的所有元素,并且执行这三个阶段。
Environment类
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
三、一个简单的测试平台
测试包含在顶层程序中,基本的测试仅仅使Environment类按默认方式运行。
program automatic test;
Environment env;
initial begin
env = new(); //创建Environment对象
env.build(); //创建测试平台对象
env.run(); //运行测试
env.wrap_up(); //清理
end
endprogram
四、使用扩展的Transaction类
为了注入错误,你需要将蓝图对象从Transaction对象变成BadTr对象。必须在环境的创建和运行阶段完成这个操作,这样顶层测试平台将运行环境的每个阶段并且改变蓝图。
在测试平台中增加了扩展了的事务
program automatic test;
Environment env;
initial begin
env = new();
env.build();
begin
BadTr bad = new(); //以bad对象取代蓝图
env.gen.blueprint = bad;
end
env.run; //运行带BadTr的测试
env.wrap_up();
end
endprogram
五、使用扩展类改变随机约束
绝大多数的测试程序需要对数据做进一步的约束,继承是实现这些要求的最佳方法。
使用继承来增加一个约束
/*如果扩展类中定义了一个约束,并且扩展后的约束名和基类里的约束名相同,
那么扩展类的约束会替代基类中的约束,这样你就可以改变现有约束的行为。
*/
class Nearby extends Transaction;
constraint c_nearby{
dst inside {[src-100 : src+100]};
}
endclass
program automatic test;
Environment env;
initial begin
env = new();
env.build();
begin
Nearby nb = new();
env.gen.blueprint = nb;
end
env.run();
env.wrap_up();
end
endprogram