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源码
virtual class uvm_reg_block extends uvm_object; //parent表示此uvm_reg_block所在的uvm_reg_block,即父uvm_reg_block; local uvm_reg_block parent; local static bit m_roots[uvm_reg_block]; //blks记录加入到此uvm_reg_block中的其他uvm_reg_block信息; local int unsigned blks[uvm_reg_block]; //regs表示加入到此uvm_reg_block中的其他uvm_reg信息; local int unsigned regs[uvm_reg]; `ifdef UVM_SPARSE_ARRAY local int unsigned regarrays[uvm_reg_file]; `endif local int unsigned vregs[uvm_vreg]; //mems表示加入到此uvm_reg_block中的uvm_mem信息; local int unsigned mems[uvm_mem]; local bit maps[uvm_reg_map]; // Variable: default_path // Default access path for the registers and memories in this block. uvm_path_e default_path = UVM_DEFAULT_PATH; local string default_hdl_path = "RTL"; local uvm_reg_backdoor backdoor; local uvm_object_string_pool #(uvm_queue #(string)) hdl_paths_pool; ... endclass
3. uvm_reg_block的函数
3.1 create_map函数
function uvm_reg_map uvm_reg_block::create_map(string name, uvm_reg_addr_t base_addr, int unsigned n_bytes, uvm_endianness_e endian, bit byte_addressing=1); uvm_reg_map map; if (this.locked) begin `uvm_error("RegModel", "Cannot add map to locked model"); return null; end map = uvm_reg_map::type_id::create(name,,this.get_full_name()); map.configure(this,base_addr,n_bytes,endian,byte_addressing); this.maps[map] = 1; if (maps.num() == 1) default_map = map; return map; endfunction
3.2 add_reg函数
function void uvm_reg_block::add_reg(uvm_reg rg); if (this.is_locked()) begin `uvm_error("RegModel", "Cannot add register to locked block model"); return; end if (this.regs.exists(rg)) begin `uvm_error("RegModel", {"Register '",rg.get_name(), "' has already been registered with block '",get_name(),"'"}) return; end regs[rg] = id++; 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所指向的对象;
class my_blk_type extends uvm_reg_block; ... virtual function void build(); this.AHB=create_map(); this.WSH=create_map(); this.default_map=this.AHB; endfunction ... endclass
(1.2)如果reg block没有任何命名的address map: build函数需要调用create_map函数实例化一个匿名的address map,并将其赋给default_map;
class my_blk_type extends uvm_reg_block; ... virtual function void build(); this.default_map=create_map(.name(default_map), .base_addr('h1000), .n_bytes(4), .endian(UVM_LITTLE_ENDIAN) ); endfunction ... 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的存取方式);
virtual function build(); ... map=create_map("map",'h0,4,UVM_LITTLE_ENDIAN); map.add_reg(reg1,32'h0,"RW"); map.add_reg(reg2,32'h4,"RW"); map.add_reg(reg3,32'h8,"RO"); map.add_reg(reg4,32'h10,"RO"); ... lock_model(); 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;
class my_blk_type extends uvm_reg_block; ... virtual function void build(); this.BLK1.build(); this.BLK2.build(); this.default_map.add_submap(this.BLK1.default_map,'h8000); this.default_map.add_submap(this.BLK2.default_map,'hc000); endfunction 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 class reg_model extends uvm_reg_block; `uvm_object_utils(reg_model) rand reg_invert invert; function new(input string name="reg_model"); super.new(name,UVM_NO_COVERAGE); endfunction virtual function void build(); default_map=create_map("default_map",0,2,UVM_BIG_ENDIAN,0); invert=reg_invert::type_id::create("invert",,get_full_name()); invert.configure(this,null,""); invert.build(); default_map.add_reg(invert,'h9,"RW"); endfunction endclass
//示例2 class my_regmodel extends uvm_reg_block; `uvm_object_utils(my_regmodel) rand my_reg version; function new(input string name="unnamed_my_regmodel"); super.new(name,UVM_NO_COVERAGE); endfunction function void build(); default_map=create_map("default_map",0,2,UVM_LITTLE_ENDIAN); version=my_reg::type_id::create("version",,get_full_name()); version.configure(this,null,"version"); version.build(); default_map.add_reg(version,16'h47,"RW"); endfunction endclass
//示例3 class my_blk_type extends uvm_reg_block; `uvm_object_utils(my_blk_type) uvm_reg_map AHB; uvm_reg_map WSH; rand my_r1_type R1; rand my_r2_type R2[3]; rand my_rf1_type RF1; rand my_rf2_type RF2[3]; my_mem1_type RAM1; my_mem2_type RAM2[3]; rand my_blk1_type BLK1; rand my_blk2_type BLK2[3]; function new(string name="my_blk_type"); super.new(.name(name),.has_coverage(UVM_NO_COVERAGE)); endfunction virtual function void build(); this.AHB=create_map(); this.WSH=create_map(); this.default_map=this.AHB; this.BLK1=my_blk1_type::type_id::create("BLK1",null,get_full_name()); this.BLK1.configure(this,...); this.BLK1.build(); ... this.R1=my_reg1_type::type_id::create("R1",null,get_full_name()); this.R1.configure(this,...); this.R1.build(); this.default_map.addr_reg(this.R1,'h04,...); .. endfunction endclass
//示例4 package pss_reg_pkg; import uvm_pkg::*; `include "uvm_macros.svh" import spi_reg_pkg::*; import gpio_reg_pkg::*; class pss_reg_block extends uvm_reg_block; `uvm_object_utils(pss_reg_block) rand spi_reg_block spi; rand gpio_reg_block gpio; function new(string name="pss_reg_block"); super.new(name); endfunction function void build(); AHB_map=create_map("AHB_map",0,4,UVM_LITTLE_ENDIAN); spi=spi_reg_block::type_id::create("spi"); spi.configure(this); spi.build(); AHB_map.add_submap(this.spi.default_map,0); gpio=gpio_reg_block::type_id::create("gpio"); gpio.configure(this); gpio.build(); AHB_map.add_submap(this.gpio.default_map,32'h100); lock_mode(); endfunction: build endclass: pss_reg_block endpackage: pss_reg_pkg
标签:map,default,build,model,reg,block,uvm From: https://www.cnblogs.com/lanlancky/p/17071162.html