其他分享
首页 > 其他分享> > (21)UVM 虚拟类序列(virtual sequence)

(21)UVM 虚拟类序列(virtual sequence)

作者:互联网

UVM 虚拟类序列(virtual sequence)

文章目录


在上一节中,已经讲过了层次类序列(hierarchical sequence)。接下来要讲的是虚拟类序列(virtual sequence)。如何区别接下来讲到的virtual sequence与hierarchical sequence呢?
在这里插入图片描述
它们两者之间的共同点就是对于各个sequence的协调。它们的不同在于,hierarchical sequence面对的对象是同一个sequencer,即hierarchical sequence本身也会挂载到sequencer上面,而对于virtual sequence而言,它内部不同的sequence可以允许面向不同的sequencer种类。

virtual sequence介绍

virtual sequencer起到一个简单路由的作用
在这里插入图片描述

virtual存在对于sequence和sequencer的改变

就之前的sequence和sequencer而言,它们之间的差别在于:

virtual sequence示例

接下来的示例用来表示element sequence/hierarchical sequence与virtual sequence的关系,以及底层sequencer与virtual sequencer的联系,同时也说明virtual sequence与virtual sequencer的挂载关系。

class mcdf_normal_seq extends uvm_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.reg_sqr)
		// 传送channel数据包
		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

m_sequencer是一个父类句柄,是uvm_seq自己预定义的
p_sequencer是一个子类句柄,在这个实例中它的类型就是mcdf_virtual_sequencer,和m_sequencer不一样,它不是预定义好的,是新鲜定义的,定义它的宏内容完成了两部。

  1. 定义了成员变量的类型mcdf_virtual_sequencer p_sequencer;
  2. 进行了句柄转换$cast(p_sequencer,m_sequencer);把m_sqr父类句柄转换成了子类句柄p_sqr。不论是m_sqr还是p_sqr都指向virtual_sqr,当然virtual_sqr是一个子类的类型
//子一级的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 chnl_sqr0;
	chnl_master_sequencer chnl_sqr1;
	chnl_master_sequencer chnl_sqr2;
	fmt_slave_sequencer fmt_sqr;
	`uvm_component_utils(mcdf_virtual_sequencer)
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction
endclass

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

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

virtual sequence示例解析

virtual sequence建议

  1. 需要区分virtual sequence同其他普通sequence(element sequence、hierarchical sequence)。
  2. 需要区分virtual sequencer同其它底层负责传送数据对象的sequencer。
  3. 在virtual sequence中记得使用宏`uvm_declare_p_sequencer来创建正确类型的p_sequencer变量,方便接下来各个目标sequencer的索引。
  4. 在顶层环境中记得创建virtual sequencer,并且完成virtual sequencer中各个sequencer句柄与底层sequencer的跨层次连接。

关注作者

标签:21,sequence,sqr,virtual,chnl,uvm,sequencer
来源: https://blog.csdn.net/qq_42419590/article/details/121425345