一.transaction
1.声明随机变量并添加约束
class ue_transaction extends uvm_sequence_item;
typedef enum{IDLE,SET_SCALER,WR_BASE_NUMBER} trans_type;
rand trans_type ttype;
randc bit [`NO_WIDTH-1:0] no;
randc bit [`BASE_NUMBER_WIDTH-1:0] base_number;
randc bit [`SCALER_WIDTH-1:0] wr_scaler;
rand int idle_cycles;
bit [`SCALER_WIDTH-1:0] rd_scaler;
bit rd_valid;
bit [`RD_DATA_WIDTH-1:0] rd_data;
constraint cstr {
soft idle_cycles inside {[0:2]};
soft idle_cycles dist {[0:50],[1:25],[2:30]};
工作状态有3种:IDLE // SET_SCALER // WR_BASE_NUMBER
软约束可以被覆盖,优先级较低;如果都是硬约束,约束冲突则会随机失败;
2.域的自动化
`uvm_object_utils_begin(ue_transaction)
`uvm_field_enum (trans_type,ttype , UVM_ALL_ON)
`uvm_field_int (no, UVM_ALL_ON)
`uvm_field_int (base_number, UVM_ALL_ON)
`uvm_field_int (wr_scaler, UVM_ALL_ON)
`uvm_field_int (rd_scaler, UVM_ALL_ON)
`uvm_field_int (rd_valid, UVM_ALL_ON)
`uvm_field_int (rd_data, UVM_ALL_ON)
`uvm_field_int (idle_cycles, UVM_ALL_ON)
`uvm_object_utils_end
使用宏定义后,可以使用uvm自带的方法
3.打印信息
function new(string name = "ue_trans_inst");
super.new(name);
`uvm_info(get_type_name(), "obj created", UVM_FULL)
endfunction
function void print_info(string stage);
string s;
s={s,$sformatf("\n=========%s==============\n",stage)};
s={s,$sformatf("no:%0d\t",no)};
s={s,$sformatf("trans_type:%s\t",ttype)};
s={s,$sformatf("base_number:%d\t",base_number)};
s={s,$sformatf("wr_scaler:%d\t",wr_scaler)};
s={s,$sformatf("rd_scaler:%d\t",rd_scaler)};
s={s,$sformatf("rd_data:%d\t",rd_data)};
s={s,$sformatf("idle_cycles:%d\n",idle_cycles)};
s={s,"=======================================================\n"};
$display("%s",s);
endfunction:print_info
二.sequencer
class ue_sequencer extends uvm_sequencer #(ue_transaction);
`uvm_component_utils(ue_sequencer)
extern function new(string name ="ue_sequencer",uvm_component parent = null);
extern function void build();
endclass
//--------------------------------------------------------------------------------------------------------
// sv
//--------------------------------------------------------------------------------------------------------
function ue_sequencer::new(string name ="ue_sequencer",uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), $sformatf("created"), UVM_LOW)
endfunction : new
function void ue_sequencer::build();
super.build();
`uvm_info(get_type_name(), "built", UVM_LOW)
endfunction : build
sequencer的结构非常简单, 继承于uvm_sequencer,使用宏注册。后续的new与build中也基本没有内容。
三.sequence
1.base_sequence
class ue_base_sequense extends uvm_sequence #(ue_transaction);
ue_transaction m_trans;
`uvm_object_utils(ue_base_sequense)
extern function new(string name="ue_base_sequense");
extern function int get_rand_number_except(int min_thre,int max_thre,int except_num);
extern function int get_rand_number(int min_thre,int max_thre);
endclass
function ue_base_sequense::new(string name="ue_base_sequense");
super.new(name);
endfunction : new
function int ue_base_sequense::get_rand_number_except(int min_thre,int max_thre,int except_num);
int val=get_rand_number( min_thre, max_thre);
while(val==except_num)
val=get_rand_number( min_thre, max_thre);
return val;
endfunction
function int ue_base_sequense::get_rand_number(int min_thre,int max_thre);
int val;
void'(std::randomize(val) with { val inside {[min_thre:max_thre]};});
return val;
endfunction
base_sequence包含sequence的基本方法,后续的测试用例中使用配套的直接继承于base_sequence的sequence。(虽然后续个人没找到使用该方法的地方)
2.base_sequence_lib
{
subseq_set_scaler: 设定scaler
class subseq_set_scaler extends ue_base_sequense;
rand bit [`SCALER_WIDTH-1:0] scaler;
`uvm_object_utils(subseq_set_scaler)
function new(string name="subseq_set_scaler");
super.new(name);
endfunction : new
virtual task body();
`uvm_do_with(req, {no==0;base_number==0;wr_scaler == local::scaler;ttype==ue_transaction::SET_SCALER;idle_cycles==0;})
get_response(rsp);
if(scaler!=rsp.rd_scaler)
`uvm_error("SET_SCALER_ERR", $sformatf("subseq_set_scaler err, exp:%0d act:%0d",scaler,rsp.rd_scaler))
else
`uvm_info(get_type_name(),$sformatf("subseq_set_scaler success"), UVM_LOW)
endtask : body
endclass : subseq_set_scaler
subseq_wr_number: 写入base_number
class subseq_wr_base_number extends ue_base_sequense;
rand logic [ 7:0] base_number;
rand int idle_cycles;
rand int no;
`uvm_object_utils(subseq_wr_base_number)
function new(string name="");
super.new(name);
endfunction : new
virtual task body();
`uvm_do_with(req, {no==local::no;base_number== local::base_number;ttype==ue_transaction::WR_BASE_NUMBER;idle_cycles==local::idle_cycles;})
get_response(rsp);
endtask : body
endclass : subseq_wr_base_number
subseq_idle: idle
class subseq_idle extends ue_base_sequense;
rand int idle_cycles;
`uvm_object_utils(subseq_idle)
function new(string name="subseq_idle");
super.new(name);
`uvm_info(get_type_name(), $sformatf("created"), UVM_LOW)
endfunction : new
virtual task body();
`uvm_do_with(req, {no==0;ttype==ue_transaction::IDLE;idle_cycles==local::idle_cycles;})
// get_response(rsp);
endtask : body
endclass : subseq_idle
}
通过继承base_sequence,生成了三个sequence,对应于三个test,run不同的test其实就是不同的sequence在起作用。