//
// -------------------------------------------------------------
// Copyright 2004-2009 Synopsys, Inc.
// Copyright 2010-2011 Mentor Graphics Corporation
// Copyright 2010 Cadence Design Systems, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
// -------------------------------------------------------------
//
//------------------------------------------------------------------------------
//
// Title: 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.
//
//------------------------------------------------------------------------------
`ifndef UVM_MEM_MAM__SV
`define UVM_MEM_MAM__SV
typedef class [docs]uvm_mem_mam_cfg;
typedef class [docs]uvm_mem_region;
typedef class [docs]uvm_mem_mam_policy;
typedef class [docs]uvm_mem;
//------------------------------------------------------------------------------
// CLASS: uvm_mem_mam
//------------------------------------------------------------------------------
// Memory allocation manager
//
// Memory allocation management utility class similar to C's malloc()
// and free().
// A single instance of this class is used to manage a single,
// contiguous address space.
//------------------------------------------------------------------------------
class [docs]uvm_mem_mam;
//----------------------
// Group: Initialization
//----------------------
// Type: alloc_mode_e
//
// Memory allocation mode
//
// Specifies how to allocate a memory region
//
// GREEDY - Consume new, previously unallocated memory
// THRIFTY - Reused previously released memory as much as possible (not yet implemented)
//
typedef enum {GREEDY, THRIFTY} [docs]alloc_mode_e;
// Type: locality_e
//
// Location of memory regions
//
// Specifies where to locate new memory regions
//
// BROAD - Locate new regions randomly throughout the address space
// NEARBY - Locate new regions adjacent to existing regions
typedef enum {BROAD, NEARBY} [docs]locality_e;
// Variable: default_alloc
//
// Region allocation policy
//
// This object is repeatedly randomized when allocating new regions.
uvm_mem_mam_policy default_alloc;
local uvm_mem memory;
local uvm_mem_mam_cfg cfg;
local uvm_mem_region in_use[$];
local int for_each_idx = -1;
local string fname;
local int lineno;
// 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 [docs]new(string name,
uvm_mem_mam_cfg cfg,
uvm_mem mem=null);
// Function: reconfigure
//
// Reconfigure the manager
//
// Modify the maximum and minimum addresses of the address space managed by
// the allocation manager, allocation mode, or locality.
// The number of bytes per memory location cannot be modified
// once an allocation manager has been constructed.
// All currently allocated regions must fall within the new address space.
//
// Returns the previous configuration.
//
// if no new configuration is specified, simply returns the current
// configuration.
//
extern function uvm_mem_mam_cfg [docs]reconfigure(uvm_mem_mam_cfg cfg = null);
//-------------------------
// Group: Memory Management
//-------------------------
// Function: reserve_region
//
// Reserve a specific memory region
//
// Reserve a memory region of the specified number of bytes
// starting at the specified offset.
// A descriptor of the reserved region is returned.
// If the specified region cannot be reserved, ~null~ is returned.
//
// It may not be possible to reserve a region because
// it overlaps with an already-allocated region or
// it lies outside the address range managed
// by the memory manager.
//
// Regions can be reserved to create "holes" in the managed address space.
//
extern function uvm_mem_region [docs]reserve_region(bit [63:0] start_offset,
int unsigned n_bytes,
string fname = "",
int lineno = 0);
// Function: request_region
//
// Request and reserve a memory region
//
// Request and reserve a memory region of the specified number
// of bytes starting at a random location.
// If an policy is specified, it is randomized to determine
// the start offset of the region.
// If no policy is specified, the policy found in
// the <uvm_mem_mam::default_alloc> class property is randomized.
//
// A descriptor of the allocated region is returned.
// If no region can be allocated, ~null~ is returned.
//
// It may not be possible to allocate a region because
// there is no area in the memory with enough consecutive locations
// to meet the size requirements or
// because there is another contradiction when randomizing
// the policy.
//
// If the memory allocation is configured to ~THRIFTY~ or ~NEARBY~,
// a suitable region is first sought procedurally.
//
extern function uvm_mem_region [docs]request_region(int unsigned n_bytes,
uvm_mem_mam_policy alloc = null,
string fname = "",
int lineno = 0);
// Function: release_region
//
// Release the specified region
//
// Release a previously allocated memory region.
// An error is issued if the
// specified region has not been previously allocated or
// is no longer allocated.
//
extern function void [docs]release_region(uvm_mem_region region);
// Function: release_all_regions
//
// Forcibly release all allocated memory regions.
//
extern function void [docs]release_all_regions();
//---------------------
// Group: Introspection
//---------------------
// Function: convert2string
//
// Image of the state of the manager
//
// Create a human-readable description of the state of
// the memory manager and the currently allocated regions.
//
extern function string [docs]convert2string();
// Function: for_each
//
// Iterate over all currently allocated regions
//
// If reset is ~TRUE~, reset the iterator
// and return the first allocated region.
// Returns ~null~ when there are no additional allocated
// regions to iterate on.
//
extern function uvm_mem_region [docs]for_each(bit reset = 0);
// Function: get_memory
//
// Get the managed memory implementation
//
// Return the reference to the memory abstraction class
// for the memory implementing
// the locations managed by this instance of the allocation manager.
// Returns ~null~ if no
// memory abstraction class was specified at construction time.
//
extern function uvm_mem [docs]get_memory();
endclass: uvm_mem_mam
//------------------------------------------------------------------------------
// CLASS: uvm_mem_region
//------------------------------------------------------------------------------
// Allocated memory region descriptor
//
// Each instance of this class describes an allocated memory region.
// Instances of this class are created only by
// the memory manager, and returned by the
// <uvm_mem_mam::reserve_region()> and <uvm_mem_mam::request_region()>
// methods.
//------------------------------------------------------------------------------
class [docs]uvm_mem_region;
/*local*/ bit [63:0] Xstart_offsetX; // Can't be local since function
/*local*/ bit [63:0] Xend_offsetX; // calls not supported in constraints
local int unsigned len;
local int unsigned n_bytes;
local uvm_mem_mam parent;
local string fname;
local int lineno;
/*local*/ uvm_vreg XvregX;
extern /*local*/ function [docs]new(bit [63:0] start_offset,
bit [63:0] end_offset,
int unsigned len,
int unsigned n_bytes,
uvm_mem_mam parent);
// Function: get_start_offset
//
// Get the start offset of the region
//
// Return the address offset, within the memory,
// where this memory region starts.
//
extern function bit [63:0] [docs]get_start_offset();
// Function: get_end_offset
//
// Get the end offset of the region
//
// Return the address offset, within the memory,
// where this memory region ends.
//
extern function bit [63:0] [docs]get_end_offset();
// Function: get_len
//
// Size of the memory region
//
// Return the number of consecutive memory locations
// (not necessarily bytes) in the allocated region.
//
extern function int unsigned [docs]get_len();
// Function: get_n_bytes
//
// Number of bytes in the region
//
// Return the number of consecutive bytes in the allocated region.
// If the managed memory contains more than one byte per address,
// the number of bytes in an allocated region may
// be greater than the number of requested or reserved bytes.
//
extern function int unsigned [docs]get_n_bytes();
// Function: release_region
//
// Release this region
//
extern function void [docs]release_region();
// Function: get_memory
//
// Get the memory where the region resides
//
// Return a reference to the memory abstraction class
// for the memory implementing this allocated memory region.
// Returns ~null~ if no memory abstraction class was specified
// for the allocation manager that allocated this region.
//
extern function uvm_mem [docs]get_memory();
// Function: get_virtual_registers
//
// Get the virtual register array in this region
//
// Return a reference to the virtual register array abstraction class
// implemented in this region.
// Returns ~null~ if the memory region is
// not known to implement virtual registers.
//
extern function uvm_vreg [docs]get_virtual_registers();
// Task: write
//
// Write to a memory location in the region.
//
// Write to the memory location that corresponds to the
// specified ~offset~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::write()> for more details.
//
extern task [docs]write(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
// Task: read
//
// Read from a memory location in the region.
//
// Read from the memory location that corresponds to the
// specified ~offset~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::read()> for more details.
//
extern task [docs]read(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
// Task: burst_write
//
// Write to a set of memory location in the region.
//
// Write to the memory locations that corresponds to the
// specified ~burst~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::burst_write()> for more details.
//
extern task [docs]burst_write(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value[],
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
// Task: burst_read
//
// Read from a set of memory location in the region.
//
// Read from the memory locations that corresponds to the
// specified ~burst~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::burst_read()> for more details.
//
extern task [docs]burst_read(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value[],
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
// Task: poke
//
// Deposit in a memory location in the region.
//
// Deposit the specified value in the memory location
// that corresponds to the
// specified ~offset~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::poke()> for more details.
//
extern task [docs]poke(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value,
input uvm_sequence_base parent = null,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
// Task: peek
//
// Sample a memory location in the region.
//
// Sample the memory location that corresponds to the
// specified ~offset~ within this region.
// Requires that the memory abstraction class be associated with
// the memory allocation manager that allocated this region.
//
// See <uvm_mem::peek()> for more details.
//
extern task [docs]peek(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value,
input uvm_sequence_base parent = null,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
extern function string [docs]convert2string();
endclass
//------------------------------------------------------------------------------
// Class: uvm_mem_mam_policy
//------------------------------------------------------------------------------
//
// An instance of this class is randomized to determine
// the starting offset of a randomly allocated memory region.
// This class can be extended to provide additional constraints
// on the starting offset, such as word alignment or
// location of the region within a memory page.
// If a procedural region allocation policy is required,
// it can be implemented in the pre/post_randomize() method.
//------------------------------------------------------------------------------
class [docs]uvm_mem_mam_policy;
// variable: len
// Number of addresses required
int unsigned len;
// variable: start_offset
// The starting offset of the region
rand bit [63:0] start_offset;
// variable: min_offset
// Minimum address offset in the managed address space
bit [63:0] min_offset;
// variable: max_offset
// Maximum address offset in the managed address space
bit [63:0] max_offset;
// variable: in_use
// Regions already allocated in the managed address space
uvm_mem_region in_use[$];
constraint uvm_mem_mam_policy_valid {
start_offset >= min_offset;
start_offset <= max_offset - len + 1;
}
constraint uvm_mem_mam_policy_no_overlap {
foreach (in_use[i]) {
!(start_offset <= in_use[i].Xend_offsetX &&
start_offset + len - 1 >= in_use[i].Xstart_offsetX);
}
}
endclass
//
// CLASS: uvm_mem_mam_cfg
// Specifies the memory managed by an instance of a <uvm_mem_mam> memory
// allocation manager class.
//
class [docs]uvm_mem_mam_cfg;
// variable: n_bytes
// Number of bytes in each memory location
rand int unsigned n_bytes;
// FIXME start_offset and end_offset should be "longint unsigned" to match the memory addr types
// variable: start_offset
// Lowest address of managed space
rand bit [63:0] start_offset;
// variable: end_offset
// Last address of managed space
rand bit [63:0] end_offset;
// variable: mode
// Region allocation mode
rand uvm_mem_mam::alloc_mode_e mode;
// variable: locality
// Region location mode
rand uvm_mem_mam::locality_e locality;
constraint uvm_mem_mam_cfg_valid {
end_offset > start_offset;
n_bytes < 64;
}
endclass
//------------------------------------------------------------------
// Implementation
//------------------------------------------------------------------
function uvm_mem_region::new(bit [63:0] start_offset,
bit [63:0] end_offset,
int unsigned len,
int unsigned n_bytes,
uvm_mem_mam parent);
this.Xstart_offsetX = start_offset;
this.Xend_offsetX = end_offset;
this.len = len;
this.n_bytes = n_bytes;
this.parent = parent;
this.XvregX = null;
endfunction: new
function bit [63:0] uvm_mem_region::get_start_offset();
return this.Xstart_offsetX;
endfunction: get_start_offset
function bit [63:0] uvm_mem_region::get_end_offset();
return this.Xend_offsetX;
endfunction: get_end_offset
function int unsigned uvm_mem_region::get_len();
return this.len;
endfunction: get_len
function int unsigned uvm_mem_region::get_n_bytes();
return this.n_bytes;
endfunction: get_n_bytes
function string uvm_mem_region::convert2string();
$sformat(convert2string, "['h%h:'h%h]",
this.Xstart_offsetX, this.Xend_offsetX);
endfunction: convert2string
function void uvm_mem_region::release_region();
this.parent.release_region(this);
endfunction
function uvm_mem uvm_mem_region::get_memory();
return this.parent.get_memory();
endfunction: get_memory
function uvm_vreg uvm_mem_region::get_virtual_registers();
return this.XvregX;
endfunction: get_virtual_registers
function uvm_mem_mam::new(string name,
uvm_mem_mam_cfg cfg,
uvm_mem mem = null);
this.cfg = cfg;
this.memory = mem;
this.default_alloc = new;
endfunction: new
function uvm_mem_mam_cfg uvm_mem_mam::reconfigure(uvm_mem_mam_cfg cfg = null);
uvm_root top;
uvm_coreservice_t cs;
if (cfg == null)
return this.cfg;
cs = uvm_coreservice_t::get();
top = cs.get_root();
// Cannot reconfigure n_bytes
if (cfg.n_bytes !== this.cfg.n_bytes) begin
top.uvm_report_error("uvm_mem_mam",
$sformatf("Cannot reconfigure Memory Allocation Manager with a different number of bytes (%0d !== %0d)",
cfg.n_bytes, this.cfg.n_bytes), UVM_LOW);
return this.cfg;
end
// All currently allocated regions must fall within the new space
foreach (this.in_use[i]) begin
if (this.in_use[i].get_start_offset() < cfg.start_offset ||
this.in_use[i].get_end_offset() > cfg.end_offset) begin
top.uvm_report_error("uvm_mem_mam",
$sformatf("Cannot reconfigure Memory Allocation Manager with a currently allocated region outside of the managed address range ([%0d:%0d] outside of [%0d:%0d])",
this.in_use[i].get_start_offset(),
this.in_use[i].get_end_offset(),
cfg.start_offset, cfg.end_offset), UVM_LOW);
return this.cfg;
end
end
reconfigure = this.cfg;
this.cfg = cfg;
endfunction: reconfigure
function uvm_mem_region uvm_mem_mam::reserve_region(bit [63:0] start_offset,
int unsigned n_bytes,
string fname = "",
int lineno = 0);
bit [63:0] end_offset;
this.fname = fname;
this.lineno = lineno;
if (n_bytes == 0) begin
`uvm_error("RegModel", "Cannot reserve 0 bytes");
return null;
end
if (start_offset < this.cfg.start_offset) begin
`uvm_error("RegModel", $sformatf("Cannot reserve before start of memory space: 'h%h < 'h%h",
start_offset, this.cfg.start_offset));
return null;
end
end_offset = start_offset + ((n_bytes-1) / this.cfg.n_bytes);
n_bytes = (end_offset - start_offset + 1) * this.cfg.n_bytes;
if (end_offset > this.cfg.end_offset) begin
`uvm_error("RegModel", $sformatf("Cannot reserve past end of memory space: 'h%h > 'h%h",
end_offset, this.cfg.end_offset));
return null;
end
`uvm_info("RegModel",$sformatf("Attempting to reserve ['h%h:'h%h]...",
start_offset, end_offset),UVM_MEDIUM)
foreach (this.in_use[i]) begin
if (start_offset <= this.in_use[i].get_end_offset() &&
end_offset >= this.in_use[i].get_start_offset()) begin
// Overlap!
`uvm_error("RegModel", $sformatf("Cannot reserve ['h%h:'h%h] because it overlaps with %s",
start_offset, end_offset,
this.in_use[i].convert2string()));
return null;
end
// Regions are stored in increasing start offset
if (start_offset > this.in_use[i].get_start_offset()) begin
reserve_region = new(start_offset, end_offset,
end_offset - start_offset + 1, n_bytes, this);
this.in_use.insert(i, reserve_region);
return reserve_region;
end
end
reserve_region = new(start_offset, end_offset,
end_offset - start_offset + 1, n_bytes, this);
this.in_use.push_back(reserve_region);
endfunction: reserve_region
function uvm_mem_region uvm_mem_mam::request_region(int unsigned n_bytes,
uvm_mem_mam_policy alloc = null,
string fname = "",
int lineno = 0);
this.fname = fname;
this.lineno = lineno;
if (alloc == null) alloc = this.default_alloc;
alloc.len = (n_bytes-1) / this.cfg.n_bytes + 1;
alloc.min_offset = this.cfg.start_offset;
alloc.max_offset = this.cfg.end_offset;
alloc.in_use = this.in_use;
if (!alloc.randomize()) begin
`uvm_error("RegModel", "Unable to randomize policy");
return null;
end
return reserve_region(alloc.start_offset, n_bytes);
endfunction: request_region
function void uvm_mem_mam::release_region(uvm_mem_region region);
if (region == null) return;
foreach (this.in_use[i]) begin
if (this.in_use[i] == region) begin
this.in_use.delete(i);
return;
end
end
`uvm_error("RegModel", {"Attempting to release unallocated region\n",
region.convert2string()});
endfunction: release_region
function void uvm_mem_mam::release_all_regions();
in_use.delete();
endfunction: release_all_regions
function string uvm_mem_mam::convert2string();
convert2string = "Allocated memory regions:\n";
foreach (this.in_use[i]) begin
$sformat(convert2string, "%s %s\n", convert2string,
this.in_use[i].convert2string());
end
endfunction: convert2string
function uvm_mem_region uvm_mem_mam::for_each(bit reset = 0);
if (reset) this.for_each_idx = -1;
this.for_each_idx++;
if (this.for_each_idx >= this.in_use.size()) begin
return null;
end
return this.in_use[this.for_each_idx];
endfunction: for_each
function uvm_mem uvm_mem_mam::get_memory();
return this.memory;
endfunction: get_memory
task uvm_mem_region::write(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::write() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to write to an offset outside of the allocated region (%0d > %0d)",
offset, this.len));
status = UVM_NOT_OK;
return;
end
mem.write(status, offset + this.get_start_offset(), value,
path, map, parent, prior, extension);
endtask: write
task uvm_mem_region::read(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::read() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to read from an offset outside of the allocated region (%0d > %0d)",
offset, this.len));
status = UVM_NOT_OK;
return;
end
mem.read(status, offset + this.get_start_offset(), value,
path, map, parent, prior, extension);
endtask: read
task uvm_mem_region::burst_write(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value[],
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::burst_write() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset + value.size() > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to burst-write to an offset outside of the allocated region (burst to [%0d:%0d] > mem_size %0d)",
offset,offset+value.size(),this.len))
status = UVM_NOT_OK;
return;
end
mem.burst_write(status, offset + get_start_offset(), value,
path, map, parent, prior, extension);
endtask: burst_write
task uvm_mem_region::burst_read(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value[],
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::burst_read() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset + value.size() > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to burst-read to an offset outside of the allocated region (burst to [%0d:%0d] > mem_size %0d)",
offset,offset+value.size(),this.len))
status = UVM_NOT_OK;
return;
end
mem.burst_read(status, offset + get_start_offset(), value,
path, map, parent, prior, extension);
endtask: burst_read
task uvm_mem_region::poke(output uvm_status_e status,
input uvm_reg_addr_t offset,
input uvm_reg_data_t value,
input uvm_sequence_base parent = null,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::poke() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to poke to an offset outside of the allocated region (%0d > %0d)",
offset, this.len));
status = UVM_NOT_OK;
return;
end
mem.poke(status, offset + this.get_start_offset(), value, "", parent, extension);
endtask: poke
task uvm_mem_region::peek(output uvm_status_e status,
input uvm_reg_addr_t offset,
output uvm_reg_data_t value,
input uvm_sequence_base parent = null,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
uvm_mem mem = this.parent.get_memory();
this.fname = fname;
this.lineno = lineno;
if (mem == null) begin
`uvm_error("RegModel", "Cannot use uvm_mem_region::peek() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance");
status = UVM_NOT_OK;
return;
end
if (offset > this.len) begin
`uvm_error("RegModel",
$sformatf("Attempting to peek from an offset outside of the allocated region (%0d > %0d)",
offset, this.len));
status = UVM_NOT_OK;
return;
end
mem.peek(status, offset + this.get_start_offset(), value, "", parent, extension);
endtask: peek
`endif // UVM_MEM_MAM__SV