UVM相关要点(摘抄于网络)

接口的作用
对各个模块做清晰有序的连接,同时将DUT和testch隔离开来,提高环境的复用性。需要注意的是:接口中的信号应该定义为四值逻辑,这样是为了防止接口与DUT相连时,X与Z的信号丢失。
接口还可以使用modport进一步确立不同对象对信号的连接方向。

program的使用
一般将设计部分放在module中,而将测试采样的部分放在program中。因此,program可以认为是软件的区域。所以always,module,interface等不应该出现在program中。
2.program驱动外部的硬件信号时应该使用非阻塞赋值

随机约束:
1.典型的随机分为俩大类:场景随机和接口随机。
2.应该在类中使用rand来声明随机变量,并且可以继承和复用。
3.可以使用randc来完成不重复的随机化
4.要完成随机化,例化的对象要显示调用randomize();
5.随机化生成二值逻辑。logic也只能生产二值。
6.没有在类中rand声明的变量也可以被外部随机化。

约束块
使用inside产生一个值的集合。
使用dist产生权重分布
使用unique来产生不重复的随机数。
使用foreach来完成迭代约束
内部约束均为硬约束,我们可以使用soft来定义软约束,当后来的约束与软约束冲突时,以硬约束为准。


随机化的控制
可以使用rand_mode来控制整个对象或某个成员的随机属性。
也可以使用constraint_mode来控制和关闭约束块。
我们可以使用randomize() with 来增加额外的约束。
我们使用randomize()可以传递变量的一个子集,只随机化类里的几个变量。例如:r.randomize(med)只随机华med。这种应用针对的是类里所有被指定或者没有被指定rand的变量都可以作为randomize()的参数而被随机化。
SV可以使用foreach对数组的每一个元素进行约束。
对句柄数组随机化时,要保证句柄的每一个元素都是非悬空的,需要在随机化之前为每一个元素句柄构建对象。

在SV中,类可以定义在program, module, package中,但是一般一个类或几个相关的类会单独写在一个文件中。最终在program中调用。而且在SV中,所有成员默认都是public类型的,除非显示的用local/protected来声明。实际上,SV class中的变量应该尽可能的用public并且rand,来增加可控性。
基类的指针可以直接指向扩展类的对象,但是只能调用扩展类中基类的那一部分。基类的指针也可以直接转换为扩展类的指针,通过$cast函数,此时的基类指针指向的已经是扩展类对象,通过$cast,转变为扩展类指针,可以调用扩展类中自有的元素。
类中的静态变量可以通过类名::变量名的方式来引用。类中的其他变量都默认是automatic的修饰符,而且可以通过this.变量名,来直接调用类一级别的变量。在类的外部定义方法时,可以用关键字extern来在类中声明,后在类外通过类名::方法名的方式来定义。
类的继承(Inheritance),扩展类拥有基类的一切变量与方法,在扩展类中调用基类的变量与函数,可以通过super.+变量/方法来调用。在扩展类的构造函数中,应该先对基类先进行new函数。在扩展类的对象中调用对象时,SV比较句柄的类型来决定调用的是基类function还是扩展类function。但是当function是virtual类型时,SV会根据对象的类型来决定调用基类function还是扩展类function。推荐在需要扩展的基类中使用virtual function的形式,这样符合OOP的多态概念,也有利于向下转换。

类的三要素
4.1类的封装
类与结构体的异同:

都可以定义数据成员
类需要构造函数来构建对象实体。struct在变量声明就开辟了内存。
类可以声明方法,struct不能
struct只是一种数据结构,而类包含了数据成员以及操作方法。
类与module的异同:
二者都可以作为封闭的容器来定义和存储。
module必须在仿真一开始就确定是否被例化,而类可以在任何时间创建对象。
封装性来看,module内部的方法是开放的,而类内部的方法可以是protected或local。
继承性来看,module没有任何继承性,而类可以。
4.2类的继承
子类作用域如果与父类有相同的变量或方法名,以子类作用域为准。
父类的句柄指向子类的对象,只能访问子类中属于父类的部分。
4.3类的多态
-利用虚方法 实现类的动态方法查找
在定义虚方法时,要尽量定义在底层父类中。
虚方法通过virtual声明,且只用声明一次。
虚方法的继承遵循相同的参数和返回类型。
通过动态转换$cast可以判断父类句柄是否成功转换为子类句柄。

interface clocking
作用:用来进行事件的同步,输入的采样,输出的驱动。

线程的控制
fork join等所有线程都执行完毕,才跳出循环。
fork join_any只要有一个线程执行完,就跳出循环
fork join_none只是启动所有线程,并不等他们执行完毕。
如果希望所有fork块都执行完毕再退出,我们可以使用wait_fork语句。
我们可以使用disable来停止线程。

组件的通信
event ,单一的通知功能,用来做事件的触发。@是边沿敏感,阻塞等待事件的变化,wait(e1.triggered()是电平敏感。
semaphore,共享资源的安全卫士。使用前要用new对其进行初始化
mailbox,精小的SV原生fifo。也需要使用new对其进行初始化。


.uvm_component和uvm_object之间有何区别?
或者我们已经拥uvm_object,为什么我们需要uvm_component这种实际派生自的uvm_object类?(比特大陆、寒武纪面试题)

uvm_component:
准静态实体(在构建阶段之后,它在整个模拟过程中可用)
始终连接到给定硬件(DUT接口)或TLM端口
具有用于控制仿真行为的phase机制
配置组件拓扑结构

uvm_object:
动态实体(在需要时创建,从一个组件转移到另一个组件然后取消引用)
不连接到给定的硬件或任何TLM端口
没有phase机制

UVM phase如何启动?
通过在顶层模块中调用run test(“test1”)来启动UVM phase。当调用run test()方法时,
它首先会创建一个test_top的对象然后调用所有phase。

模块和基于class的tb的区别有哪些?
模块是在仿真期间始终存在的静态对象。
class是一个动态对象,因为它们可以在仿真的生命周期中来去。
特别指出:interface是静态对象,因此只能用于top、模块等静态对象中,driver为动态的对像类,因此driver等类中使用的为virtual interface,通过虚的指针指向实际的interface。

什么是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的理解?(NXP、百度面试题)
模块化和可重用性 - 该验证方法被分为模块化组件(驱动程序,序列发生器,代理,env等),可以将组件级别之间的组件重用于多单元或芯片级别验证以及跨项目。
将测试用例与验证平台分开 - 测试用例与实际的测试平台层次结构分开,因此可以在不同的单元或跨项目中重用激励。
独立于仿真器 - 所有仿真器都支持基类库和方法,因此不依赖于任何特定的仿真器。
更好地控制激励产生 - sequence方法可以很好地控制激励的产生。有一些方法可以开发序列,包括随机化,layer sequence,virtual sequence等,它们提供了良好的控制和扩展激励生成的能力。
轻松配置 - configure机制简化了具有深层次结构的对象的配置。configure机制有助于根据验证环境轻松配置不同的测试平台组件,而无需担心任何组件在测试平台层次结构中的深度。
factory机制 - factory机制简化了组件的修改。使用工厂创建每个组件使它们可以在不同的测试或环境中被覆盖,而无需更改底层代码库。

什么是UVM寄存器模型?为什么需要它?
在验证上下文中,寄存器模型(或寄存器抽象层)是一组类,用于模拟DUST中寄存器和存储器的存储器映射行为,以便于激励生成和功能检查(以及可选的功能覆盖的某些方面)。 UVM提供了一组基类,可以扩展它们以实现全面的寄存器建模功能。

new()和create之间的区别是什么?思科面试题)
我们都知道用于为对象实例分配内存的new()方法.在UVM(和OVM)中,create()方法可以从factory创建对象实例,这允许使用factory重载时将所需对象替换为不同类型的对象,而无需重新编码。
http://blog.eetop.cn/blog-1635120-6943543.html

声明和例化
声明是声明一个变量,其中保存类对象的句柄。
例化是通过构造函数,创建对象,分配内存空间,并将声明的句柄指向这段内存空间。
虽然在SV中可以在声明的时候例化对象,但是不建议如此。一般是在块语句之外声明类对象,在块语句内例化对象;可以控制对象的实例化顺序。


always:

可用于module和interface中
always @ (posedge clk)----时序逻辑  " <= "
always @ ( * )----组合逻辑  " = "

eg:上文提到了always具备描述硬件电路行为和核心要素,你认为下列选项哪些是正确使用always的方式?
A. 由时钟驱动    B. 由其他非时钟信号驱动    C. 不同always语句块之间是并行执行的    D. 可以在always中初始化变量
答案:A B C
解析:由时钟驱动就是时序逻辑,由其他非时钟信号驱动就是组合逻辑,所以AB对。
always是并行执行,C对。可以对变量进行复位(rst_n),而不能初始化。D错

initial:(多用于testbench)
initial非常符合软件的执行方式,即只执行一次。
initial和always一样,无法被延迟执行,即在仿真一开始它们都会同时执行,执行时没有先后顺序之分。
initial内部是按时间顺序进行的。
initial块从仿真0时刻开始执行,在整个仿真过程中只执行一次。如果一个模块中包括了若干个initial块,则这些initial块从仿真0时刻开始并发执行,且每个块的执行是各自独立的。

2020 12 21
关于UVM组件连接:同层次组件间的连接应该在更高一层来connect;

2020 12 23
在后仿真中将布局布线的时延 反标到设计中去,使仿真既包含门延时,又包含线延时信息。这种后仿真是最准确的仿真,能较好地反映芯片的实际工作情况。仿真工具与综合前仿真工具相同。

2020 12 29
run_phase和main phase都是task phase,且是并行运行的,后者称为动态运行(run-time)的phase。如果想执行一些耗费时间的代码,那么要在此phase下任意一个component中至少提起一次objection,这个结论只适用于12个run-time的phase。对于run_phase则不适用,由于run_phase与动态运行的phase是并行运行的,如果12个动态运行的phase有objection被提起,那么run_phase根本不需要raise_objection就可以自动执行。
run_phase跟12个task phase所属的domain并不一样,run_phase属于common_domain, 其余的12个task phase属于uvm_domain

常用的uvm_do和uvm_do_with宏产生的transaction的优先级为默认优先级,为-1;
uvm_do_pri和uvm_do_pre_with能够改变产生的transaction的优先级;
改变优先级后需要选择sequencer的仲裁算法才能使得设置的优先级有效;UVM存在的优先级算法有:

仲裁算法                    效果
SEQ_ARB_FIFO            先入先出,不考虑优先级
SEQ_ARB_WEIGHTED    加权的仲裁算法
SEQ_ARB_RANDOM            完全随机选择
SEQ_ARB_STRICT_FIFO    严格按照优先级,同一优先级先入先出
SEQ_ARB_STRICT_RANDOM    严格按照优先级,同一优先级内部随机
SEQ_ARB_USER    用户自定义
利用set_arbitration设置仲裁算法;

特殊操作
lock和unlock
lock和unlock操作,lock操作后该sequence可以一直发送transaction,直到unlock操作后才按照正常的优先级发送;lock操作需要等到前面所有请求完成后lock操作才起作用;

grab和ungrab
grab操作结果与lock类似,但是grab请求直接放在仲裁队列前面,几乎已发出就获得sequencer的权限;

is_relevant
squencer仲裁时,会查看sequence的is_relevant返回值,为1时该sequence有效,否则无效。可以重载is_relevant来控制sequence是否有效;
is_relevant和wait_for_relevant一般成对重载,不能重载其中一个;
 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux UVM实战例子环境配置需要以下步骤: 1. 安装Linux操作系统:首先,从官方网站下载适用于您的计算机的Linux版本的ISO文件。然后,将ISO文件刻录到安装介质上,并在计算机上引导以启动安装程序。按照安装向导的指示安装Linux操作系统。 2. 安装UVM:在Linux环境中,您可以通过以下方式安装UVM库: - 通过包管理器:对于大多数Linux发行版,可以使用包管理器(例如,apt、yum、zypper)直接从软件源中安装UVM。您可以使用以下命令之一来安装UVM: - 对于Debian/Ubuntu系统使用apt-get:sudo apt-get install uvm - 对于Fedora系统使用dnf:sudo dnf install uvm - 对于openSUSE系统使用zypper:sudo zypper install uvm - 从源代码安装:您还可以从UVM官方网站下载源代码,并按照提供的安装说明进行编译和安装。 3. 配置环境变量:为了让系统能够正确找到UVM库,需要配置环境变量。可以在终端中执行以下命令将UVM库路径添加到环境变量中: export UVM_HOME=/path/to/uvm 4. 配置仿真工具:根据您使用的仿真工具(例如,ModelSim、VCS等),需要进行相应的配置。具体的配置步骤可能因仿真工具而异,请参考相应工具的使用手册或官方文档。 5. 下载UVM实战例子:您可以从UVM官方网站或其他可靠的资源站点下载UVM实战例子的代码。将代码下载到本地目录中。 6. 编译和运行实战例子:通过终端进入实战例子代码所在的目录,并使用您的仿真工具编译和运行例子。具体的编译和运行命令可能因仿真工具而异,请参考实战例子的说明文档。 通过按照上述步骤进行操作,您应该能够成功配置Linux UVM实战例子的环境,并能够编译和运行例子。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值