- 什么是UVM?UVM的优势有哪些?
UVM(通用验证方法)是一种用于验证数字设计标准化的简单方法。
优势:
- 第一种自动化方法和第二种自动化类库的集合
- 贯穿于验证平台的可重用性
- 即插即用的验证IP
- 通用的验证平台开发
- 供应商和模拟器独立
- 高智能的验证平台(即从预先设计的覆盖计划中产生合法的激励)
- 支持CDV(覆盖率驱动)验证
- 支持CRV(受限随机)验证
- UVM在Accelerate System Initiative下标准化
- 支持寄存器模型
- uvm_component和uvm_object之间有何区别?
或者我们已经拥uvm_object,为什么我们需要uvm_component这种实际派生自的uvm_object类?
uvm_component:
- 准静态实体(在构建阶段之后,它在整个模拟过程中可用)
- 始终连接到给定硬件(DUT接口)或TLM端口
- 具有用于控制仿真行为的phase机制
- 配置组件拓扑结构
uvm_object:
- 动态实体(在需要时创建,从一个组件转移到另一个组件然后取消引用)
- 不连接到给定的硬件或任何TLM端口
- 没有phase机制
- UVM phase中top-down(自顶而下)、down-top(自底而上)以及并行执行的phase分别有哪些?
只有build_phase是自顶而下的,除了run_phase,其他phased都是自底而上的。run_phase自顶而下工作,可以配置测试工作台层次结构,因此我们需要在构建叶子之前构建分支。
build_phase方法自顶向下执行,以便在顶部(测试)设置的配置可以向下传播到各component中。在build_phase中主要就是做实例化的工作,顶层实例化以后,一层层向下实例化才不会引发调用错误。connect_phase主要是连接各个component之间的传输问题,用于在组件之间建立TLM类型的连接,这就是它在构建阶段之后发生的原因。它自底而上工作,以便在设计层次结构中获得正确的实现。
- 寄存器模块验证中常见的测试点有哪些?
- 检查寄存器的复位值;
- 需要检查寄存器的域常见读写属性;
- 检查每个寄存器的地址映射关系是否正确;
- 检查寄存器的反馈是否及时准确,这一点需要检查硬件状态信号是否连接到寄存器端,如果是更新方式是主动更新,那么可以通过后门访问进行快速检查(不占用总线),如果更新方式是被动更新,那么只能通过前门访问除法ing吉安状态值更新。
- 对于一些特殊寄存器(wc/rc/wo)需要集合其特定属性,进行单独访问,并通过后门访问或者检测内部信号检查其功能。
- 为什么建议配置放在对象创建之前?
这是为了将所需配置的变量事先嵌入uvm_config_db进行存储,而在后续子一级组件例化并且进入build_phase()从uvm_config_db获得配置时,可以确保所配置的变量都已先于子一级组件进行过配置,避免出现配置变量无法获取的现象。
- 为什么build_phase是自顶而下而connect_phase是自底而上?
connect_phase旨在用于在组件之间建立TLM类型的连接,这就是它在构建阶段之后发生的原因。它自底而上工作,以便在设计层次结构中获得正确的实现,如果从上到下工作,这是不可能的。
- 模块和基于class的tb的区别有哪些?
模块是在仿真期间始终存在的静态对象。class是一个动态对象,因为它们可以在仿真的生命周期中来去。
特别指出:interface是静态对象,因此只能用于top、模块等静态对象中,driver为动态的对像类,因此driver等类中使用的为virtual interface,通过虚的指针指向实际的interface。
- 为什么要用类来做UVM的通信事务?为什么不可以是结构体呢?
- class和struct都可以包含数据;
- class可以对数据做封装,struct不可以;
- class可以对父类做继承,添加新的成员,struct要添加新的变量只能文本拷贝;
- class可以内置成员方法对成员变量做操作,struct不可以;
- transaction需要随机化和约束,这是类的专长,struct不可以;
- 可以使用对象内建的randomize()函数随机化对象中的随机变量,而struct无法轻松办到这一点(不是不可以;
- class本身也是naming space,它也可以在自己的body中定义一些类型,而struct不是naming space,由于这一特性class中也可以定义静态变量和方法,struct不可以;
- 在UVM中,考虑到环境的复用性,如果要对transaction添加成员或者修改constraint,合理的做法是扩展子类从顶层利用factory做类型覆盖(override),这首先需要transaction类可以实现注册,而struct无法注册,也自然享受不到这个待遇;
- 在UVM组件的通信中,initiator与target的通信实际上是同一个数据实体,可以实现对同一个数据对象的共享,所以class是合适的,如果修改为struct,那么则发生的是数据拷贝,两端实际上是不同的数据对象。
- 从VHDL到UVM验证平台转变的优点评估.(可重用,标准化)
- VHDL不太支持约束随机激励, 而System Verilog则支持,因此在UVM验证平台中ADC和GPIO可以带约束随机。
- 非常少的简单VHDL验证平台可以被重用。通过创建package,高级VHDL验证平台可以被重用。但是因为没有标准的方法,连接到一个新的验证平台并不直观。Package是结构性的,它只组织代码。此外,数据定义和函数定义(package 主体)被分离开。OOP会将这两者结合起来以便更好维护。UVM 验证平台因为OOP特点会更从容处理这些,使得验证组件和结构具有很高重用率。
- 两个VHDL验证平台迫使工程师侧重于创建激励而不是check。但我们所需要的是对两者都重视,这点在UVM中实现了。
- 简单VHDL验证平台的代码覆盖率是78%, 高级VHDL验证平台是74%。回想起从简单到高级VHDL的转变不是为了提高代码覆盖率本身,其目的是使用先进的结构(即record和procedure)并更具组织性。当使用有次序的test sequence时,UVM的代码覆盖率是79%,而当使用随机化的test sequence时,代码覆盖率提高到85%。代码覆盖率的改善难易程度在这里很重要。
- UVM增加了功能验证的鲁棒性,允许创建灵活的,适应性强的,可扩展性的验证平台。它提供了量化的,可测量的进展,同时通过改变test sequence可以方便增加代码覆盖率。
- UVM会降低工具集成时间,从而允许我们达到减少实验室集成周期的终极目标。
- 最后,UVM重点不是肉眼检查波形,这点非常重要,因为FPGA变得越来越大,对于肉眼检查越来越困难。
- 为什么不建议在sequence中使用pre_body()和post_body()?
只有通过uvm_sequence::start()方法调用时,才会间接调用pre_body()和post_body();而经常使用的序列宏发送宏序列例如`uvm_do则不会调用pre_body()和post_body().
- 什么是uvm_config_db?uvm_config_db和uvm_resource_db之间有什么区别?
uvm_config_db是一个参数化类,用于将不同类型的参数配置到uvm数据库中,如此它可以被任何较低级别层次结构中的组件使用。
uvm_config_db是一个构建在uvm_resource_db之上的便利层,但这种便利非常重要。特别是,uvm_resource_db使用“最后写入获胜”方法。另一方面,uvm_config_db通过end_of_elaboration查看层次结构中的内容,因此“父获胜”。一旦启动start_of_simulation,config_db就会变成“最后写入获胜”。
uvm_config_db#(T)中的所有函数都是静态的,因此必须使用::运算符调用它们。uvm_config_db#(T)是从uvm_resource_db#(T)扩展而来的,所以它是uvm_resource_db#(T)的子类。
- `uvm_do和`uvm_rand_send之间的区别是什么?
uvm_do执行以下步骤:
- Create
- Start item
- Randomize
- Finish item
- Get response (optional)
`uvm_rand_send执行除create之外的所有上述步骤。用户需要创建sequence或sequence item。
- uvm_transaction和uvm_seq_item之间的区别?
uvm_sequence_item类扩展了uvm_transaction。
uvm_sequence_item类仅从uvm_transaction类扩展,uvm_sequence_item类具有更多支持sequence和sequencer特征的功能。Uvm_sequence_item为sequencer和sequence提供了钩子,所以你可以使用sequence和sequencer生成事务,而uvm_transaction只提供do print和do record等基本方法。
- 说说你对UVM的理解?
- 模块化和可重用性 - 该验证方法被分为模块化组件(驱动程序,序列发生器,代理,env等),可以将组件级别之间的组件重用于多单元或芯片级别验证以及跨项目。
- 将测试用例与验证平台分开 - 测试用例与实际的测试平台层次结构分开,因此可以在不同的单元或跨项目中重用激励。
- 独立于仿真器 - 所有仿真器都支持基类库和方法,因此不依赖于任何特定的仿真器。
- 更好地控制激励产生 - sequence方法可以很好地控制激励的产生。有一些方法可以开发序列,包括随机化,layer sequence,virtual sequence等,它们提供了良好的控制和扩展激励生成的能力。
- 轻松配置 - configure机制简化了具有深层次结构的对象的配置。configure机制有助于根据验证环境轻松配置不同的测试平台组件,而无需担心任何组件在测试平台层次结构中的深度。
- factory机制 - factory机制简化了组件的修改。使用工厂创建每个组件使它们可以在不同的测试或环境中被覆盖,而无需更改底层代码库。
- 什么是UVM寄存器模型?为什么需要它?
在验证上下文中,寄存器模型(或寄存器抽象层)是一组类,用于模拟DUT中寄存器和存储器的存储器映射行为,以便于激励生成和功能检查(以及可选的功能覆盖的某些方面)。 UVM提供了一组基类,可以扩展它们以实现全面的寄存器建模功能。
- new()和create之间的区别是什么?
我们都知道用于为对象实例分配内存的new()方法.在UVM(和OVM)中,create()方法可以从factory创建对象实例,这允许使用factory重载时将所需对象替换为不同类型的对象,而无需重新编码。
- 什么是objection机制?
UVM中的objection机制是允许组件之间的分层状态通信,这有助于决定验证结束的时间。
每个内置phase都有一个内置的objection机制,它为组件和对象提供了一种同步其测试活动的方法,并指示何时可以安全地结束phase,最终确定验证进程的结束。
组件或sequence将在活动开始时rAIse objection(提起异议),该活动必须在phase结束之前完成,因此将在该活动结束时drop objection(撤销异议)。一旦所有被raise的 objection都被drop,phase就会终止。
- start()和`uvm_do_on()有什么区别?
Start()是uvm_sequence的方法,而`uvm_do/`uvm_do_on等一系列的宏只能在uvm_sequence中使用.在vum_test中,如果要将顶层virtual sequence挂载到virtual sequencer上,应该使用uvm_sequence::start()方法,而不是`uvm_do的宏,原因就是在uvm_test中无法使用该类宏.
- What are the benefit of using UVM?
Some of the major and immediate benefit are:
- Testbench prototyping becomes faster because of all the base classes for drivers, monitors, sequencers
- There's a well defined reporting system which supports various levels of verbosities like LOW, DEBUG, etc
- Supports register model creation and maintainence which simplifies the way DUT registers are accessed
- Well structured plug and play style components like agents that can be plugged into any environment to support a particular protocol
- Factory helps to override certain components without having to modify existing connections in the testbench
- Configuration databases that allow components to share objects and data between each other
- Make use of TLM features that enable different components that receive transactions to perform different operations on it.
- Promotes re-usability, flexibility, uniformity and robustness to every testbench built on UVM
- What is p_sequencer ?
p_sequencer is a handle to the sequencer on which the current sequence should be executed and is made available in a sequence bt the macro `uvm_declare_p_sequencer.
- What is a UVM RAL model? Why is it required?
RAL is short for Register Abstration Layer. It is a set of base classes that can be used to create register models to micmic the register contents in a design. It is much easier to write and read from design using a register model than sending a bus transation for every read and write. Also the register model stores the current state of the design in a local copy called as a mirrored value.
- What is an analysis port?
An analysis port is a TLM mechanism to allow a component to broadcast a class object to multiple listence so that they can inplement different methods to perform different operation on the data it receives.
- What is the different between new() and create()?
The new() method is the classical way of how SV create an object instance. The create() is an addition in UVM that allows the factory to return an object of the type that we want.
- Is UVM independent of SV?
No. UVM is build on SV and hence you cannot run UVM with any tool that does not support SV.
- Why do we need to register a class with a factory?
You donot necessarily need to. It is registered with factory simply to make the TB more re-usable and have the capability to override it with some other derivative component later on.
- What is the difference between `uvm_do and `uvm_send?
`uvm_do macro will automatically create a new object, randomize it and send to the sequencer. `uvm_send is used when the object is already created and randomize but need to be executed on a sequencer.
- What is the difference between uvm_transaction and uvm_sequence_item ?
The uvm_transaction class is the root base class for UVM transactions and has a timing and recording interface as well. Use of this class as a base for user-defined transactions is deprecated, and instead its sub-class uvm_sequence_item should be used. The intended use of transaction API is to call accept_tr, begin_tr and end_tr during the course of sequence item execution in order to record the events to a vendor-specific transaction database. uvm_sequence_item is primarily used to define data objects and related methods.
- What is the difference between RAL backdoor and frontdoor accesses ?
A backdoor access in RAL is a way to dump values directly onto the DUT registers via a hard coded RTL signal path and does not consume simulation time. A frontdoor access in RAL is usually done by sending the data as a transaction through an associated peripheral bus interface and hence consumes simulation time.
- What is a phase objection ?
In UVM, all components synchronize with each other through a set of phases. Every component has to finish its processes in a particular phase until it can proceed to the next. So, objection is a mechanism to allow a component to stall other components from proceeding to the next phase until it gets the chance to finish its own tasks. This is normally done using raise_objection() and drop_objection() methods from the uvm_phase class.
- How can we access a DUT signal in a component or sequence ?
Interface signals can be accessed via a virtual interface handle that points to the actual physical interface. Signals within the DUT can be accessed directly by providing a hierarchical RTL path to the signal such as top.eatable.fruits.apple.slice
- What are reg2bus and bus2reg functions for ?
They are RAL functions that enable conversion from generic register contents to actual bus transactions and vice-versa. You have to define them based on the protocol you are dealing with by assigning the data object of the protocol with values from rw internal variable and vice-versa.
- How do you connect a monitor with a scoreboard ?
You can declare the implementation of an analysis port within a scoreboard and connect the monitor's analysis port with it in the environment's connect method.
- How do you connect driver and sequencer ?
Driver has a TLM port called seq_item_port that can be connected with the sequencer's seq_item_export in an agent's connect method.
- What is uvm_config_db and uvm_resource_db ?
Both are mechanisms that allow a component to place an object in a central look-up table under a specified name and path, so that they can be retrieved by another component using the same name and path. The uvm_config_db class provides a convenience interface on top of the uvm_resource_db to simplify the basic interface that is used for configuring uvm_component instances.
- What does a sequence normally contain ?
A sequence has a task called body() within which we can write the actual stimulus to test the design for a particular feature.