数字IC验证面试(常问题88道)

数字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)或者igger)进⾏等待,->进⾏触发。
Semaphore旗语:主要是⽤于对资源访问的⼀个交互,通过key的获取和返回实现⼀个线程对资源的⼀个访问。使⽤put和 get函数获取返回key。⼀次可以多个。
Q4. Task和function的区别
function函数能调⽤另⼀个函数,但不能调⽤任务,task任务能调⽤另⼀个任务,也能调⽤另⼀个函数
函数总是在仿真时刻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到环境中;
虽然SV可以通过层次化的interface的索引完成传递,但是这种传递⽅式不利于软件环境的封装和复⽤。通过使⽤uvm_config_db配置机制来传递接⼝,可以将接⼝的传递与获取彻底分离开。
接⼝传递从硬件世界到UVM环境可以通过uvm_config_db来实现,在实现过程中应当注意:
接⼝传递应发⽣在run_test()之前。这保证了在进⼊build_phase之前,virtual interface已经被传递到uvm_config_db中。
⽤户应当把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的树形结构
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之间的通信
⽆论是sequence还是driver,它们通话的对象都是sequencer。当多个sequence试图要挂载到同⼀个sequencer上时,涉及
sequencer的仲裁功能。
重点分析sequencer作为sequence与driver之间握⼿的桥梁,是如何扮演好这⼀⾓⾊的。
我们将抽取去这三个类的主要⽅法,利⽤时间箭头演⽰出完整的TLM通信过程。
对于sequence⽽⾔,⽆论是flat sequence还是hierarchical sequence,进⼀步切分的话,流向sequencer的 都是sequence item,所以就每个item的"成长周期”来看,它起始于reate_item(),继⽽通过start item()尝试从sequencer获取可以通过的权限。
对于sequencer的仲裁机制和使⽤⽅法我们暂且略过,⽽driver⼀侧将⼀直处于"吃不饱”的状态,如果它没有了item可以使⽤,将调⽤get_next_item()来尝试从sequencer⼀侧获取item。
在sequencer将通过权限交给某⼀个底层的sequence前,⽬标sequence中的item应该完成随机化,继⽽在获取sequencer的通过权限后,执⾏finish_ item()。
接下来sequence中的item将穿过sequencer到达driver⼀侧, 这个重要节点标志着sequencer第⼀次充 当通信桥梁的⾓⾊已经完成。
driver在得到新的item之后,会提取有效的数据信息,将其驱动到与DUT连接的接⼝上⾯。
在完成驱动后,driver应当通过item_done()来告知sequence已经完成数据传送,⽽sequence在 获取该消息后,则表⽰driver与sequence双⽅完成了这⼀次item的握⼿传输。
金属弹片
在这次传递中,driver可以选择将RSP作为状态返回值传递给sequence,⽽sequence也可以选择调⽤get_response(RSP)等待从driver⼀侧获取返回的数据对象。
在多个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。具体详细的设计流程(含各流程EDA⼯具)可参考以下链接:
Q22. Find 队列和find index队列
find的队列应该是返回队列的值,⼀般的话是和with配合使⽤,find index应该是返回索引值
Q23. ⽤过断⾔嘛?写⼀个断⾔,a为⾼的时候,b为⾼,还有a为⾼的时候,下⼀个周期b为⾼
1  1. a_ high_ then_ b high:assert property();
2  2. property a high then b_ high;  //a和b同时为⾼
3  3. @(posedge clk)
4  4.    a|->b;
5  5. endproperty
6  6. property a high_ then b_ high;
77. @(posedge clk)                //a为⾼,下⼀个周期b为⾼
88.    a|=>b;
99. endproperty
Q24. ⽴即断⾔和并⾏断⾔
可以将断⾔分为两种常见的类型:
⽴即断⾔(immediate assertion) .
⾮时序的。
执⾏时如同过程语句。
可以Einitia/alwaysi过程块或者task/function中使⽤。
并⾏断⾔( concurrent assertion)双面胶贴
时序性的。
关键词property⽤来区分⽴即断⾔和并⾏断⾔。
之所以称之为并⾏,是因为它们与设计模块⼀同并⾏执⾏。
Q25. 形式验证
形式验证指从数学上完备地证明或验证电路的实现⽅案是否确实实现了电路设计所描述的功能。形式验证⽅法分为等价性验证、模型检验和定理证明等。
形式验证主要验证数字IC设计流程中的各个阶段的代码功能是否⼀致,包括综合前RTL代码和综合后⽹表的验证,因为如今IC设计的规模越来越⼤,如果对门级⽹表进⾏动态仿真,会花费较长的时间,⽽形式验证只⽤⼏个⼩时即可完成⼀个⼤型的验证。另外,因为版图后做了时钟树综合,时钟树的插⼊意味着进⼊布图⼯具的原来的⽹表已经被修改了,所以有必要验证与原来的⽹表是逻辑等价的
Q26. 如何保证验证的完备性?

本文发布于:2024-09-25 12:26:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/338516.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数组   验证   需要   传递   数据   信号   覆盖率   函数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议