UVM在test组件内启动sequence/virtual sequence的方法

在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 :

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 :

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值