问题描述
假如有uvm_reg_block
A, A有以下特性:
- A有default_map,并且实例化
- A有四个sub-block的实例:A0/A1/A2/A3, 均为leaf block
- A0/A1/A2/A3的default_map均通过add_submap的方式,添加到A的default_map中
假如有uvm_reg_block
B扩展自uvm_reg_block, B有以下特性:
- B有default_map,并且实例化
- B有一个block A的实例
- B有若干块mem的实例
- A的实例通过add_submap的方式添加到A的default_map中
- mem通过default_map.add_mem的方式添加到B的default_map中去
执行uvm_reg_hw_reset_seq
,发现A0/A1/A2/A3
的寄存器被重复读了2次。
定位发现在uvm_reg_hw_reset_seq
的do_block
task中,认为B有
一个memory map
,即default_map
。default_map
有5个sub map:
- A
- A.A0
- A.A1
- A.A2
- A.A3
do_block
会对block进行遍历,遍历到叶子block时,进行寄存器的读操作。首先对A进行遍历,此时会执行A0~A3的读操作;接着执行A0的读操作;再接着执行A1的读操作;然后接着执行A2的读操作;最后执行A3的读操作。
因此导致A0/A1/A2/A3
的寄存器被重复读了2次。
解决办法
- B派生子A
- B中只对mem进行例化,并添加到default_map中
systemRDL是将每个memory独立封装在一个uvm_reg_block中,每个uvm_reg_block有自己的default_map,示例代码如下:
//rdl文件定义
mem U_RAM_0 {
mementries = 512;
memwidth = 24;
sw = rw;
};
addrmap csr_ahb {
external U_RAM_0 U_RAM_0 @0x10000000;
};
生成的ral model代码如下:
// Mem - U_RAM_0
class U_RAM_0 extends uvm_reg_block;
`uvm_object_utils(U_RAM_0)
rand uvm_mem m_mem;
function new(string name = "U_RAM_0");
super.new(name);
endfunction : new
virtual function void build();
this.default_map = create_map("reg_map", 0, 3.0, UVM_NO_ENDIAN);
this.m_mem = new("m_mem", 512, 24, "RW");
this.m_mem.configure(this);
this.default_map.add_mem(this.m_mem, 0);
endfunction : build
endclass : U_RAM_0
例化如下:
class csr_ahb extends uvm_reg_block;
...
rand U_RAM_0 U_RAM_0;
this.U_RAM_0 = U_RAM_0::type_id::create("U_RAM_0");
this.U_RAM_0.configure(this);
this.U_RAM_0.build();
this.default_map.add_submap(this.U_BASE_FLOW_RAM_0.default_map, 'h10000000);
endclass