前言
在验证过程中,我们会经常用到mem,希望能够对mem做动态内存管理,能够像C语言一样动态malloc一段空闲的地址空间。UVM的底层代码提供uvm_mem_man这个底层代码可以很方便用于实现上述功能。
一、uvm_mem_man介绍
uvm提供了uvm_mem_man这个mem的接口代码,放在uvm-1.2/src/reg/中,可以很方便的用来实现mem的管理。
主要的几个class如下所示,其中
- uvm_mem_mam_cfg用于对mem的大小等一些参数进行配置;
- uvm_mem_region用于动态申请内存后,申请到的内存空间;
- uvm_mem_mam_policy用于约束每次申请的内存,例如4byte对齐;
- uvm_mem用于表示实际的mem;
- uvm_mem_mam用于mem管理的整个入口。
class uvm_mem_mam_cfg;
class uvm_mem_region;
class uvm_mem_mam_policy;
class uvm_mem;
class uvm_mem_mam;
二、uvm_mem_man使用
首先需要对uvm_mem_man进行初始化配置,然后再去动态内存分配。
1、初始化配置
具体代码如下,在cfg中对mem_man进行初始化以及配置,并设置默认的随机约束政策。
class my_cfg extends base_env_cfg;
uvm_mem_man my_mem_man;
uvm_mem_man_cfg my_mem_man_cfg;
// 自定义的随机约束政策
class my_policy extends uvm_mem_mam_policy;
constraint addr_sync {
start_offset[3:0] == 0;
};
endclass
my_policy my_mem_mam_policy;
function new(string name="");
super.new(name);
//初始化mem的配置参数
my_mem_man_cfg = new();
my_mem_man_cfg.n_bytes = 1;
my_mem_man_cfg.start_offset = 0;
my_mem_man_cfg.end_offset = 32'hFFFF_FFFF;
my_mem_man_cfg.mode = uvm_mem_man::GREEDY;
// BROAD - Locate new regions randomly throughout the address space
// NEARBY - Locate new regions adjacent to existing regions
my_mem_man_cfg.locality = uvm_mem_man::BROAD;
// 初始化mem mam,将配置参数传进去
my_mem_man = new("my_mem", my_mem_man_cfg);
//set default policy
my_mem_mam_policy = new();
my_mem_man.default_alloc = my_mem_mam_policy;
endfunction : new
endclass
2、动态内存分配
uvm_mem_mam提供了如下函数用于动态内存分配。
- reserve_region
- request_region
- release_region
- release_all_regions
当我们需要一个内存空间的时候,只需要调用request_region,给一个需要数据的长度,先得到随机分配的一段地址空间,然后再通过这个地址空间的句柄去获取相关信息。
uvm_mem_region my_malloc_region;
bit[31:0] my_malloc_mem_addr;
bit[15:0] my_malloc_mem_len;
//随机分配一段指定长度的地址空间
my_malloc_region = cfg.m_mem_mam.request_region(q_size);
//获取分配后地址空间的基地址
my_malloc_mem_addr = my_malloc_region.get_start_offset();
//获取分配后地址空间的长度
my_malloc_mem_len = my_malloc_region.get_len();
//用完后可以释放
cfg.m_mem_mam.release_region(my_malloc_region);
通过上面上面的演示可以看到,利用UVM自带的mem管理,可以很方便的去管理mem的地址分配。
但是值得注意的是,这里仅仅是管理了地址空间的分配,并没有真正实例化mem,通过对uvm_mem_mam的new函数观察可以看到,如果需要mem的实体,可以在外部直接实例化一个uvm_mem,通过new函数传进去即可。
// Function: new
//
// Create a new manager instance
//
// Create an instance of a memory allocation manager
// with the specified name and configuration.
// This instance manages all memory region allocation within
// the address range specified in the configuration descriptor.
//
// If a reference to a memory abstraction class is provided, the memory
// locations within the regions can be accessed through the region
// descriptor, using the <uvm_mem_region::read()> and
// <uvm_mem_region::write()> methods.
//
extern function new(string name,
uvm_mem_mam_cfg cfg,
uvm_mem mem=null);
大部分情况下,我们的mem通常有VIP去存储数据,在环境里边只需要对mem进行管理即可,确保是随机分配的,且并未使用的内存空间。
3、axi vip mem
task write_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, bit[7:0] data);
task read_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, output bit[7:0] data);
总结
本文主要简单介绍了一下uvm中自带的mem管理使用方法,可以很方便的用于随机动态的分配mem的空间。