IC验证面试常问88道

IC验证面试常问题88道
Q1.定宽数组、动态数组、关联数组、队列各自特点和使用
队列:队列结合了链表和数组的优点,可以在一个队列的任何位置进行增加或者删除元素;
定宽数组:属于静态数组,编译时便已经确定大小。其可以分为压缩定宽数组和非压缩定宽数组:压缩数组是定义在类型后面,名字前面;非压缩数组定义在名字后面。Bit [7:0][3:0] name; bit[7:0] name [3:0];
动态数组:其内存空间在运行时才能够确定,使用前需要用new[]进行空间分配。
关联数组:其主要针对需要超大空间但又不是全部需要所有数据的时候使用,类似于,通过一个索引值和一个数据组成,索引值必须是唯一的。
Q2.多线程fork join/fork join_any/fork join_none的用法差异
:内部 块并行运行,直到所有线程运行完毕才会进入下一个阶段。
:内部 块并行运行,任意一个块运行结束就可以进入下一个阶段。
:内部 块并行运行,无需等待可以直接进入下一个阶段。
:会引起调用进程阻塞,直到它的所有子进程结束,一般用来确保所有子进程(调用进程产生的进程,也即一级子进程)执行都已经结束。
:用来终止调用进程 的所有活跃进程, 以及进程的所有子进程。
Q3. 多线程的同步调度方法
多线程之间同步主要由三种进行一个通信交互。
:主要用于两个线程之间的数据通信,通过put函数和 get 函数还有peek函数进行数据的发送和获取。
:事件主要用于两个线程之间的一个同步运行,通过事件触发和事件等待进行两个线程间的运行同步。使用@(event)或者 wait(event.trigger)进行等待,->进行触发。
:旗语主要是用于对资源访问的一个交互,通过key的获取和返回实现一个线程对资源的一个访问。使用put和 get函数获取返回key。一次可以多个。
Q4. Task和function的区别
函数能调用另一个函数,但不能调用任务,任务能调用另一个任务,也能调用另一个函数
函数总是在仿真时刻0就开始执行,任务可以在非零时刻执行
函数一定不能包含任何延迟、事件或者时序控制声明语句,任务可以包含延迟、事件或者时序控制声明语句
函数至少有一个输入变量,可以有多个输入变量,任务可以没有或者多个输入(input)、输出(output)和双向(inout)变量
函数只能返回一个值,函数不能有输出(output)或者双向(inout)变量,任务不返回任何值,任务可以通过输出(output)或者双向(inout)变量传递多个值
Q5.简述在TB中使用interface和clocking blocking的好处
是一组接口,用于对信号进行一个封装,捆扎起来。如果像中对各个信号进行连接,每一层我们都需要对接口信号进行定义,若信号过多,很容易出现人为错误,而且后期的可重用性不高。因此使用接口进行连接,不仅可以简化代码,而且提高可重用性,除此之外,内部提供了其他一些功能,用于测试平台与DUT之间的同步和避免竞争。
:在内部我们可以定义块,可以使得信号保持同步,对于接口的采样vrbg和驱动有详细的设置操作,从而避免与 的接口竞争,减少我们由于信号竞争导致的错误。采样提前,驱动落后,保证信号不会出现竞争。
Q6. OPP(面向对象)的特性?
封装、继承和多态
封装:通过将一些数据和使用这些数据的方法封装在一个集合里,成为一个类。
继承:允许通过现有类去得到一个新的类,且其可以共享现有类的属性和方法。现有类叫做基类,新类叫做派生类或扩展类
多态:得到扩展类后,有时我们会使用基类句柄去调用扩展类对象,这时候调用的方法如何准确去判断是想要调用的方法呢?通过对类中方法进行声明,这样当调用基类句柄指向扩展类时,方法会根据对象去识别,调用扩展类的方法,而不是基类中的。而基类和扩展类中方法有着同样的名字,但能够准确调用,叫做多态。
Q7. 简述UVM的工厂机制
机制也叫工厂机制,其存在的意义就是为了能够方便的替换TB中的实例或者已注册的类型。一般而言,在搭建完TB后,我们如果需要对TB进行更改配置或者相关的类信息,我们可以通过使用机制进行覆盖,达到替换的效果,从而大大提高TB的可重用性和灵活性。
要使用factory机制先要进行:
将类注册到factory表中
创建对象,使用对应的语句 (type_id::create)
编写相应的类对基类进行覆盖。
Q8. SV中的interface的clock blocking的功能
是一组接口,用于对信号进行一个封装,捆扎起来。如果像 中对各个信号进行连接,每一层我们都需要对接口信号进行定义,若信号过多,很容易出现人为错误,而且后期的可重用性不高。因此使用接口进行连接,不仅可以简化代码,而且提高可重用性,除此之外,内部提供了其他一些功能,用于测试平台与之间的同步和避免竞争。
:在内部我们可以定义块,可以使得信号保持同步,对于接口的采样和驱动有详细的设置操作,从而避免与 的接口竞争,减少我们由于信号竞争导致的错误。采样提前,驱动落后,保证信号不会出现竞争。
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
其实就是的一个封装,将我们在搭建测试平台过程中的一些重复性和重要的工作进行封装,从而使我们能够快速的搭建一个需要的测试平台,并且可重用性还高。但是又不仅仅是封装。
Q13. 说一下ref类型,你用到过嘛
Ref参数类型是引用
向子程序传递数组时应尽量使用获取最佳性能,如果不希望子程序改变数组的值,可以使用类型
在任务里可以修改变量而且修改结果对调用它的函数随时可见。
Q14.说一下component和object的区别,item是component还是object
UVM中也是由派生出来的,不过相比于, 有很多其没有的属性,例如机制和树形结构等。在中,不仅仅需要这种较为复杂的类,进行的层次化搭建,也需要这种基础类进行TB的事务搭建和一些环境配置等。Item是object
Q15. UVM的树形结构
Q16. UVM验证环境的组成
:负责将数据转给
负责数据的发送;有时钟/时序的概念。
:其实只是简单的把 ,和封装在一起。
:对应的是物理接口协议,不同的接口协议对应不同的 ,一个平台通常会有多个 。
:则相当于是一个特大的容器,将所有成员包含进去。
Q17. Virtual sequencer 和sequencer的区别
主要用于对不同的进行协调时,需要有一定顶层的对内部各个中的进行协调
是面向多个的多个群,而是面向一个 的群。
桥接着所有底层的的句柄,其本身也不需要传递,不需要和连接。只需要将其内部的底层句柄和 实体对象连接。
Q18.平台往里边输入数据的话怎么输入sequence, sequence,sequencer,driver之间的通信
在多个同时向发送时,需要有ID信息表明该从哪个来,ID信息在创建时就赋值了。
Q19. 代码覆盖率、功能覆盖率和断言覆盖率的区别
代码覆盖率——是针对RTL设计代码的运行完备度的体现,包括行覆盖率、条件覆盖率、FSM覆盖率、跳转覆盖率、分支覆盖率,只要仿真就可以收集,可以看DUT的哪部分代码没有动,如果有一部分代码一直没动看一下是不是case没有写到。
功能覆盖率---与比较来发现,是否行为正确,需要按来比较进度。用来衡量哪些设计特征已经被测试程序测试过的一个指标
首要的选择是使用更多的种子来运行现有的测试程序;
其次是建立新的约束,只有在确实需要的时候才会求助于定向测试,改进功能覆盖率最简单的方法是仅仅增加仿真时间或者尝试新的随机种子。
验证的目的就是确保设计在实际环境中的行为正确。设计规范里详细说明了设备应该如何运行,而验证计划里则列出了相应的功能应该如何激励、验证和测量
断言覆盖率:用于检查几个信号之间的关系,常用在查找错误,主要是检查时序上的错误,测量断言被触发的频繁程度。
Q20. 为什么选验证?
这个问题很重要,建议好好准备,面试的时候经常会问~
Q21. IC设计流程也即ASIC设计流程
芯片架构-RTL设计-功能仿真-综合&扫描链的插入(DFT)-等价性检查-形式验证-静态时序分析(STA)-布局规划-布局布线-布线图和原理图比较-设计规则检查-GDII
Q22. Find 队列和find index队列
find的队列应该是返回队列的值,一般的话是和with配合使用,find index应该是返回索引值
Q23. 用过断言嘛?写一个断言,a为高的时候,b为高,还有a为高的时候,下一个周期b为高
Q24. 立即断言和并行断言
Q25. 形式验证
形式验证指从数学上完备地证明或验证电路的实现方案是否确实实现了电路设计所描述的功能。形式验证方法分为等价性验证、模型检验和定理证明等。
形式验证主要验证数字IC设计流程中的各个阶段的代码功能是否一致,包括综合前RTL代码和综合后网表的验证,因为如今IC设计的规模越来越大,如果对门级网表进行动态仿真,会花费较长的时间,而形式验证只用几个小时即可完成一个大型的验证。另外,因为版图后做了时钟树综合,时钟树的插入意味着进入布图工具的原来的网表已经被修改了,所以有必要验证与原来的网表是逻辑等价的
Q26. 如何保证验证的完备性?
首先不可能百分百完全完备,即遍历所有信号的组合,这既不经济也不现实。
所以只能通过多种验证方法一起验证尽可能减少潜在风险,一般有这些验证流程:ip级验证、子系统级验证、soc级验证,除这些以外,还有upf验证、fpga原型验证等多种手段。
前端每走完一个阶段都需要跟设计以及系统一起验证功能点,测试用例,以及特殊情况下的波形等。
芯片后端也会做一些检查,像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
Q31. 哪些继承于component,哪些继承于object
除了driver、monitor、agent、model、scoreboard、env、test之外全部用uvm_object。
Q32. get_next_item()和try_next_item()有什么区别
是一个阻塞调用,直到存在可供驱动的为止,并返回指向的指针。
是非阻塞调用,如果没有可供驱动的,则返回空指针。
Q33. 断言 and 和 和 intersect 区别
指的是两个序列具有相同的起始点,终点可以不同。
指的是两个序列具有相同的起始点和终点。
指的是两个序列只要满足一个就可以
指的是满足前面要求才能执行后面的序列
Q34. Break;continue;return的含义,return之后,function里剩下的语句会执行吗
语句结束整个循环。
立即结束本次循环,继续执行下一次循环。
语句会终止函数的执行并返回函数的值(如果有返回值的话)。
之后,里剩下的语句不能执行,其是终止函数的执行,并返回函数的值。
Q35. 触发器和锁存器的区别
触发器:时钟触发,受时钟控制,只有在时钟触发时才采样当前的输入,产生输出。
锁存器由电平触发,非同步控制。在使能信号有效时锁存器相当于通路,在使能信号无效时锁存器保持输出状态。触发器由时钟沿触发,同步控制。
锁存器对输入电平敏感,受布线延迟影响较大,很难保证输出没有毛刺产生;触发器则不易产生毛刺
Q36. 一个简单的UVM验证平台
Q37. 怎么编写测试用例?
主要是编写,然后在里面根据测试功能要求写相应的激励,然后再通过和判断功能是否实现?
Q38. 如果有很多测试用例,如何让它们自动执行?
可以写脚本让它们自动执行,例如makefile...
Q39.断言$past的用法
例如让你写abcd四个信号在时钟沿处监测,当cd同时为1时,在时钟的前两个周期要ab同时为1的断言
图片
Q40. 如何关闭约束
通过关闭默认范围的约束块
是打开约束
可以用关键字修饰特定的约束语句,这样既可以让变量在一般的情况下取默认值,也可以直接给变量赋默认值范围外的取值。
Q41. 队列的使用方法,以及push back和pop front的区别
队列的使用方法:插入,取出前边,后边
Q42. Rand 和randc的区别
修饰符:修饰的变量,每次随机时,都在取值范围内随机取一个值,每个值被随机到的概率是一样的,就想掷骰子一样。
修饰符:表示周期性随机,即所有可能的值都取到过后,才会重复取值
Q43. 组件之间的通信机制,analysis port和其它的区别
通信分为,单向通信,双向通信和多向通信
单向通信:指的是从到之间的数据流向是单一方向的
双向通信:双向通信的两端也分为和,但是数据流向在端对端之间是双向的
多向通信:仍然是两个组件之间的通信,是指与之间的相同TLM端口数目超过一个时的处理解决办法。
blocking阻塞传输的方法包含:
Put():先生成数据,同时将该数据传送至。
Get():从获取数据,而中的该数据则应消耗。
Peek(): 从获取数据,而中的该数据还应保留。
通信管道:
:可以进行数据缓存,功能类似于,不同的地方在于提供了各种端口供用户使用
:一端对多端,用于多个组件同时对一个数据进行处理,如果这个数据是从同一个源的端口发出到达不同组件,则要求该端口能够满足一端到多端,如果数据源端发生变化需要通知跟它关联的多个组件时,我们可以利用软件的设计模式之一观察者模式实现,即广播模式
a. 由于端口提出实现了一端到多端的数据传输,而一个新的数据缓存组件类为用户们提供了可以搭配端口端口和函数。
b.类继承于,这表明它本身具有面向单一端口的数据缓存特性,而同时该类又有一个端口并且实现了函数:
request & response通信管道双向通信端口,即通过在端实现方法可以在一次传输中既发送又可以接收。
Q44. 简述深拷贝和浅拷贝
浅拷贝可以使用列表自带的函数(如),或者使用模块的函数。深拷贝只能使用模块的,所以使用前要导入:
如果拷贝的对象里的元素只有值,没有引用,那浅拷贝和深拷贝没有差别,都会将原有对象复制一份,产生一个新对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。
如果拷贝的对象里的元素包含引用(像一个列表里储存着另一个列表,存的就是另一个列表的引用),那浅拷贝和深拷贝是不同的,浅拷贝虽然将原有对象复制一份,但是依然保存的是引用,所以对新对象里的引用里的值进行修改,依然会改变原对象里的列表的值,新对象和原对象完全分离开并没有完全分离开。而深拷贝则不同,它会将原对象里的引用也新创建一个,即新建一个列表,然后放的是新列表的引用,这样就可以将新对象和原对象完全分离开。
Q45. 类的public、protected和local的区别
如果没有指明访问类型,那么成员的默认类型是public,子类和外部均可以访问成员。
如果指明了访问类型是,那么只有该类或者子类可以访问成员,而外部无法访问。
如果指明了访问类型是,那么只有该类可以访问成员,子类和外部均无法访问。
Q46. 对UVM验证方法学的理解
刚开始接触的时候,我认为其实就是的一个封装,将我们在搭建测试平台过程中的一些重复性和重要的工作进行封装,从而使我们能够快速的搭建一个需要的测试平台,并且可重用性还高。因此我当时觉得它就是一个库。
不过,随着学习的不断深入,当我深入理解中各种机制和模型的构造和相互之间关系之后,我觉得其实方法学对于使用何种语言其实并不重要,重要的是他的思想,比如:在中有机制,以往如果我们使用进行搭建时,我们一般会采用一个类进行数据的产生,转换,发送,或者使用和两个进行,这种方式可重用性很低,而且代码臃肿;但是在UVM中我们通过将拆开,相互独立而又有联系,因此我们只需关注每一个类需要做的工作就可以,可重用性高。我在学习时,我经常把 比作蓄水池,就是水,就是一个调度站,就是总工厂,通过这种方式进行处理,我们的总工厂不需要管其他,只需处理运送过来的水资源就可以,而只需要调度水资源,只需要产生不同的水资源。而这种处理方式和现实世界中的生产模式又是基本吻合的。除此之外,还有好多好多,其实方法学中很多思想就是来源于经验,来源于现实生活,而不在乎是何种语言。
Q47.请谈一下UVM的验证环境结构,各个组件间的关系
画出的验证环境结构,如图所示
图片
首先,测试平台基本是由和 组成的,其中 搭建了的一个树形结构,其基本包含了;然后一般包含和一些其他需要的类。各个组件相互独立,又通过事务级传输进行通信,除此之外, 与和 又通过进行连接,实现驱动和采集,最后在层进行例化调用进行测试。
Q48.举例说明UVM组件中常用的方法,各种phase关系,phase机制作用
中有很多非常有趣的机制,例如机制,机制,机制,打印机制,机制,机制等,这些机制使得我们搭建的能够有很好的可重用性和使得我们平台运行有秩序稳定。
例如机制,机制主要是使得的运行仿真层次化,使得各种例化先后次序正确。的机制主要有9个,外加12个小。主要的 有等,其中除了是,其余都是,然后和都是自顶向下运行,其余都是自底向上运行。和12个小( )是并行运行的,有这12个小主要是进一步将 中的事务划分到不同的进行,简化代码。注意,和 12个小最好不要同时使用。从运行上来看,9个顺序执行,不同组件中的同一个执行有顺序,为自顶向下,只有同一个全部执行完毕才会执行下一个。
所有的按照以下顺序自上而下自动执行:(九大phase,其中run phase又分为12个小phase)build_pase
connect_phase
end_of_elaboration_phase
start_of_simulation_phase
run_pase
extract_phase
check_phase
report_phase
final_phase
其中,run_phase按照以下顺序自上而下执行:
pre_reset_phase
reset_phase
post_reset_phase
pre_configure_phase
configure_phase
post_configure_phase
pre_main_phase
main_phase
post_main_phase
pre_shutdown_phase
shutdown_phase
post_shutdown_phase
Q49.phase中的domain概念
是用来组织不同组件,实现独立运行的概率。默认情况下,的9个属于 ,12个小属于。例如,如果我们有两个类,默认情况下,两个类中的复位和 必须同时执行,但是我们可以设置两个属于不同的,这样两个就是独立运行的了,相当于处于不同的时钟域(只针对12个小有效)。
Q50.run_phase和main_phase之间的关系;
和(动态运行)都是,且是并行运行的,后者称为动态运行()的。
如果想执行一些耗费时间的代码,那么要在此下任意一个中至少提起一次,这个结论只适用于12个的。对于则不适用,由于与动态运行的是并行运行的,如果12个动态运行的有被提起,那么根本不需要就可以自动执行。
Q51. main_phase要如何跳转到reset_phase;
在执行过程中,突然遇到信号被置起,可以用实现从到的跳转:
Q52.UVM组件的通信方式TLM的接口分类和用法,peek和get的差异
中采用事务级传输机制进行组件间的通信,可以大大提高仿真的速度和使得我们简化组件间的数据传输,简化工作,独立于组件之外,降低组件间的依赖关系。 接口主要由;驱动这些接口方式有 等。
其中是查看端口内部的数据事务但是不删除,是获取后立即删除。我们一般会先使用进行获取数据,但不删除(保证端不会立马又发送一个数据),处理完毕后再用删除。
lmp只能作为终点接口,transport表示双向通信,analysis可以连接多个imp(类似于广播)。
Q53.Analysis port是否可以不连或者连多个impport
都可以。类似于广播,其可以同时对多个进行事务通信,只需要在每一个对应的端口申明函数即可。对比 他们都只能进行一对一传输,且也必须申明对应的函数如 等。是可以不用申明操作函数的,其内部封装了很多的通信端口,如等,我们只需要将端口与其连接即可实现通信。
Q54.Sequence和item(uvm_sequece,uvm_sequence_item)以及sequence的分类
是基于类,这表明了它具备核心基类所必要的数据操作方法,例如等。
对象的生命应该开始于的方法,而后经历了随机化并穿越最终到达,直到被消化之后,它的生命一般来讲才会结束。
item与sequence的关系一个可以包含一些有序组织起来的实例,考虑到在创建后需要被随机化,在声明时也需要预留一些可供外部随机化的变量,这些随机变量一部分是用来通过层级传递约束来最终控制对象的随机变量,一部分是用来对对象之间加以组织和时序控制的。
Sequence的分类:
扁平类:这一类往往只用来组织更细小的粒度,即item实例构成的组织。
层次类:这一类是由更高层的sequence用来组织底层的,进而让这些或者按照顺序方式,或者按照并行方式,挂载到同一个上。
虚拟类:这一类则是最终控制整个测试场景的方式,鉴于整个环境中往往存在不同种类的和其对应的,我们需要一个虚拟的来协调顶层的测试场景。之所以称这个方式为,是因为该序列本身并不会固定挂载于某一种类型上,而是将其内部不同类型最终挂载到不同的目标上面。这也是不同于的最大一点。
Q55.Sequence和sequencer的关系
机制用于产生激励,它是中最重要的机制之一。机制有两大组成部分:和。
在整个验证平台中处于一个比较特殊的位置。不属于验证平台的任何一部分,但是它与之间有着密切的关系。
只有在的帮助下,产生的才能最终送给;同样,只有在出现的情况下才能体现出其价值,如果没有,几乎没有任何作用。
除此之外,与还有显著的区别。从本质上说,是一个,而是一个。与一样,也有其生命周期。它的生命周期比要更长一点,其内部的全部发送完毕后,它的生命周期也就结束了。
Q56.Sequencer的仲裁特性(set_arbitration)及锁定机制(lock和grab)
图片
图片
Q57.Virtual sequence和virtual sequencer中virtual含义
含义就是其 并不需要传递,也不会与连接,其只是一个去协调各个的中央路由器。通过我们可以实现多个的多个他们的 的调度和可重用。可以组织不同 的群落。
Q58.为什么会有sequence、sequencer以及driver,为什么要分开实现,这样做的好处是什么?
在中有机制,以往如果我们使用进行搭建时,我们一般会采用 一个类进行数据的参数,转换,发送,或者使用和两个进行,这种方式可重用性很低,而且代码臃肿;
但是在UVM中我们通过将拆开,相互独立而又有联系,因此我们只需关注每一个类需要做的工作就可以,可重用性高。我在学习时,我经常把 比作蓄水池,就是水,就是一个调度站,就是总工厂,通过这种方式进行处理,我们的总工厂不需要管其他,只需处理运送过来的水资源就可以,而只需要调度水资源,只需要产生不同的水资源。
Q59.如何在driver中使用interface,为什么
如果不进行声明的话是不能直接使用在中的,会报错,因为声明的是一个实际的物理接口。一般在中使用进行申明接口,然后通过进行接口参数传递,这样我们可以从上层组件获得虚拟的接口进行处理。
传递时只能传递接口,即的句柄,否则传递的是一个实际的物理接口,这在 中是不能实现的,且这样的话不同组件中的接口一一对应一个物理接口,那么操作就没有意义了。
Q60.你了解uvm的factory机制和callback机制嘛
机制也叫工厂机制,其存在的意义就是为了能够方便的替换中的实例或者已注册的类型。一般而言,在搭建完后,我们如果需要对进行更改配置或者相关的类信息,我们可以通过使用 机制进行覆盖,达到替换的效果,从而大大提高的可重用性和灵活性。要使用机制先要进行:
将类注册到表中
创建对象,使用对应的语句
编写相应的类对基类进行覆盖。
机制其作用是提高的可重用性,其还可进行特殊激励的产生等,与类似,两者可以有机结合使用。与不同之处在于 的类还是原先的类,只是内部的函数变了,而是产生一个新的扩展类进行替换。
组件中内嵌函数或者任务
定义一个常见的
从空壳类扩展类
在验证环境中创建并登记
Q61.field_automation机制和objection机制
机制:可以自动实现等三个函数。当使用系列相关宏注册之后,可以直接调用以上三个函数,而无需自己定义。这极大的简化了验证平台的搭建,尤其是简化了和,提高了效率。
中通过机制来控制验证平台的关闭,需要在之前先。验证在进入到某一时,会收集此提出的所有,并且实时监测所有是否已经被撤销了,当发现所有都已经撤销后,那么就会关闭此,开始进入下一个。当所有的都执行完毕后,就会调用来将整个验证平台关掉。如果发现此没有提起任何,那么将会直接跳转到 下一个中。
的设计哲学就是全部由来控制激励生成,因此一般情况下只在中控制。另外还需注意的是,语句必须在中第一个消耗仿真时间的语句之前。
Q62.Config_db的作用,以及传递其使用时的参数含义
机制主要作用就是传递参数使得的可配置性高,更加灵活。机制主要传递的有三种类型:
一种是虚拟接口,通过传递使得和 能够与连接,并驱动接口和采集接口信号。
第二种是单一变量参数,如等,这些主要就是为了配置某些循环次数,号是多少等等。
第三种是类,这种主要是当配置参数较多时,我们可以将其封装成一个类,去包含这些属性和相关的处理方法,这样传递起来就比较简单明朗,不易出错。
的参数主要由四个参数组成,如下所示,第一个参数为父的根,第二个参数为接下来的路径,对应的组件,第三个是传递时的名字(必须保持一致),第四个是变量名。uvm_config_db #(virtual interface) :: set(uvm_root:.get(),"uvm_test_top.c1",'vif",vif);uvm_config_db #(virtual interface) :: get(this,"”,"vif",vif);
Q63.UVM中各个component之间是如何组织运行的,串行还是并行,通过什么机制进行调度的
之间通过在函数创建时指定参数指定子关系,通过这种方法来将形成一个树形结构。中运行是通过机制进行层次化仿真的。从组件来看各个组件并行运行,从上看是串行运行,有层次化的。机制的9个是串行运行的,不同组件中的同一个都运行完毕后才能进入下一个运行,同一个在不同组件中的运行也是由一定顺序的, 和 是自顶向下。
Q64.UVM如何启动一个sequence
启动有很多的方法:常用的方法有使用进行调用,其会将对应的 与 绑定,当请求获得时,就会调用对应的去运行函数,从而产生。
除此之外,还可以使用函数进行,其参数主要就是对应的需要绑定的和该类的上层。如此,就可以实现启动的功能。
注意:一般仿真开始结束会在 中 和
Q65.你所搭建的验证平台为什么要用RAL(寄存器)
首先,我们要了解寄存器对于设计的重要性,其是模块间交互的窗口,我们可以通过读寄存器值去观察模块的运行状态,通过写寄存器去控制模块的配置和功能改变。
然后,为什么我们需要RAL呢?由于前面寄存器的重要性,我们可以知道,如果我们不能先保证我们寄存器的读写正确,那么就不用谈后续 DUT是否正确了,因此,寄存器的验证是排在首要位置的。
那么我们应该用什么方法去读写和验证寄存器呢?采用RAL寄存器模型去测试验证,是目前最成功的方法吧,寄存器模型独立于之外,我们可以搭建一个测试寄存器的,去通过前门或者后门访问去控制的寄存器,使得 按照我们的要求去运行。
除此之外,中内建了很多的,用于帮助我们去检测寄存器,除此之外,还有一些其他的类和变量去帮助我们搭建,以提高的可重用性和便捷性还有更全的覆盖率。
Q66.前门访问和后门访问的区别
前门访问和后门访问的比较
前门访问,顾名思义指的是在寄存器模型上做的读写操作,最终会通过总线UVC来实现总线上的物理时序访问,因此是真实的物理操作。
后门访问,指的是利用,将寄存器的操作直接作用到DUT内的寄存器变量,而不通过物理总线访问。
前门访问在使用时需要将设置为
在进行后门访问时,用户首先需要确保寄存器模型在建立时,是否将各个寄存器映射到了一侧的路径:使用
5. 从上面的差别可以看出,后门访问较前门访问更便捷更快一些,但如果单纯依赖后门访问也不能称之为“正道”。6. 实际上,利用寄存器模型的前门访问和后门访问混合方式,对寄存器验证的完备性更有帮助。
Q67. 后门访问的路径怎么配置
Q68. 如果寄存器的地址不匹配的错误怎么测试出来
在通过前门配置寄存器A之后,再通过后门访问来判断HDL地址映射的寄存器A变量值是否改变,最后通过前门访问来读取寄存器A的值。
Q69. 寄存器模型的常规方法(期望值、镜像值、真实值)
我们在应用寄存器模型的时候,除了利用它的寄存器信息,也会利用它来跟踪寄存器的值。寄存器有很多域每一个域都有两个值
寄存器模型中的每一个寄存器,都应该有两个值,一个是镜像值( ) , 一个是期望值() 。
期望值是先利用寄存器模型修改软件对象值,而后利用该值更新硬件值;镜像值是表示当前硬件的已知状态值。
镜像值往往由模型预测给出,即在前门访问时通过观察总线或者在后门访问时通过自动预测等方式来给出镜像值
镜像值有可能与硬件实际值不一致
Q70.Prediction的分类(自动预测和显式预测)
UVM提供了两种用来跟踪寄存器值的方式,我们将其分为自动预测()和显式预测( )。
如果用户想使用自动预测的方式,还需要调用函数
两种预测方式的显著差别在于,显式预测对寄存器数值预测更为准确,我们可以通过下面对两种模式的分析得出具体原因。自动预测
如果用户没有在环境中集成独立的,而是利用寄存器的操作来自动记录每一次寄存器的读写数值,并在后台自动调用方法的话,这种方式被称之为自动预测。
这种方式简单有效,然而需要注意,如果出现了其它一些直接在总线层面上对寄存器进行操作(跳过寄存器级别的操作,或者通过其它总线来访问寄存器等这些额外的情况,都无法自动得到寄存器的镜像值和预期值。显式预测
更为可靠的一种方式是在物理总线上通过监视器来捕捉总线事务,并将捕捉到的事务传递给外部例化的,该由参数化类例化并集成在顶层环境中。
在集成的过程中需要将与的句柄也一并传递给,同时将采集的事务通过接入到一侧。
这种集成关系可以使得,一旦捕捉到有效事务,会发送给,再由其利用的桥接方法,实现事务信息转换,并将转化后的寄存器模型有关信息更新到中。
默认情况下,系统将采用显式预测的方式,这就要求集成到环境中的总线需要具备捕捉事务的功能和对应的,以便于同连接。
Q71.寄存器怎么配置,adapter怎么集成
Q72.AMBA总线中AHB/APB/AXI协议的区别
高级高性能总线。高级外围总线高级可拓展接口
主要是针对高效率、高频宽及快速系统模块所设计的总线,它可以连接如微处理器、芯片上或芯片外的内存模块和等高效率模块。
主要用在低速且低功率的外围,可针对外围设备作功率消耗及复杂接口的最佳化。在和低带宽的外围设备之间提供了通信的桥梁,所以是的二级拓展总线。
高速度、高带宽,管道化互联,单向通道,只需要首地址,读写并行,支持乱序,支持非对齐操作,有效支持初始延迟较高的外设,连线非常多。
AHB协议
1. AHB的组成
能够发起读写操作,提供地址和控制信号,同一时间只有1个会被激活。
在给定的地址范围内对读写操作作响应,并对返回成功、失败或者等待状态。
负责保证总线上一次只有1个在工作。仲裁协议是规定的,但是仲裁算法可以根据应用决定。
负责对地址进行解码,并提供片选信号到各。每个都需要1个仲裁器和1个中央解码器。
图片
2. AHB基本信号(经常会问Htrans和Hburst,以及AHB的边界地址怎么确定)
HADDR:32位系统地址总线。
HTRANS:M指示传输状态,NONSEQ、SEQ、IDLE、BUSY。
HWRITE:传输方向1-写,0-读。
HSIZE:传输单位。
HBURST:传输的burst类型,SINGLE、INCR、WRAP4、INCR4等。
HWDATA:写数据总线,从M写到S。
HREADY:S应答M是否读写操作传输完成,1-传输完成,0-需延长传输周期。
HRESP:S应答当前传输状态,OKAY、ERROR、RETRY、SPLIT。
HRDATA:读数据总线,从S读到M。
APB协议及读写操作
1. APB的状态转移
图片
2. APB写操作
图片
图片
3. APB读操作
图片
Q73.你写过assertion嘛,assertion分几种?简述一下assertion的用法
可以分为立即断言和并发断言。
立即断言的话就是和时序无关,比如我们在对激励随机化时,我们会使用立即断言,如果随机化出错我们就会触发断言报错。
并发断言的话主要是用来检测时序关系的,由于在很多模块或者总线中,单纯使用覆盖率或者事务并不能完全检测多个时序信号之间的关系,但是并发断言却可以使用简洁的语言去监测,除此之外,还可以进行覆盖率检测。
并发断言的用法的话,主要是有三个层次:
序列编写,将多个信号的关系用断言中特定的操作符进行表示;
属性的编写,它可以将多个和多个进行嵌套,外加上触发事件;
的编写,调用就可以。编写完断言后我们可以将它用在很多地方,比如内部,或者在层嵌入 中,还可以在处进行编写,基本能够检测到信号的地方都可以进行断言检测。
Q74.a[*3]、a[->3]和a[=3]区别
a[*3]指的是:重复3次a,且其与前后其他序列不能有间隔,a中间也不可有间隔。
a[->3]指的是:重复3次,其 a中间可以有间隔,但是其后面的序列与a之间不可以有间隔。
a[=3]指的是:只要重复3次,中间可随意间隔。
Q75.项目中会考虑哪些coverage
主要会考虑三个方面吧,代码覆盖率,功能覆盖率,断言覆盖率。
代码覆盖率,主要由行覆盖率、条件覆盖率、覆盖率、跳转覆盖率、分支覆盖率,他们是否都是运行到的,比如 ,是否各个状态都运行到了,然后不同状态之间的跳转是否也都运行到了。
功能覆盖率的话主要是自己编写和去覆盖我们想要覆盖的数据和地址或者其他控制信号。
断言覆盖率主要检测我们的时序关系是否都运行到了,比如总线的地址数据读写时序关系是否都有实现。
Q76.Coverage一般不会直接达到100%,当你发现condition未cover到的时候,你该怎么做?
又称为条件覆盖率,当条件覆盖率未被覆盖时,我们需要通过查看覆盖率报告去定位哪些条件没有被覆盖到,是因为没有满足该条件的前提条件还是因为根本就遗漏了这些情况,根据这个我们去编写相应的,进而将其覆盖到。
Q77.Function coverage和 code coverage的区别,以及他们分别对项目的含义
功能覆盖率主要是针对文档中功能点的覆盖检测-覆盖率主要是针对设计代码的运行完备度的体现,其包括行覆盖率、条件覆盖率、覆盖率、跳转覆盖率、分支覆盖率(只要仿真就可以,看看的哪些代码没有动,如果有一部分代码一直没动,看一下是不是没写到)。
功能覆盖率和代码覆盖率两者缺一不可,功能覆盖率表示着代设计是否具备这些功能,代码覆盖率表示我们的测试是否完备,代码是否冗余。当功能覆盖率高而代码覆盖率低时,表示是不是写少了,写少了;或者代码冗余。当功能覆盖率很低而代码覆盖率高时,表示代码设计是不是全面,功能点遗漏;写的是不是冗余了。只有当两者覆盖率都高的时候才表明我们验证的大部分是可靠的。
代码覆盖率很难达到100%,一般情况下达到90%多已经非常不错了,如果有一部分代码没有被触动到,需要有经验的验证工程师去分析,如果确实没啥问题,就可以签字通过了
Q78.你在做验证时的流程是怎么样的,你是怎么做的。
对于流程的话
首先第一步我会先去查看文档,将模块的功能和接口总线时序搞明白,尤其是工作的时序,这对于后续写非常重要;
第二步我会根据功能点去划分我的应该怎么搭建,我的大致会有哪些,这些功能点我应该如何去覆盖,时序应该如何去检查,总结列出这样的一个清单;
第三步开始去搭建我们的,包括各种组件,和一些基础的 还有,暂时先就写一两个基础的,然后还有一些环境配置参数的确定等,最后能够将正常运行,保证无误;
第四步就是根据清单去编写和 ,然后去仿真,保证仿真正确性,收集覆盖率;
第五步就是分析收集的覆盖率,然后查看覆盖率报告去分析还有哪些没有被覆盖,去写一些定向,和更换不同的去仿真;
第六步就是回归测试,通过不同的 去跑,收集覆盖率和检测是否有其它;
第七步就是总结
79.你在进行验证的过程中,碰到过什么难点,重点是什么呢?
刚开始的难点还是TB的搭建,想要搭建出一个可重用性很高的TB,配置灵活的TB还是有一定困难,对于哪些参数应该放在配置类,哪些参数应该放在事务类的抉择,哪些单独配置。
除此之外,还有就是时序的理解,这对于和还有和 的编写至关重要,只有正确理解时序才能编写出正确的。
最后就是实现覆盖率的尽可能高,这也是比较困难的,刚开始的好写,也比较快就可以达到较高的覆盖率,但是那些边边角角的需要自己去琢磨,去分析还需要写什么。这些难点就是重点,还要能够自动化监测判断是否正确。
Q80.你发现过哪些验证过程中的 bug,如何发现的,怎么解决的?
这个问题面试的时候经常问,建议面试之前考虑一下,再做决定
Q81.你的验证环境是什么?目录结构是什么样的
我是使用验证方法学搭建的,然后在平台进行仿真的。目录结构的话:主要由文件、文件、文件、文件、文件这几部分。
Q82.UVM有什么优缺点:
UVM的优点:UVM有各个机制、促进验证平台的标准化,UVM中和验证平台是隔离独立的,可以更好的控制激励而不需要重新设计. 改变测试可以简单高效提高代码覆盖率。支持工业标准,这会促进验证平台标准化。此外,通过(面向对象编程)的特点(例如继承)以及使用覆盖组件提高了重复使用率。因此UVM环境方便移植,架构清晰,组件连接方便,有利于进行大规模的验证。
UVM的缺点:代码冗余,工作量大,运行速度有缺失
Q83.通过工厂进行覆盖有什么要求?
无论是重载的类()还是被重载的类(),都要在定义时注册到机制中。
被重载的类()在实例化时,要使用机制式的实例化方式,而不能使用传统的方式。
最重要的是,重载的类()要与被重载的类()有派生关系。重载的类必须派生自被重载的类,被重载的类必须是重载类的父类。
Q84.如果环境中有两个config_db set,哪个有效?
更高的层次更接近用户,为了让用户少和底层组件打交道,所以层次越高优先级越高,高层次的会覆盖底层次的,如果是层次相同再看时间先后顺序,谁发生的晚谁有效,时间靠后的会覆盖之前的。
Q85.VIP怎么写?
阶段1(定义)。
功能特性提取
特性覆盖率创建及映射
VIP的架构
阶段2(VIP基本搭建)
driver,sequencer,monitor (少量特性实现)。
实现基本的端到端的sequence
阶段3(完成monitor与scoreboard)
完成monitor -100%实现(checkers,assertions)
完成scoreboard -100%实现(数据完整性检查)
在monitor中,完成监测到的transaction与function coverage实现映射。
为映射更多的基本功能覆盖率,创建其它sequences。
阶段4(扩充test和sequence阶段)
实现更多sequences,从而获得80%的功能覆盖率
阶段5(完成标准)
Sequence最终可以实现100%的功能覆盖率。
回归测试结果和最终的总结报告。
Q86.验证流程,验证环境怎么搭
验证流程:
看文档和协议,将的功能和接口总线时序搞明白
制定验证计划和测试点分解
写或者是用别人给的,搭建验证环境和,包括各种组件,各个模块的,基础的 还有,暂时先就写一两个基础的 ,然后还有一些环境配置参数的确定等,最后能够将正常运行,保证无误;
根据测试点编写和 ,然后去仿真,保证仿真正确性,收集覆盖率;
分析收集的覆盖率,然后查看覆盖率报告去分析还有哪些没有被覆盖,去写一些定向,和更换不同的去仿真;
回归测试,通过不同的去跑,收集覆盖率和检测是否有其它;
总结
验证环境的搭建:
图片
给 发送激励,监测 输出的数据,参考模型( )能实现与 相同的功能,把 接受到的数据和 的输出数据进行比对,如果比对成功就表示 能完成设计的功能,
Q87.Uvm_component_utils有什么作用
机制的实现被集成在了一个宏中:。
这个宏最主要的任务是,将字符串登记在内部的一张表中,这张表是功能实现的基础。只要在定义一个新的类时使用这个宏,就相当于把这个类注册到了这张表中。这样,机制可以实现:根据一个字符串自动创建一个类的实例,并且调用其中的函数()和任务(),这个类的就会被自动调用。
Q88.TLM怎么用
通信的步骤:
分辨出和和。
在中实现通信方法。
在俩个对象中创建端口。
在更高层次中将俩个对象进行连接。
端口类型有三种:
,一般是的发起端。
,作为和的中间端口。
,只能作为接受的末端。
多个可以连接同一个或,但是单个或不能连接多个。
端口的连接:通过函数进行连接,例如与进行连接,可以使用
uvm_*_imp#(T,IMP);IMP定义中第一个参数T是这个IMP传输的数据类型,第二个参数IMP是实现这个接口所在的。
你好,我是酒酒,毕业于成电,自学算法leetcode刷题,双修IC验证,斩获互联网 BAT offer 以及一些IC大厂offer:zeku、展锐、华为、寒武纪、地平线的程序媛 and IC媛一枚~。
日常分享高质量资料,输出面试、工作经验,欢迎围观。
图片
(别问,图片就是本人啦~)