UVM MAM (Memory Allocation Manager) manages the exclusive allocation of consecutive
memory locations called regions.
The regions can subsequently be accessed like little memories of their own, without
knowing in which memory or offset they are actually located.
The memory allocation manager should be used by any application-level process that
requires reserved space in the memory, such as DMA buffers.
A region will remain reserved until it is explicitly released.
The following example usage of UVM MAM is shown:
//Source code
program test;
import uvm_pkg::*;
class mam_unit extends uvm_object;
`uvm_object_utils(mam_unit)
string str;
uvm_mem_mam_cfg mam_cfg;
uvm_mem_mam mam;
uvm_mem_region region;
function new (string name = "mam_unit");
super.new(name);
mam_cfg = new();
mam_cfg.n_bytes = 4; //Set number of bytes in each memory location as 4
mam_cfg.start_offset = 0; //Set start offset of the memory as 0
mam_cfg.end_offset = 1<<8; //Set start offset of the memory as 256
mam = new("vmm_mam", this.mam_cfg);
endfunction
virtual function void randomize_mem();
bit[31:0] start_addr;
bit[31:0] end_addr;
int i;
for(i=0; i<2; i++)
begin
region = mam.request_region(8); //Request and reserve 8 bytes memory region
//which occupies 2 memory locations
start_addr = region.get_start_offset(); //Get the start offset of reserved region
end_addr = region.get_end_offset(); //Get the end offset of reserved region
str = $psprintf("%0d start_addr=='h%0h, end_addr=='h%0h\n", i, start_addr, end_addr);
`uvm_info(get_type_name(), str, UVM_MEDIUM)
end
endfunction
endclass
initial
begin
mam_unit mam = new();
mam.randomize_mem();
end
endprogram
//Simulation Result
UVM_INFO /usr/install/vcs_2011.03/etc/uvm-1.0/reg/uvm_mem_mam.svh(724) @ 0: rep
orter [RegModel] Attempting to reserve ['h0000000000000065:'h0000000000000066]..
.
UVM_INFO mam_unit.sv(35) @ 0: reporter [mam_unit] 0 start_addr=='h65, end_addr=='h66
UVM_INFO /usr/install/vcs_2011.03/etc/uvm-1.0/reg/uvm_mem_mam.svh(724) @ 0: rep
orter [RegModel] Attempting to reserve ['h000000000000000f:'h0000000000000010]..
.
UVM_INFO mam_unit.sv(35) @ 0: reporter [mam_unit] 1 start_addr=='hf, end_addr=='h10
======================================================================================
Using the Memory Allocation Manager in memories modeled through VMM RAL
A memory defines a region of consecutively addressable locations. In the Register Abstraction Layer (RAL), registers and
memories are grouped into blocks, which correspond to individually designed and verified components with their
own host processor interfaces, address decoding and memory-mapped registers and memories.
An abstraction class is generated for each memory definition. For each independently defined memory named 'memnam',
there is a class named 'ral_mem_memnam' or 'ral_mem_blknam_memnam', if the memory definition is inlined in the block
('blknam') definition. In both cases, the memory abstraction class is derived from the vmm_ral_mem class. Each virtual
method in this class is then overloaded to implement memory-specific behavior of the memory as defined in the RALF
description.
The VMM Register Abstraction Layer is used to abstract the configuration process in the sub-environment from the physical
details of writing registers and memories. If the block-level functionality requires access to memory that may be shared
at the system-level, a memory allocation manager must be used to ensure that different blocks use different memory regions.
The Memory Allocation Manager is an element of the VMM base classes, which is used to dynamically allocate or reserve memory
regions in a large RAM. This memory allocation management utility class has methods similar to C's malloc() and free().
A single instance of the MAM class is used to manage a single, contiguous address space. In RAL, for each memory definition,
a single instance of the 'vmm_mam' (Memory Allocation Manger class) is now associated through a property in the 'vmm_ral_mem'
base class. Hence, this instance can be used by any application-level process that require reserved space in the memory
through the generated class handle. The section of memory (called a region) will remain reserved until it is explicitly
released. The region descriptor will act like its own little RAL memory abstraction class that can be dynamically allocated
and freed.
The following snippets of code shows how the MAM handle can be leveraged to manage allocations efficiently
through in memories modeled through RAL.
RALF definition:
block b {
...
memory ram @0 { size 32; bits 16; access rw; initial 0; }
}
Now the MAM handle can be used as following:
vmm_mam_region rg;
rg = b.ram.mam.request_region(8); // will allocate a region which is free, or not allocate to any other thread
trying to access the same memory
//In the above statement, b is an instance of derived from 'ral_block_b', 'ram' is the instance of 'ral_mem_b_ram'
and 'mam' is the 'vmm_mam' or MAM property of the base class 'vmm_ral_mem'.
The generated code for the above RALF snippet would ensure that the MAM configuration handle (instance of
vmm_ral_cfg) will get updated with the start_offset ('h0), end_offset (1), and n_bytes (2), once the memory abstraction
class is generated, and hence when 'request_region' is invoked, the allocated region would be between the
start_offset and end_offset.
Now, to use the allocated region, you can have:
$write("Writing through region...\n");
rg.write(status, 0, 32'h55AA00CC);
// Verify that the correct memory location was written
addr = rg.get_start_offset();
b.ram.peek(status, addr, dat);
The value written can be checked to verify that data was written and read from the same location.
Similarly, all the functions in the 'vmm_mam' class and that of its properties like vmm_mam_allocator and vmm_mam_region
can now be used to effectively manage the memory/memories modeled through RAL. For example, if there were two MAM's (for each
domain), managing the single memory, and one domain has a narrower address space than the other, then you can use
a different vmm_mam_allocator instance when calling request_region for the narrower domain. This would ensure that the
same memory region is not erroneously allocated through each domain. Similarly, multiple such applications of the MAM
utility class can now be brought into the RAL domain.
==================================================================================
Question:
Questions:
1. Does VMM memory allocation manager in VMM 1.1 support
allocation of aligned addresses (addresses aligned to
4-bytes - last 2 bits are zero, etc.)?
2. Does VMM memory allocation manager in VMM 1.1 support
dynamic change of the alignment from one allocation to another?
Answer:
I. Does VMM memory allocation manager in VMM 1.1 support
allocation of aligned addresses (addresses aligned to
4-bytes - last 2 bits are zero, etc.)?
Yes. You can do that by constraining the 'start_offset'
variable in 'vmm_mam_allocator' class.
II. Does VMM memory allocation manager in VMM 1.1 support
dynamic change of the alignment from one allocation to another?
The ability to change alignment from one allocation to another can
be achieved via extension of the 'request_region' function in
'vmm_mam' class.
Per the following example, alignment is set via 'set_alignment_cnstr'
constraint in 'vmm_mam_allocator_aligned' class. This class implements
the ability to change the alignment per allocation achieved via extending
'vmm_mam::request_region()' function.
/
//compilation command: vcs -R -sverilog -ntb_opts rvm test.sv
program test;
`include "vmm.sv"
`include "vmm_ral.sv"
class vmm_mam_allocator_aligned extends vmm_mam_allocator;
int aligned_modulo;
bit is_aligned = 0;
constraint set_alignment_cnstr {
if(is_aligned == 1) start_offset % aligned_modulo == 0;
}
endclass
class vmm_mam_aligned extends vmm_mam;
function new(string name,
vmm_mam_cfg cfg,
vmm_ral_mem mem = null);
super.new(name,cfg,mem);
endfunction
function vmm_mam_region request_region(int unsigned _n_bytes, vmm_mam_allocator_aligned _alloc = null, int _aligned_modulo = null);
set_alignment(_alloc,_aligned_modulo);
return super.request_region(_n_bytes,_alloc);
endfunction
task set_alignment(vmm_mam_allocator_aligned _alloc = null,int _aligned_modulo = null);
if ((_alloc !== null) & (_aligned_modulo !== null)) begin
_alloc.is_aligned = 1;
_alloc.aligned_modulo = _aligned_modulo;
end
else if (_alloc !== null) begin
_alloc.is_aligned = 0;
end
endtask
endclass
initial
begin
vmm_mam_cfg cfg;
vmm_mam_aligned mgr;
vmm_mam_region bfr;
cfg = new;
cfg.n_bytes = 1;
cfg.start_offset = 8'h00;
cfg.end_offset = 8'hFF;
mgr = new("Mem Mgr", cfg);
begin
vmm_mam_allocator_aligned alloc = new;
// request 6 bytes through vmm_mam (default usage)
$display("request_region()-, no allocator,-------------------\n");
repeat (5) begin
bfr = mgr.request_region(6);
$display("%s\n", bfr.psdisplay());
end
// request 7 bytes through vmm_mam using our allocator, default alignment
$display("request_region()--,allocator with default alignment,-\n");
repeat (5) begin
bfr = mgr.request_region(7, alloc);
$display("%s\n", bfr.psdisplay());
end
// request 9 bytes through vmm_mam, address is 4-bytes aligned
$display("request_region()-,allocator with alignment,-----\n");
repeat (5) begin
bfr = mgr.request_region(9, alloc, 4);
$display("%s\n", bfr.psdisplay());
end
end
end
endprogram