UVM实战_4_UVM中的sequence总结

本文详细介绍了UVM中的sequence使用,包括start启动、default_sequence启动、sequence的执行流程,以及sequence的仲裁机制,如transaction优先级、sequence的锁(lock)、grab等。此外,还探讨了sequence的进阶应用,如嵌套sequence、uvm_sequence_item、p_sequencer,并讲解了virtual sequence在复杂同步场景中的应用,以及sequence中如何利用config_db传递参数。最后,介绍了sequence library的创建与使用。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本篇主要总结《UVM实战》第6章:sequence基础


一、sequence的启动与执行

sequence在test_case中启动,有两种形式:1.start启动;2.default_sequence启动

1. start启动

my_sequence my_seq;
my_seq = my_sequence::type_id::create("my_seq");
my_seq.file_name = "data.txt";  //手动启动的好处是,可以向sequence传递参数
my_seq.start(sequencer);

2. default_sequence启动

uvm_config_db#(uvm_object_wrapper)::set(this,
									"env.i_agt.sqr.main_phase",//设置成sqr的main_phase,当sqr执行到main_phase时,发现有
									"default_sequence",        //default_sequence,那么就启动sequence
									case0_sequence::type_id::get());
//或者先实例化要启动的sequence,在通过default_sequence启动
function void my_case0::build_phase(uvm_phase phase);
	case0_sequence cseq;
	super.build_phase(phase);
	cseq = new("cseq");
	uvm_config_db#(uvm_object_wrapper)::set(this,
									"env.i_agt.sqr.main_phase",
									"default_sequence",
									cseq);
endfunction

3. 执行

sequence启动后,会自动按序执行sequence的body任务:pre_body,body,post_body。主要工作都在body中进行。
body中常有两种形式写法:1.uvm_do;2.start_item/finish_item;

//第一种形式
virtual task body();
	tr = transaction::type_id::create("tr");
	start_item(tr);
	assert(tr.randomize());
	finish_item(tr);
endtask
//第二种形式
task body();
	repeat (10) begin
		`uvm_do(m_trans);
	end
endtask
//uvm_do系列宏还有如下几个
`uvm_do(SEQ_OR_ITEM)  //第一个系数可以是tr或者seq
`uvm_do_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS)
`uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)
`uvm_do_on(SEQ_OR_ITEM)
`uvm_do_on_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_on_with(SEQ_OR_ITEM, CONSTRAINTS)
`uvm_do_on_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)

二、sequence仲裁

1. 在同一sequencer启动多个sequence

针对transaction优先级

对于transaction来说,存在优先级的概念。当使用uvm_do或者uvm_do_with宏时,产生的transaction的优先级是默认的优先级,即-1。可以通过uvm_do_pri及uvm_do_pri_with改变所产生transaction的优先级

代码如下所示:

task my_case0::main_phase(uvm_phase phase);
   sequence0 seq0;
   sequence1 seq1;

   seq0 = new("seq0");
   seq0.starting_phase = phase;
   seq1 = new("seq1");
   seq1.starting_phase = phase;
   env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);//需要设置仲裁算法,其他的仲裁算法见P169
   fork
      seq0.start(env.i_agt.sqr);
      seq1.start(env.i_agt.sqr);
   join
endtask

sequence0和sequence1

class sequence0 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
   ...
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (5) begin
         `uvm_do_pri(m_trans, 100)	//一般第二个参数是优先级,这个数值必须大于-1,数字越大,优先级越高
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

endclass

class sequence1 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
	...
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (5) begin
         `uvm_do_pri_with(m_trans, 200, {
   
   m_trans.pload.size < 500;})
         `uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(sequence1)
endclass

运行上述代码,由于sequ

UVM(Universal Verification Methodology)框架中,`uvm_sequence_item` 和 `uvm_object` 是两个关键的基类,它们之间存在明确的继承关系和功能差异。 ### 继承关系 `uvm_sequence_item` 是 `uvm_transaction` 的子类,而 `uvm_transaction` 又是 `uvm_object` 的子类。因此,`uvm_sequence_item` 间接继承了 `uvm_object` 的所有属性和方法。这种继承结构使得 `uvm_sequence_item` 拥有 `uvm_object` 的基本功能,并在此基础上扩展了适用于事务生成和驱动的功能[^1]。 ### 主要区别 #### 1. **用途不同** - **uvm_object** 是 UVM 中最基础的类之一,它提供了对象创建、复制、比较、随机化等通用功能。`uvm_object` 可以作为其他所有类的基类,适用于需要进行序列化、克隆或随机化的场景。 - **uvm_transaction** 是 `uvm_object` 的子类,专门用于表示事务级别的数据交换。它通常用于描述在组件之间传输的数据内容,例如寄存器读写操作、总线事务等。 - **uvm_sequence_item** 是 `uvm_transaction` 的子类,主要用于在 sequence 和 driver 之间传递事务。它不仅具备 `uvm_transaction` 的功能,还支持与 sequencer 的交互机制,如设置 sequence ID、sequencer 上下文等[^3]。 #### 2. **与 sequencer 的交互能力** - **uvm_object** 不具备与 sequencer 交互的能力,因为它不涉及事务调度或序列控制。 - **uvm_sequence_item** 则专门设计用于 sequence 与 driver 之间的通信。它可以通过 `start_item()` 和 `finish_item()` 方法与 sequencer 协调,确保事务的正确发送和接收。此外,它还可以使用宏 `uvm_do(req)` 来简化事务的创建、随机化和发送过程[^2]。 #### 3. **生命周期管理** - **uvm_object** 的生命周期由用户直接管理,通常用于静态数据结构或不需要参与事务调度的对象。 - **uvm_sequence_item** 的生命周期则受到 sequencer 和 driver 的影响。当 sequence 调用 `start_item()` 时,sequencer 会等待 driver 准备好接收事务;调用 `finish_item()` 后,事务被发送给 driver 并等待其完成处理[^2]。 ### 联系 尽管 `uvm_sequence_item` 和 `uvm_object` 在用途上有显著区别,但它们之间也存在紧密联系: - **继承关系**:`uvm_sequence_item` 继承自 `uvm_transaction`,而 `uvm_transaction` 又继承自 `uvm_object`,因此 `uvm_sequence_item` 具备 `uvm_object` 的所有基本功能,如随机化、复制、比较等。 - **共享通用接口**:两者都支持 `do_print()`, `do_copy()`, `do_compare()` 等方法,这些方法为调试、日志记录和数据一致性检查提供了统一的接口。 - **可作为泛型使用**:由于 `uvm_sequence_item` 是 `uvm_object` 的子类,它可以被当作 `uvm_object` 使用,从而在需要通用对象处理的地方灵活应用。 ### 示例代码 以下是一个简单的 `uvm_sequence_item` 定义示例: ```systemverilog class my_sequence_item extends uvm_sequence_item; rand bit [7:0] data; rand bit [3:0] addr; `uvm_object_utils_begin(my_sequence_item) `uvm_field_int(data, UVM_ALL_ON) `uvm_field_int(addr, UVM_ALL_ON) `uvm_object_utils_end function new(string name = "my_sequence_item"); super.new(name); endfunction endclass ``` 而在 sequence 中使用该 item 的方式如下: ```systemverilog task my_sequence::body(); my_sequence_item req; `uvm_do(req) // 自动调用 start_item, randomize, finish_item endtask ``` ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值