[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
复制代码

 

 

 

posted on   知北游。。  阅读(2635)  评论(0编辑  收藏  举报

编辑推荐:
· .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吗?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示