在UVM中需要启动sequence的场景主要分为以下两种:
1. 在 uvm_test 组件中启动顶层 sequence 或者 virtual sequence 运行测例;
2. 在层次化sequence 的顶层 sequence 中启动 sub-sequence;virtual sequence中启动相应的sequence;
情况一: 在uvm_test 组件中启动顶层 sequence 或者 virtual sequence 运行测例
在 test 中启动 sequence,可以有两种方式进行启动,通过start()以及通过default_sequence的方式启动。
通过start()启动:
class my_test extends base_test;
`uvm_component_utils(my_test)
function new(string new, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
virtual_sequence vseq = virtual_sequence::type_id::create("vseq");
phase.raise_objection(this);
vseq.start(env.vseqr);
phase.drop_objection(this);
endtask
endclass
通过start( ) 方式启动,首先需要创建待启动sequence的对象,之后便可以通过指向该sequence对象的句柄调用对应的task start( ) 来启动该sequence。通过start( ) 方法在uvm_test 的run_time phase 启动 sequence,需要控制相应phase的 objection。
通过default_sequence启动:
方式1,无需实例化sequence。此时传入config_db的参数为 uvm_object_wrapper
class my_test extends base_test;
`uvm_component_utils(my_test)
function new(string new, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this, "env.vseqr.main_phase", "default_sequence", virtual_sequence::type_id::get());
endfunction
......
endclass
方式二,启动前先对sequence进行例化。此时传入config_db的 参数为 uvm_sequence_base
class my_test extends base_test;
`uvm_component_utils(my_test)
function new(string new, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
virtual_sequence vseq = virtual_sequence::type_id::create("vseq");
//vseq.randomize() with { };
uvm_config_db#(uvm_sequence_base)::set(this, "env.vseqr.main_phase", "default_sequence", vseq);
//uvm_resource_db#(uvm_sequence_base)::set(get_full_name(), ".vseqr.main_phase", "default_sequence", vseq, this);
endfunction
......
endclass
通过 default_sequence 的方式启动 sequence,首先注意调用 config_db 的位置最好在uvm_test 的 build_phase 进行,而不能在 run time phase 进行。通过该方式启动sequence的本质是通过工厂机制创建对应的sequence,并且调用 start( ) 完成sequence的发送。
当通过default_sequence的方式开启sequence时,需要通过sequence来控制objection。因为通过config的方式将sequence配置到对应sequencer的某个phase后,并没有对这个phase的objection进行控制,所以需要通过当前这个sequence进行objection控制。对于UVM1.2版本,只需要在 sequence 的 new( ) 函数中添加 set_automatic_phase_objection(1); 语句即可实现objection的自动控制。
function new(string name = "base_sequence");
super.new(name);
set_automatic_phase_objection(1);
endfunction : new
注意!:在uvm_test 组件中不能通过 `uvm_do 系列宏开启 顶层sequence或virtual sequence
以 `uvm_do_on 为例:
`define uvm_do_on(SEQ_OR_ITEM, SEQR) \
`uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, -1, {})
调用 `uvm_do_on 后,会调用内部包含的 `uvm_do_on_pri_with 宏:
`define uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS)
begin
uvm_sequence_base __seq;
`uvm_create_on(SEQ_OR_ITEM, SEQR)
if (!$cast(__seq,SEQ_OR_ITEM)) start_item(SEQ_OR_ITEM, PRIORITY);
if ((__seq == null || !__seq.do_not_randomize) && !SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin
`uvm_warning("RNDFLD", "Randomization failed in uvm_do_with action")
end
if (!$cast(__seq,SEQ_OR_ITEM)) finish_item(SEQ_OR_ITEM, PRIORITY);
else __seq.start(SEQR, this, PRIORITY, 0);
end
`define uvm_create_on(SEQ_OR_ITEM, SEQR)
begin
uvm_object_wrapper w_;
w_ = SEQ_OR_ITEM.get_type();
$cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));
end
通过分析 `uvm_do_on_pri_with 宏具体操作可以看出,其内部直接调用的一些方法,例如:start_item( ) 、 finish_item( ) 、create_item( )等, 都是属于 uvm_sequence_base 的方法,而这些方法在 uvm_component 类中无法直接被调用。
所以类似的 `uvm_do 系列宏只可以在 sequence 内部被调用,例如在顶层sequence中通过 `uvm_do 开启sub-sequence、在virtual sequence中通过 `uvm_do_on 开启各部分sequence 等。
而在构建用户的 test 时,是无法直接在uvm_test 组件内部直接通过 `uvm_do 系列宏开启最顶层 sequence 或是 virtual sequence。
情况二:在层次化 sequence 中启动 sub-sequence;virtual sequence中启动相应的sequence
通过start()启动 sub-sequence :
class sub_sequence extends uvm_sequence;
`uvm_object_utils(sub_sequence)
......
task body();
......
endtask
endclass
class top_sequence extends uvm_sequence;
`uvm_object_utils(top_sequence)
......
task body();
sub_sequence sub_seq;
sub_seq = sub_sequence::type_id::create("sub_seq");
......
sub_seq.start(m_sequencer, this);
......
endtask
endclass
通过`uvm_do系列宏启动 sub_sequence:
class sub_sequence extends uvm_sequence;
`uvm_object_utils(sub_sequence)
......
task body();
......
endtask
endclass
class top_sequence extends uvm_sequence;
`uvm_object_utils(top_sequence)
......
task body();
sub_sequence sub_seq;
......
`uvm_do(sub_seq)
......
endtask
endclass
通过start()启动 virtual sequence 中的目标 sequence :文章来源:https://www.toymoban.com/news/detail-498311.html
class ahb_sequence extends uvm_sequence;
`uvm_object_utils(ahb_sequence)
......
task body();
......
endtask
endclass
class apb_sequence extends uvm_sequence;
`uvm_object_utils(apb_sequence)
......
task body();
......
endtask
endclass
class uart_sequence extends uvm_sequence;
`uvm_object_utils(uart_sequence)
......
task body();
......
endtask
endclass
class virtual_sequence extends uvm_sequence;
`uvm_object_utils(virtual_sequence)
`uvm_declare_p_sequencer(virtual_sequencer)
ahb_sequence ahb_seq;
apb_sequence apb_seq;
uart_sequence uart_seq;
......
task body();
ahb_seq = ahb_sequence::type_id::create("ahb_seq");
apb_seq = apb_sequence::type_id::create("apb_seq");
uart_seq = uart_sequence::type_id::create("uart_seq");
......
ahb_seq.start(p_sequencer.ahb_seqr);
apb_seq.start(p_sequencer.apb_seqr);
uart_seq.start(p_sequencer.uart_seqr);
......
endtask
endclass
通过`uvm_do_on系列宏启动 virtual sequence 中的目标 sequence :文章来源地址https://www.toymoban.com/news/detail-498311.html
task body();
ahb_sequence ahb_seq
apb_sequence apb_seq
uart_sequence uart_seq
......
`uvm_do_on(ahb_seq, p_sequencer.ahb_seqr)
`uvm_do_on(apb_seq, p_sequencer.apb_seqr)
`uvm_do_on(uart_seq, p_sequencer.uart_seqr)
......
endtask
到了这里,关于UVM在test组件内启动sequence/virtual sequence的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!