[CU]reg model构建篇-uvm_reg_block
1. uvm_reg_block的特点
(1) 一个寄存器模型必须包含一个reg_block; 一般DUT内具有相同的基地址的所有寄存器,会放在一个reg_block中.
(2) uvm_reg_block可以包含任意数量的uvm_reg, register files, memories以及其他低层次的uvm_reg_block;
(3) uvm_reg block里含有uvm_reg_map类对象default_map,用于地址映射以及完成寄存器前门访问操作;
(4) 一个uvm_reg_block可以包含多个uvm_reg_map,从而实现一个uvm_reg_block应用到不同总线,或不同地址段上;
2. uvm_reg_block源码
1 virtual class uvm_reg_block extends uvm_object; 2 //parent表示此uvm_reg_block所在的uvm_reg_block,即父uvm_reg_block; 3 local uvm_reg_block parent; 4 5 local static bit m_roots[uvm_reg_block]; 6 //blks记录加入到此uvm_reg_block中的其他uvm_reg_block信息; 7 local int unsigned blks[uvm_reg_block]; 8 //regs表示加入到此uvm_reg_block中的其他uvm_reg信息; 9 local int unsigned regs[uvm_reg]; 10 `ifdef UVM_SPARSE_ARRAY 11 local int unsigned regarrays[uvm_reg_file]; 12 `endif 13 local int unsigned vregs[uvm_vreg]; 14 //mems表示加入到此uvm_reg_block中的uvm_mem信息; 15 local int unsigned mems[uvm_mem]; 16 local bit maps[uvm_reg_map]; 17 18 // Variable: default_path 19 // Default access path for the registers and memories in this block. 20 uvm_path_e default_path = UVM_DEFAULT_PATH; 21 22 local string default_hdl_path = "RTL"; 23 local uvm_reg_backdoor backdoor; 24 local uvm_object_string_pool #(uvm_queue #(string)) hdl_paths_pool; 25 ... 26 endclass
3. uvm_reg_block的函数
3.1 create_map函数
1 function uvm_reg_map uvm_reg_block::create_map(string name, 2 uvm_reg_addr_t base_addr, 3 int unsigned n_bytes, 4 uvm_endianness_e endian, 5 bit byte_addressing=1); 6 7 uvm_reg_map map; 8 9 if (this.locked) begin 10 `uvm_error("RegModel", "Cannot add map to locked model"); 11 return null; 12 end 13 14 map = uvm_reg_map::type_id::create(name,,this.get_full_name()); 15 map.configure(this,base_addr,n_bytes,endian,byte_addressing); 16 17 this.maps[map] = 1; 18 if (maps.num() == 1) 19 default_map = map; 20 21 return map; 22 endfunction
3.2 add_reg函数
1 function void uvm_reg_block::add_reg(uvm_reg rg); 2 if (this.is_locked()) begin 3 `uvm_error("RegModel", "Cannot add register to locked block model"); 4 return; 5 end 6 7 if (this.regs.exists(rg)) begin 8 `uvm_error("RegModel", {"Register '",rg.get_name(), 9 "' has already been registered with block '",get_name(),"'"}) 10 return; 11 end 12 13 regs[rg] = id++; 14 endfunction: add_reg
4. uvm_reg_block的实现
4.1 变量声明
(1) 声明rand类型的uvm_reg;
(2) 可能会声明uvm_reg_map,当然也可能不声明,而是采用已经声明过的default_map;
4.2 实现new函数
4.3 实现build函数
注1:当uvm_reg_block的build()函数执行完成后,整个register model的层次就构建成功了;
4.3.1 调用create_map函数例化default_map
(1.1)如果reg block内有命名的address map: build()函数需要通过调用uvm_reg_block:: create_map例化所有命名的address maps,并指定合适的参数值; 其中一个命名的address map会自动赋值给default_map,当然可以通过调用函数或者直接改变default_map所指向的对象;
1 class my_blk_type extends uvm_reg_block; 2 ... 3 virtual function void build(); 4 this.AHB=create_map(); 5 this.WSH=create_map(); 6 this.default_map=this.AHB; 7 endfunction 8 ... 9 endclass
(1.2)如果reg block没有任何命名的address map: build函数需要调用create_map函数实例化一个匿名的address map,并将其赋给default_map;
1 class my_blk_type extends uvm_reg_block; 2 ... 3 virtual function void build(); 4 this.default_map=create_map(.name(default_map), 5 .base_addr('h1000), 6 .n_bytes(4), 7 .endian(UVM_LITTLE_ENDIAN) 8 ); 9 endfunction 10 ... 11 endclass
(1.3) create_map函数参数的含义:
参数1含义:名字;
参数2含义:该reg_block的基地址;
参数3含义:寄存器所映射到的总线的宽度(单位是byte,不是bit);
4.3.2 build函数需要例化所有的register, register file, memory, sub-register block;
4.3.3 build函数需要调用所有register ,register file, memory, sub-register block的configure函数;
(1)以调用uvm_reg的configure函数为例,解释configure函数参数的含义:
参数1含义:此寄存器所在uvm_reg_block的指针,通常为this;
参数2含义:reg_file指针,参考uvm_reg_file使用方法二;
参数3含义:此寄存器的后门访问路径;
4.3.4 build函数需要调用所有register ,register file, memory, sub-register block的build函数;
4.3.5 build函数需要调用所有register ,register file, memory, sub-register block的add_hdl_path函数;
4.3.6 register或mem例化后,build函数需要调用合适的uvm_reg_map::add_*()函数;
(1) 需要将uvm_reg或uvm_mem添加到uvm_reg_map中,否则无法进行前门访问操作(如果一个寄存器可以通过两个物理总线访问,则需要将其添加到多个address map中);
(2) 以uvm_reg_map的add_reg函数为例,说明其参数的含义:
参数1含义:要加入的寄存器;
参数2含义:寄存器相对于uvm_reg_map base_addr的偏移地址;
参数3含义:寄存器的存取方式(uvm_reg_field是否能进行读写访问,不仅取决于其存取方式,也取决于其所在uvm_reg的存取方式);
1 virtual function build(); 2 ... 3 map=create_map("map",'h0,4,UVM_LITTLE_ENDIAN); 4 map.add_reg(reg1,32'h0,"RW"); 5 map.add_reg(reg2,32'h4,"RW"); 6 map.add_reg(reg3,32'h8,"RO"); 7 map.add_reg(reg4,32'h10,"RO"); 8 ... 9 lock_model(); 10 endfunction
4.3.7 调用add_submap函数建立顶层reg_block于sub_reg_block的reg_map的联系;
(1) sub-uvm_reg_block建成后,对于sub-uvm_reg_block内的每一个address map, parent-uvm_reg_block的build函数都需要调用uvm_reg_map::add_submap函数,并且制定sub address map相对于parent address map的offset;
1 class my_blk_type extends uvm_reg_block; 2 ... 3 virtual function void build(); 4 this.BLK1.build(); 5 this.BLK2.build(); 6 this.default_map.add_submap(this.BLK1.default_map,'h8000); 7 this.default_map.add_submap(this.BLK2.default_map,'hc000); 8 endfunction 9 10 endclass
4.3.8 lock_model();
5. uvm_reg_block示例
(1) uvm_reg_map不应该是rand类型的,同样也不能是array;
(2) uvm_reg/uvm_reg_file/sub-uvm_reg_block应该有rand属性,并且可能是array;
(3) uvm_mem不应该是rand类型的,但可能是array;
1 //示例1 2 class reg_model extends uvm_reg_block; 3 `uvm_object_utils(reg_model) 4 rand reg_invert invert; 5 6 function new(input string name="reg_model"); 7 super.new(name,UVM_NO_COVERAGE); 8 endfunction 9 10 virtual function void build(); 11 default_map=create_map("default_map",0,2,UVM_BIG_ENDIAN,0); 12 13 invert=reg_invert::type_id::create("invert",,get_full_name()); 14 invert.configure(this,null,""); 15 invert.build(); 16 17 default_map.add_reg(invert,'h9,"RW"); 18 endfunction 19 endclass
1 //示例2 2 class my_regmodel extends uvm_reg_block; 3 `uvm_object_utils(my_regmodel) 4 5 rand my_reg version; 6 function new(input string name="unnamed_my_regmodel"); 7 super.new(name,UVM_NO_COVERAGE); 8 endfunction 9 10 function void build(); 11 default_map=create_map("default_map",0,2,UVM_LITTLE_ENDIAN); 12 13 version=my_reg::type_id::create("version",,get_full_name()); 14 version.configure(this,null,"version"); 15 version.build(); 16 17 default_map.add_reg(version,16'h47,"RW"); 18 endfunction 19 20 endclass
1 //示例3 2 class my_blk_type extends uvm_reg_block; 3 `uvm_object_utils(my_blk_type) 4 5 uvm_reg_map AHB; 6 uvm_reg_map WSH; 7 8 rand my_r1_type R1; 9 rand my_r2_type R2[3]; 10 11 rand my_rf1_type RF1; 12 rand my_rf2_type RF2[3]; 13 14 my_mem1_type RAM1; 15 my_mem2_type RAM2[3]; 16 17 rand my_blk1_type BLK1; 18 rand my_blk2_type BLK2[3]; 19 20 function new(string name="my_blk_type"); 21 super.new(.name(name),.has_coverage(UVM_NO_COVERAGE)); 22 endfunction 23 24 virtual function void build(); 25 this.AHB=create_map(); 26 this.WSH=create_map(); 27 this.default_map=this.AHB; 28 29 this.BLK1=my_blk1_type::type_id::create("BLK1",null,get_full_name()); 30 this.BLK1.configure(this,...); 31 this.BLK1.build(); 32 ... 33 34 this.R1=my_reg1_type::type_id::create("R1",null,get_full_name()); 35 this.R1.configure(this,...); 36 this.R1.build(); 37 this.default_map.addr_reg(this.R1,'h04,...); 38 .. 39 endfunction 40 endclass
1 //示例4 2 package pss_reg_pkg; 3 import uvm_pkg::*; 4 `include "uvm_macros.svh" 5 6 import spi_reg_pkg::*; 7 import gpio_reg_pkg::*; 8 9 class pss_reg_block extends uvm_reg_block; 10 `uvm_object_utils(pss_reg_block) 11 rand spi_reg_block spi; 12 rand gpio_reg_block gpio; 13 14 function new(string name="pss_reg_block"); 15 super.new(name); 16 endfunction 17 18 function void build(); 19 AHB_map=create_map("AHB_map",0,4,UVM_LITTLE_ENDIAN); 20 21 spi=spi_reg_block::type_id::create("spi"); 22 spi.configure(this); 23 spi.build(); 24 AHB_map.add_submap(this.spi.default_map,0); 25 26 gpio=gpio_reg_block::type_id::create("gpio"); 27 gpio.configure(this); 28 gpio.build(); 29 AHB_map.add_submap(this.gpio.default_map,32'h100); 30 31 lock_mode(); 32 endfunction: build 33 34 endclass: pss_reg_block 35 36 endpackage: pss_reg_pkg
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?