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

本文详细介绍了UVM寄存器模型中期望值、镜像值和实际值的概念,以及uvm_reg_field中的关键方法如randomize、set、get、mirror、update等的工作原理。此外,还探讨了uvm_reg中与寄存器操作相关的功能,如write、read、predict等。

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

讨论寄存器模型中涉及到各种值以及对应的方法,我们还是要从其中的最小存储单元uvm_reg_field开始讲起

uvm_reg_field

我们先看看uvm_reg_field的定义
在这里插入图片描述

我们可以看到这里涉及到了4个值类型:

  1. value:唯一一个没有被local修饰的值类型,即寄存器模型可以直接访问,也是唯一一个用rand修饰的字段,即对寄存器模型里的寄存器进行随机时value用来存储随机后的随机值(关于这个随机值的值内容有什么特点我们后面会具体讲),并且这个值也是我们对寄存器模型收集覆盖率所sample的值。

  2. m_mirrored(镜像值):存放我们认为此时DUT里寄存器的实际值。

  3. m_desired(期望值):存放我们期望DUT寄存器被赋予的值。

  4. m_reset[“HARD”](复位值):存放硬复位值。m_reset其实是一个以字符串为索引(key)以uvm_reg_data_t为值(value)的联合数组类型,除了默认的key="HARD"类型的硬复位值,我们还可以添加我们自定义的复位类型对。

上面这4种值类型,除了value都是用local修饰的,即除了uvm_reg_field本身和它的子类,其他外部类都无法直接访问,所以自然就需要提供一些访问(写和读)它们的函数。

首先我们看下我们创建uvm_reg_fiedl都会调用的configure()函数具体都执行了什么
在这里插入图片描述
在这里插入图片描述

这里需要注意的几点就是,当在uvm_reg中调用某个uvm_reg_field的configure()函数时:

  1. has_reset参数决定了m_reset[“HARD”]是否被赋值,赋值内容为reset参数所给的值

  2. access和is_rand共同决定了在执行randomize的时候value值是否会被随机。

set_reset()

在这里插入图片描述

这里我们涉及到了第一个修改uvm_reg_field里复位值的函数set_reset(),我们可以通过调用set_reset()函数实现对m_reset[string]关联数组的赋值,这样便可以覆盖我们在调用寄存器模型初始化configure的硬复位值,全局修改m_reset[“HARD”]值,当然也可以自定义添加其他复位值类型。

reset()

在这里插入图片描述

这是与复位相关的另一个函数,它实现了将uvm_reg_field中m_mirred、m_desired、value都赋值成我们预先设置的reset值(reset值即可以是默认的key=“HARD”,也可以是我们预先定义的key对应的reset值),同时将m_written变量赋值为0表示该uvm_reg_field没有被写过,纵观整个uvm_reg_field类的定义,只有在do_predict()函数里才有涉及到将m_written赋值为1的情况,后面我们再具体介绍do_predict()函数,这里先埋个伏笔。

set_reset()和reset()是用来修改reset值,而获取reset值包含如下两个函数
在这里插入图片描述<

UVM寄存器模型中,mirror方法用于更新寄存器模型镜像。其原理和方式与寄存器模型镜像概念以及整体操作机制相关镜像表示当前硬件状态的已知,往往由模型预测给出,在前门访问时通过观察总线或在后门访问时通过自动预测等方式来给出。不过,镜像有可能与硬件实际不一致,无法保持同步更新[^3]。 mirror方法更新镜像的具体方式和原理如下: - **前门访问情况**:当使用前门访问时,monitor会捕捉到总线上面的行为(对DUT寄存器进行读写),然后做预测(predict)后更新镜像。但对于RAL中的寄存器,在RAL没有去读DUT中的对应的状态REG时候是不会自动更新的(后门读也可以用来更新),必须通过前门读操作走出这一步才会更新。例如,在使用UVM寄存器模型时,若通过前门访问读取硬件寄存器的,mirror方法会根据读取到的硬件来更新寄存器模型中的镜像。 - **后门访问情况**:在后门访问时,通过自动预测等方式给出镜像。当调用mirror方法时,它会获取硬件寄存器的实际,并将其更新到寄存器模型镜像中。 - **结合期望值情况**:随机化针对的是期望值,随机化对mirror value不起作用。在调用mirror方法前,若对期望值进行了设置,然后通过update方法期望值写入硬件,之后调用mirror方法,它会检查硬件镜像是否一致,并根据硬件更新镜像。例如以下代码: ```systemverilog class MyReg extends uvm_reg; rand uvm_reg_field data; function new(string name = "MyReg"); super.new(name, 32, UVM_NO_COVERAGE); endfunction virtual function void build(); data = uvm_reg_field::type_id::create("data",, get_full_name()); data.configure(this, 32, 0, "RW", 0, 32'h0, 1, 1, 1); endfunction endclass // 在测试用例中 task run_phase(uvm_phase phase); MyReg reg_inst; uvm_status_e status; uvm_reg_data_t data_val; reg_inst = reg_block.my_reg; // 假设 reg_block 是寄存器块 // 设置期望值 reg_inst.data.set(32'hA5A5_A5A5); $display("Desired value: %0h", reg_inst.data.get()); // 将期望值写入硬件 reg_inst.update(status); $display("Mirrored value after update: %0h", reg_inst.data.get_mirrored()); // 读取硬件并检查 reg_inst.mirror(status, UVM_CHECK); $display("Mirrored value after mirror: %0h", reg_inst.data.get_mirrored()); endtask ``` 在上述代码中,先设置了期望值,然后通过update方法期望值写入硬件,最后调用mirror方法读取硬件并更新镜像,同时可以通过`UVM_CHECK`参数检查硬件镜像是否一致。 若访问寄存器有多重总线访问方式,monitor可能没有都检测到,那就没法及时更新镜像。在硬件行为异常(例如写入失败)时,镜像可能无法达到期望值,验证时可以通过mirror方法检测不一致,这也体现了mirror方法在更新镜像以及验证硬件与模型一致性方面的重要作用[^1][2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值