#
# -------------------------------------------------------------
# Copyright 2004-2011 Synopsys, Inc.
# Copyright 2010-2011 Mentor Graphics Corporation
# Copyright 2010-2011 Cadence Design Systems, Inc.
# Copyright 2019 Tuomas Poikela
# 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.
#
# Original SV code has been adapter to Python.
# -------------------------------------------------------------
#import cocotb
from typing import Dict, Optional, List
from ..base.sv import sv
from ..base.uvm_object import UVMObject
from ..base.uvm_globals import uvm_check_output_args
from ..base.uvm_object_globals import (UVM_HIGH)
from ..base.uvm_pool import UVMPool, UVMObjectStringPool
from ..base.uvm_queue import UVMQueue
from ..base.uvm_resource_db import UVMResourceDb
from .uvm_reg_model import (UVM_IS_OK, UVM_HAS_X, UVM_NO_COVERAGE,
UVM_DEFAULT_PATH, UVM_HIER, uvm_reg_cvr_rsrc_db, UVM_FRONTDOOR,
UVM_NO_CHECK, UVM_CVR_ALL, UVM_NOT_OK)
from .uvm_reg_map import UVMRegMap
from .uvm_mem import UVMMem
from .uvm_reg_field import UVMRegField
from .uvm_reg import UVMReg
from ..macros import (uvm_info, uvm_error, uvm_warning, uvm_fatal, UVM_REG_DATA_WIDTH)
ERR_MSG1 = ("There are %0d root register models named %s. The names of the root"
+ " register models have to be unique")
ERR_MSG3 = ("Register model requires that UVM_REG_DATA_WIDTH be defined as %0d"
+ " or greater. Currently defined as %0d")
[docs]class UVMRegBlock(UVMObject):
"""
Block abstraction base class
A block represents a design hierarchy. It can contain registers,
register files, memories and sub-blocks.
A block has one or more address maps, each corresponding to a physical
interface on the block.
"""
m_roots: Dict['UVMRegBlock', int] = {}
id = 0
# //----------------------
# // Group: Initialization
# //----------------------
# // Function: new
# //
# // Create a new instance and type-specific configuration
# //
# // Creates an instance of a block abstraction class with the specified
# // name.
# //
# // ~has_coverage~ specifies which functional coverage models are present in
# // the extension of the block abstraction class.
# // Multiple functional coverage models may be specified by adding their
# // symbolic names, as defined by the <uvm_coverage_model_e> type.
# //
# function new(string name="", int has_coverage=UVM_NO_COVERAGE)
def __init__(self, name="", has_coverage=UVM_NO_COVERAGE):
super().__init__(name)
self.hdl_paths_pool = UVMObjectStringPool("hdl_paths", UVMQueue)
self.has_cover = has_coverage
self.cover_on = 0
# Root block until registered with a parent
UVMRegBlock.m_roots[self] = 0
self.locked = False
self.maps = UVMPool() # bit[UVMRegMap]
self.regs = UVMPool() # int unsigned[uvm_reg]
self.blks = UVMPool()
self.mems = UVMPool()
self.vregs = UVMPool()
self.root_hdl_paths = UVMPool()
self.backdoor = None
self.default_hdl_path = "RTL"
self.parent = None
# // Variable: default_path
# // Default access path for the registers and memories in this block.
self.default_path = UVM_DEFAULT_PATH
self.fname = ""
self.lineno = 0
# // Function: configure
# //
# // Instance-specific configuration
# //
# // Specify the parent block of this block.
# // A block without parent is a root block.
# //
# // If the block file corresponds to a hierarchical RTL structure,
# // its contribution to the HDL path is specified as the ~hdl_path~.
# // Otherwise, the block does not correspond to a hierarchical RTL
# // structure (e.g. it is physically flattened) and does not contribute
# // to the hierarchical HDL path of any contained registers or memories.
# //
# // Function: create_map
# //
# // Create an address map in this block
# //
# // Create an address map with the specified ~name~, then
# // configures it with the following properties.
# //
# // base_addr - the base address for the map. All registers, memories,
# // and sub-blocks within the map will be at offsets to this
# // address
# //
# // n_bytes - the byte-width of the bus on which this map is used
# //
# // endian - the endian format. See <uvm_endianness_e> for possible
# // values
# //
# // byte_addressing - specifies whether consecutive addresses refer are 1 byte
# // apart (TRUE) or ~n_bytes~ apart (FALSE). Default is TRUE.
# //
# //| APB = create_map("APB", 0, 1, UVM_LITTLE_ENDIAN, 1)
# //
# extern virtual function UVMRegMap create_map(string name,
# uvm_reg_addr_t base_addr,
# int unsigned n_bytes,
# uvm_endianness_e endian,
# bit byte_addressing = 1)
[docs] def create_map(self, name: str, base_addr: int, n_bytes: int, endian: int,
byte_addressing=True) -> Optional[UVMRegMap]:
# UVMRegMap map
if self.locked is True:
uvm_error("RegModel", "Cannot add map to locked model")
return None
_map = UVMRegMap.type_id.create(name, None, self.get_full_name())
_map.configure(self,base_addr,n_bytes,endian,byte_addressing)
self.maps[_map] = True
if self.maps.num() == 1:
self.default_map = _map
return _map
# // Function: check_data_width
# //
# // Check that the specified data width (in bits) is less than
# // or equal to the value of `UVM_REG_DATA_WIDTH
# //
# // This method is designed to be called by a static initializer
# //
# //| class my_blk extends uvm_reg_block
# //| local static bit m_data_width = check_data_width(356)
# //| ...
# //| endclass
# //
[docs] def check_data_width(self, width: int) -> int:
# if width <= sv.bits(uvm_reg_data_t):
if width <= UVM_REG_DATA_WIDTH:
return 1
uvm_fatal("RegModel", sv.sformatf(
"Register model requires that UVM_REG_DATA_WIDTH be defined as %0d or greater. Currently defined as %0d",
width, UVM_REG_DATA_WIDTH))
return 0
# // Function: set_default_map
# //
# // Defines the default address map
# //
# // Set the specified address map as the <default_map> for this
# // block. The address map must be a map of this address block.
# //
# extern function void set_default_map (UVMRegMap map)
[docs] def set_default_map(self, _map: UVMRegMap):
if _map not in self.maps:
uvm_warning("RegModel", "Map '" + _map.get_full_name() + "' does not exist in block")
self.default_map = _map
# // Variable: default_map
# //
# // Default address map
# //
# // Default address map for this block, to be used when no
# // address map is specified for a register operation and that
# // register is accessible from more than one address map.
# //
# // It is also the implicit address map for a block with a single,
# // unnamed address map because it has only one physical interface.
# //
# UVMRegMap default_map
#
# extern function UVMRegMap get_default_map ()
#
[docs] def get_default_map(self) -> UVMRegMap:
return self.default_map
# extern virtual function void set_parent(uvm_reg_block parent)
[docs] def set_parent(self, parent: 'UVMRegBlock'):
if self != parent:
self.parent = parent
# function void add_block (uvm_reg_block blk)
[docs] def add_block(self, blk: 'UVMRegBlock'):
if self.is_locked():
uvm_error("RegModel", "Cannot add subblock to locked block model")
return
if blk in self.blks:
uvm_error("RegModel", "Subblock '" + blk.get_name()
+ "' has already been registered with block '" + self.get_name() + "'")
return
self.blks[blk] = UVMRegBlock.id
UVMRegBlock.id += 1
if blk in UVMRegBlock.m_roots:
del UVMRegBlock.m_roots[blk]
# /*local*/ extern function void add_map (UVMRegMap map)
[docs] def add_map(self, _map: UVMRegMap):
if (self.locked):
uvm_error("RegModel", "Cannot add map to locked model")
return
if self.maps.exists(_map):
uvm_error("RegModel", "Map '" + _map.get_name()
+ "' already exists in '" + self.get_full_name() + "'")
return
self.maps[_map] = 1
if self.maps.num() == 1:
self.default_map = _map
# add_reg
[docs] def add_reg(self, rg: UVMReg):
if self.is_locked():
uvm_error("RegModel", "Cannot add register to locked block model")
return
if rg in self.regs:
uvm_error("RegModel", ("Register '" + rg.get_name()
+ "' has already been registered with block '"
+ self.get_name() + "'"))
return
self.regs[rg] = UVMRegBlock.id
UVMRegBlock.id += 1
# /*local*/ extern function void add_vreg (uvm_vreg vreg)
[docs] def add_vreg(self, vreg):
if self.is_locked():
uvm_error("RegModel", "Cannot add virtual register to locked block model")
return
if self.vregs.exists(vreg):
uvm_error("RegModel", ("Virtual register '" + vreg.get_name() +
"' has already been registered with block '" + self.get_name() + "'"))
return
self.vregs[vreg] = UVMRegBlock.id
UVMRegBlock.id += 1
# /*local*/ extern function void add_mem (uvm_mem mem)
[docs] def add_mem(self, mem: UVMMem):
if self.is_locked():
uvm_error("RegModel", "Cannot add memory to locked block model")
return
if mem in self.mems:
uvm_error("RegModel", "Memory '" + mem.get_name()
+ "' has already been registered with block '" + self.get_name()
+ "'")
return
self.mems[mem] = UVMRegBlock.id
UVMRegBlock.id += 1
# // Function: lock_model
# //
# // Lock a model and build the address map.
# //
# // Recursively lock an entire register model
# // and build the address maps to enable the
# // <UVMRegMap::get_reg_by_offset()> and
# // <UVMRegMap::get_mem_by_offset()> methods.
# //
# // Once locked, no further structural changes,
# // such as adding registers or memories,
# // can be made.
# //
# // It is not possible to unlock a model.
# //
[docs] def lock_model(self):
if self.is_locked():
return
self.locked = 1
for rr in self.regs.key_list():
rr.Xlock_modelX()
for mem in self.mems.key_list():
mem.Xlock_modelX()
for blk in self.blks.key_list():
blk.lock_model()
# TODO finish this
if (self.parent is None):
max_size = UVMReg.get_max_size()
if (UVMRegField.get_max_size() > max_size):
max_size = UVMRegField.get_max_size()
if (UVMMem.get_max_size() > max_size):
max_size = UVMMem.get_max_size()
if (max_size > UVM_REG_DATA_WIDTH):
uvm_fatal("RegModel", sv.sformatf(ERR_MSG3, max_size, UVM_REG_DATA_WIDTH))
self.Xinit_address_mapsX()
# Check that root register models have unique names
# Has this name has been checked before?
if self in UVMRegBlock.m_roots and UVMRegBlock.m_roots[self] != 1:
n = 0
for _blk in UVMRegBlock.m_roots:
blk = _blk # uvm_reg_block
if (blk.get_name() == self.get_name()):
UVMRegBlock.m_roots[blk] = 1
n += 1
if (n > 1):
uvm_error("UVM/REG/DUPLROOT", sv.sformatf(ERR_MSG1, n, self.get_name()))
# // Function: is_locked
# //
# // Return TRUE if the model is locked.
# //
[docs] def is_locked(self):
return self.locked
# //---------------------
# // Group: Introspection
# //---------------------
#
#
# // Function: get_name
# //
# // Get the simple name
# //
# // Return the simple object name of this block.
# //
# // Function: get_full_name
# //
# // Get the hierarchical name
# //
# // Return the hierarchal name of this block.
# // The base of the hierarchical name is the root block.
# //
# extern virtual function string get_full_name()
[docs] def get_full_name(self) -> str:
if self.parent is None:
return self.get_name()
return self.parent.get_full_name() + "." + self.get_name()
# // Function: get_parent
# //
# // Get the parent block
# //
# // If this a top-level block, returns ~None~.
# //
# extern virtual function uvm_reg_block get_parent()
[docs] def get_parent(self) -> Optional['UVMRegBlock']:
return self.parent
# // Function: get_root_blocks
# //
# // Get the all root blocks
# //
# // Returns an array of all root blocks in the simulation.
# //
# extern static function void get_root_blocks(ref uvm_reg_block blks[$])
[docs] def get_root_blocks(self, blks):
for blk in UVMRegBlock.m_roots:
blks.append(blk)
# // Function: find_blocks
# //
# // Find the blocks whose hierarchical names match the
# // specified ~name~ glob.
# // If a ~root~ block is specified, the name of the blocks are
# // relative to that block, otherwise they are absolute.
# //
# // Returns the number of blocks found.
# //
# extern static function int find_blocks(input string name,
# ref uvm_reg_block blks[$],
# input uvm_reg_block root = None,
# input uvm_object accessor = None)
# // Function: find_block
# //
# // Find the first block whose hierarchical names match the
# // specified ~name~ glob.
# // If a ~root~ block is specified, the name of the blocks are
# // relative to that block, otherwise they are absolute.
# //
# // Returns the first block found or ~None~ otherwise.
# // A warning is issued if more than one block is found.
# //
# extern static function uvm_reg_block find_block(input string name,
# input uvm_reg_block root = None,
# input uvm_object accessor = None)
# // Function: get_blocks
# //
# // Get the sub-blocks
# //
# // Get the blocks instantiated in this blocks.
# // If ~hier~ is TRUE, recursively includes any sub-blocks.
# //
# extern virtual function void get_blocks (ref uvm_reg_block blks[$],
# input uvm_hier_e hier=UVM_HIER)
[docs] def get_blocks(self, blks, hier=UVM_HIER):
for blk_ in self.blks.key_list():
blk = blk_
blks.append(blk)
if hier == UVM_HIER:
blk.get_blocks(blks)
# // Function: get_maps
# //
# // Get the address maps
# //
# // Get the address maps instantiated in this block.
# //
# extern virtual function void get_maps (ref UVMRegMap maps[$])
[docs] def get_maps(self, maps):
for key in self.maps.key_list():
maps.append(key)
# // Function: get_registers
# //
# // Get the registers
# //
# // Get the registers instantiated in this block.
# // If ~hier~ is TRUE, recursively includes the registers
# // in the sub-blocks.
# //
# // Note that registers may be located in different and/or multiple
# // address maps. To get the registers in a specific address map,
# // use the <UVMRegMap::get_registers()> method.
# //
# extern virtual function void get_registers (ref uvm_reg regs[$],
# input uvm_hier_e hier=UVM_HIER)
#
#
[docs] def get_registers(self, regs, hier=UVM_HIER):
for rg in self.regs.key_list():
regs.append(rg)
if hier == UVM_HIER:
for blk_ in self.blks.key_list():
blk = blk_
blk.get_registers(regs)
# // Function: get_fields
# //
# // Get the fields
# //
# // Get the fields in the registers instantiated in this block.
# // If ~hier~ is TRUE, recursively includes the fields of the registers
# // in the sub-blocks.
# //
# extern virtual function void get_fields (ref uvm_reg_field fields[$],
# input uvm_hier_e hier=UVM_HIER)
# // Function: get_memories
# //
# // Get the memories
# //
# // Get the memories instantiated in this block.
# // If ~hier~ is TRUE, recursively includes the memories
# // in the sub-blocks.
# //
# // Note that memories may be located in different and/or multiple
# // address maps. To get the memories in a specific address map,
# // use the <UVMRegMap::get_memories()> method.
# //
# extern virtual function void get_memories (ref uvm_mem mems[$],
# input uvm_hier_e hier=UVM_HIER)
[docs] def get_memories(self, mems, hier=UVM_HIER):
# foreach (self.mems[mem_]):
for mem_ in self.mems.key_list():
mem = mem_
mems.append(mem)
if hier == UVM_HIER:
for blk_ in self.blks.key_list():
blk = blk_
blk.get_memories(mems)
# // Function: get_virtual_registers
# //
# // Get the virtual registers
# //
# // Get the virtual registers instantiated in this block.
# // If ~hier~ is TRUE, recursively includes the virtual registers
# // in the sub-blocks.
# //
# extern virtual function void get_virtual_registers(ref uvm_vreg regs[$],
# input uvm_hier_e hier=UVM_HIER)
# // Function: get_virtual_fields
# //
# // Get the virtual fields
# //
# // Get the virtual fields from the virtual registers instantiated
# // in this block.
# // If ~hier~ is TRUE, recursively includes the virtual fields
# // in the virtual registers in the sub-blocks.
# //
# extern virtual function void get_virtual_fields (ref uvm_vreg_field fields[$],
# input uvm_hier_e hier=UVM_HIER)
# // Function: get_block_by_name
# //
# // Finds a sub-block with the specified simple name.
# //
# // The name is the simple name of the block, not a hierarchical name.
# // relative to this block.
# // If no block with that name is found in this block, the sub-blocks
# // are searched for a block of that name and the first one to be found
# // is returned.
# //
# // If no blocks are found, returns ~None~.
# //
# extern virtual function uvm_reg_block get_block_by_name (string name)
#
#
# // Function: get_map_by_name
# //
# // Finds an address map with the specified simple name.
# //
# // The name is the simple name of the address map, not a hierarchical name.
# // relative to this block.
# // If no map with that name is found in this block, the sub-blocks
# // are searched for a map of that name and the first one to be found
# // is returned.
# //
# // If no address maps are found, returns ~None~.
# //
# extern virtual function UVMRegMap get_map_by_name (string name)
[docs] def get_map_by_name(self, name) -> Optional[UVMRegMap]:
maps: List[UVMRegMap] = []
self.get_maps(maps)
for i in range(len(maps)):
if (maps[i].get_name() == name):
return maps[i]
for i in range(len(maps)):
submaps: List[UVMRegMap] = []
maps[i].get_submaps(submaps, UVM_HIER)
for j in range(len(submaps)):
if (submaps[j].get_name() == name):
return submaps[j]
uvm_warning("RegModel", "Map with name '" + name + "' does not exist in block")
return None
# // Function: get_reg_by_name
# //
# // Finds a register with the specified simple name.
# //
# // The name is the simple name of the register, not a hierarchical name.
# // relative to this block.
# // If no register with that name is found in this block, the sub-blocks
# // are searched for a register of that name and the first one to be found
# // is returned.
# //
# // If no registers are found, returns ~None~.
# //
# extern virtual function uvm_reg get_reg_by_name (string name)
[docs] def get_reg_by_name(self, name) -> Optional[UVMReg]:
for rg in self.regs.key_list():
if rg.get_name() == name:
return rg
for blk_ in self.blks.key_list():
# blk = blk_ # uvm_reg_block
subregs = [] # uvm_reg[$]
blk_.get_registers(subregs, UVM_HIER)
for j in range(len(subregs)):
if subregs[j].get_name() == name:
return subregs[j]
uvm_warning("RegModel", "Unable to locate register '" + name +
"' in block '" + self.get_full_name() + "'")
return None
#endfunction: get_reg_by_name
# // Function: get_field_by_name
# //
# // Finds a field with the specified simple name.
# //
# // The name is the simple name of the field, not a hierarchical name.
# // relative to this block.
# // If no field with that name is found in this block, the sub-blocks
# // are searched for a field of that name and the first one to be found
# // is returned.
# //
# // If no fields are found, returns ~None~.
# //
# extern virtual function uvm_reg_field get_field_by_name (string name)
#
#
# // Function: get_mem_by_name
# //
# // Finds a memory with the specified simple name.
# //
# // The name is the simple name of the memory, not a hierarchical name.
# // relative to this block.
# // If no memory with that name is found in this block, the sub-blocks
# // are searched for a memory of that name and the first one to be found
# // is returned.
# //
# // If no memories are found, returns ~None~.
# //
# extern virtual function uvm_mem get_mem_by_name (string name)
#
#
# // Function: get_vreg_by_name
# //
# // Finds a virtual register with the specified simple name.
# //
# // The name is the simple name of the virtual register,
# // not a hierarchical name.
# // relative to this block.
# // If no virtual register with that name is found in this block,
# // the sub-blocks are searched for a virtual register of that name
# // and the first one to be found is returned.
# //
# // If no virtual registers are found, returns ~None~.
# //
# extern virtual function uvm_vreg get_vreg_by_name (string name)
#
#
# // Function: get_vfield_by_name
# //
# // Finds a virtual field with the specified simple name.
# //
# // The name is the simple name of the virtual field,
# // not a hierarchical name.
# // relative to this block.
# // If no virtual field with that name is found in this block,
# // the sub-blocks are searched for a virtual field of that name
# // and the first one to be found is returned.
# //
# // If no virtual fields are found, returns ~None~.
# //
# extern virtual function uvm_vreg_field get_vfield_by_name (string name)
#
# //----------------
# // Group: Coverage
# //----------------
# // Function: build_coverage
# //
# // Check if all of the specified coverage model must be built.
# //
# // Check which of the specified coverage model must be built
# // in this instance of the block abstraction class,
# // as specified by calls to <uvm_reg::include_coverage()>.
# //
# // Models are specified by adding the symbolic value of individual
# // coverage model as defined in <uvm_coverage_model_e>.
# // Returns the sum of all coverage models to be built in the
# // block model.
# //
# extern protected function uvm_reg_cvr_t build_coverage(uvm_reg_cvr_t models)
[docs] def build_coverage(self, models):
build_coverage = UVM_NO_COVERAGE
cov_arr = []
uvm_reg_cvr_rsrc_db.read_by_name("uvm_reg::" + self.get_full_name(),
"include_coverage",
cov_arr, self)
build_coverage = cov_arr[0]
return build_coverage & models
# // Function: add_coverage
# //
# // Specify that additional coverage models are available.
# //
# // Add the specified coverage model to the coverage models
# // available in this class.
# // Models are specified by adding the symbolic value of individual
# // coverage model as defined in <uvm_coverage_model_e>.
# //
# // This method shall be called only in the constructor of
# // subsequently derived classes.
# //
# extern virtual protected function void add_coverage(uvm_reg_cvr_t models)
[docs] def add_coverage(self, models):
self.has_cover |= models
# // Function: has_coverage
# //
# // Check if block has coverage model(s)
# //
# // Returns TRUE if the block abstraction class contains a coverage model
# // for all of the models specified.
# // Models are specified by adding the symbolic value of individual
# // coverage model as defined in <uvm_coverage_model_e>.
# //
# extern virtual function bit has_coverage(uvm_reg_cvr_t models)
[docs] def has_coverage(self, models):
return ((self.has_cover & models) == models)
# // Function: set_coverage
# //
# // Turns on coverage measurement.
# //
# // Turns the collection of functional coverage measurements on or off
# // for this block and all blocks, registers, fields and memories within it.
# // The functional coverage measurement is turned on for every
# // coverage model specified using <uvm_coverage_model_e> symbolic
# // identifiers.
# // Multiple functional coverage models can be specified by adding
# // the functional coverage model identifiers.
# // All other functional coverage models are turned off.
# // Returns the sum of all functional
# // coverage models whose measurements were previously on.
# //
# // This method can only control the measurement of functional
# // coverage models that are present in the various abstraction classes,
# // then enabled during construction.
# // See the <uvm_reg_block::has_coverage()> method to identify
# // the available functional coverage models.
# //
# extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on)
[docs] def set_coverage(self, is_on):
self.cover_on = self.has_cover & is_on
for rg_ in self.regs.key_list():
rg = rg_
rg.set_coverage(is_on)
for mem in self.mems.key_list():
mem.set_coverage(is_on)
for blk_ in self.blks.key_list():
blk = blk_
blk.set_coverage(is_on)
return self.cover_on
# // Function: get_coverage
# //
# // Check if coverage measurement is on.
# //
# // Returns TRUE if measurement for all of the specified functional
# // coverage models are currently on.
# // Multiple functional coverage models can be specified by adding the
# // functional coverage model identifiers.
# //
# // See <uvm_reg_block::set_coverage()> for more details.
# //
# extern virtual function bit get_coverage(uvm_reg_cvr_t is_on = UVM_CVR_ALL)
[docs] def get_coverage(self, is_on=UVM_CVR_ALL):
if self.has_coverage(is_on) == 0:
return 0
return ((self.cover_on & is_on) == is_on)
# // Function: sample
# //
# // Functional coverage measurement method
# //
# // This method is invoked by the block abstraction class
# // whenever an address within one of its address map
# // is successfully read or written.
# // The specified offset is the offset within the block,
# // not an absolute address.
# //
# // Empty by default, this method may be extended by the
# // abstraction class generator to perform the required sampling
# // in any provided functional coverage model.
# //
# protected virtual function void sample(uvm_reg_addr_t offset,
# bit is_read,
# UVMRegMap map)
# endfunction
[docs] def sample(self, offset, is_read, _map):
pass
# // Function: sample_values
# //
# // Functional coverage measurement method for field values
# //
# // This method is invoked by the user
# // or by the <uvm_reg_block::sample_values()> method of the parent block
# // to trigger the sampling
# // of the current field values in the
# // block-level functional coverage model.
# // It recursively invokes the <uvm_reg_block::sample_values()>
# // and <uvm_reg::sample_values()> methods
# // in the blocks and registers in this block.
# //
# // This method may be extended by the
# // abstraction class generator to perform the required sampling
# // in any provided field-value functional coverage model.
# // If this method is extended, it MUST call super.sample_values().
# //
# extern virtual function void sample_values()
[docs] def sample_values(self):
for rg_ in self.regs.key_list():
rg = rg_
rg.sample_values()
for blk_ in self.blks.key_list():
blk = blk_
blk.sample_values()
# /*local*/ extern function void XsampleX(uvm_reg_addr_t addr,
# bit is_read,
# UVMRegMap map)
[docs] def XsampleX(self, addr, is_read, _map):
self.sample(addr, is_read, _map)
if (self.parent is not None):
pass
# ToDo: Call XsampleX in the parent block
# with the offset and map within that block's context
# //--------------
# // Group: Access
# //--------------
# // Function: get_default_path
# //
# // Default access path
# //
# // Returns the default access path for this block.
# //
# extern virtual function uvm_path_e get_default_path()
[docs] def get_default_path(self):
if (self.default_path != UVM_DEFAULT_PATH):
return self.default_path
if (self.parent is not None):
return self.parent.get_default_path()
return UVM_FRONTDOOR
# // Function: reset
# //
# // Reset the mirror for this block.
# //
# // Sets the mirror value of all registers in the block and sub-blocks
# // to the reset value corresponding to the specified reset event.
# // See <uvm_reg_field::reset()> for more details.
# // Does not actually set the value of the registers in the design,
# // only the values mirrored in their corresponding mirror.
# //
# extern virtual function void reset(string kind = "HARD")
[docs] def reset(self, kind="HARD"):
#
for rg_ in self.regs.key_list():
rg = rg_
rg.reset(kind)
for blk_ in self.blks.key_list():
blk = blk_ # uvm_reg_block
blk.reset(kind)
#endfunction
# // Function: needs_update
# //
# // Check if DUT registers need to be written
# //
# // If a mirror value has been modified in the abstraction model
# // without actually updating the actual register
# // (either through randomization or via the <uvm_reg::set()> method,
# // the mirror and state of the registers are outdated.
# // The corresponding registers in the DUT need to be updated.
# //
# // This method returns TRUE if the state of at least one register in
# // the block or sub-blocks needs to be updated to match the mirrored
# // values.
# // The mirror values, or actual content of registers, are not modified.
# // For additional information, see <uvm_reg_block::update()> method.
# //
# extern virtual function bit needs_update()
[docs] def needs_update(self):
for rg_ in self.regs.key_list():
rg = rg_
if rg.needs_update():
return 1
for blk_ in self.blks.key_list():
blk = blk_
if blk.needs_update():
return 1
return 0
# // Task: update
# //
# // Batch update of register.
# //
# // Using the minimum number of write operations, updates the registers
# // in the design to match the mirrored values in this block and sub-blocks.
# // The update can be performed using the physical
# // interfaces (front-door access) or back-door accesses.
# // This method performs the reverse operation of <uvm_reg_block::mirror()>.
# //
# extern virtual task update(output uvm_status_e status,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
[docs] async def update(self, status, path=UVM_DEFAULT_PATH, parent=None, prior=-1, extension=None, fname="",
lineno=0):
uvm_check_output_args([status])
stat_all = UVM_IS_OK
if self.needs_update() is False:
uvm_info("RegModel", sv.sformatf("%s:%0d - RegModel block %s does not need updating",
fname, lineno, self.get_name()), UVM_HIGH)
return
uvm_info("RegModel", sv.sformatf("%s:%0d - Updating model block %s with %s path",
fname, lineno, self.get_name(), path), UVM_HIGH)
for rg_ in self.regs.key_list():
rg = rg_
if rg.needs_update():
stat = []
await rg.update(stat, path, None, parent, prior, extension)
if (stat[0] != UVM_IS_OK and stat[0] != UVM_HAS_X):
uvm_error("RegModel", sv.sformatf("Register \"%s\" could not be updated",
rg.get_full_name()))
status.append(stat[0])
return
for blk_ in self.blks.key_list():
blk = blk_
stat_blk = []
await blk.update(status,path,parent,prior,extension,fname,lineno)
if (stat_blk[0] != UVM_IS_OK and stat_blk[0] != UVM_HAS_X):
stat_all = stat_blk
status.append(stat_all)
# // Task: mirror
# //
# // Update the mirrored values
# //
# // Read all of the registers in this block and sub-blocks and update their
# // mirror values to match their corresponding values in the design.
# // The mirroring can be performed using the physical interfaces
# // (front-door access) or back-door accesses.
# // If the ~check~ argument is specified as <UVM_CHECK>,
# // an error message is issued if the current mirrored value
# // does not match the actual value in the design.
# // This method performs the reverse operation of <uvm_reg_block::update()>.
# //
# extern virtual task mirror(output uvm_status_e status,
# input uvm_check_e check = UVM_NO_CHECK,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
[docs] async def mirror(self, status, check=UVM_NO_CHECK, path=UVM_DEFAULT_PATH, parent=None, prior=-1,
extension=None, fname="", lineno=0):
final_status = UVM_IS_OK
for rg_ in self.regs.key_list():
rg = rg_
curr_stat = []
await rg.mirror(curr_stat, check, path, None, parent, prior, extension, fname, lineno)
if (curr_stat[0] != UVM_IS_OK and curr_stat[0] != UVM_HAS_X):
final_status = curr_stat[0]
for blk_ in self.blks.key_list():
blk = blk_ # uvm_reg_block
curr_stat = []
await blk.mirror(curr_stat, check, path, parent, prior, extension, fname, lineno)
if (curr_stat[0] != UVM_IS_OK and curr_stat[0] != UVM_HAS_X):
final_status = curr_stat[0]
status.append(final_status)
# // Task: write_reg_by_name
# //
# // Write the named register
# //
# // Equivalent to <get_reg_by_name()> followed by <uvm_reg::write()>
# //
# extern virtual task write_reg_by_name(
# output uvm_status_e status,
# input string name,
# input uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
[docs] async def write_reg_by_name(self, status, name, data, path=UVM_DEFAULT_PATH,
map=None, parent=None, prior=-1, extension=None, fname="",
lineno=0):
self.fname = fname
self.lineno = lineno
status = UVM_NOT_OK
rg = self.get_reg_by_name(name)
if rg is not None:
await rg.write(status, data, path, map, parent, prior, extension)
# // Task: read_reg_by_name
# //
# // Read the named register
# //
# // Equivalent to <get_reg_by_name()> followed by <uvm_reg::read()>
# //
# extern virtual task read_reg_by_name(
# output uvm_status_e status,
# input string name,
# output uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# // Task: write_mem_by_name
# //
# // Write the named memory
# //
# // Equivalent to <get_mem_by_name()> followed by <uvm_mem::write()>
# //
# extern virtual task write_mem_by_name(
# output uvm_status_e status,
# input string name,
# input uvm_reg_addr_t offset,
# input uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# // Task: read_mem_by_name
# //
# // Read the named memory
# //
# // Equivalent to <get_mem_by_name()> followed by <uvm_mem::read()>
# //
# extern virtual task read_mem_by_name(
# output uvm_status_e status,
# input string name,
# input uvm_reg_addr_t offset,
# output uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# extern virtual task readmemh(string filename)
# extern virtual task writememh(string filename)
# //----------------
# // Group: Backdoor
# //----------------
# // Function: get_backdoor
# //
# // Get the user-defined backdoor for all registers in this block
# //
# // Return the user-defined backdoor for all register in this
# // block and all sub-blocks -- unless overridden by a backdoor set
# // in a lower-level block or in the register itself.
# //
# // If ~inherited~ is TRUE, returns the backdoor of the parent block
# // if none have been specified for this block.
# //
# extern function uvm_reg_backdoor get_backdoor(bit inherited = 1)
[docs] def get_backdoor(self, inherited=True):
if (self.backdoor is None and inherited):
blk = self.get_parent()
while (blk is not None):
bkdr = blk.get_backdoor()
if (bkdr is not None):
return bkdr
blk = blk.get_parent()
return self.backdoor
#endfunction: get_backdoor
# // Function: set_backdoor
# //
# // Set the user-defined backdoor for all registers in this block
# //
# // Defines the backdoor mechanism for all registers instantiated
# // in this block and sub-blocks, unless overridden by a definition
# // in a lower-level block or register.
# //
# extern function void set_backdoor (uvm_reg_backdoor bkdr,
# string fname = "",
# int lineno = 0)
# // Function: clear_hdl_path
# //
# // Delete HDL paths
# //
# // Remove any previously specified HDL path to the block instance
# // for the specified design abstraction.
# //
# extern function void clear_hdl_path (string kind = "RTL")
#
#
# // Function: add_hdl_path
# //
# // Add an HDL path
# //
# // Add the specified HDL path to the block instance for the specified
# // design abstraction. This method may be called more than once for the
# // same design abstraction if the block is physically duplicated
# // in the design abstraction
# //
# extern function void add_hdl_path (string path, string kind = "RTL")
[docs] def add_hdl_path(self, path, kind="RTL"):
# uvm_queue #(string) paths
paths = self.hdl_paths_pool.get(kind)
paths.push_back(path)
# // Function: has_hdl_path
# //
# // Check if a HDL path is specified
# //
# // Returns TRUE if the block instance has a HDL path defined for the
# // specified design abstraction. If no design abstraction is specified,
# // uses the default design abstraction specified for this block or
# // the nearest block ancestor with a specified default design abstraction.
# //
[docs] def has_hdl_path(self, kind=""):
if kind == "":
kind = self.get_default_hdl_path()
return self.hdl_paths_pool.exists(kind)
# // Function: get_hdl_path
# //
# // Get the incremental HDL path(s)
# //
# // Returns the HDL path(s) defined for the specified design abstraction
# // in the block instance.
# // Returns only the component of the HDL paths that corresponds to
# // the block, not a full hierarchical path
# //
# // If no design abstraction is specified, the default design abstraction
# // for this block is used.
# //
# extern function void get_hdl_path (ref string paths[$], input string kind = "")
# // Function: get_full_hdl_path
# //
# // Get the full hierarchical HDL path(s)
# //
# // Returns the full hierarchical HDL path(s) defined for the specified
# // design abstraction in the block instance.
# // There may be more than one path returned even
# // if only one path was defined for the block instance, if any of the
# // parent components have more than one path defined for the same design
# // abstraction
# //
# // If no design abstraction is specified, the default design abstraction
# // for each ancestor block is used to get each incremental path.
# //
# extern function void get_full_hdl_path (ref string paths[$],
# input string kind = "",
# string separator = ".")
[docs] def get_full_hdl_path(self, paths, kind="", separator="."):
if kind == "":
kind = self.get_default_hdl_path()
paths.clear()
if self.is_hdl_path_root(kind):
if self.root_hdl_paths[kind] != "":
paths.append(self.root_hdl_paths[kind])
return
if not self.has_hdl_path(kind):
uvm_error("RegModel", "Block " + self.get_full_name() +
" does not have hdl path defined for abstraction '" + kind + "'")
return
hdl_paths = self.hdl_paths_pool.get(kind) # uvm_queue #(string)
parent_paths = []
if self.parent is not None:
self.parent.get_full_hdl_path(parent_paths, kind, separator)
for i in range(len(hdl_paths)):
hdl_path = hdl_paths.get(i)
if len(parent_paths) == 0:
if hdl_path != "":
paths.append(hdl_path)
continue
for j in range(len(parent_paths)):
if hdl_path == "":
paths.append(parent_paths[j])
else:
paths.append(parent_paths[j] + separator + hdl_path)
# // Function: set_default_hdl_path
# //
# // Set the default design abstraction
# //
# // Set the default design abstraction for this block instance.
# //
# extern function void set_default_hdl_path (string kind)
[docs] def set_default_hdl_path(self, kind: str):
if kind == "":
if self.parent is None:
uvm_error("RegModel", ("Block has no parent. " +
"Must specify a valid HDL abstraction (kind)"))
else:
kind = self.parent.get_default_hdl_path()
self.default_hdl_path = kind
# // Function: get_default_hdl_path
# //
# // Get the default design abstraction
# //
# // Returns the default design abstraction for this block instance.
# // If a default design abstraction has not been explicitly set for this
# // block instance, returns the default design abstraction for the
# // nearest block ancestor.
# // Returns "" if no default design abstraction has been specified.
# //
# extern function string get_default_hdl_path ()
[docs] def get_default_hdl_path(self) -> str:
if self.default_hdl_path == "" and self.parent is not None:
return self.parent.get_default_hdl_path()
return self.default_hdl_path
# // Function: set_hdl_path_root
# //
# // Specify a root HDL path
# //
# // Set the specified path as the absolute HDL path to the block instance
# // for the specified design abstraction.
# // This absolute root path is prepended to all hierarchical paths
# // under this block. The HDL path of any ancestor block is ignored.
# // This method overrides any incremental path for the
# // same design abstraction specified using <add_hdl_path>.
# //
# extern function void set_hdl_path_root (string path, string kind = "RTL")
# set_hdl_path_root
[docs] def set_hdl_path_root(self, path, kind="RTL"):
if kind == "":
kind = self.get_default_hdl_path()
self.root_hdl_paths[kind] = path
# // Function: is_hdl_path_root
# //
# // Check if this block has an absolute path
# //
# // Returns TRUE if an absolute HDL path to the block instance
# // for the specified design abstraction has been defined.
# // If no design abstraction is specified, the default design abstraction
# // for this block is used.
# //
# extern function bit is_hdl_path_root (string kind = "")
[docs] def is_hdl_path_root(self, kind=""):
if kind == "":
kind = self.get_default_hdl_path()
return self.root_hdl_paths.exists(kind)
#endfunction
# extern virtual function void do_print (uvm_printer printer)
# extern virtual function void do_copy (uvm_object rhs)
# extern virtual function bit do_compare (uvm_object rhs,
# uvm_comparer comparer)
# extern virtual function void do_pack (uvm_packer packer)
# extern virtual function void do_unpack (uvm_packer packer)
# extern virtual function string convert2string ()
# extern virtual function uvm_object clone()
# extern local function void Xinit_address_mapsX()
[docs] def Xinit_address_mapsX(self):
for map_ in self.maps.key_list():
map_.Xinit_address_mapX()
# map.Xverify_map_configX()
#------------------------------------------------------------------------
#
#---------------
# Initialization
#---------------
#
#
#
#
#
#--------------------------
# Get Hierarchical Elements
#--------------------------
#
# get_fields
#
#function void uvm_reg_block::get_fields(ref uvm_reg_field fields[$],
# input uvm_hier_e hier=UVM_HIER)
#
# foreach (regs[rg_]):
# uvm_reg rg = rg_
# rg.get_fields(fields)
# end
#
# if (hier == UVM_HIER)
# foreach (blks[blk_])
# begin
# uvm_reg_block blk = blk_
# blk.get_fields(fields)
# end
#
#endfunction: get_fields
#
#
# get_virtual_fields
#
#function void uvm_reg_block::get_virtual_fields(ref uvm_vreg_field fields[$],
# input uvm_hier_e hier=UVM_HIER)
#
# foreach (vregs[vreg_]):
# uvm_vreg vreg = vreg_
# vreg.get_fields(fields)
# end
#
# if (hier == UVM_HIER)
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# blk.get_virtual_fields(fields)
# end
#endfunction: get_virtual_fields
#
#
#
#
# get_virtual_registers
#
#function void uvm_reg_block::get_virtual_registers(ref uvm_vreg regs[$],
# input uvm_hier_e hier=UVM_HIER)
#
# foreach (vregs[rg])
# regs.push_back(rg)
#
# if (hier == UVM_HIER)
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# blk.get_virtual_registers(regs)
# end
#endfunction: get_virtual_registers
#
#
#
#
#
#
#
#
# find_blocks
#
#function int uvm_reg_block::find_blocks(input string name,
# ref uvm_reg_block blks[$],
# input uvm_reg_block root = None,
# input uvm_object accessor = None)
#
# uvm_resource_pool rpl = uvm_resource_pool::get()
# uvm_resource_types::rsrc_q_t rs
#
# blks.delete()
#
# if (root is not None) name = {root.get_full_name(), ".", name}
#
# rs = rpl.lookup_regex(name, "uvm_reg::")
# for (int i = 0; i < rs.size(); i++):
# uvm_resource#(uvm_reg_block) blk
# if (!$cast(blk, rs.get(i))) continue
# blks.push_back(blk.read(accessor))
# end
#
# return blks.size()
#endfunction
#
#
# find_blocks
#
#function uvm_reg_block uvm_reg_block::find_block(input string name,
# input uvm_reg_block root = None,
# input uvm_object accessor = None)
#
# uvm_reg_block blks[$]
# if (!find_blocks(name, blks, root, accessor))
# return None
#
# if (blks.size() > 1):
# `uvm_warning("MRTH1BLK",
# {"More than one block matched the name \"", name, "\"."})
# end
#
#
# return blks[0]
#endfunction
#
#
#
#------------
# Get-By-Name
#------------
#
# get_block_by_name
#
#function uvm_reg_block uvm_reg_block::get_block_by_name(string name)
#
# if (get_name() == name)
# return this
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
#
# if (blk.get_name() == name)
# return blk
# end
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# uvm_reg_block subblks[$]
# blk_.get_blocks(subblks, UVM_HIER)
#
# foreach (subblks[j])
# if (subblks[j].get_name() == name)
# return subblks[j]
# end
#
# `uvm_warning("RegModel", {"Unable to locate block '",name,
# "' in block '",get_full_name(),"'"})
# return None
#
#endfunction: get_block_by_name
#
#
#
#
# get_vreg_by_name
#
#function uvm_vreg uvm_reg_block::get_vreg_by_name(string name)
#
# foreach (vregs[rg_]):
# uvm_vreg rg = rg_
# if (rg.get_name() == name)
# return rg
# end
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# uvm_vreg subvregs[$]
# blk_.get_virtual_registers(subvregs, UVM_HIER)
#
# foreach (subvregs[j])
# if (subvregs[j].get_name() == name)
# return subvregs[j]
# end
#
# `uvm_warning("RegModel", {"Unable to locate virtual register '",name,
# "' in block '",get_full_name(),"'"})
# return None
#
#endfunction: get_vreg_by_name
#
#
# get_mem_by_name
#
#function uvm_mem uvm_reg_block::get_mem_by_name(string name)
#
# foreach (mems[mem_]):
# uvm_mem mem = mem_
# if (mem.get_name() == name)
# return mem
# end
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# uvm_mem submems[$]
# blk_.get_memories(submems, UVM_HIER)
#
# foreach (submems[j])
# if (submems[j].get_name() == name)
# return submems[j]
# end
#
# `uvm_warning("RegModel", {"Unable to locate memory '",name,
# "' in block '",get_full_name(),"'"})
# return None
#
#endfunction: get_mem_by_name
#
#
# get_field_by_name
#
#function uvm_reg_field uvm_reg_block::get_field_by_name(string name)
#
# foreach (regs[rg_]):
# uvm_reg rg = rg_
# uvm_reg_field fields[$]
#
# rg.get_fields(fields)
# foreach (fields[i])
# if (fields[i].get_name() == name)
# return fields[i]
# end
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# uvm_reg subregs[$]
# blk_.get_registers(subregs, UVM_HIER)
#
# foreach (subregs[j]):
# uvm_reg_field fields[$]
# subregs[j].get_fields(fields)
# foreach (fields[i])
# if (fields[i].get_name() == name)
# return fields[i]
# end
# end
#
# `uvm_warning("RegModel", {"Unable to locate field '",name,
# "' in block '",get_full_name(),"'"})
#
# return None
#
#endfunction: get_field_by_name
#
#
# get_vfield_by_name
#
#function uvm_vreg_field uvm_reg_block::get_vfield_by_name(string name)
#
# foreach (vregs[rg_]):
# uvm_vreg rg =rg_
# uvm_vreg_field fields[$]
#
# rg.get_fields(fields)
# foreach (fields[i])
# if (fields[i].get_name() == name)
# return fields[i]
# end
#
# foreach (blks[blk_]):
# uvm_reg_block blk = blk_
# uvm_vreg subvregs[$]
# blk_.get_virtual_registers(subvregs, UVM_HIER)
#
# foreach (subvregs[j]):
# uvm_vreg_field fields[$]
# subvregs[j].get_fields(fields)
# foreach (fields[i])
# if (fields[i].get_name() == name)
# return fields[i]
# end
# end
#
# `uvm_warning("RegModel", {"Unable to locate virtual field '",name,
# "' in block '",get_full_name(),"'"})
#
# return None
#
#endfunction: get_vfield_by_name
#
#
#----------------
# Run-Time Access
#----------------
#
#
#
# read_reg_by_name
#
#task uvm_reg_block::read_reg_by_name(output uvm_status_e status,
# input string name,
# output uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# uvm_reg rg
# self.fname = fname
# self.lineno = lineno
#
# status = UVM_NOT_OK
# rg = self.get_reg_by_name(name)
# if (rg is not None)
# rg.read(status, data, path, map, parent, prior, extension)
#endtask: read_reg_by_name
#
#
# write_mem_by_name
#
#task uvm_reg_block::write_mem_by_name(output uvm_status_e status,
# input string name,
# input uvm_reg_addr_t offset,
# input uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# uvm_mem mem
# self.fname = fname
# self.lineno = lineno
#
# status = UVM_NOT_OK
# mem = get_mem_by_name(name)
# if (mem is not None)
# mem.write(status, offset, data, path, map, parent, prior, extension)
#endtask: write_mem_by_name
#
#
# read_mem_by_name
#
#task uvm_reg_block::read_mem_by_name(output uvm_status_e status,
# input string name,
# input uvm_reg_addr_t offset,
# output uvm_reg_data_t data,
# input uvm_path_e path = UVM_DEFAULT_PATH,
# input UVMRegMap map = None,
# input uvm_sequence_base parent = None,
# input int prior = -1,
# input uvm_object extension = None,
# input string fname = "",
# input int lineno = 0)
# uvm_mem mem
# self.fname = fname
# self.lineno = lineno
#
# status = UVM_NOT_OK
# mem = get_mem_by_name(name)
# if (mem is not None)
# mem.read(status, offset, data, path, map, parent, prior, extension)
#endtask: read_mem_by_name
#
#
# readmemh
#
#task uvm_reg_block::readmemh(string filename)
# // TODO
#endtask: readmemh
#
#
# writememh
#
#task uvm_reg_block::writememh(string filename)
# // TODO
#endtask: writememh
#
#
#---------------
# Map Management
#---------------
#
#----------------
# Group- Backdoor
#----------------
#
# set_backdoor
#
#function void uvm_reg_block::set_backdoor(uvm_reg_backdoor bkdr,
# string fname = "",
# int lineno = 0)
# bkdr.fname = fname
# bkdr.lineno = lineno
# if (self.backdoor is not None &&
# self.backdoor.has_update_threads()):
# `uvm_warning("RegModel", "Previous register backdoor still has update threads running. Backdoors with active mirroring should only be set before simulation starts.")
# end
# self.backdoor = bkdr
#endfunction: set_backdoor
#
#
#
# clear_hdl_path
#
#function void uvm_reg_block::clear_hdl_path(string kind = "RTL")
#
# if (kind == "ALL"):
# hdl_paths_pool = new("hdl_paths")
# return
# end
#
# if (kind == "")
# kind = get_default_hdl_path()
#
# if (!hdl_paths_pool.exists(kind)):
# `uvm_warning("RegModel",{"Unknown HDL Abstraction '",kind,"'"})
# return
# end
#
# hdl_paths_pool.delete(kind)
#endfunction
#
#
#
#
#
# get_hdl_path
#
#function void uvm_reg_block::get_hdl_path(ref string paths[$], input string kind = "")
#
# uvm_queue #(string) hdl_paths
#
# if (kind == "")
# kind = get_default_hdl_path()
#
# if (!has_hdl_path(kind)):
# `uvm_error("RegModel",{"Block does not have hdl path defined for abstraction '",kind,"'"})
# return
# end
#
# hdl_paths = hdl_paths_pool.get(kind)
#
# for (int i=0; i<hdl_paths.size();i++)
# paths.push_back(hdl_paths.get(i))
#
#endfunction
#
#
#
#
#
#
#
#
#
#
#
#
#----------------------------------
# Group- Basic Object Operations
#----------------------------------
#
# do_print
#function void uvm_reg_block::do_print (uvm_printer printer)
# super.do_print(printer)
#
# foreach(blks[i]):
# uvm_reg_block b = i
# uvm_object obj = b
# printer.print_object(obj.get_name(), obj)
# end
#
# foreach(regs[i]):
# uvm_reg r = i
# uvm_object obj = r
# printer.print_object(obj.get_name(), obj)
# end
#
# foreach(vregs[i]):
# uvm_vreg r = i
# uvm_object obj = r
# printer.print_object(obj.get_name(), obj)
# end
#
# foreach(mems[i]):
# uvm_mem m = i
# uvm_object obj = m
# printer.print_object(obj.get_name(), obj)
# end
#
# foreach(maps[i]):
# UVMRegMap m = i
# uvm_object obj = m
# printer.print_object(obj.get_name(), obj)
# end
#
#endfunction
#
#
#
# clone
#
#function uvm_object uvm_reg_block::clone()
# `uvm_fatal("RegModel","RegModel blocks cannot be cloned")
# return None
#endfunction
#
# do_copy
#
#function void uvm_reg_block::do_copy(uvm_object rhs)
# `uvm_fatal("RegModel","RegModel blocks cannot be copied")
#endfunction
#
#
# do_compare
#
#function bit uvm_reg_block::do_compare (uvm_object rhs,
# uvm_comparer comparer)
# `uvm_warning("RegModel","RegModel blocks cannot be compared")
# return 0
#endfunction
#
#
# do_pack
#
#function void uvm_reg_block::do_pack (uvm_packer packer)
# `uvm_warning("RegModel","RegModel blocks cannot be packed")
#endfunction
#
#
# do_unpack
#
#function void uvm_reg_block::do_unpack (uvm_packer packer)
# `uvm_warning("RegModel","RegModel blocks cannot be unpacked")
#endfunction
#
#// convert2string
#
#def string uvm_reg_block::convert2string(self):
# string image
# string maps[]
# string blk_maps[]
# bit single_map
# uvm_endianness_e endian
# string prefix = " "
#
#`ifdef TODO
# single_map = 1
# if (map == ""):
# self.get_maps(maps)
# if (maps.size() > 1) single_map = 0
# end
#
# if (single_map):
# $sformat(image, "%sBlock %s", prefix, self.get_full_name())
#
# if (map != "")
# $sformat(image, "%s.%s", image, map)
#
# endian = self.get_endian(map)
#
# $sformat(image, "%s -- %0d bytes (%s)", image,
# self.get_n_bytes(map), endian.name())
#
# foreach (blks[i]):
# string img
# img = blks[i].convert2string({prefix, " "}, blk_maps[i])
# image = {image, "\n", img}
# end
#
# end
# else begin
# $sformat(image, "%Block %s", prefix, self.get_full_name())
# foreach (maps[i]):
# string img
# endian = self.get_endian(maps[i])
# $sformat(img, "%s Map \"%s\" -- %0d bytes (%s)",
# prefix, maps[i],
# self.get_n_bytes(maps[i]), endian.name())
# image = {image, "\n", img}
#
# self.get_blocks(blks, blk_maps, maps[i])
# foreach (blks[j]):
# img = blks[j].convert2string({prefix, " "},
# blk_maps[j])
# image = {image, "\n", img}
# end
#
# self.get_subsys(sys, blk_maps, maps[i])
# foreach (sys[j]):
# img = sys[j].convert2string({prefix, " "},
# blk_maps[j])
# image = {image, "\n", img}
# end
# end
# end
#`endif
# return image