1、seq相关的phase机制
首先你需明确的是UVM的框架下,消耗时间的task的执行都在在uvm_component底下的objection的机制来实现的。也就是说phase的机制跟uvm_component是紧密相关的。
uvm_sequence是一个uvm_object的类,uvm_sequencer是一个uvm_component的类。
seq需要挂载在seqr上执行。
run_time_phase.svh
在前面我们讲过UVM_PHASE的机制,在execute函数的地方有对uvm_sequencer_base类型的做处理。
- start_phase_sequence(phase):处理default_sequencer
- 这里先做个遗留,到底这里是什么从外面获得default_sequencer的。
方法一:利用default_sequence启动seq
也只有在用default_sequence的方式启动seq的时候,start_phase != null,原因是如果是sqr的时候在uvm_task_phase.svh里面有介绍,会自己调用start_phase_sequence,里面会对seq.set_starting_phase(phase);进行set。
前提
对应uvm1.2版本,
或者是my_seq.set_automatic_phase_objection(1);
在start_phase_sequence里面已经指定了phase,seq.set_starting_phase(phase);
命令行设置default_sequencer:
+UVM_SET_DEFAULT_SEQUENCE=uvm_test_top.env.i_agt.sqr,main_phase,case0_sequence
- 第一个参数是指定seqr的路径
- 第二个参数是指定要执行的phase阶段
- 第三个参数是指定你的seq
uvm_config_db设置default_sequencer
uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", case0_sequence::type_id::get());
function void my_case0::build_phase(uvm_phase phase);
case0_sequence my_seq;
super.build_phase(phase);
my_seq = new("my_seq");
uvm_config_db#(uvm_sequence_base)::set(this,
"env.i_agt.sqr.main_phase",
"default_sequence",
my_seq);
endfunction
super.build_phase到一定不能省略。应该跟config_db的get/set相关的源码有关,后面再具体分析!https://www.cnblogs.com/xuqing125/p/15761695.html
这两个都要包含的信息其实跟命令行是一样的!!!
方法二:利用seq.start(seqr)显示启动
前提:如果想用starting_phase的话,需要为其指定,不像default_sequencer那样,start_phase_sequence(phase)里面已经调用了set_starting_phase
- 利用starting_phase来启动objection:直接调用seq.start(seqr)
- 或者将
my_seq.starting_phase=phase
替换成my_seq.set_starting_phase
这种写法。 - 利用common的objection机制:直接调用seq.start(seqr)
参考UVM_UG:
方法三:利用uvm_do_on系列的宏
`uvm_do系列的宏,我们知道这些宏最终都是调用的uvm_do_on_pri_with的宏。uvm_do系列的宏是可以在uvm_sequence_base以及其扩展类中才能调用的!
- 当第一个参数是sequence类型的时候,会调用seq.start,也就是能启动seq。
- my_seq.start() -> my_seq.body() -> uvm_do(my_seq_0) -> my_seq_0.start() -> my_seq_0.body()
那么这里自然而言,我就会想可以在顶层这样做吗?
刚刚入行的时候,总会有这些问题,为什么不能这么做的?
首先宏是啥意思?在代码编译的时候,宏会依次展开,所以create_item/start_item/finish_item都会暴露出来,由于你是在uvm_sequencer中调用的,根据扩展关系,是找不到create_item/start_item/finish_item这些东西的啊,同学!!!!
create_item/start_item/finish_item是在uvm_sequence_base里面定义的。
也就是说uvm_do系列的宏是可以在uvm_sequence_base以及其扩展类中才能调用的!
小结:从本质上讲,seq的启动都是调用了uvm_squence_base的start函数。
下面简单来看一下;uvm_sequence_base::start(sqr)的源码:
- 设置m_sequencer和p_sequencer
- 注册m_sequencer和sequence,将seq_id sqr_id等关联起来
- pre_start/pre_body/body/post_body/post_start,是一些callback函数。
- parent_sequence也有pre_do/mid_do/post_do的callback函数,但这些很不常用。
- 重点关注body()的override就行。
- m_sequence_exiting()将sequence从arb_sequence_q[]中删除。
真正sequence的跟driver交互的东西就是在body()里面实现的。