IC验证面试常问88道

您所在的位置:网站首页 uvm面试 IC验证面试常问88道

IC验证面试常问88道

2024-07-15 00:11| 来源: 网络整理| 查看: 265

IC验证面试常问题88道 Q1. 定宽数组、动态数组、关联数组、队列各自特点和使用

队列:队列结合了链表和数组的优点,可以在一个队列的任何位置进行增加或者删除元素;

定宽数组:属于静态数组,编译时便已经确定大小。其可以分为压缩定宽数组和非压缩定宽数组:压缩数组是定义在类型后面,名字前面;非压缩数组定义在名字后面。Bit [7:0][3:0] name; bit[7:0] name [3:0];

动态数组:其内存空间在运行时才能够确定,使用前需要用new[]进行空间分配。

关联数组:其主要针对需要超大空间但又不是全部需要所有数据的时候使用,类似于hash,通过一个索引值和一个数据组成,索引值必须是唯一的。

Q2.多线程fork join/fork join_any/fork join_none的用法差异

Fork join:内部 begin end块并行运行,直到所有线程运行完毕才会进入下一个阶段。

Fork join_any:内部 begin end块并行运行,任意一个begin end块运行结束就可以进入下一个阶段。

Fork join_none:内部 begin end块并行运行,无需等待可以直接进入下一个阶段。

wait fork:会引起调用进程阻塞,直到它的所有子进程结束,一般用来确保所有子进程(调用进程产生的进程,也即一级子进程)执行都已经结束。

disable fork:用来终止调用进程 的所有活跃进程, 以及进程的所有子进程。

Q3. 多线程的同步调度方法

多线程之间同步主要由mailbox、event、 semaphore三种进行一个通信交互。

mailbox邮箱:主要用于两个线程之间的数据通信,通过put函数和 get 函数还有peek函数进行数据的发送和获取。

Event:事件主要用于两个线程之间的一个同步运行,通过事件触发和事件等待进行两个线程间的运行同步。使用@(event)或者 wait(event.trigger)进行等待,->进行触发。

Semaphore:旗语主要是用于对资源访问的一个交互,通过key的获取和返回实现一个线程对资源的一个访问。使用put和 get函数获取返回key。一次可以多个。

Q4. Task和function的区别

函数能调用另一个函数,但不能调用任务,任务能调用另一个任务,也能调用另一个函数

函数总是在仿真时刻0就开始执行,任务可以在非零时刻执行

函数一定不能包含任何延迟、事件或者时序控制声明语句,任务可以包含延迟、事件或者时序控制声明语句

函数至少有一个输入变量,可以有多个输入变量,任务可以没有或者多个输入(input)、输出(output)和双向(inout)变量

函数只能返回一个值,函数不能有输出(output)或者双向(inout)变量,任务不返回任何值,任务可以通过输出(output)或者双向(inout)变量传递多个值

Q5.简述在TB中使用interface和clocking blocking的好处

Interface是一组接口,用于对信号进行一个封装,捆扎起来。如果像verilog中对各个信号进行连接,每一层我们都需要对接口信号进行定义,若信号过多,很容易出现人为错误,而且后期的可重用性不高。因此使用interface接口进行连接,不仅可以简化代码,而且提高可重用性,除此之外,interface内部提供了其他一些功能,用于测试平台与DUT之间的同步和避免竞争。

Clocking block:在interface内部我们可以定义clocking块,可以使得信号保持同步,对于接口的采样vrbg和驱动有详细的设置操作,从而避免TB与 DUT的接口竞争,减少我们由于信号竞争导致的错误。采样提前,驱动落后,保证信号不会出现竞争。

Q6. OPP(面向对象)的特性?

封装、继承和多态

封装:通过将一些数据和使用这些数据的方法封装在一个集合里,成为一个类。

继承:允许通过现有类去得到一个新的类,且其可以共享现有类的属性和方法。现有类叫做基类,新类叫做派生类或扩展类。

多态:得到扩展类后,有时我们会使用基类句柄去调用扩展类对象,这时候调用的方法如何准确去判断是想要调用的方法呢?通过对类中方法进行virtual声明,这样当调用基类句柄指向扩展类时,方法会根据对象去识别,调用扩展类的方法,而不是基类中的。而基类和扩展类中方法有着同样的名字,但能够准确调用,叫做多态。

Q7. 简述UVM的工厂机制

Factory机制也叫工厂机制,其存在的意义就是为了能够方便的替换TB中的实例或者已注册的类型。一般而言,在搭建完TB后,我们如果需要对TB进行更改配置或者相关的类信息,我们可以通过使用factory机制进行覆盖,达到替换的效果,从而大大提高TB的可重用性和灵活性。

要使用factory机制先要进行:

将类注册到factory表中

创建对象,使用对应的语句 (type_id::create)

编写相应的类对基类进行覆盖。

Q8. SV中的interface的clock blocking的功能

Interface是一组接口,用于对信号进行一个封装,捆扎起来。如果像 verilog中对各个信号进行连接,每一层我们都需要对接口信号进行定义,若信号过多,很容易出现人为错误,而且后期的可重用性不高。因此使用interface接口进行连接,不仅可以简化代码,而且提高可重用性,除此之外,interface内部提供了其他一些功能,用于测试平台与DUT之间的同步和避免竞争。

Clocking block:在interface内部我们可以定义clocking块,可以使得信号保持同步,对于接口的采样和驱动有详细的设置操作,从而避免TB与 DUT的接口竞争,减少我们由于信号竞争导致的错误。采样提前,驱动落后,保证信号不会出现竞争。

Q9. 动态数组和联合数组的区别?

动态数组:其内存空间在运行时才能够确定,使用前需要用new[]进行空间分配。

关联数组:其主要针对需要超大空间但又不是全部需要所有数据的时候使用,类似于hash,通过一个索引值和一个数据组成: bit [63:0] name[bit[63:0]];索引值必须是唯一的。

【关联数组】可以用来保存稀疏矩阵的元素。当你对一个非常大的地址空间寻址时,该数组只为实际写入的元素分配空间,这种实现方法所需要的空间要小得多。

此外,关联数组有其它灵活的应用,在其它软件语言也有类似的数据存储结构,被称为哈希(Hash)或者词典(Dictionary),可以灵活赋予键值(key)和数值(value) 。

Q10. UVM从哪里启动,接口怎么传递到环境中

UVM的启动 总结:

在导入uvm_pkg文件时,会自动创建UVM_root所例化的对象UVM_top,UVM顶层的类会提供run_test()方法充当UVM世界的核心角色,通过UVM_top调用run_test()方法.

在环境中输入run_test来启动UVM验证平台,run_test语句会创建一个my_case0的实例,得到正确的test_name

依次执行uvm_test容器中的各个component组件中的phase机制,按照顺序:

build-phase(自顶向下构建UVM 树)

connet_phase(自低向上连接各个组件)

end_of_elaboration_phase

start_of_simulation_phase

run_phase() objection机制仿真挂起,通过start启动sequence(每个sequence都有一个body任务。当一个sequence启动后,会自动执行sequence的body任务),等到sequence发送完毕则关闭objection,结束run_phase()(UVM_objection提供component和sequence共享的计数器,当所有参与到objection机制中的组件都落下objection时,计数器counter才会清零,才满足run_phase()退出的条件)

执行后面的phase

Q11. 接口怎么传递到验证环境中(uvm_config_db)

传递virtual interface到环境中;

配置单一变量值,例如int、string、enum等;

传递配置对象(config_object)到环境;

传递virtual interface到环境中;

a) 虽然SV可以通过层次化的interface的索引完成传递,但是这种传递方式不利于软件环境的封装和复用。通过使用uvm_config_db配置机制来传递接口,可以将接口的传递与获取彻底分离开。

b) 接口传递从硬件世界到UVM环境可以通过uvm_config_db来实现,在实现过程中应当注意:

c) 接口传递应发生在run_test()之前。这保证了在进入build_phase之前,virtual interface已经被传递到uvm_config_db中。

d) 用户应当把interface与virtual interface区分开来,在传递过程中的类型应当为virtual interface,即实际接口的句柄。

配置单一变量值,例如int、string、enum等;在各个test中,可以在build_phase阶段对底层组件的各个变量加以配置,进而在环境例化之前完成配置,使得环境可以按照预期运行。

传递配置对象(config_object)到环境;

在test配置中,需要配置的参数不只是数量多,可能还分属于不同的组件。对这么多层次的变量做出类似上边的单一变量传递,需要更多的代码,容易出错且不易复用。

如果整合各个组件中的变量,将其放置在一个uvm_object中,再对中心化的配置对象进行传递,将有利于整体环境的修改维护,提升代码的复用性。

Q12.  UVM的优势,为什么要用UVM

UVM其实就是SV的一个封装,将我们在搭建测试平台过程中的一些重复性和重要的工作进行封装,从而使我们能够快速的搭建一个需要的测试平台,并且可重用性还高。但是UVM又不仅仅是封装。

Q13. 说一下ref类型,你用到过嘛

Ref参数类型是引用

向子程序传递数组时应尽量使用ref获取最佳性能,如果不希望子程序改变数组的值,可以使用const ref类型

在任务里可以修改变量而且修改结果对调用它的函数随时可见。

Q14.说一下component和object的区别,item是component还是object

UVM中component也是由object派生出来的,不过相比于object, component有很多其没有的属性,例如phase机制和树形结构等。在UVM中,不仅仅需要component这种较为复杂的类,进行TB的层次化搭建,也需要object这种基础类进行TB的事务搭建和一些环境配置等。Item是object

Q15. UVM的树形结构 9ebcbf01b2967afb83705f8b116706df.png Q16. UVM验证环境的组成

Sequencer:负责将数据转给driver

driver负责数据的发送;driver有时钟/时序的概念。

Agent:其实只是简单的把driver ,monitor和sequencer封装在一起。

Agent:对应的是物理接口协议,不同的接口协议对应不同的agent ,一个平台通常会有多个 agent 。

Env:则相当于是一个特大的容器,将所有成员包含进去。

Q17.  Virtual sequencer 和sequencer的区别

Virtual sequencer主要用于对不同的agent进行协调时,需要有一定顶层的sequencer对内部各个agent中的sequencer进行协调

virtual sequencer是面向多个sequencer的多个sequence群,而sequencer是面向一个sequencer 的sequence群。

Virtual sequencer桥接着所有底层的sequencer的句柄,其本身也不需要传递item,不需要和driver连接。只需要将其内部的底层sequencer句柄和sequencer 实体对象连接。

Q18.平台往里边输入数据的话怎么输入sequence, sequence,sequencer,driver之间的通信 793bb40bd11f50177f03ccac49a242bf.png 71034e902bf24a0351b8a340cd41f527.png

8447c8109a075c9073bb3839f8908f5f.png在多个sequence同时向sequencer发送item时,需要有ID信息表明该item从哪个sequence来,ID信息在sequence创建item时就赋值了。

Q19. 代码覆盖率、功能覆盖率和断言覆盖率的区别

代码覆盖率——是针对RTL设计代码的运行完备度的体现,包括行覆盖率、条件覆盖率、FSM覆盖率、跳转覆盖率、分支覆盖率,只要仿真就可以收集,可以看DUT的哪部分代码没有动,如果有一部分代码一直没动看一下是不是case没有写到。

功能覆盖率---与spec比较来发现,design是否行为正确,需要按verification plan来比较进度。用来衡量哪些设计特征已经被测试程序测试过的一个指标

首要的选择是使用更多的种子来运行现有的测试程序;

其次是建立新的约束,只有在确实需要的时候才会求助于定向测试,改进功能覆盖率最简单的方法是仅仅增加仿真时间或者尝试新的随机种子。

验证的目的就是确保设计在实际环境中的行为正确。设计规范里详细说明了设备应该如何运行,而验证计划里则列出了相应的功能应该如何激励、验证和测量

断言覆盖率:用于检查几个信号之间的关系,常用在查找错误,主要是检查时序上的错误,测量断言被触发的频繁程度。

Q20. 为什么选验证?

这个问题很重要,建议好好准备,面试的时候经常会问~

Q21. IC设计流程也即ASIC设计流程

芯片架构-RTL设计-功能仿真-综合&扫描链的插入(DFT)-等价性检查-形式验证-静态时序分析(STA)-布局规划-布局布线-布线图和原理图比较-设计规则检查-GDII

Q22. Find 队列和find index队列

find的队列应该是返回队列的值,一般的话是和with配合使用,find index应该是返回索引值

Q23. 用过断言嘛?写一个断言,a为高的时候,b为高,还有a为高的时候,下一个周期b为高 ebc50740480e873bacdff092131b07cf.png Q24. 立即断言和并行断言 5c444b5513f33d0edd74b0161dd16bd2.png Q25. 形式验证

形式验证指从数学上完备地证明或验证电路的实现方案是否确实实现了电路设计所描述的功能。形式验证方法分为等价性验证、模型检验和定理证明等。

形式验证主要验证数字IC设计流程中的各个阶段的代码功能是否一致,包括综合前RTL代码和综合后网表的验证,因为如今IC设计的规模越来越大,如果对门级网表进行动态仿真,会花费较长的时间,而形式验证只用几个小时即可完成一个大型的验证。另外,因为版图后做了时钟树综合,时钟树的插入意味着进入布图工具的原来的网表已经被修改了,所以有必要验证与原来的网表是逻辑等价的

Q26. 如何保证验证的完备性?

首先不可能百分百完全完备,即遍历所有信号的组合,这既不经济也不现实。

所以只能通过多种验证方法一起验证尽可能减少潜在风险,一般有这些验证流程:ip级验证、子系统级验证、soc级验证,除这些以外,还有upf验证、fpga原型验证等多种手段。

前端每走完一个阶段都需要跟设计以及系统一起review验证功能点,测试用例,以及特殊情况下的波形等。

芯片后端也会做一些检查,像sta、formality、DFM、DRC检查等,也会插入一些DFT逻辑供流片回来测试用。流片归来进行测试,有些bug可以软件规避,有些不能规避,只能重新投片

Q27. 启动Sequence的方法

严格意义上有2种:

通过sequence.start的方式显示启动

通过default sequence来隐式启动也可以通过‘uvm_do系列宏启动

Q28. 面向对象编程的优势

易维护:采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。

质量高:在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。

效率高:在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。

易扩展:由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。

Q29. 事件的触发

用来触发事件时,使用->;用来等待事件使用@或者wait。

Q30. 约束的几种形式

权重约束 dist:有两种操作符::=n :/n 第一种表示每一个取值权重都是n,第二种表示每一个取值权重为n/num。

条件约束 if else 和->(case):if else 就是和正常使用一样;->通过前面条件满足后可以触发后面事件的发生。

范围约束inside:inside{[min:max]};范围操作符,也可以直接使用大于小于符号进行,但是不可以连续使用,如 min



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3