写在前面:本章可能个人认为是全书最为复杂的一章,也是UVM的提升所在.通过自己的学习,自己有以下几点针对本章的学习建议;
1.如果可能的话,建议先有sv验证reg的经验,这样更能体会UVM的方便之处
2.前边六章内容,要熟悉,第七章不会刻意提及前边的知识点
3.如果第一次看不懂不要勉强,多看几次.另外看的时候一定结合代码,必要的时候看看源代码,有助于理解
4.个人感觉这部分我依据书中的思路梳理的不是很好,可以参考我单独写的一篇关于UVM寄存器模型的知识梳理UVM寄存器模型笔记_IC-V的博客-CSDN博客
目录
1.reg_mod怎么通过seq产生一个uvm_re_bus_op变量?
7.1寄存器模型简介
1 2.2.1和7.1.1的dut
可能部分同学对dut的理解不透彻,可以结合下边两个图来理解,分别是2.2.1和7.7.1的dut图.
2.什么是寄存器配置总线?
用于配置寄存器的端口的集合.在7.1.1中端口有
rand bit[15:0] rd_data;
rand bit[15:0] wr_data;
rand bit[15:0] addr;
rand bus_op_e bus_op;
参考前6章的构造,我们还需要搭建一套UVM层次结构发送transaction到dut_reg,从而实现配置寄存器,实现的这一系列构造称之为总线.
同样的我们把bus_seq放在了case中,最好打开7.1.1my_case0.sv的代码进行阅读,对比之前发生了什么变化.
3.引入寄存器模型
需要是:在ref_mod中获取dut_reg的值,以便更新ref_mod_output,才可以和dut_output在scb中进行对比.遇到的问题有:①如何在ref_mod中控制seq,读回data②假设读回之后,如何发送至ref_mod
解决是:引入寄存器模型reg_mod,具体使用要看后边讲解,有些书中的总结性语言,可能一开始不会明白,但是一定要记住初始的需求是什么,这样有助于理解.
不过参考代码清单7-6,你可以大概理解寄存器模型直接用read这个函数,读取到了value.
4.关于uvm_reg_map
需要自行了解一下基地址/偏移地址/绝对地址等相关寻址的知识
7.2 简单的寄存器模型
1.reg_mod怎么通过seq产生一个uvm_re_bus_op变量?
这个变量的出现会让初学者一开始有点懵逼,同时会影响对adapter以及相关集成的理解,因为这个变量出现在了adapter中,但是他是怎么从ref_mod中产生的呢?我们又该怎么理解这句话呢(书p.225顶部)?
我们先找到了my_modle,其中要通过寄存器模型前门访问获得寄存器的值:
task my_model::main_phase(uvm_phase phase);
my_transaction tr;
my_transaction new_tr;
uvm_status_e status;
uvm_reg_data_t value;
super.main_phase(phase);
p_rm.invert.read(status, value, UVM_FRONTDOOR);//我们关注这个value是什么?
while(1) begin
port.get(tr);
new_tr = new("new_tr");
new_tr.copy(tr);
//`uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
//new_tr.print();
if(value)
invert_tr(new_tr);
ap.write(new_tr);
end
endtask
查整个read函数的声明
task uvm_reg::read(output uvm_status_e status,
output uvm_reg_data_t value,//发现value是uvm_reg_data_t
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
XatomicX(1);
XreadX(status, value, path, map, parent, prior, extension, fname, lineno);
XatomicX(0);
endtask: read
查一下uvm_re_bus_op
typedef struct {
uvm_access_e kind;
uvm_reg_addr_t addr;
uvm_reg_data_t data;//发现uvm_reg_data_
int n_bits;
uvm_reg_byte_en_t byte_en;
uvm_status_e status;
} uvm_reg_bus_op;
2.集成寄存器模型
本质上是reg_mod/adapter/bus_agent.sqr三者的集成
先例化reg_mod(并进行一系列配置)/adapter,最后通过reg_mod.map.set_sequencer集成
3.对寄存器模型的读写
1.在ref_mod或其他comp中从reg_mod读取值
ref_mod的层次结构是env.ref_mod,而env和reg_mod一起在base_test中例化,因此通过env.p_rm可以进行传递,然后ref_mod可以调用reg_mod
2.向reg_mod写入
写便是向reg_mod使用write函数写入transaction,在seq中调用write,同在seq中获取sqr一样,同样把reg_mod在v_sqr中声明,在base_test中完成连接(如同之前在base_test中完成sqr的连接一样),然后就可以在seq中调用了.