UVM—virtual sequencer and virtual sequence详解

目录

1、前言

2、virtual sequencer使用环境

 3、 virtual sequencer 和virtual sequence的作用

4、m_sequencer与p_sequencer

4.1 m_sequencer

4.2 p_sequencer

5、实例


1、前言

        在UVM里Sequence层次化这一块是重点,这里主要介绍virtual sequence。 对于顶层的测试环境, 测试序列所要协调的不再只是面向一个sequencer的sequence群,而是要面向多个sequencer的sequence群, 面向不同sequencer的sequence群如何挂载到不同的sequencer上呢? 这就需要用到virtual sequence和virtual sequencer来解决。对于单一的sequencer下的sequence群,其挂接较为简单,通过uvm_sequence::start()来挂载root sequence,而在内部的child sequence可以通过宏`uvm_do()来实现。

2、virtual sequencer使用环境

        考虑到环境的可扩展性,一般会在一开始生成环境的时候就把virtual sequencer给加上。即使暂时用不到,也比以后再去加的要好。而且目前的验证环境大部分是脚本生成的,加virtual sequencer其实也不存在什么额外的工作量 。

使用条件:

  • 环境中只有一个driver agent,此时不需要virtual sequencer;
  • 环境中有多个driver_agent,但是这些driver之间不需要同步,此时不需要virtual sequencer;
  • 环境中有多个driver_agent,且这些driver之间需要同步,此时需要virtual sequencer。

 3、 virtual sequencer 和virtual sequence的作用

  • virtual sequence:承载不同目标sequencer的sequence群落,实现sequence同步;virtual sequence一般只会挂载到virtual sequencer上,且没有自己的sequence_item,只用于控制其他的sequence执行顺序,起统一调度作用。
  • virtual sequencer:桥接其它sequencer,即连接所有底层sequencer的句柄(指针),是一个中心化的路由器。virtual sequencer本身并不传送item数据对象,因此不需要与driver进行TLM连接。所以用户需在顶层的connect阶段做好virtual sequencer中各个sequencer句柄与sequencer实体对象的一一连接,避免句柄悬空。

 virtual sequencer和(real) sequencer都继承自uvm_sequencer;

 virtual sequence 和(real) sequence 都继承自uvm_sequence;

        virtual sequence/sequencer的virtual主要是指这种sequence/sequencer不像直接作用在具体driver上的sequence/sequencer,它不处理具体的transaction,主要是来做不同类型sequence间的控制和调度的

4、m_sequencer与p_sequencer

4.1 m_sequencer

        当我们使用宏`uvm_do或者xxx_seq.start(sqr)方法启动sequence后(当sequence和sequencer关联后),sequence内部自有的m_sequencer句柄就自动地指向了对应的sequencer上了。这个操作是start()方法内部实现的,对用户不可见,因此一般我们都不会直接去操作m_sequencer变量。事实上,uvm中直接以'm_'开头的变量都不应该直接被用户使用。

        但通过m_sequencer不能直接使用seqr里的变量,否则会出现编译错误。只能使用cast强制向子类转换后,才能通过m_sequencer.xxx来访问该seqr内的xxx变量。

4.2 p_sequencer

        与m_sequencer变量作用相反,p_sequencer变量就是为了方便用户而提供的。p_sequencer变量需要用户使用宏`uvm_declare_p_sequencer去定义和设置。

`uvm_declare_p_sequencer宏一般在sequence的内部使用,主要完成以下两件事情:

  1. 创建了p_sequencer变量;
  2. 将uvm内部的m_sequencer变量赋给了p_sequencer变量;

5、实例

 该例子来自于红宝书394页

typedef class mcdf_virtual_sequencer;
//底层sequence定义,分别属于不同的sequencer
//clk_rst_seq
//reg_cfg_seq
//data_trans_seq
//fmt_slv_cfg_seq
class mcdf_normal_seq extends uvm_sequence; //mcdf_normal_seq相当于virtual sequence
    `uvm_object_utils(mcdf_normal_seq)//注册
    `uvm_declare_p_sequencer(mcdf_virtual_sequencer);
  ...                                                   //省略
  task body();
    clk_rst_seq clk_seq; 
    reg_cfg_seq cfg_seq;
    data_trans_seq data_seq;
    fmt_slv_cfg_seq fmt_seq;

     //配置formatter slave agent
     `uvm_do_on(fmt_seq,p_sequencer.fmt_sqr)
     //打开时钟完成复位
     `uvm_do_on(clk_seq,p_sequencer.cr_sqr)
     //配置MCDF寄存器
     `uvm_do_on(cfg_seq,p_sequencer.cr_sqr)
     //传送channel数据包
     `uvm_do_on(clk_seq,p_sequencer.cr_sqr)
     fork
        `uvm_do_on(data_seq,p_sequencer.chnl_sqr0)
        `uvm_do_on(data_seq,p_sequencer.chnl_sqr1)
        `uvm_do_on(data_seq,p_sequencer.chnl_sqr2)
     join
 endtask
endclass

        通过宏`uvm_declare_p_sequencer( )来绑定virtual sequencer同时声明p_sequencer,并操作virtual sequencer中的内容;通过宏`uvm_do_on( )将虚序列器句柄与虚序列句柄相连接,这就可以把sequence挂载到对应的sequencer上面。从上述代码来看,mcdf_normal_seq(即virtual sequence)可以承载各个子模块环境的elment sequence。

//子一级的sequencer和agent定义
// cr_master_sequencer      |   cr_master_agent
// reg_master_sequencer     |   reg_master_agent 
// chnl_master_sequencer    |   chnl_master_agent  
// fmt_slave_sequencer      |   fmt_slave_agent 
//
class mcdf_virtual_sequencer extends uvm_sequencer
    cr_master_sequencer cr_sqr;
    reg_master_sequencer reg_sqr;
    chnl_master_sequencer chn_sqr0;
    chnl_master_sequencer chn_sqr1;
    chnl_master_sequencer chn_sqr2;
    fmt_slave_sequencer  fmt_sqr;
    
    `uvm_compoent_utils(mcdf_virtual_sequencer)   //注册 
    
    function new(string name, uvm_compoent_parent);
        super.new(name,parent);
    endfunction
endclass

 mcdf_virtual_sequncer(即virtual sequencer)拿到各sequencer的句柄。

class mcdf_env extends uvm_env;
	cr_master_agent cr_agt;
	reg_master_agent re_agt;
	chnl_master_agent chnl_agt0;
	chnl_master_agent chnl_agt1;
	chnl_master_agent chnl_agt2;
	fmt_slave_agent fmt_agt;
	mcdf_virtual_agent virt_sqr;
	`uvm_component_utils(mcdf_env)
	function new(string name, uvm_component parent);
		super.new(name,parent);
	endfunction
	function void build_phase(uvm_pahse phase);
		cr_agt = cr_master_agent::type_id::create("cr_agt",this);
		re_agt = reg_master_agent::type_id::create("re_agt",this);
		chnl_agt0  = chnl_master_agent::type_id::create("chnl_agt0",this);
		chnl_agt1  = chnl_master_agent::type_id::create("chnl_agt1",this);
		chnl_agt2  = chnl_master_agent::type_id::create("chnl_agt2",this);
		fmt_agt = fmt_slave_agent::type_id::create("fmt_agt",this);
		virt_sqr =  mcdf_virtual_agent::type_id::create("virt_sqr",this);
	endfunction
	function void connect_phase(uvm_pahse phase);
		virt_sqr.cr_sqr = cr_agt.sqr;
		virt_sqr.reg_sqr = re_agt.sqr;
		virt_sqr.chnl_sqr0 = chnl_agt0.sqr;
		virt_sqr.chnl_sqr1 = chnl_agt0.sqr;
		virt_sqr.chnl_sqr2 = chnl_agt0.sqr;
		virt_sqr.fmt_sqr = fmt_agt.sqr;
	endfunction
endclass

        在build_phase中利用工厂创建并例化对象,方便接下来对接,即UVM用户需在顶层的connect阶段做好virtual sequencer中各sequencer句柄与底层sequencer实体对象对接,避免句柄悬空。

class test1 extends uvm_test;
	mcdf_env e;
	...
	task run_phase(uvm_phase phase)
		mcdf_normal_seq seq;
		phase.raise_objection(phase);
		seq = new();
		seq.start(e.virt_sqr);
		phase.drop_objection(phase);
	endtask
endclass

        在test层中奖virtual sequence 挂载到virtual sequencer上,但这种挂载的根本目的是给virtual sequence提供一个中心化的sequencer路由,而借助virtual sequence(此处mcdf_normal_seq)中使用宏`uvm_declare_p_sequencer( )virtual sequence 可以使用声明后的成员变量p_sequncer(类型为mcdf_virtual_sequencer),进一步回溯到virtual sequncer内部的各个sequencer句柄。

        这里使用宏`uvm_declare_p_sequencer( )较为方便,因为在宏的后台,可以新创建一个p_sequncer变量,而将m_sequncer的默认变量(uvm_sequencer_base类型)通过动态的转换变为类型为mcdf_virtual_sequencer的p_sequncer。

 virtual sequence的协调作用和virtual sequencer的路由作用如下图

 

 参考链接:

理解UVM中的virtual sequencer和virtual sequence_kevindas的博客-CSDN博客

  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值