数字验证:一文弄懂UVM的objection机制

1. objection与phase

        前文中我们了解了uvm的phase机制:数字验证:一文弄懂UVM的phase机制-CSDN博客,而objection与phase之间关系紧密。objection字面的意思就是反对、异议。在验证平台中,可以通过raise_objection来提起“反对”,通过drop_objection来通知系统可以关闭验证平台。当然,一定是raise在drop之前:

task main_phase(uvm_phase phase);
   phase.raise_objection(this);
   …
   phase.drop_objection(this);
endtask

        在进入到某一phase时,UVM会收集此phase提出的所有objection,并且实时监测所有objection是否已经被撤销了,当发现所有都已经撤销后,那么就会关闭此phase,开始进入下一个phase。当所有的phase都执行完毕后,就会调用$finish来将整个的验证平台关掉。

        如果UVM发现此phase没有提起任何objection,那么将会直接跳转到下一个phase中。假如验证平台中只有driver中提起了异议,而monitor等都没有提起,代码如下所示:

task driver::main_phase(uvm_phase phase);
  phase.raise_objection(this);
  #100;
  phase.drop_objection(this);
endtask
task monitor::main_phase(uvm_phase phase);
  while(1) begin
  …
  end
endtask

         driver中的代码是肯定可以执行的,那么monitor中的代码能够执行吗?

        可以。当进入到monitor后,系统会监测到已经有objection被提起了,所以会执行monitor中的代码。当过了100个时间单位之后,driver中的objection被撤销。此时,UVM监测发现所有的objection都被撤销了(因为只有driver raise_objection),于是UVM会直接杀死monitor中的无限循环进程,并跳到下一个phase,即post_main_phase()。

        如果driver里也没有就没有raise_objection,并且所有其他component的main_phase里面也没有raise_objection,即driver变成如下情况:

task driver::main_phase(uvm_phase phase);
  #100;
endtask

        那么在进入main_phase时,UVM发现没有任何objection被提起,于是虽然driver中有一个延时100个单位时间的代码,monitor中有一个无限循环,UVM也都不理会,它会直接跳转到post_main_phase,假设进入main_phase的时刻为0,那么进入post_main_phase的时刻还是为0。

2. objection的使用

        对于12个小phase来说:如果想执行一些耗费时间的代码,那么要在此phase下任意一个component中至少提起一次objection。

 task my_case0::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   #100;
   phase.drop_objection(this);
 endtask

 task my_case0::run_phase(uvm_phase phase);
   for(int i = 0; i < 9; i++) begin
     #10;
     `uvm_info("case0", "run_phase is executed", UVM_LOW)
   end
 endtask

        可以看到在main_phase中提起了objection,但为什么run_phase的输出仍然有效呢?因为run_phase与12个小phase是并行运行的,当小phase中有objection被提起,run_phase也可以自动执行。但是反过来,main_phase则不会有输出出现。

        这是因为对于run_phase来说,有两种运行方式:

        (1)其他动态运行的phase中有objection提起。此时运行时间受小phase的objection控制。

        (2)run_phase中提起objection。此时运行时间完全受run_phase自身控制。

        raise_phase语句也必须在第一个消耗仿真时间的语句之前声明

3. 参数phase的必要性

在UVM中所有phase的函数/任务参数中,都有一个phase:

task main_phase(uvm_phase phase);

        这个输入参数中的phase是什么意思?为什么要加入这样一个东西?因为要便于在任何component的main_phase中都能raise_objection,而要raise_objection则必须通过phase.raise_objection来完成,所以必须将phase作为参数传递到main_phase等任务中。如果没有这个phase参数,那么想要提起一个objection就会比较麻烦了。

        那么类似build_phase等function phase是否可以提起和撤销objection呢?

        不会报错,但是一般不会这么用。phase的引入是为了解决何时结束仿真的问题,它更多面向main_phase等task phase,而不是面向function phase。

4. objection的控制

        在整棵UVM树中,在什么地方控制objection最合理呢?driver中、monitor中、agent中、scoreboard中抑或是env中?

        在drv,monitor,ref model等component都是通过while(1)无限循环的,因此一般不在其中控制objection。

        一般来说,控制objection的策略有两个:

        (1)在scoreboard中进行控制。如果要在scoreboard中控制objection,则需要去除scb中的无限循环,通过config_db::set的方式设置收集到的transaction的数量pkt_num,当收集到足够数量的transaction后跳出循环:

task my_scoreboard::main_phase(uvm_phase phase);
  phase.raise_objection(this);
  fork
    while (1) begin
      exp_port.get(get_expect);
      expect_queue.push_back(get_expect);
  end
  for(int i = 0; i < pkt_num; i++) begin
    act_port.get(get_actual);
    …
  end
join_any
phase.drop_objection(this);
endtask

        (2)在sequence中提起sequencer的objection,sequence完成后再撤销objection。

        UVM更提倡采用第二种方法,全部由sequence控制激励的生成。

5. set_drain_time的使用

        无论任何功能的模块,都有其处理延时。如下图所示,0时刻DUT开始接收输入,直到p时刻才有数据输出。

        在sequence中,n时刻发送完毕最后一个transaction,如果此时立刻drop_objection,那么最后在n+p时刻DUT输出的包将无法接收到。因此,在sequence中,最后一个包发送完毕后,要延时p时间才能drop_objection

virtual task body();
  if(starting_phase != null)
    starting_phase.raise_objection(this);
  repeat (10) begin
    `uvm_do(m_trans)
  end
  #100;
  if(starting_phase != null)
    starting_phase.drop_objection(this);
endtask

         延长的时间与激励有很大关系,因此只能根据激励选择一个最大的延时。这种延时对于所有sequence都是必须的,但对每个sequence都进行这样的处理不够合理,如果DUT处理的延时变大,那么要修改所有的延时大小,非常麻烦。

        因此UVM设置了drain_time这一属性:当所有的objection被drop之后,不会马上进入下一层,而是等待一段时间。drain_time的设置方式为:

task base_test::main_phase(uvm_phase phase);
   phase.phase_done.set_drain_time(this, 200);
 endtask

        当调用phase.raise_objection或者phase.drop_objection时,其实质是调用phase_done的raise_objection和drop_objection。当UVM在main_phase检测到所有的objection被撤销后,接下来会检查有没有设置drain_time。如果没有设置,则马上进入到post_main_phase,否则延迟drain_time后再进入post_main_phase。如果在post_main_phase及其后都没有提起objection,那么最终会前进到final_phase,结束仿真。

        drain_time属于uvm_objection的一个特性,一个drain_time对应一个phase,并不是所有共享,在没有设置时会默认取0.

    

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值