IC验证面试经验分享——UVM篇

验证最需要会的技能树是什么?!那肯定是非UVM莫属了,趁着校招之际,准备IC面试的ICer赶快码住!


UVM篇

UVM是一个库,在这个库中,几乎所有的东西都是使用类(class)来实现的,当要实现一个功能时,首先应该想到的是从UVM的某个类派生出一个新的类,在这个新的类中实现所期望的功能。所以,使用UVM的第一条原则是:验证平台中所有的组件应该派生自UVM中的类。———摘自《UVM实战》白皮书

UVM是基于SV语言开发的框架,这个是验证er的常识哦。


一、UVM验证平台组件

  1. driver: 给dut添加各种激励,激励的实现就是通过driver;
  2. scoreboard: 根据DUT的输出来判断DUT的行为是否与预期相符合,也被称为checker;
  3. monitor:收集接口信号并转换为事务转送给scb和refm;
  4. reference model: 模拟dut的行为得到参考输出作为scb的评判标准。

此外,uvm中还引入了agent,sequencer的概念。

  • agent:封装容器;
  • sequencer:连接管道,串联driver和sequence,组织并管理sequence。
    在这里插入图片描述

二、UVM_component和uvm_object

在这里插入图片描述
根据白皮书,uvm_component其实是继承自uvm_object,但是学过面向对象的都知道面向对象的三大特性之一就是多态,那么子类可能拥有一些父类没有的特性。uvm_component有两大特性是uvm_object所没有的:

  • 一是通过在new的时候指定parent参数来形成一种树形的组织结构;
  • 二是有phase的自动执行特点。
    在这里插入图片描述

三、sequence启动方式

  • 直接用my_seq.start(sequencer);
    在这里插入图片描述
  • 通过default sequence启动,有两种方式
    • 通过wrapper,直接调用start
      在这里插入图片描述
    • 先实例化要启动的sequence,之后再通过default_sequence启动
      在这里插入图片描述
      所以从上面也可以看到,uvm_config_db机制将sequence送到agen.sqr的main_phase中

四、seqence是怎么给到dut的?

这里先说sequence和sequencer的区别?

  • 按照白皮书的比喻不难理解,sqr是弹夹,sequence是子弹
    • 只有在sequencer的帮助下,sequence产生出的transaction才能最终送给driver;同样,sequencer只有在sequence出现的情况下才能体现其价值,如果没有sequence,sequencer就几乎没有任何作用。sequence就像是一个弹夹,里面的子弹是transaction,而sequencer是一把枪。——摘自《UVM实战卷I》白皮书

因此,从sqr中获取transaction,按照dut的行为模块驱动transaction至interface,返回响应到sqr,再转给seq。

五、p_sequencer和m_sequencer的区别

1)含义

  • m_sequencer 是一个定义在用户构建的 sequence/sequence_item 基类里的 sequencer 基类句柄,通过这种方式,建立起 sequence - sequencer 之间的连接,使 sequence 有通过 m_sequencer 句柄来访问 sequencer 变量的能力。
  • p_sequencer 是一个 uvm_sequencer 类型 (通常情况) 的句柄,由用户在调用宏 `uvm_declare_p_sequencer(SEQUENCER) 时指定。

2)区别

  • m_sequencer 的局限性:m_sequencer 的存在建立了 sequencer-sequence 之间的桥梁,但是由于 m_sequencer 句柄类型相较于实际用户构建的 sequencer 来说都是基于更底层的 uvm_sequencer_base 类型。虽然可以保证 m_sequencer 句柄可以指向用户构建的 sequencer,但是 m_sequencer 能访问到的变量和方法仍具有局限性 (基类句柄指向扩展类对象,但只能访问扩展类中属于基类的变量和方法)。
  • p_sequencer的引入 :基于以上问题,需要引入一个类型与用户构建的 sequencer 一致的扩展类句柄 p_sequencer,通过动态类型转化,让 p_sequencer 与 m_sequencer 都指向用户构建的 sequencer 对象,并且由于 p_sequencer 是扩展类类型的句柄,可以通过 p_sequencer 句柄,在 sequence 中访问到属于 sequencer 的内容。最终 m_sequencer 与 p_sequencer 指向对象都为用户构建的 sequencer,只是可访问的范围不一致

六、UVM_do系列宏

1)uvm_do和uvm_do_on的区别

uvm_do_on系列用于显式地指定使用哪个sequencer发送此transaction,第一个参数是transaction的指针,第二个参数是sequencer的指针。

2)系列宏的含义

	//uvm_do
	uvm_do(seq or item)
	uvm_do_pri(seq or item,优先级数)一般默认的tr优先级是-1,所以数一般要更大  	uvm_do_with(seq or item, 约束)
	uvm_do_pri_with(seq or item, 优先级数,约束)

	//uvm_do_on
	uvm_do_on(seq or item,seqr)
	uvm_do_on_pri(seq or item,seqr,优先级)
	uvm_do_on_with(seq or item,seqr,约束)
	uvm_do_on_pri_with(seq or item,seqr,优先级,约束)

七、UVM phase机制

首先,uvm中分为两类phase,这些phase自上而下执行:

  • function phase不消耗仿真时间,
  • task phase消耗仿真时间(下图灰色部分);
    在这里插入图片描述

1)运行情况

function phase

对于function phase来说,,在同一时间只有一个phase在执行

task phase

但是task phase中,run_phase和pre_reset_phase等12个小的phase并行运行,称为动态运行;4个核心phase,这四个phase通常模拟DUT的正常工作方式:

  • reset_phase:对DUT进行复位、初始化等操作;
  • configure_phase:进行DUT的配置;
  • main_phase:完成DUT的运行;
  • shutdown_phase:做一些与DUT断电相关的操作。

2)main_phase和run_phase之间关系

包含关系,run_phase中包含main_phase,run_phase和main_phase都是task phase,是并行运行的。

3)执行顺序

Build phase 自顶向下(因为要实例化,比如driver是agent的成员变量,必须先实例化agent才有driver,否则就报错),其他function phase 自底向上,task phase自顶向下,同时运行(类似run_phase、main_phase等task_phase也都是按照自下而上的顺序执行的)

此外,对于component来说,12个run-time的phase是顺序执行的,但是它们也仅仅是顺序执行,并不是说前面一个phase执行完就立即执行后一个phase。一般是等所有component的同一个phase执行完才会执行下一个phase,所以对于component来说会存在空白等待的时间,但是对于整个验证平台来说,是没有空白时间,是连续完成的
在这里插入图片描述

八、objection机制

UVM通过objection机制来控制验证平台的关闭

  • 在每个phase中,UVM会检查是否有objection被提起(raise_objection),如果有,那么等待这个objection被撤销(drop_objection)后停止仿真,如果没有则马上结束当前phase。
  • raise_objection和drop_objection要成双成对出现。raise_objection必须放在main_phase第一个消耗仿真时间的语句之前。
  • 在UVM中,objection一般伴随着sequence,通常只在sequence出现的地方raise_objection和drop_objection,sequence产生transaction,产生tr发送完毕后就可以结束仿真了。

如果想执行一些耗费时间的代码,就要在此phase下的任意一个component中至少提起一次objection。值得一提的是,如果12个动态phase有objection提起,那么run_phase根本不需要raise_objection就可以自动执行。反过来则不行。

九、UVM factory机制

factory的重载是一大特点:将父类的函数/任务定义为virtual,虚函数可以重载,重载的最大优势是使得一个子类的指针以父类的类型传递时,其表现出的行为依然是子类的行为。

1)super关键字

super关键字,父类成员被重载,那么再访问就必须用super。

super.new()

  • 在new中使用super,super.new是执行的第一条语句。
  • 在uvm中,super.new()是一个特殊的构造函数,它用于在子类构造函数中调用父类的构造函数,这是因为在uvm中,一般情况下他们都是继承来扩展已有的类,当我们在子类中创建对象时,需要先调用父类的构造函数,以初始化父类的成员变量和方法
  • 因此,super.new()的作用就是确保在子类构造函数中先调用父类的构造函数,以便完成父类的初始化工作,需要注意的时,super.new()必须放在子类构造函数的第一行,否则会出现编译错误。
  • 此外,如果父类的构造函数需要参数,也需要传递参数的

super.phase()

  • super.phase其实就是继承在uvm_compoent中已经定义好的变量/方法,建议有的可以写有的可不写,但是个人建议写上去,以免后续uvm库有更新,自己还要更改代码风格。

2)使用factory机制的重载的前提

  1. 第一,无论是重载的类(parrot)还是被重载的类(bird),都要在定义时注册到factory机制中。
  2. 第二,被重载的类(bird)在实例化时,要使用factory机制式的实例化方式(create创建对象),而不能使用传统的new方式。
  3. 第三,最重要的是,重载的类(parrot)要与被重载的类(bird)有派生关系。重载的类必须派生自被重载的类,被重载的类必须是重载类的父类。
  4. 第四,component与object之间互相不能重载。虽然uvm_component是派生自uvm_object,但是这两者的血缘关系太远了,远到根本不能重载。从两者的new参数的函数就可以看出来,二者互相重载时,多出来的一个parent参数会使factory机制无所适从。

总结

以上就是面试过程中被问的比较多的一些问题,也算是IC验证的必背八股文了吧,创作不易,都是博主精心整理的笔记,如有问题或者错误欢迎大家指正,一起学习!

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值