提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本篇主要总结《UVM实战》第6章:sequence基础
一、sequence的启动与执行
sequence在test_case中启动,有两种形式:1.start启动;2.default_sequence启动
1. start启动
my_sequence my_seq;
my_seq = my_sequence::type_id::create("my_seq");
my_seq.file_name = "data.txt"; //手动启动的好处是,可以向sequence传递参数
my_seq.start(sequencer);
2. default_sequence启动
uvm_config_db#(uvm_object_wrapper)::set(this,
"env.i_agt.sqr.main_phase",//设置成sqr的main_phase,当sqr执行到main_phase时,发现有
"default_sequence", //default_sequence,那么就启动sequence
case0_sequence::type_id::get());
//或者先实例化要启动的sequence,在通过default_sequence启动
function void my_case0::build_phase(uvm_phase phase);
case0_sequence cseq;
super.build_phase(phase);
cseq = new("cseq");
uvm_config_db#(uvm_object_wrapper)::set(this,
"env.i_agt.sqr.main_phase",
"default_sequence",
cseq);
endfunction
3. 执行
sequence启动后,会自动按序执行sequence的body任务:pre_body,body,post_body。主要工作都在body中进行。
body中常有两种形式写法:1.uvm_do;2.start_item/finish_item;
//第一种形式
virtual task body();
tr = transaction::type_id::create("tr");
start_item(tr);
assert(tr.randomize());
finish_item(tr);
endtask
//第二种形式
task body();
repeat (10) begin
`uvm_do(m_trans);
end
endtask
//uvm_do系列宏还有如下几个
`uvm_do(SEQ_OR_ITEM) //第一个系数可以是tr或者seq
`uvm_do_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS)
`uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)
`uvm_do_on(SEQ_OR_ITEM)
`uvm_do_on_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_on_with(SEQ_OR_ITEM, CONSTRAINTS)
`uvm_do_on_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)
二、sequence仲裁
1. 在同一sequencer启动多个sequence
针对transaction优先级
对于transaction来说,存在优先级的概念。当使用uvm_do或者uvm_do_with宏时,产生的transaction的优先级是默认的优先级,即-1。可以通过uvm_do_pri及uvm_do_pri_with改变所产生transaction的优先级:
代码如下所示:
task my_case0::main_phase(uvm_phase phase);
sequence0 seq0;
sequence1 seq1;
seq0 = new("seq0");
seq0.starting_phase = phase;
seq1 = new("seq1");
seq1.starting_phase = phase;
env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);//需要设置仲裁算法,其他的仲裁算法见P169
fork
seq0.start(env.i_agt.sqr);
seq1.start(env.i_agt.sqr);
join
endtask
sequence0和sequence1
class sequence0 extends uvm_sequence #(my_transaction);
my_transaction m_trans;
...
virtual task body();
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat (5) begin
`uvm_do_pri(m_trans, 100) //一般第二个参数是优先级,这个数值必须大于-1,数字越大,优先级越高
`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
end
#100;
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
endclass
class sequence1 extends uvm_sequence #(my_transaction);
my_transaction m_trans;
...
virtual task body();
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat (5) begin
`uvm_do_pri_with(m_trans, 200, {
m_trans.pload.size < 500;})
`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
end
#100;
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
`uvm_object_utils(sequence1)