《UVM实战》学习笔记——第三章UVM基础


前言

2022.11.22
今天开始学习张强作者的《UVM实战》,感觉很有意思,讲的非常清楚,推荐大家去看看。


在这里插入图片描述

一、uvm_component两大特性

1、通过在new函数时指定parent参数来形成树形结构
只有uvm_component派生的类,才有节点。
2、phase机制自动执行
build_phase的内容,一般有:利用config_db set/get传递参数;实例化成员变量。
build_phase是一个function,不消耗仿真时间;main_phase是一个task,消耗仿真时间

两大特性带来的限制
uvm_component:只能使用copy函数,不能使用clone函数。
因为clone出来的实例没有指定parent参数

在这里插入图片描述

二、常用派生自uvm_object的类

除派生自uvm_component类之外的类都是派生自uvm_object的类
1、uvm_sequence_item:产生transaction

为什么不从uvm_transaction类直接去产生transaction?
uvm_sequence_item派生于uvm_transaction,但前者添加了更多函数和变量、任务,直接从前者派生可以直接使用这些。

uvm_sequence和uvm_sequencer,以及uvm_sequence_item的区别?
sequence:object类,生命周期较短,sequence_item的组合
sequencer:component类,存在于整个仿真期间,调度其中的sequence和driver之间的传输
在这里插入图片描述

2、uvm_sequence:sequence是sequence_item的组合,将transaction发送给sequencer

3、config:规范验证平台的行为方式
把所有的参数放到一个object中,然后使用config_db进行配置

4、uvm_reg_item:派生自uvm_sequence_item,用于reference model

5、uvm_phase:控制uvm_component的行为

二、常用派生自uvm_component的类

记住每个组件的功能

在这里插入图片描述

(1)driver(参数化类):主动向sequencer索要sequence_item,即transaction。并将sequence_item的信息驱动到DUT的端口上。相当于完成从transaction到signal端口级别的转换。默认RSP=REQ

//driver的端口
uvm_seq_item_pull_port #(REQ, RSP) seq_item_port(可以get和put)
uvm_analysis_port #(RSP) rsp_port(广播模式,一对多,广播response)

//sequencer的端口
uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export(名字叫export,实际上是imp类型)
uvm_analysis_export #(RSP) rsp_export(代表中间节点,因为sequencer里面有个rsp tlm fifo,export连接到内部的imp端口。没有req的端口,不会对request缓存)

//连接
driver::seq_item_port.connect(sequencer::seq_item_export)
driver::rsp_port.connect(sequencer::rsp_export)

seq_item_port所支持的方法/任务(重要):

  • task get_next_item(output REQ req_arg):blocking的方法等待从sequence获得下一个item
  • task try_next_item(output REQ req_arg):nonblocking的方法等待从sequence获得下一个item,返回的结果是null,表示没有准备好
  • function void item_done(input RSP rsp_arg = null):通知sequence item已经消化完毕,也可以选择性传递response
  • task wait_for_sequences():等待当前的sequence直到产生下一个item。和2配合起来就是1的作用
  • function bit has_do_available():如果当前的sequence准备好且可以获取下一个item则返回1,否则0
  • function void put_response(input RSP rsp_arg):采取nonblocking的方式发送response,成功返回1,否则为0。可以独立地发送response
  • task get/peek/put():put是采用blocking的方式把response发送给sequence(这三个是由于此处端口继承于TLM 端口,所以继承了响应的方法)

在这里插入图片描述

在这里插入图片描述

(2)sequence:包含一些item/transaction

  • 通过方法create_item()创建request item对象
  • 调用start_item()准备发送item。立即返回的,是非阻塞类型
  • 在完成发送item之前对item进行随机处理。一定要在发送之前做完
  • 调用finish_item()完成item发送。不是立即返回的,是阻塞类型,要等待driver发送出来的item_done
  • 有必要的情况下可以从driver获取response item.如果item_done传递了rsp,那么久需要配对使用,也是阻塞的

item在start_item之后,因为挂载在了sequencer的上面,所以会通过句柄调用sequencer的send_requestwait_for_item_done函数,同时这两个又会去调用driver的函数,连接起来。

(3)sequencer(参数化类):负责调度sequence与driver之间的传输。

没有指明传输的transaction类型的话,缺省就是uvm_sequence_item类型,是父类类型,因此后续存在类型转换,父类句柄指向子类的对象, 将REQ转换为子类的item类型,才能获取有效的成员数据。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

时序图:
在这里插入图片描述

(4)monitor:没有增加任何新的成员和方法,继承自uvm_component,但是基本没有任何扩展功能,就是为了完善UVM验证的树形结构,使验证环境完善而已。

(5)agent(is_active枚举变量):包括driver和monitor。继承自uvm_component,但是基本上没有任何扩展。

(6)reference model:uvm里没有定义这个类,通常定义referrence model继承自uvm_component,可以用systemverilog或者DPI等接口调用其它语言,来完成与DUT相同的功能。

(7)scoreboard:负责比较referrence model与monitor分别发送过来的数据,根据比较结果判断DUT是否验证成功的工作。继承自uvm_component,但是基本没有任何扩展功能。

(8)env:继承自uvm_component,但是基本上没有任何扩展,封装固定不变的component。

(9)test:uvm_test里,都要实例化uvm_env。继承自uvm_component,但是基本上没有任何扩展。

(10)rootuvm_topuvm_root类唯一的实例,所在的域是uvm_pkg,是全局变量,可以通过uvm_root::get()函数来获取句柄。uvm_top是所有test组件的顶层(parent是null,默认是uvm_top)
在这里插入图片描述

在这里插入图片描述

三、相关的宏

头文件
'include "uvm_macros.svh" //加载所有uvm宏
import uvm_pkg:: *; //加载所有uvm类

uvm_object_utils:把一个直接或间接继承自uvm_object的类,注册到factory里。

uvm_object_utils_begin:主要是配合field_automation机制
uvm_object_utils_end:主要是配合field_automation机制

uvm_object_param_utils:把一个直接或间接继承自uvm_object的带参数的类,注册到factory里。

四、树形层次结构获取函数

get_parent():当前实例的parent,每个component只有一个parent,但是可以有多个child
get_child(string name):获取child的parent
get_children(ref uvm_component children[$]):得到所有child
get_first_child
get_next_child
get_num_children:数量
get_full_name():在driver中使用得到的是——uvm_test_top.env.i_agt.drv

五、field_automation机制

'uvm_field_int/real/string/event/object/enum
动态静态数组、队列中就没有real和event类型

常用函数:
copy:B.copy(A),复制
clone
print
compare:相同为1,不同为0
pack pack_bytes pack_bits pack_ints
unpack…

六、UVM打印信息

1、信息显示冗余度级别 verbosity(整数): 低于设置值的都会显示
UVM_NONE = 0,表示没有filter可以过滤,表示最重要
UVM_LOW = 100,表示很难滤除,则表示该条信息很重要,low以及low以下的会被打印出来
UVM_MEDIUM = 200
UVM_HIGH = 300,表示很高,很容易滤除
UVM_FULL = 400
UVM_DEBUG = 500
在这里插入图片描述

2、uvm_action_type:不同的位偏移,所以用连接在一起
UVM_NO_ACTION = 6’b000000 不做任何操作
UVM_DISPLAY = 6’b000001 输出显示
UVM_LOG = 6’b000010 输出到日志文件
UVM_COUNT = 6’b000100 计数
UVM_EXIT = 6’b001000 直接退出
UVM_CALL_HOOK = 6’b010000 调用回调函数
UVM_STOP = 6’b100000 停止仿真,进入命令行交互模式
在这里插入图片描述

3、相关函数
get_report_verbosity_level:得到某个component的冗余度阈值
set_report_verbosity_level:设置,由于牵扯到层次,需要在connect phase及之后使用
set_report_verbosity_level_hier:递归设置,他和以下层次的都设置
set_report_id_verbosity:区分不同id的冗余度

可以通过命令行设置
+UVM_VERBOSITY = UVM_HIGH

error达到一定数量停止仿真:build phase中设置,其他phase也可以
set_report_max_quit_count(5)

对warning进行计数
drv.set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_COUNT)

设置断点
drv.set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_STOP)

4、相关宏
在这里插入图片描述

七、config_db机制

在UVM验证平台间传递参数

1、set、get成对出现,set是寄信,get是收信

uvm_config_db #(int) :: set(this, "env.i_agt.drv", "num", 100)
第一个+第二个参数是目标路径,第二个参数是相对于此实例的相对路径
第三个参数是要set值得名称,set和get中要一样,才能找到
第四个参数是要设置的值
在这里插入图片描述

uvm_config_db #(int) :: get(this, " ", "num", num)
第一个参数都必须是component实例的指针

在top_db中设置virtual interface的时候,第一个参数为null
原因:top-db不是类,无法使用component实例的指针,所以使用null。null相当于uvm_root :: get( ),这样得到的就是uvm_top
第二个参数:uvm_test_top.env.i_agt.drv

2、有的情况下,只有set,没有get,不能省略set(满足如下三个条件)

  • 类在factory中注册
  • 该变量使用域的自动化声明
  • build_phase中调用super.build_phase( ),在这里会自动指向get语句

3、多层次设置

第一:优先级
第二:时间先后顺序,以最近的为准。build_phase是自上之下执行,以此来判断

4、检查配置是否成功

check_config_usage( ):显示出截止到此函数调用,哪些参数被设置过但是没有读取。在connect_phase中调用。

print_config(1):1表示递归查询,0表示显示当前component的信息
遍历验证平台的所以结点,找出哪些设置信息是可见的。在connect_phase中调用。

命令行:+UVM_CONFIG_DB_TRACE

5、多个变量进行配置

可以把变量写到config的包里面,这个config继承于uvm_object

首先,uvm_config_db去get的时候拿到的是uvm_object类,要转换为子类,才能使用子类的成员变量。

在这里插入图片描述

而在顶层环境中,要先创建这个config包,然后set给component,之后才能根据配置进行创建实例。必须要先set再创建实例

在这里插入图片描述

八、uvm_coreservice_t类

内置了UVM世界核心的组件和方法,独立于object和component之外,仿真开始时自动例化一次。该类并非uvm_component或uvm_object,它并没有例化在UVM环境中,而是独立于UVM环境之外。

  • uvm_factory:唯一,用来做注册、覆盖和例化
  • report_serve:全局,用来做消息统筹和报告
  • tr_database:全局,记录transaction,方便调试
  • get_root:返回当前UVM环境的结构顶层对象

这个核心组件如同一个随时待命的仆人,做好服务的准备。理论上,用户可以获取核心服务类中的任何一个对象,例如uvm_default_factory对象,继而直接利用factory来实现创建和覆盖。当然,创建和覆盖也可以由其它方式完成。

九、总结

在这里插入图片描述


面试题

1、什么是UVM?UVM的优势有哪些?

UVM(通用验证方法)是一种用于验证数字设计标准化的简单方法。
优势

  • 第一种自动化方法和第二种自动化类库的集合
  • 贯穿于验证平台的可重用性
  • 即插即用的验证IP
  • 通用的验证平台开发
  • 供应商和模拟器独立
  • 高智能的验证平台(即从预先设计的覆盖计划中产生合法的激励)
  • 支持CDV(覆盖率驱动)验证
  • 支持CRV(受限随机)验证
  • UVM在Accelerate System Initiative下标准化
    支持寄存器模型

2.uvm_component和uvm_object之间有何区别?
或者我们已经拥uvm_object,为什么我们需要uvm_component这种实际派生自的uvm_object类?

最大的不同就是树形结构phase机制

  • uvm_component派生于uvm_object,作为组件,准静态实体,存在于整个仿真周期,生命周期较长;而object类在需要时创建,从一个 组件到另一个组件然后消失,生命周期较短,动态实体
  • 前者连接到DUT端口或TLM端口,后者不连接
  • 前者有phase机制,自动执行,后者没有
  • 前者有new函数指定的parent形成的树形结构,后者没有

3、为什么build_phase是自顶而下而connect_phase是自底而上?

connect_phase旨在用于在组件之间建立TLM类型的连接,这就是它在构建阶段之后发生的原因。它自底而上工作,以便在设计层次结构中获得正确的实现,如果从上到下工作,这是不可能的。

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值