验证那些事儿【UVM 寄存器模型】

本系列文章从秋招高频问题入手,深度剖析 UVM 寄存器模型,如有错误之处,欢迎批评指正!

联系邮箱:zhangshaopu@ufl.edu

高频问题 1:讲讲你理解的寄存器模型?

从本质上讲,UVM 通过一系列复杂的机制,在验证环境中 构建了一个【和 DUT 侧寄存器组完全等价】的寄存器模型

  • 对于验证环境的 开发者 而言,集成寄存器模型是比较复杂的:不仅涉及到寄存器模型本身的开发,还要设计配套的 adapter predictor coverage model
  • 对于验证环境的 使用者 而言,使用寄存器模型是十分便捷的:使用者只需要和验证环境中的寄存器模型交互即可,不需要关心总线层面是如何通信的;与此同时,UVM 还提供了一系列 内建的 sequence 用于寄存器的各项检查

因此,在实际的验证项目中,需要考虑到开发模型的成本:如果模块的寄存器组 非常简单,并且后续 没有迭代 的需求,那么就没有开发的必要

高频问题 2:讲讲寄存器模型的结构?

从寄存器模型内部看:

  • 最基本的单元是 uvm_reg_field,多个 uvm_reg_field 组成一个 uvm_reg,多个 uvm_reg 组成一个 uvm_reg_block
  • 其中,uvm_reg_block 通常作为寄存器模型的 顶层,它还可以包含其他的 uvm_reg_block
  • 每个 uvm_reg_block 还包括一个 addresss map

从寄存器模型外部的配套组件看:

  • adapter 【map】和【DUT 总线 sequencer】之间 的桥梁
  • predictor 【map】和【DUT 总线 monitor】之间 的桥梁

高频问题 3:如何集成寄存器模型?

寄存器模型的集成包含三个步骤: 集成寄存器模型本身集成 adapter集成 predictor

集成寄存器模型本身:

  • 在 env 和 vsqr 中 包含寄存器模型的指针
  • 在 base_test 中 例化寄存器模型
  • 在 base_test 的 connect_phase 中 将指针赋值

这样,无论是验证环境的组件还是 sequence 都可以和寄存器模型交互

集成 adapter:

  • 在 base_test 中 例化 adapter
  • 在 base_test 的 connect_phase 中,通过寄存器模型的 set_sequencer 函数将 adapter mapDUT 总线的 sequencer 联系起来

集成 predictor:

  • 在 base_test 中 例化 predictor
  • 在 base_test 的 connect_phase 中
    • predictor 的成员变量 map adapter 赋值
    • DUT 总线的 monitor 的 TLM 端口 连接到 predictor 的 TLM 端口

高频问题 4:讲讲 adapter?两个重要函数?

adapter 充当的是 map 总线 sequencer 之间的桥梁:

寄存器模型无论读写,都会产生一个 uvm_reg_bus_op 类型的事务,这个 trans 如果想要被 总线 sequener 接收,势必要转换为总线 sequencer 对应的事务类型,这就是 reg2bus 的作用

反之,如果寄存器模型希望从总线 monitor 读回一些数据,需要将总线事务转换为 uvm_reg_bus_op 类型,因为寄存器模型同样无法直接处理总线事务,这就是 bus2reg 的作用

所以,adapter 需要通过 set_sequencer 关联特定的 mapsequencer,保证自己是它们中间的通信桥梁

​​​​​​​

高频问题 5:前门访问和后门访问的区别?

前门访问:在寄存器模型上做的读写操作,最终会 通过实际的总线 访问 DUT 的寄存器

后门访问:绕过实际总线,利用 DPI+VPI 的层次结构索引 直接操作 DUT 内的寄存器

区别前门访问后门访问
时间上由于是真实的物理操作,因此会 消耗仿真时间不消耗仿真时间
调试上任何前门访问都会 有波形文件,方便调试没有波形文件 的记录,调试难度增加
应用上能验证 总线协议本身 是否正确

大规模寄存器的 快速初始化

能够操作 只读寄存器

注入故障

高频问题 6:后门访问路径如何配置?

某个寄存器的后门访问路径通常拆分为两个部分:该寄存器所在的 block 的路径该 reg 相对于这个 block 的路径

  • 针对第一个部分,需要配置 uvm_reg_block 的路径,可以使用 configureadd_hdl_path;两者没有区别
  • 针对第二个部分,需要配置 uvm_reg 的路径,可以使用 configureadd_hdl_path_slice;两者的区别在于,如果一个寄存器的域支持单独存取,则不能使用 configure 配置 hdl 路径

当然,针对 uvm_reg_block,还有一种配置 hdl 的方法:set_hdl_path_root,这个方法配置的 hdl 会 覆盖其他方法配置的 hdl

高频问题 7:有哪些前门访问和后门访问的方法?

先说最常见的四类:readwritepeekpoke

其中,read 和 write 既可以前门访问,又可以后门访问,只需要在使用的之后指定访问类型即可

// 前门访问
p_sequencer.p_reg_model.FLOW_CFG.read(status, data, UVM_FRONTDOOR);
p_sequencer.p_reg_model.FLOW_CFG.write(status, 0xffff_ffff, UVM_FRONTDOOR);
// 后门访问
p_sequencer.p_reg_model.FLOW_CFG.read(status, data, UVM_BACKDOOR);
p_sequencer.p_reg_model.FLOW_CFG.write(status, 0xffff_ffff, UVM_BACKDOOR);

peek 和 poke 是 UVM 针对后门访问内建的函数:相比于 read 和 write,无视寄存器的读写属性,更贴合后门访问的特性

p_sequencer.p_reg_model.FLOW_CFG.peek(status, data);
p_sequencer.p_reg_model.FLOW_CFG.poke(status, 0xffff_ffff);

还有两个特殊的函数:mirror update,它们也可以读取或修改硬件寄存器

mirror() 会调用 read() 读取 硬件寄存器 的值,并更新 镜像值期望值;它和 read 的区别在于,它不会返回读取的数值,只会返回读取的状态

update() 首先会检查 镜像值期望值 是否一致,如果不一致,则调用 write() 修改 硬件寄存器 的值,并更新 镜像值;它和 write 的区别在于,它不需要人为指定写入的数据,因为写入的数据是 期望值

因此在实际使用中,经常和 set() 配套使用:首先通过 set() 修改 期望值,再通过 update() 将这个新的 期望值 更新到 DUT 镜像值

高频问题 8:讲讲镜像值、期望值?

UVM 源代码规定了每一个 uvm_reg_field 都有四个成员变量:复位值随机值镜像值期望值

复位值

复位值通过 configure() 配置;在配置好寄存器模型之后,通常使用 reset() 对寄存器模型进行复位,实际上就是将【剩余三个值】全部更新为【复位值】

如果后续想修改复位值,可以使用 set_reset();如果想读取复位值,可以使用 get_reset() 函数

随机值

随机值是 唯一使用 rand 修饰 的成员变量;我们通常在 configure() 中配置 field 的随机属性

  • 如果允许随机:调用 randomize 函数 就会更新 随机值期望值
  • 如果不允许随机:调用 randomize 函数 就会将 期望值 赋值给 随机值

镜像值和期望值

镜像值表示的是 当前硬件寄存器值的映射;期望值表示的是 user 期望硬件寄存器拥有的值;UVM 提供了 predict() 函数来修改这两个值,目的是 保证【寄存器模型中的镜像值和期望值】最大程度的等价于【硬件寄存器组】;这个函数通常不需要 user 去调用

  • 如果 user 使用 后门访问,那么这个函数会在每一次后门访问之后 自动调用
  • 如果 user 使用 前门访问,必须要打开 set_auto_predict(),这个函数才会在每一次前门访问之后 自动调用

高频问题 9:什么是预测?两种预测方式?

讲到预测,就要说一下每一个 uvm_reg_field 包含的两个值:镜像值期望值;镜像值表示的是 当前硬件寄存器值的映射;期望值表示的是 user 期望硬件寄存器拥有的值

预测的目的就是:保证【寄存器模型中的镜像值和期望值】最大程度的等价于【硬件寄存器组】预测的方式有两种:自动预测 显示预测

自动预测

自动预测是通过 UVM 内建的 predict() 完成的,这个函数的作用是 更新寄存器模型的【镜像值】和【期望值】:如果 user 使用 后门访问,那么这个函数会在每一次后门访问之后 自动调用;如果 user 使用 前门访问,必须要打开 set_auto_predict(),这个函数才会在每一次前门访问之后 自动调用

自动预测的缺点显而易见:如果 user 不通过寄存器模型指定的访问方式(前门、后门)去访问硬件寄存器,那么寄存器模型的值将无法更新;

显示预测

使用显示预测可以弥补自动预测的不足:只要寄存器配置总线上有活动,就可以通过 monitor 捕捉,再通过 predictor 更新到寄存器模型中;缺点就是工作量大,需要实现 monitor 并集成 predictor

一旦集成了 predictor,就可以关闭 set_auto_predict(),因为寄存器模型的更新行为 只和 monitor 有关,和 predict() 脱钩了;但仅限于前门访问,因为 monitor 本质上还是在监测总线上的行为;对于后门访问,仍然需要 predict() 来更新寄存器模型

UVM(Universal Verification Methodology)寄存器模型是一用于验证芯片寄存器功能的标准方法。它提供了一个统一的、可重用的框架,用于建立和管理寄存器模型,以及执行寄存器访问和验证UVM寄存器模型的主要组成部分包括寄存器模型寄存器层次结构、寄存器操作和寄存器验证环境。 1. 寄存器模型UVM寄存器模型是一个抽象的表示,用于描述芯片内部的寄存器寄存器字段。它提供了一种结构化的方式来定义寄存器的属性、寄存器字段的位宽和访问权限等。 2. 寄存器层次结构:UVM寄存器模型支持多层级的寄存器结构,可以通过层级关系来描述芯片内部的寄存器模块和子模块。这样可以更好地组织和管理寄存器模型,并提供寄存器之间的相互作用和访问。 3. 寄存器操作:UVM提供了一系列的API,用于执行寄存器读写操作。通过这些API,可以向寄存器模型发送读写请求,并获取响应。同时,还可以对寄存器的访问进行配置和控制,如重置、写入默认值等。 4. 寄存器验证环境:UVM寄存器模型可以与其他验证环境进行集成,以验证寄存器功能的正确性。通过使用事务级建模(TLM)接口,可以将寄存器操作与其他验证组件进行交互,并进行功能验证、覆盖率分析和错误注入等。 总之,UVM寄存器模型提供了一种规范化的方法来描述和验证芯片寄存器功能。它具有可重用性、灵活性和扩展性,并能与其他验证组件进行集成,从而提高验证效率和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值