《UVM实战》学习笔记——第五章 UVM验证平台的运行(phase和objection机制)

本文详细介绍了UVM验证框架中的phase机制,包括phase的分类、执行顺序、调试方法以及超时退出策略。此外,还阐述了objection的作用,如何在不同组件中使用objection控制仿真时间,以及set_drain_time的使用场景。内容涵盖了phase和objection在验证平台运行中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

2023.2.25开启学习的一天~


一、phase机制

在这里插入图片描述

在这里插入图片描述

1、phase分类

(1)function phase:除run_phase以外的其他phase
task phase:消耗仿真时间($time打印出来的时间,区别于CPU的运行时间),run_phase
(2)run_phase和其他12个小的phase并行运行
这12个小的phase成为run-time phase(动态运行的phase),通过细分实现了对DUT的精确控制
主要:reset、configure、main、shutdown四个,模拟DUT的正常工作方式
reset:复位、初始化操作等
configure:进行DUT的配置
main:DUT的运行
shutdown:DUT断电操作等

在这里插入图片描述

在这里插入图片描述

2、phase的执行顺序

这里说的是空间顺序,上面说的是时间顺序,时间顺序就是按照自上至下。

(1)自上至下:build_phase

build_phase是做实例化工作的,driver和monitor都是agent的成员变量,所以它们的实例化都是在agent的build_phase中执行。如果在agent的build_phase之前执行driver的build_phase,此时driver还根本没有实例化,所以调用driver.build_phase只会引发错误。

如果是是uvm_object的实例化,则可以在任何phase完成,当然也包括build_phase。

(2)自下至上:除build_phase之外的其他function phase
上下关系的component:按照自下至上运行

同级关系的component(兄弟关系)按照实例化名字的字典序。不是看谁先被实例化,而是看实例化名字的字母顺序,这种顺序是UVM1.1d代码定义的,如果要改变也是可以修改代码的。

叔侄关系的component(例如scoreboard和agent里面的driver):UVM按照深度优先的原则,agent的build_phase先执行,再去执行driver、monitor、sequencer的build_phase;执行完毕再去执行scoreboard的build_phase。(也就是先执行完agent这个uvm树的小分支,再去执行同级的uvm树杈)

(3)自下至上:run_phase
这种task phase消耗时间,它不是等下面的phase全部运行完再执行上面的phase,而是通过fork..join_none的形式全部启动,准确的说是自下至上顺序全部启动,然后再同时运行

这张图的意思是不同component的phase执行完毕的时间不一定会相等,先完成的component要等待其他component的phase执行完毕后再一起进入下一个phase,保证系统的phase是按照时间先后顺序进行的。

此外,同一个component的run_phasepost_shutdown_phase并行都全部完成后才会一起进入extract_phase。
在这里插入图片描述

3、super.phase

在build_phase中一般会出现super.build_phase(),如果不用configdb这个功能,可以不加super.build_phase()。
其他phase一般没啥功能,可以不加super。

4、phase之间可以相互跳转(高级功能)

5、phase的调试

命令行参数 UVM_PHASE_TRACE来调试

6、超时退出

(1)在base_test的build_phase
第一个参数是设置的退出时间,第二个参数是是否允许后面的settime设置进行覆盖

uvm_top.set_timeout(500ns,0);

(2)命令行参数设置,一般默认是9200s

+ UVM_TIMEOUT = "300ns YES"

7、验证平台的运行(重要)

理解0时刻前、0时刻、0时刻后三个阶段

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、objection机制

1、objection和task phase

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

如果此phase没有提起任何的objection,那么会直接跳到下一个phase。

(2)run-time phase:12个动态运行的phase,如果想要执行一些消耗时间的代码,就需要在此phase下的任意一个component里面至少提起一次objection。

(3)run_phase有两种情况可以运行代码:
其他动态运行的phase有objection被提起:run_phase的运行时间受其控制
run_phase有objection被提起:运行时间由自己决定。此时如果其他动态运行的phase没有objection的话也就不会执行代码了。

2、phase参数

目的:解决何时结束仿真的问题(也可以放在function phase里面,不会报错,但主要是面对task phase
好处:在任意component的main_phase中都可以raise_objection

3、objection的最佳位置

driver和monitor一般都是无限循环,进去了就退不出来了,所以一般不放在这
(1)scoreboard
scoreboard的main_phase也是一个无限循环。如果要在scoreboard中控制objection,则需要去除这个无限循环,通过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   //之前这里是join,现在第二个for循环结束后,就会退出
	phase.drop_objection(this); 
endtask

(2)在sequence中提起sequencer的objection,当sequence完成后,再撤销此objection,推荐该方式。
在sequence中raise objection,再在testcase的build_phase里面去设置default sequence

class case0_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
      end
      #100;   //等待sequence完全被接收
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
   
   `uvm_object_utils(case0_sequence)
endclass
class my_case0 extends base_test;

   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case0)
endclass

function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           case0_sequence::type_id::get());
endfunction

4、set_drain_time

一般来说,发送完sequence之后不会立马drop objection,因为dut接收处理这些sequence需要一定的时间,所以在上述代码中设置了100ns延时,但是这样在每个sequence立马去设置延时比较麻烦,还得估计这个sequence接收完毕的时间。

phase_done:uvm_phase里面预定义的成员变量,是uvm_objection类型
一个phase对应一个drain_time,不是共用的。
一般在drop_objection之后,会去看有没有设置这个时间,有就延时,没有就下一个phase。

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

5、objection的调试

命令行参数:+UVM_OBJECTION_TRACE

6、domain

(1)用于组织不同组件,比如希望DUT中的两个部分独立运行,隔开了两个时钟域,但是仅限于12个动态运行的phase,其他的phase还是同步的(如run_phase和其他function phase)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三、自测题

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值