UVM的sequence机制

什么是UVM的sequence机制

  • 控制产生一系列事务,并将事务发送给driver的一套机制
  • 是一个过程,需要消耗仿真时间,需要用在task phase当中

(1)控制何时产生、发送事务

(2)产生事务

(3)发送给driver

UVM sequence机制过程

  1. 仿真进入某一个task phase,比如run phase,与sequencer相连的sequence就会被启动
  2. 启动后的sequence会在内部产生一个事务对象并处于等待状态
  3. 当driver要驱动DUT时候,首先要从sequencer获得一个事务对象,driver向sequencer发送一个事务请求,sequencer收到这个请求会将这个请求转发给sequence
  4. sequence收到请求后会将已经产生好的事务对象发送出去,先发送给与自己相连的sequencer,再由sequencer转发给driver
  5. driver收到事务后,对此事务进行一系列处理,比如驱动DUT等
  6. driver处理好当前事务,会产生一个完成好的标志响应,先发送到sequencer,再转发给sequence
  7. sequence得知driver已经处理好当前事务,会产生下一个事务,并继续等待

以上过程,循环往复,直到所有的事物都产生完毕

测试平台示意图

为什么要使用UVM sequence机制

UVM将激励的产生完全从测试平台独立出来,提高组件的独立性, 将事物的产生和驱动分离

UVM sequence机制的原理

00 参与sequence机制主要有三个部分

driver、sequencer、sequence:sequence扮演一个中间者的角色,事务的产生在 sequence当中,事务的处理在driver当中

01 sequencer中的实现

很复杂的sequencer实现,UVM已经全部给出,不需要细究

  1. 当进入某一个task phase,sequencer检查其内部的default_sequence(指针)是否被配置
  2. 如果被配置,就会实例化default_sequence对象
  3. 然后设置default_sequence的starting_phase(raise和drop objection)
  4. 随机化sequence
  5. 调用sequence的start( )方法来启动sequence

02 sequence中的实现:start( )方法

start( )执行内部的body( )方法:UVM中通过 宏  'uvm_do(req)

03 driver中的实现

一直进行:forever

  1. 当driver要驱动DUT时候,首先向sequencer发送事物请求,然后处于等待状态;
  2. sequence收到事务请求后,查看fifo中是否有已经产生好的事务,如果没有就等待sequence的产生,如果有,就将该事务发送给driver
  3. 当driver成功获取事务后,结束等待状态,接下来将该事务进行分解并且驱动DUT
  4. 完成以上操作后,driver向sequencer返回一个完成标志,通知该事务已经处理完毕,这个标志也会最终传入sequence

UVM的sequence机制常用的宏 'uvm_do_*宏系列

UVM sequence机制的启动

1 直接启动

sequence定义-实例化-启用start任务

my_sequence my_seq;     //定义
my_seq = my_sequence::type_id::creat("my_seq");    //注册
my_seq.start(sequencer);  //调用start函数启动

2 使用default_sequence启动

2.1 直接default_sequence

2.2 先实例化要启动的sequence,再通过default_sequence启动

  • 可以在不同的地方通过default_sequence来启动sequence,比如在env中,第一个参数是this,第二个是相对于第一个参数的相对路径,路径需要指定到phase一级,比如main_phase,第三个和第四个参数纯属规定,照抄就行。
function void my_case::build_phase(uvm_phase phase);
	case_sequence seq;
	super.build_phase(phase);
	seq = new("seq");
	uvm_config_db(uvm_object_wrapper)::set(this,
									   "env.i_agt.sqr.main_phase",
									   "default_sequence",
									   seq);

3 'uvm_do启动

之后再说

此外,sequence启动后会发生什么呢?

会自动执行sequence的body任务,还会调用sequence的pre_body、post_body

UVM sequence的仲裁机制

引言:sequence可通过sequencer向drive发送你的待测case,如果一个sequencer只发送一个sequence是不需要仲裁的,但在实际使用中,如果一个sequencer接收了两个sequence或者更多的时候,会怎样发送各自sequence的case呢?

  1. 通过指定优先级决定仲裁
  2. 通过lock或者grap决定仲裁
  3. 通过is_relevant和对wait_for_relevant重载进行仲裁
  4. 通过virtual sequence和virtual sequencer进行复杂同步

01 指定sequence优先级

  • 在实际使用中,我们可以通过uvm_sequencer::set_arbitration(UVM_SEQ_ARB_TYPE val)函数来设置仲裁模式。

  • 这里的仲裁模式UVM_SEQ_ARB_TYPE有下面几种值可以选择

1.**UVM_SEQ_ARB_FIFO**:    // 默认模式。来自于sequences的发送请求,按照FIFO先进先出的方式被依次授权,和优先级没有关系。
2.**UVM_SEQ_ARB_WEIGHTED**://不同sequence的发送请求,将按照它们的优先级权重随机授权。            
3.**UVM_SEQ_ARB_RANDOM**:  //不同的请求会被随机授权,而无视它们的抵达顺序和优先级。       
//--若想使优先级起作用, 应该strict设置仲裁算法
4.**UVM_SEQ_ARB_STRICT_FIFO**:     不同的请求,会按照它们的优先级以及抵达顺序来依次授权,因此与优先级和抵达时间都有关。
5.**UVM_SEQ_ARB_STRICT_RANDOM**:  不同的请求,会按照它们的最高优先级随机授权,与抵达时间无关。
//---------不会用------------------------------------------------------------------
6.**UVM_SEQ_ARB_USER**:            用户可以自定义仲裁方法user_priority_arbitration()来裁定那个sequence的请求被优先授权。
m_sequencer.set_arbitration(UVM_SEQ_ARB_STRICT_FIFO); 
//设置sqr仲裁算法

transaction优先级设置

在sequence被启动是会自动执行它的body、pre_body和post_bosy三个任务,我们常用的是body任务。body任务中可以通过’uvm_do_pri‘uvm_do_pri_with设置所产生的transaction的优先级。uvm_do_pri与uvm_do_pri_with的第二个参数是优先级,这个数值必须是大于等于-1的整数,数字越大,优先级越高

PRIORITY:为item或者sequence指定优先级

'uvm_do_pri(SEQ_OR_ITEM,PRIORITY)
'uvm_do_pri_with(SEQ_OR_ITEM,PRIORITY,CONSTRAINTS)
'uvm_do_on_pri(SEQ_OR_ITEM,SEQR,PRIORITY)

以上结果:乱序sequence0 sequence1因为有很多仲裁算法

sequence优先级设置

start第1个参数:sequencer

start第2个参数:parent sequence 

start第3个参数:优先级

task my_case::main_phase(uvm_phase phase);
	env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);   //仲裁算法设置
	fork                                                  //sequence优先级设置
		seq0.start(env.i_agt.sqr, null, 200);
		seq1.start(env.i_agt.sqr, null, 400);
	join
endtask

总代码

如下面的这段代码指定了sequence0的优先级为100,sequence1的优先级为200,sequence1的优先级高于sequence0的优先级,同事设定了sequencer采用优先级仲裁机制,这样则会将sequence1的transcation都发送完成后再发送sequence0的transaction。对sequence设置优先级的本质即设置其内产生的transaction的优先级。

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class sequence0 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence0");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (5) begin
         `uvm_do_pri(m_trans, 100)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence0)
endclass
 
class sequence1 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence1");
      super.new(name);
   endfunction 
   
   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
 
 
class my_case0 extends base_test;
 
   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   `uvm_component_utils(my_case0)
   extern virtual task main_phase(uvm_phase phase);
endclass
 
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);
   fork
      seq0.start(env.i_agt.sqr);
      seq1.start(env.i_agt.sqr);
   join
endtask
 
`endif

02 lock独占

03 grap独占

UVM sequence机制的嵌套

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值