uvm_primer ch11基于uvm的test
从本章正式进入uvm的世界
使用factory创建case
使用下边的命令,我们可以只编译一次跑多个case;
vsim top_optimized -coverage +UVM_TESTNAME=add_test
vsim top_optimized -coverage +UVM_TESTNAME=random_test
使用UVM_TESTNAME去调用 run_test() 去使用factory,构造不同的类的对象;
传递interface,run_test()
- set是一个static的方法;
- run_test()读取+UVM_TESTNAME的参数,并构造这个case的对象;
module top;
import uvm_pkg::*;
`include "uvm_macros.svh"
import tinyalu_pkg::*;
`include "tinyalu_macros.svh"
tinyalu_bfm bfm();
tinyalu DUT (.A(bfm.A), .B(bfm.B), .op(bfm.op),
.clk(bfm.clk), .reset_n(bfm.reset_n),
.start(bfm.start), .done(bfm.done), .result(bfm.result));
initial begin
uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm);
run_test();
end
endmodule : top
random_test()
- `uvm_component_utils使用这个宏,将class注册到factory,这样就不用更改factory的代码,从而可以构造这个random_test的对象;
- 使用get()函数,得到set的interface;如果get失败,则返回0;
- 对于objection的理解:run_phase()在退出前,会核实各个对象是否还有raise_objection;如果有就等待;知道最后一个对象drop_objection;
class random_test extends uvm_test;
`uvm_component_utils(random_test);
virtual tinyalu_bfm bfm;
function new (string name, uvm_component parent);
super.new(name,parent);
if(!uvm_config_db #(virtual tinyalu_bfm)::get(null, "*","bfm", bfm))
$fatal("Failed to get BFM");
endfunction : new
task run_phase(uvm_phase phase);
random_tester random_tester_h;
coverage coverage_h;
scoreboard scoreboard_h;
phase.raise_objection(this);
random_tester_h = new(bfm);
coverage_h = new(bfm);
scoreboard_h = new(bfm);
fork
coverage_h.execute();
scoreboard_h.execute();
join_none
random_tester_h.execute();
phase.drop_objection(this);
endtask : run_phase
endclass