• 搜索

  • 移动端

    APP下载
  • 学习中心

IC验证常见面试问题汇总
2023-04-20 15:56:38997浏览
精选10道高频数字验证面试题

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

公司总部

电话:199 2141 1380
地址:上海市浦东区碧波路690号张江微电子港7号楼

合肥分公司

电话:199 2141 1380
地址:安徽省合肥市高新区创新大道2800号创新产业园二期E1栋

分销合作商

西安宸极教育咨询有限公司

电话:177 9121 8629
地址:陕西省西安市碑林区文艺路街道友谊东路81号天伦盛世

产品链接

移知官网:www.eeeknow.com
教育培训:edu.eeeknow.com
求职招聘:job.eeeknow.com

友情链接

Arm
  • 在线客服
  • 就业老师