实验5中完成以下内容:
关于 UVM 寄存器模块的应用。
- 对uvm_reg的定义,以及uvm_reg_block的组织
- 对uvm_reg_adapter的定义,以及它与uvm_reg_block 之间的关系0
- 对uvm_reg_predictor的使用,以及它与uvm_reg_adapter和uvm_reg_block之间的关系。
- 改造之前的寄存器发送序列,并以uvm_reg 的操作方式去取代
- 应用内建的寄存器序列,做全面的寄存器测试
一、知识巩固复习
P405页:
类名 | 功能 |
uvm_reg_field | 用来针对寄存器功能域来构建对应的比特位 |
uvm_reg | 与寄存器相匹配,其内部可以例化和配置多个uvm_reg_field对象 |
uvm_mem | 匹配硬件存储模型 |
uvm_reg_map | 用来指定寄存器列表中各个寄存器的偏移地址、访问属性以及对应的总线 |
uvm_reg_block | 可以容纳多个寄存器(uvm_reg)、存储器(uvm_mem)、和寄存器列表(uvm_reg_map) |
二、实验部分
寄存器模型的完善和嵌入
在接下来的实验中,同学们可以看到,uvm_reg和uvm_reg_block 的定义已经完成。请结合红宝书14.1节,来理解mcdf_rgm 寄存器模块的定义同时,请继续完成以下的实验步骤
实验1.1,请实现 reg2mcdf_adapter 类的方法reg2bus以及bus2reg,可参考红宝书14.2.3节
uvm_reg类如下:(uvm白皮书P223-224有详细介绍)
uvm_reg_block类如下:
reg2mcdf_adapter 类的方法reg2bus以及bus2reg如下:
实验1.2,请在 mcdf_env 中分别声明 register block,adapter和 predictor,并完成例化。同时,在 connect 阶段中,请组织它们的关系,做必要的句柄连接。
声明和例化及连接
set_sequencer的用法???????
monitor.analysis_port的连接
寄存器模型的使用
寄存器模型很大的一个优势在于它的抽象性和复用性,接下来,我们将会改造之前的激励序列。请按照以下要求完成实验:
实验2.1,请完成register block 句柄的传递
mcdf_rgm rgm在mcdf_virtual_sequencer、mcdf_env、mcdf_base_virtual_sequence中均例化了,在mcdf_virtual_sequencer中只是声明了一个句柄,并未进行连接,其声明如下:
句柄的传递主要发生在mcdf_env、mcdf_base_virtual_sequence中(这两个其中也声明了),如下所示:
实验2.2,请将mcdf_data_consistence basic_virtual sequence 原有的由总线sequence实现的寄存器读写,改为由寄存器模型操作的寄存器读写方式,可参考红宝书14.2.5 节
改用了寄存器方式的读写如下:
rgm.chnl0_ctrl_reg.write(status, wr_val);
rgm.chnl0_ctrl_reg.read(status, rd_val);
uvm_reg::read()/write()任务:
这两个任务常用的参数是前三个,
其中第一个是uvm_status_e型的变量,这是一个输出,用于表明读/写操作是否成功;
第二个是读取或者要写的值,也是一个输出/输入;
第三个是读取/写入的方式,可选UVM_FRONTDOOR和UVM_BACKDOOR。
实验2.3,请将mcdf full random_virtual_sequence 原有的由总线sequence 实现的营存器读写,改为由寄存器模型预先设置寄存器值,再统一做总线寄存器更新的方式,并且稍后由后门读取的方式取得寄存器值,加以比较
修改前:
修改后:
mirror()操作:
跑仿真时可以试试rgm.mirror(status, UVM_CHECK, UVM_BACKDOOR);
用于读取DUT中寄存器的值,并将他们更新到寄存器模型中。
他有多个参数,常用的只有前三个。其中第二个参数指的是如果发现DUT中寄存器的值与寄存器模型中的镜像值不一样,那么在更新寄存器模型之前是否给出错误提示。其可选的值为UVM_CHECK和UVM_NO_CHECK。
它有两种应用场景,一是在仿真中不断地调用它,使得到整个寄存器模型的值与DUT中寄存器的值保持一致,此时check选项 是关闭的。二是在仿真即将结束时,检查DUT中寄存器的值与寄存器模型中寄存器的镜像值是否一致,这种情况下,check选项是打开的。
mirror操作会更新期望值和镜像值。同update操作类似,mirror操作既可以在uvm_reg级别被调用,也可以在uvm_reg_block级别 被调用。当调用一个uvm_reg_block的mirror时,其实质是调用加入其中的所有寄存器的mirror。
前文已经说过,在通信系统中存在大量的计数器。当网络出现异常时,借助这些计数器能够快速地找出问题所在,所以必须 要保证这些计数器的正确性。一般的,会在仿真即将结束时使用mirror操作检查这些计数器的值是否与预期值一致。
寄存器内建序列的应用
参考红宝书14.3.5节,UVM 已经内建了一些寄存器序列,在接下来的实验中,我们将选择一些序列对寄存器展开全面测试:
实验3.1,在新建的mcdf_reg_builtin_virtual_sequence 类中,请使用uvm_reg_hw_reset_seq , uvm_reg_bit_bash_seq 和 uvm_reg_access_seq 对MCDF寄存器模块展开全面测试。在仿真过程中,请注意理解寄存器测试序列中打印的消息,对照红宝书表14.6,理解这些内建寄存器测试序列的作用。
经过六次 UVM 入门和进阶实验的“艰苦作战”,UVM 新兵训练终于可以结束了! 恭喜你,已经成为了一名新鲜出道的UVM verifier。在短暂的兴奋过后,路还会将你送上“真枪实弹”的UVM 实战现场,去零距离地感受一一什么是真实的硬件设计(MCDF 在设计上的升级版本)以及什么是更加完善的验证环境(现有 MCDF 验证环境的升级)。在接下来的 UVM 实战模块中我们将进一步降低授课时间而提高编程时间,目的仍然在于培养大家在“眼到”之后,可以“手到”和“心到”,知行合一。那么,就让我们在接下来的 UVM 实战模块中见吧!
randomize的其实是desired value的值
component和object都用type_id::create()创建的都是什么类型,端口使用new()创建