sequence启动的三种方式

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)的源码:

start
  • 设置m_sequencer和p_sequencer
  • 注册m_sequencer和sequence,将seq_id sqr_id等关联起来
set_item_context

m_register_sequence
start
start
  • 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[]中删除。
m_sequence_exiting

真正sequence的跟driver交互的东西就是在body()里面实现的。

你可能感兴趣的:(sequence启动的三种方式)