在UVM中,产生异常激励的方法(以白皮书中源码为例)
- 在my_transaction中添加一个crc_err的标志位这样,在post_randomize中计算CRC前先检查一下crc_err字段,如果为1,那么直接使用随机值,否则使用真实的CRC。
class my_transaction extends uvm_sequence_item;
rand bit[47:0] dmac;//A 48-bit Ethernet destination address
rand bit[47:0] smac;// a 48-bit Ethernet source address
rand bit[15:0] ether_type;
rand byte pload[];//the size of the data
rand bit[31:0] crc;
rand bit crc_err;
constraint pload_cons{pload.size >= 46; pload.size <= 1500;}
function bit [31:0] calc_crc;
return 32'h0;
endfunction
function void post_randomize();
if (crc_err)
;//do nothing
else
crc = calc_crc;
endfunction
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(dmac, UVM_ALL_ON)
`uvm_field_int(smac, UVM_ALL_ON)
`uvm_field_int(ether_type, UVM_ALL_ON)
`uvm_field_array_int(pload, UVM_ALL_ON)
`uvm_field_int(crc, UVM_ALL_ON)
`uvm_field_int(crc_err, UVM_ALL_ON | UVM_NOPACK)
`uvm_object_utils_end
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
然后在sequence中使用如下方式产生异常激励
`uvm_do_with(tr, {tr.crc_err == 1;})
- 使用重载功能。
class my_transaction extends uvm_sequence_item;
…
constraint crc_err_cons{
crc_err == 1'b0;
}
...
endclass
如上:在测试正常用例时,约束错误标志位均为0,通过`uvm_do随机化
my_transaction tr;
`uvm_do(tr)
然后通过SystemVerilog中一个非常有用的特性是支持约束的重载。因此,依然使用第一种方式中my_transaction的定义,在其基础上派生一个新的transaction
class error_transaction extends my_transaction;
`uvm_object_utils(error_transaction)
function new(string name = "error_transaction");
super.new(name);
endfunction
constraint crc_error_cons{
crc_error dist {0 := 1, 1 := 1};
}
endclass
在UVM中,可以使用uvm的factory机制实现重载。在test中实现覆盖,这种方法相比于sv的覆盖,会少写一个sequence,但是会多写一个error_test
class error_test extends uvm_test;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
//覆盖原有transaction类型
set_type_override_by_type(my_transaction::get_type(),error_transaction::get_type());
endfunction
//后者覆盖前者