[UVM源代码研究] 聊聊寄存器模型的后门访问

本文详细探讨了UVM源代码中如何实现寄存器模型的后门访问,涉及uvm_reg_backdoor类、HDL路径管理、寄存器模型与RTL映射以及DPI的使用,为理解寄存器后门操作提供了深入剖析。

[UVM源代码研究] 聊聊寄存器模型的后门访问

引言

我们在之前的文章 [UVM源代码研究] 当我们使用寄存器模型里的寄存器调用write/read方法,数据包是如何在寄存器模型、adapter、sequencer中传递的 一文中 介绍了读写寄存器时UVM源代码的实现过程,对于后门访问只是一笔带过,不是所有的寄存器都支持后门访问,并且如果rtl的寄存器路径比较分散的话也不利于寄存器模型后门路径的设置,所以现实工作中使用后门访问的场景确实比较有限。但是后门访问有时可以大大简化我们的验证工作,尤其是在有些不得不使用寄存器模型后门访问的场景下又显得尤为重要(比如在check_phase这样一个function phase里试图获取DUT寄存器的值),本文就带着大家一起窥探下源代码中是如何实现寄存器模型的后门访问的。
寄存器模型相关的基本概念在之前的相关文章中已经详细讲解过了,这里就不多赘述了,具体可以参考以下几篇文章:

[UVM源代码研究] 当我们使用寄存器模型里的寄存器调用write/read方法,数据包是如何在寄存器模型、adapter、sequencer中传递的

[UVM源代码研究] 我们在使用UVM寄存器模型内建的sequence检查寄存器时UVM源代码都执行了些啥?

[UVM源代码研究] 聊聊寄存器模型中的期望值(desired value)、镜像值(mirrored value)以及DUT中的实际值(actual value)的相关概念及方法

[UVM源代码研究] 谈谈寄存器模型中predict

UVM源代码溯源

我们以后门写寄存器为例结合具体实例讲解下UVM源代码是如何实现寄存器模型的后门访问的。

源代码中涉及到的相关方法首先是write任务,如图1所示

图1 src/reg/uvm_reg.svh中的write()任务

在这里插入图片描述

wirte()中的核心方法是do_write(),其他内容可以认为是在等待寄存器的访问权限(Xtomic()任务)和更新期望值(set()函数)。do_write()任务如图2所示。

图2 src/reg/uvm_reg.svh中的do_write任务

在这里插入图片描述

do_write()我们分5大块来讲解其中UVM_BACKDOOR相关的代码,首先是第1步调用get_backdoor来获取uvm_reg_backdoor的句柄,uvm_reg_backdoor类的定义和描述如图2所示。

图3 src/reg/uvm_reg_backdoor.svh中uvm_reg_backdoor类的定义与描述

在这里插入图片描述

简单概括下这个类的功能就是作为用户使用backdoor的方式访问寄存器或者memory的积累,用户如果不想通过sv或者内置的DPI方式去后门访问寄存器模型的话,就可以从该类派生出自定义的backdoor访问类,override其中的相关方法来实现自定义形式的后门访问,默认情况下UVM源代码中是使用sv语法的DPI方式来实现寄存器的后门访问的,这个实现方法我们后面会具体讲,等于说我们要进行后面访问都是通过uvm_reg_backdoor或者其派生类来实现的,后面我们还会讲其中相关方法的具体实现。

继续回到图2中的第一步,我们是通过get_backdoor()来获取uvm_reg_backdoor的句柄的,get_backdoor()的定义如图4所示。

图4 src/reg/uvm_reg.svh中的get_backdoor函数

在这里插入图片描述

如果我们未曾对backdoor进行任何的设置(没有自定义的uvm_reg_backdoor模型),那么默认的m_backdoor就是null,inherited缺省值为1,图4中1368行就会调用该uvm_reg所在的寄存器模型uvm_reg_block中的get_backdoor()函数,如图5所示。

UVM(Universal Verification Methodology)寄存器模型提供了一种抽象的方式来描述硬件寄存器的行为和访问方式。后门访问Backdoor Access)是UVM寄存器模型中一个关键的机制,它允许在仿真环境中绕过标准的寄存器访问路径,直接对DUT(Design Under Test)中的寄存器进行读写操作。 后门访问的核心思想是通过直接访问DUT的信号层级,而不是通过寄存器模型的前端接口(如AHB、APB等)。这种访问方式在验证过程中非常有用,尤其是在需要快速设置寄存器值或检查寄存器状态时,避免了复杂的事务级操作。 ### 后门访问的实现方式 在UVM中,后门访问通常通过以下几种方式实现: 1. **使用`uvm_hdl`任务** UVM提供了一组`uvm_hdl`相关的任务和函数,用于直接访问DUT的信号。例如: - `uvm_hdl_read(path, value)`:读取DUT中指定路径的信号值。 - `uvm_hdl_write(path, value)`:将指定值写入DUT中指定路径的信号。 这些任务通过HDL路径(如`dut.reg1`)直接访问DUT的信号,从而实现对寄存器的后门操作。这种方式的优点是简单直接,但需要确保路径名称正确,并且依赖于仿真工具的支持[^1]。 2. **通过寄存器模型的`backdoor`方法** UVM寄存器模型中的寄存器和字段可以通过`backdoor`方法进行访问。例如,调用`reg.write(.value(32'hDEAD_BEEF), .path(UVM_BACKDOOR))`会直接通过后门写入寄存器,而不会触发前端接口的事务。类似地,`reg.read(.value(data), .path(UVM_BACKDOOR))`可以直接读取寄存器的值。这种方式的优点是与寄存器模型紧密结合,能够自动处理寄存器字段的位掩码和偏移量。 3. **使用`UVM_REG_BACKDOOR`宏** 在寄存器模型的定义中,可以通过`UVM_REG_BACKDOOR`宏指定某些寄存器或字段的后门访问方式。这种方式通常用于配置寄存器模型,使其在特定情况下自动使用后门访问。 ### 后门访问的应用场景 后门访问机制在验证过程中有多种应用场景: - **快速初始化寄存器**:在测试开始时,后门访问可以快速设置寄存器的初始值,而不需要通过复杂的前端接口进行逐个写入。 - **调试和验证**:在调试过程中,后门访问可以绕过复杂的事务流程,直接检查或修改寄存器的值,帮助快速定位问题。 - **覆盖测试**:在某些测试中,可能需要覆盖寄存器的某些特殊状态,而后门访问可以绕过硬件逻辑的限制,直接设置这些状态。 ### 后门访问的限制 尽管后门访问在验证中非常有用,但它也有一些限制: - **依赖于仿真工具**:后门访问通常依赖于仿真工具的支持,某些工具可能不支持直接访问信号路径,或者需要特定的编译选项。 - **不触发硬件逻辑**:后门访问直接修改寄存器的值,而不会触发硬件逻辑(如中断、状态机变化等),这可能导致某些行为无法被完全验证。 - **路径名称的维护**:使用`uvm_hdl`任务时,需要维护DUT信号的路径名称,这在设计变更时可能会导致问题。 ### 示例代码 以下是一个使用后门访问的简单示例: ```systemverilog class my_test extends uvm_test; my_reg_block reg_model; virtual task run_phase(uvm_phase phase); phase.raise_objection(this); // 使用后门写入寄存器 reg_model.my_reg.write(.value(32'hDEAD_BEEF), .path(UVM_BACKDOOR)); // 使用后门读取寄存器 reg_model.my_reg.read(.value(data), .path(UVM_BACKDOOR)); `uvm_info("BACKDOOR", $sformatf("Register value: %0h", data), UVM_LOW) phase.drop_objection(this); endtask endclass ``` 在上述代码中,`my_reg.write`和`my_reg.read`通过后门访问直接操作寄存器的值,而不需要通过前端接口。 ### 相关问题 1. UVM寄存器模型中如何配置后门访问的路径? 2. 后门访问与前端访问的主要区别是什么? 3. 如何在UVM中调试后门访问失败的问题? 4. 后门访问是否会影响覆盖率收集? 5. 在哪些情况下应避免使用后门访问
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值