UVM register model 寄存器模型中:peek()与reg_model.reg_name.value获取的值不同的原因

本文详细解析了UVM验证平台中寄存器模型的实现及其前后门访问方法的区别。作者通过具体案例阐述了使用不同函数(如get_mirrored_value(), peek()等)获取寄存器值时的现象与原因,揭示了寄存器模型与DUT间值同步的机制。

最近因为项目需要,负责给基于UVM验证平台添加寄存器模型。
参考了张强的《UVM实战:卷1》中第七章的内容,并借鉴了其他项目的code。
总算实现了寄存器模型,利用predictor和adapter,实现了寄存器模型的前门访问。
然后进而实现后门访问。代码实现比较简单。但是之后验证功能时,发现与自己的预估有出入。
发现,对UVM寄存器模型的认识,更深入了。
特此将碰到情况及理解记录下来。

首先说明遇到的问题。
在实现寄存器模型的后门访问后,采用了几种读取值的办法去验证代码功能,但是竟然发现有些方法读取的值并不是我期望的。
首先用寄存器模型的前门访问方式,给模型的某个寄存器写值,然后分别用
(1)get_reg_by_offset() 获取寄存器模型中的寄存器指针,由 get_mirrored_value() 从该指针获取值
(2)reg_model.reg_name.value 通过层次结构直接获取寄存器模型中寄存器的值
(3)reg_model.reg_name.peek() 利用peek()函数直接后门读取dut的reg(或者poke(),功能是写dut的reg)

在代码中的形式如下:

xx.get_reg_by_offset()                                     //  获取寄存器模型中的寄存器指针
value1 = xx.get_mirrored_value()                           //  从该指针获取值
value2 = reg_model.reg_name.value                          //  通过层次结构直接获取寄存器模型中寄存器的值
value3 = reg_model.reg_name.peek(status, reg_value)        //  利用peek()函数直接后门读取dut的reg(或者poke(),功能是写dut的reg)

发现value1和value2的值保持一致,value3有时与value1/value2不同。

纠结了一番后,总算明白了其中缘由。

首先明白一个概念,这里涉及到了两个地方的值,一个是寄存器模型中的寄存器的值,一个是dut内部真正的寄存器的值,要搞清楚上面提到的现象,就得时刻区分读取的值,到底是dut内部的寄存器的值,还是寄存器模型中的寄存器的值。

value1和value2,都是读取的寄存器模型中的寄存器的值。
value3读取的dut中寄存器的值。

先说说,实际仿真看到的波形。
最起初,三者的值相同。
然后利用predictor更新寄存器模型中寄存器的值,注意,这个操作只更新寄存器模型中的值,并不更新dut中寄存器的值。
于是乎,此时,value1和value2的值相同是更新后的值,value3的值依旧是刚开始的值。
然后用poke()功能,给dut的该寄存器写一个值。
此时,value1,value2和value3的值都是新写的值。

那么问题就来了,为什么中间会出现value1和value2的值相同,和value3的值不同?

其实并没有真正发生value1和value2的值相同,和value3的值不同的情况。
由于测试激励写的不够充分,在测试激励文件的initial模块中,每次查看值的时候,都会按顺序调用上面的代码片段。在systemverilog的initial块中,代码是顺序执行的。
因为value1和value2都是读取的寄存器模型的值,所以二者是一样的。
value3读取的是dut的值,因为predictor只更新寄存器模型的值,并不修改dut的值,所以,value3自然还是保持之前的值。
另外,调用peek()函数读取dut中的值,会顺带更新寄存器模型中的值,如果写激励时在获取value3后,再次获取value1和value2的值,就会发现value1与value2的值也变得和value3相同。

说到底,还是一开始不知道peek()函数执行后,会更新寄存器模型的值。

<think>我们正在讨论UVM中的寄存器访问方法。用户的问题集中在两个方面:1.如何使用`uvm_hdl_read`来获取层次化路径(hier)的实际2.如何通过UVM寄存器模型registermodel获取寄存器的实际根据引用内容,我们有一些关于UVM寄存器模型的背景信息,但并没有直接提到`uvm_hdl_read`。不过,我们可以结合UVM知识和引用内容来回答。首先,`uvm_hdl_read`是UVM提供的一个DPI(DirectProgrammingInterface)函数,用于通过后门(backdoor)访问HDL信号的。它可以直接读取RTL中信号的,而不通过总线接口(即不通过前门访问)。其次,UVM寄存器模型提供了一个抽象的寄存器表示,它可以通过前门(使用总线事务)或后门(直接访问HDL信号)来读写寄存器。寄存器模型中的寄存器通常是其抽象表示,要获取实际RTL中的,可以通过后门读取或使用预测器(predictor)来保持同步。下面我们详细说明:一、使用`uvm_hdl_read`获取层次化路径的实际`uvm_hdl_read`的函数原型为:`functionintuvm_hdl_read(stringpath,outputbit[63:0]value);`其中:-`path`是RTL中信号的完整层次路径(必须是字符串)-`value`是读取到的信号(最多64位)使用步骤:1.在验证环境中,确定要读取的信号的完整层次路径。例如,顶层模块中的某个信号:`top.dut.reg1.field1`。2.调用`uvm_hdl_read`函数,传入路径和用于存储的变量。3.检查返回:如果返回0表示读取失败,返回1表示成功。示例代码:```systemverilogbit[31:0]reg_value;if(uvm_hdl_read("top.dut.reg1.field1",reg_value))`uvm_info("HDL_READ",$sformatf("Valueoftop.dut.reg1.field1is%0h",reg_value),UVM_LOW)else`uvm_error("HDL_READ","Failedtoreadsignal")```注意:使用前需要确保该路径在UVM的HDL路径映射中已经设置(通常通过`uvm_reg::add_hdl_path`等函数设置),或者直接使用绝对路径。如果路径不正确,读取会失败。二、通过UVM寄存器模型获取寄存器的实际寄存器模型提供了两种访问方式:前门(frontdoor)和后门(backdoor)。要获取寄存器的实际,我们可以使用后门读取,因为它直接读取RTL中的当前。在寄存器模型中,每个寄存器都关联了HDL路径。通过后门读取,寄存器模型会使用`uvm_hdl_read`(内部调用)来获取。步骤:1.寄存器模型中,对目标寄存器调用`read`或`peek`方法,并指定访问路径为后门(UVM_BACKDOOR)。-`read`:通过总线协议读取(前门)或后门读取,并将读取的更新到寄存器模型的镜像。-`peek`:只通过后门读取,不经过总线,同样会更新镜像。2.读取后,可以通过寄存器模型的镜像(`get_mirrored_value()`)或者期望(`get_desired_value()`)来获取。但是,如果我们使用后门读取,那么镜像就是实际硬件中的。示例代码:```systemveriloguvm_status_estatus;uvm_reg_data_tvalue;//使用后门读取reg_model.reg1.read(status,value,.path(UVM_BACKDOOR));//或者使用peek(专门用于后门)reg_model.reg1.peek(status,value);//读取成功后,value就是实际寄存器的if(status==UVM_IS_OK)`uvm_info("REG_READ",$sformatf("Valueofreg1is%0h",value),UVM_LOW)else`uvm_error("REG_READ","Failedtoreadregister")```注意:使用后门访问之前,必须确保寄存器模型中已经设置了正确的HDL路径(在构建寄存器模型时通过`add_hdl_path`等方法设置)。否则,寄存器模型无法找到对应的HDL信号。三、引用内容的相关信息引用[2]提到了访问路径的枚举:-UVM_FRONTDOOR:使用前门-UVM_BACKDOOR:使用后门-UVM_PREDICT:通过预测器更新-UVM_DEFAULT_PATH:由上下文指定引用[3]提到了生成寄存器模型时使用`ralgen`工具,其中选项`-b`用于生成完整的后门路径(hdl_path)。这说明了在生成寄存器模型时,后门路径的设置非常重要。总结:1.`uvm_hdl_read`是一个底层的DPI调用,可以直接读取HDL信号,但需要提供完整的层次路径。2.寄存器模型通过后门访问(使用`peek`或`read`指定后门路径)可以间接调用`uvm_hdl_read`来获取寄存器的实际,但前提是寄存器模型已经正确配置了HDL路径。下面生成相关问题:</think>### 通过 UVM 获取寄存器实际的两种方法 #### **1. 使用 `uvm_hdl_read` 获取层次化信号** `uvm_hdl_read` 是 UVM 提供的 DPI-C 接口函数,**直接读取 RTL 层次路径对应的信号**(后门访问)。 **步骤**: 1. **定义信号路径**: 提供完整的 RTL 层次路径(如 `"top.dut.reg_field"`)。 2. **调用函数**: ```systemverilog bit [63:0] value; // 存储读取(最大64位) int status = uvm_hdl_read("top.dut.reg_field", value); ``` - `status=1`:读取成功,`value` 为实际信号。 - `status=0`:路径错误或信号不存在。 3. **示例**: ```systemverilog if (uvm_hdl_read("tb.dut.ctrl_reg.enable", value)) `uvm_info("HDL_READ", $sformatf("Enable bit= %0d", value[0]), UVM_LOW) else `uvm_error("HDL_READ", "Path not found") ``` #### **2. 通过寄存器模型获取寄存器** 寄存器模型(RAL)通过抽象方法访问寄存器,支持**前门(Frontdoor)** 和**后门(Backdoor)** 两种方式: - **后门读取(推荐)**:直接读取 RTL 信号(底层调用 `uvm_hdl_read`)。 ```systemverilog uvm_status_e status; uvm_reg_data_t reg_value; // 存储寄存器 reg_model.reg_name.read(status, reg_value, .path(UVM_BACKDOOR)); // 显式指定后门 ``` - **前门读取**:通过总线协议访问(需适配器 `uvm_reg_adapter`)。 ```systemverilog reg_model.reg_name.read(status, reg_value, .path(UVM_FRONTDOOR)); ``` - **镜像 vs. 实际**: - `get()`:返回寄存器模型的**镜像**(可能未同步)。 - `read()`/`peek()`:返回**实际硬件**(`peek` 仅限后门)[^3]。 #### **关键配置** - **后门路径映射**: 寄存器模型需关联 RTL 路径(通常在 `add_hdl_path` 中定义): ```systemverilog reg_block.add_hdl_path("top.dut", "RTL"); // 关联层次路径 ``` - **生成寄存器模型**: 使用 `ralgen` 工具时,添加 `-b` 选项生成后门访问逻辑[^3]: ```bash ralgen -b -t my_block -c my_regs.xml ``` #### **两种方法对比** | **方法** | **优点** | **缺点** | |------------------------|-----------------------------------|------------------------------| | `uvm_hdl_read` | 直接访问任意信号,无需寄存器模型 | 需手动管理路径,易出错 | | **寄存器模型后门访问** | 抽象度高,路径自动映射,支持同步 | 需提前构建寄存器模型 | > **应用场景建议**: > - 调试临时信号 → `uvm_hdl_read` > - 寄存器验证 → 寄存器模型(后门优先) --- ### 相关问题 1. **如何确保 `uvm_hdl_read` 的路径正确性?有哪些调试技巧?** 2. **寄存器模型镜像实际不同步时如何排查?** 3. **RAL 模型中 `frontdoor` 和 `backdoor` 访问的性能差异是什么?** 4. **使用 `ralgen` 生成寄存器模型时,`-b` 和 `-B` 选项的具体作用是什么?**[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值