UVM知识点总结-config+phase+覆盖+打印

基础的点

type_id::create函数:如果一个component在实例化时,其parent被设置为null(也就是通过type_id::create创建对象,此时第二个参数为null),那么这个componentparent将被系统设置为系统中唯一的uvm_root的实例uvm_top。针对component进行type_id::create时需要注意以下几种情况:例子:(1)如果创建了类A和类B,并且在A中实例化一个Bb),那么在A中对b进行create时,实际上parent_phase实际上就是A,因此可以写成this,因为bA的成员变量,那么自然的bparent_phase实际上就是A2)如果不是这种交叉的例化方式(比如先把两个类创建好后),比如对象就是在自己的类中,那么实际在create时其parent_phase就是在对该对象进行构建操作时构造函数的parent_phase3)接着第一点,如果在此出现一个类C,在C中例化Aa),可以实现的操作是对a.b进行赋值,但是需要注意的是,在类C中无法完成对A中不存在的变量进行赋值,也就是无法对a.d赋值(UVM实战p65页)

configure函数的两种应用:(1)针对域(2)针对寄存器

config_db机制

  1. 一些基本的点

传递对象:接口(接口的传递是虚接口),单一变量值(int,string,enum),配置对象,一般在build_phase阶段使用

set与get调用顺序:先set再get,有时候get放在继承于uvm_test中的某一个类中(再该类中实现具体的get),此时再顶层环境中一定要先set,再进行该类的运行

set和get函数的参数:对于set来说,其中第一个参数和第二个参数联合起来组成目标路径,和此路径符合的目标才能接收。第一个参数必须是uvm_component实例的指针,第二个参数是相对于此实例的路径。第三个参数表示一个记号,用于表示这个值是传递给目标中的哪个成员,第四个参数是要设置的值(前面是针对变量来说的,如果是interface表示的是要将哪个interface传递出去,而此时对于get来说第四个参数表示的是将得到的interface传递给组件实例的哪一个成员变量)。对于get来说,第一个参数和第二个参数与前者类似,一般如果第一个参数设置为this,第二个参数可以设置为空(针对get),第三个参数与和set函数中的第三个参数保持一致,第四个参数是要设置的变量。

子类与父类中的config_db:set和get的类型应当一致,对具体实例进行操作时,如果类型不一致(比如子类句柄通过父类的方式传递,也就是set过程中具体的实例是子类,但是传递类型是父类,最终体现的是子类的句柄通过父类传递,并且随后get拿到的也是父类的,因此如果get回来的父类想实现对子类的访问,需要实现类型转化),需要转换:(1)调用$cast函数进行转化(2)为了实现对子类的访问,可以在set和get的过程中就更改类型,在set过程中将传递的类型变为子类(也就是说实例是子类,传递的类型也是子类),在此基础上,在get的过程中,将具体实例和传递类型都改为子类(set和get传递类型和实例均一致,均为子类),此时get回来的就是子类。

对通配符的支持,支持通配符,但是不建议这么做:白皮书p95

  1. 多重设置

跨层次

(1)如果set过程中第一个参数和第二个参数组成的层次越高,其优先级越高(2)如果层次相同的情况下,遵循先后原则,也就是后set进去的内容会覆盖先前set进去的内容

同一层次

遵循时间顺序,也就是后续的set值会覆盖前面的set值,需要注意的是,如果set的此时较多的情况时,可以将set的内容放在base_test的build_phase中,后续写各个类时将该类继承与base_test,然后再通过super.build_phase(phase)调用ser的内容,在后续如果需要修改set的内容仅仅只需修改base_test修改

  1. 非直线的设置与获取

在其他组件中获取其他组件设置给xx的参数值,称为非执行获取,在非直线获取过程中需要仔细设置set(或get)的第一个参数及第二个参数  白皮书p94

  1. 一些调试的函数

check_config_usage,检查截至到次函数调用前有哪些参数是被设置过但是没有调用过,常用来检查set过程中第1,2个参数是否正确,在set和get的阶段(build_phase)之后的connect_phase阶段使用

print_config(),遍历所有验证平台的结点,找出哪些设置过的信息是可见的,括号中为0表示只显示当前组件的信息,括号为1表示递归查询

设置全局函数check_all_config,通过全局函数调用check_config的静态函数check_all,可以实现set的第二个参数的检查

例子: 在initial中set; 在uvm_test的子类中set(重要,实验部分)

phase机制

1.执行机制

SV的缺点:无法满足(1)验证环境在实现层次化的时候保证组件例化的顺序及例化后的连接(需要等到整个环境构建好后才能进行连接);(2)无法满足底层组件在例化前进行连接

UVM可以解决上述SV的问题,UVM树的遍历过程中采用深度优先原则,先遍历组件A及其相关组件,再遍历与组件A同级的组件B,组件A与组件B遍历的先后是根据类例化后具体实例的首字母顺序

2. 9+12

主要phase:针对直接扩展与uvm_component的类,super.build_phase(phase),在build_phase中,super不可省略,主要解决get省略问题,但是有如下前提:(1)组件名必须通过`uvm_component_utils_begin/end宏注册(2)传递过程中成员名(set中的第三个参数)必须通过`uvm_field_int宏注册,并且该参数必须在set和get过程中保持一致;而针对自定义的类,是否可以省略super需要具体考虑

分支phase:phase机制的跳转:phase.jump(xx),xx指代具体跳转的内容,比如uvm_reset_phase::get(),执行此语句后便从当前phase跳转到uvm_reset_phase。但需要注意的是,仅仅uvm_pre_reset_phase::get()后的所有phase可以作为xx的内容,此外跳转既可以向前跳,也可以向后跳,跳的内容既可以是uvm_pre_reset_phase后的分支phase,也可以是run_phase后(不包含run_phase)的主要phase

phase的调试:仿真过程中调用+UVM_PHASE_TRACE可以在不使用uvm_info的前提下打印更为详细的phase信息

3.domain

通过domain实现对phase跳转的隔断,也就是跳转只能在当前domain中进行

通过domain可以把两个类的两个时钟块隔开(再某个类中进行uvm_domain new_domain操作),之后两个domain的12个分支phase将会是独立运行,但是run_phase和其他function_phase任然是同步的

domain有两个参数,第二个参数为1表示该类的子类均会加入到新的domain中,一般在现在构建前进行uvm_domain new_domain,而子类的声明一般在build_phase阶段,因此往往会在connect_phase进行set_domain(new_domain,1)(函数原先参见白皮书p159)

4.仿真的开始

定义继承与uvm_test的子类a,可以在initial语句中,将其运行(run_test("a");),或者将run_test的内容设置为空,在仿真过程中通过+UVM_TESTNAME=a来实现

5.仿真的结束(objection机制)

基本的点:(1)raise_objection和drop_objection必须在run_phase或其并行的12个分支phase中的开始或者结尾使用,如果在开始延迟一定时间后在进行那么实际上并不能起到作用(2)对于run_phase来说,有两种运行方式,其一是被动的接受其并行的12个分支phase中的raise_objection,另一种方式是执行自己的raise_objection。需要指出的是,如果想要并行的12个分支的某一个phase执行,就必须要在该分支中raise_objection,否则该phase将不会执行,在进入extract_phase之前,系统的准则是先检查12个分支phase中每一个phase是否均完成drop_objection,再检查run_phase是否完成,上述都满足的情况下,进入extract_phase(3)raise_objection(xx,xx,int count=1)表示挂起一个objection,可以设count参数,使其挂起多个objection

超时退出:在uvm_root的set_timeout函数中可以设置时间和是否可以被其他的set_timeout函数覆盖,eg:uvm_top.set_timeout(500ns,0)表示超过500ns后会自动退出仿真,此外也可以在仿真过程中通过设置 +UVM_TIMEOUT"xx , xx"第一个参数填时间,第二个参数填YES(可以被覆盖)或NO(不可以被覆盖)

objection的控制:建议在scoreboard或sequence(建议后者)中raise_objection,对于前者需要去除其中main_phase的无线循环

objection的调试:+UVM_OBJECTION_TRACE

field automation机制

相关的宏:枚举加变量:typedef enum {...} A; A a; `uvm_field_enum(A,a,UVM_ALL_ON)

相关函数

标志位:`uvm_field_int(crc,UVM_ALL_ON | UVM_NOPACK),执行上面语句后打包时就不会考虑该字段了

uvm_object(仅仅针对factory机制):uvm_object_utils;uvm_object_param_utils(针对参数化类);uvm_object_utils_begin/uvm_object_utils_end

uvm_component:uvm_component_utils,其最大的优势在于通过super.build_phase(phase)再build_phase中省略config.db的get语句;uvm_component_param_utils(针对参数化类);uvm_component_utils_begin/uvm_component_utils_end(针对同时需要factory机制和field_automation机制的类);uvm_component_param_utils_begin/uvm_component_utils_end(注意结束标志都是一样的,没有param,这个宏主要用于参数化的类,并且该类中某些变量要使用field_automation机制)

消息宏:

`uvm_info(ID,MESSAGE,VERBOSITY);

`uvm_info(get_type_name(), $sformatf("sent data 'h%8x", t.data[i]), UVM_HIGH)

`uvm_error(ID,MESSAGE);

`uvm_warning(ID,MESSAGE);

`uvm_fatal(ID,MESSAGE)

工厂机制

SV中可以对任务,函数及约束进行重载,UVM中存在着独有的factory机制,其核心就是覆盖,使用工厂机制进行覆盖有如下要求:(1)类必须使用工厂机制进行定义和例化(使用宏和type::id创建对象)(2)两个类必须是继承关系,并且覆盖的类是子类,被覆盖的类是父类,component和object不能相互覆盖,虽然component是object的子类,但是两者之间中间还差一个对象,并且两者参数也不相同,component多一个parent参数

 1.factory的调试机制

以monitor为例,env.o_agt.mon.print_override_info("my_monitor"),会输出相关重载的参数(在前面已经通过new_monitor覆盖了my_monitor,书中是把其放在了connect_phase机制中);factory.debug_create_by_type(my_monitor::get_type(),"uvm_test_top.env.o_agt.mon")也会输出相关重载的参数

extern function void print (int all_types=1);参见白皮书p274

2.覆盖方法

uvm_component(component的子类中用):set_type/inst_override_by_type;set_type/inst_override

uvm_factory(在top中可用,比如initial语句中,也可在component中,调用方式是factory.函数):set_type/inst_override_by_type;set_type/inst_override_by_name

仿真过程中调用:+uvm_set_type/inst_override="...";" "中的内容根据是type(两个参数:被覆盖对象,覆盖对象,[第三个参数为0或1,可选,分别表示不可被重复覆盖和可被重复覆盖])还是inst(三个参数:被覆盖对象,覆盖对象,路径)确定

3.除了上述说的B是A的子类,可以通过B覆盖A的方法以外,还存在着一些其他的覆盖情况:(1)连续的重载,比如B继承与A,C继承与B,那么可以用B覆盖A,再用C覆盖B,最终是C(此时是A和B都是C)(2)替换式的重载:比如B继承与A,C继承也继承A,此时先用B覆盖A,再用C覆盖A,如果覆盖函数的第三个参数replace为1,那么运行对同一个对象进行多次的覆盖,最终A 的表现为C,如果参数为0,对同一对象的多次覆盖将会失败(3)上述过程还可以变为B覆盖A,再用C覆盖B,此时执行A实际上还是执行C(参见白皮书p273)

4.factory机制的实现

打印信息的控制

1.打印函数:

set_*_action

冗余度及阀值:(1)get_report_verbosity_level可以得到某个component的冗余度阀值(牵扯到层次的引用时需要在connect_phase及其以后的phase中使用,如果不牵扯层次的引用可以在connect之前使用);(2)set_report_verbosity_level可以设置某个component的冗余度阀值;set_report_verbosity_level_hier递归的设置,可以对agent进行操作,他会对agent下面所有的component进行设置;set_report_id_verbosity,对component内部某个id设置冗余度,有两个参数,第一个参数是id,第二个参数是等级;(均是独立使用)

打印消息的严重性: `uvm_warning;`uvm_error;`uvm_fata;`uvm_info

打印函数的重载:(1)对某个component的进行重载,env.i_agt.drv.set_report_severity_override(UVM_WARNING,UVM_ERROR),用error重载warning(2)对component内的某个id进行重载env.i_agt.drv.set_report_severity_id_override(UVM_WARNING,"my_driver",UVM_ERROR)

计数: (1)对于error信息可以进行通过计数控制其退出,直接写:set_report_max_quit_count(5),可以在build_phase中写(也可以在其他的phase中写),也可以在顶层test位置中写,顶层写的部分会覆盖其他位置中的;get_report_max_quit_count返回退出error的临界值,如果返回0表示无论多少error都不退出(2)除了error以外,还可以增加计数的对象,包括WARNING和INFO,env.i_agt.drv.set_report_severity_action(UVM_WARNING,UVM_DISPLAY|UVM_COUNT),也可以递归的将agent下面的所有component的中的warning加入到计数部分,env.i_agt.drv.set_report_severity_action_hier(UVM_WARNING,UVM_DISPLAY|UVM_COUNT);也可以针对某个component特定的id进行计数,env.i_agt.drv.set_report_id_action("my_driver",UVM_DISPLAY|UVM_COUNT),其递归方式是env.i_agt.set_report_id_action_hier("my_driver",UVM_DISPLAY|UVM_COUNT)(3)可以将id和严重性相结合env.i_agt.drv.set_report_severity_id_action(UVM_WARNING,"my_driver",UVM_DISPLAY|UVM_COUNT),表示my_driver中的UVM_WARNING信息加入计数,其递归的方式是env.i_agt.drv.set_report_severity_id_action_hier(UVM_WARNING,"my_driver",UVM_DISPLAY|UVM_COUNT),(4)默认状态下,error已经加入了计数的对象中,可以采用env.i_agt.drv.set_report_severity_action(UVM_ERROR,UVM_DISPLAY)将UVM_ERROR从计数对象中移除;

2.断点功能:将上述计数中的2和3点中的UVM_COUNT变为UVM_STOP,比如env.i_agt.drv.set_report_severity_action(UVM_WARNING,UVM_DISPLAY|UVM_COUNT);表示只要执行到语句出现UVM_WARNING就会自动停止

3.控制打印信息的行为

UVN_NO_ACTION;加上后所有信息都不会输出

UVM_DISPLAY:显示操作

UVN_LOG:将信息输出到日志文件中。具体操作如下:UVM_FILE info_log;info_log =$fopen("info.log","w");env.i_agt.drv.set_report_severity_file(UVM_INFO,info_log);env.i_agt.drv.set_report_severity_action(UVM_INFO,UVM_DISPLAY|UVM_LOG);(后面三个步骤建议在connect_phas中使用);也可以针对agent进行递归,函数后面+hier;也可通过id,将severity替换成id(id同样可以递归,+hier);也可将ID和严重性组合进行操作(这种方式同样有递归的操作+hier)

UVM_COUNT:计数操作

UVM_EXIT:退出仿真操作

UVM_CALL_HOOK:调用一个回调函数****比如,report_hook是针对所有打印部分的回调函数(也就是针对report_phase的回调函数),其默认返回值是1,当然也可以自己定义其他返回值,如果返回值为1的情况下,他会继续执行下面一个回调函数(比如report_info/error/fatal/warning_hook)**注意这部分回调函数先执行,再执行自身函数

UVM_STOP:停止仿真操作

注意,控制打印信息的行为均是针对set_*_action(xx,xx|xx),后面一个参数用于控制打印信息

4.仿真过程中的控制

冗余度:+UVM_VERBOSITY=UVM_HIGH/HIGH,相当于从test一级进行调用

重载:(1)id:+uvm_set_severity="uvm_test_top.env.i_agt.drv,my_driver,UVM_WARNING,UVM_ERROR"(2)所有id,也就是component:+uvm_set_severity="uvm_test_top.env.i_agt.drv,_ALL_,UVM_WARNING,UVM_ERROR"

最大erro值及加入计数对象:(1)最大erro值:+UVM_MAX_QUIT_COUNT=   ,YES/NO,第一个参数表示最大erro计数数量(默认error是加入计数的),第二个参数表示设置的最大计数数量是否可以被后面设置的语句重载(2)某一个id,+uvm_set_action="uvm_test_top.env.i_agt.drv,my_driver,UVM_NG,UVM_DISPLAY|UVM_COUNT",其中UVM_NG表示severity(3)所有id,也就是component,+uvm_set_action="uvm_test_top.env.i_agt.drv,_ALL_,UVM_WARNING,UVM_DISPLAY|UVM_COUNT"

断点功能,+uvm_set_action="uvm_test_top.env.i_agt.drv,my_driver,UVM_WARNING,UVM_DISPLAY|UVM_STOP"

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM验证是一种基于SystemVerilog的硬件验证方法,广泛应用于半导体行业。它提供了一套强大的验证框架,可以帮助工程师有效地进行验证工作。 异步FIFO验证是UVM验证中的一个重要部分,用于验证异步First-In-First-Out(FIFO)电路。异步FIFO电路在大多数存储器系统中被广泛使用,因此验证其功能和性能非常重要。 在异步FIFO验证中,需要编写UVM验证环境和测试用例,以验证FIFO电路的功能和时序。首先,可以使用UVM的类来建立一个FIFO模型,包括读写指针、写入和读出逻辑等。然后,可以编写Constrained Random测试用例,以测试FIFO的各种情况,例如空FIFO、满FIFO和部分写入/读出的情况。验证环境会控制测试用例的生成和执行,同时收集和分析验证结果。 在异步FIFO验证中,还需处理时序相关的问题。由于读写指针的异步性质,可能会出现读指针追赶写指针或写指针追赶读指针的情况。为了验证这些情况,可以引入时序检查和约束,以确保FIFO电路在各种时序条件下都能正常工作。 总结来说,UVM验证是一种基于SystemVerilog的硬件验证方法,可以帮助工程师进行有效的验证工作。在异步FIFO验证中,需要建立UVM验证环境和编写测试用例,以验证异步FIFO电路的功能和时序。该验证过程涉及到建模、生成测试用例和进行时序验证等步骤,以确保FIFO电路能够正常工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值