//
// -------------------------------------------------------------
// Copyright 2010 Synopsys, Inc.
// Copyright 2010 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.
// -------------------------------------------------------------
//
//
// CLASS: uvm_reg_file
// Register file abstraction base class
//
// A register file is a collection of register files and registers
// used to create regular repeated structures.
//
// Register files are usually instantiated as arrays.
//
virtual class [docs]uvm_reg_file extends uvm_object;
local uvm_reg_block parent;
local uvm_reg_file m_rf;
local string default_hdl_path = "RTL";
local uvm_object_string_pool #(uvm_queue #(string)) hdl_paths_pool;
//----------------------
// Group: Initialization
//----------------------
//
// Function: new
//
// Create a new instance
//
// Creates an instance of a register file abstraction class
// with the specified name.
//
extern function [docs]new (string name="");
//
// Function: configure
// Configure a register file instance
//
// Specify the parent block and register file of the register file
// instance.
// If the register file is instantiated in a block,
// ~regfile_parent~ is specified as ~null~.
// If the register file is instantiated in a register file,
// ~blk_parent~ must be the block parent of that register file and
// ~regfile_parent~ is specified as that register file.
//
// If the register file corresponds to a hierarchical RTL structure,
// its contribution to the HDL path is specified as the ~hdl_path~.
// Otherwise, the register file 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.
//
extern function void [docs]configure (uvm_reg_block blk_parent,
uvm_reg_file regfile_parent,
string hdl_path = "");
//---------------------
// Group: Introspection
//---------------------
//
// Function: get_name
// Get the simple name
//
// Return the simple object name of this register file.
//
//
// Function: get_full_name
// Get the hierarchical name
//
// Return the hierarchal name of this register file.
// The base of the hierarchical name is the root block.
//
extern virtual function string [docs]get_full_name();
//
// Function: get_parent
// Get the parent block
//
extern virtual function uvm_reg_block [docs]get_parent ();
extern virtual function uvm_reg_block [docs]get_block ();
//
// Function: get_regfile
// Get the parent register file
//
// Returns ~null~ if this register file is instantiated in a block.
//
extern virtual function uvm_reg_file [docs]get_regfile ();
//----------------
// Group: Backdoor
//----------------
//
// Function: clear_hdl_path
// Delete HDL paths
//
// Remove any previously specified HDL path to the register file instance
// for the specified design abstraction.
//
extern function void [docs]clear_hdl_path (string kind = "RTL");
//
// Function: add_hdl_path
// Add an HDL path
//
// Add the specified HDL path to the register file instance for the specified
// design abstraction. This method may be called more than once for the
// same design abstraction if the register file is physically duplicated
// in the design abstraction
//
extern function void [docs]add_hdl_path (string path, string kind = "RTL");
//
// Function: has_hdl_path
// Check if a HDL path is specified
//
// Returns TRUE if the register file instance has a HDL path defined for the
// specified design abstraction. If no design abstraction is specified,
// uses the default design abstraction specified for the nearest
// enclosing register file or block
//
// If no design abstraction is specified, the default design abstraction
// for this register file is used.
//
extern function bit [docs]has_hdl_path (string kind = "");
//
// Function: get_hdl_path
// Get the incremental HDL path(s)
//
// Returns the HDL path(s) defined for the specified design abstraction
// in the register file instance. If no design abstraction is specified, uses
// the default design abstraction specified for the nearest enclosing
// register file or block.
// Returns only the component of the HDL paths that corresponds to
// the register file, not a full hierarchical path
//
// If no design abstraction is specified, the default design abstraction
// for this register file is used.
//
extern function void [docs]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 register file instance. If no design abstraction
// is specified, uses the default design abstraction specified for the
// nearest enclosing register file or block.
// There may be more than one path returned even
// if only one path was defined for the register file 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 register file or block is used to get each
// incremental path.
//
extern function void [docs]get_full_hdl_path (ref string paths[$],
input string kind = "",
input string separator = ".");
//
// Function: set_default_hdl_path
// Set the default design abstraction
//
// Set the default design abstraction for this register file instance.
//
extern function void [docs]set_default_hdl_path (string kind);
//
// Function: get_default_hdl_path
// Get the default design abstraction
//
// Returns the default design abstraction for this register file instance.
// If a default design abstraction has not been explicitly set for this
// register file instance, returns the default design abstraction for the
// nearest register file or block ancestor.
// Returns "" if no default design abstraction has been specified.
//
extern function string [docs]get_default_hdl_path ();
extern virtual function void [docs]do_print (uvm_printer printer);
extern virtual function string [docs]convert2string();
extern virtual function uvm_object [docs]clone ();
extern virtual function void [docs]do_copy (uvm_object rhs);
extern virtual function bit [docs]do_compare (uvm_object rhs,
uvm_comparer comparer);
extern virtual function void [docs]do_pack (uvm_packer packer);
extern virtual function void [docs]do_unpack (uvm_packer packer);
endclass: uvm_reg_file
//------------------------------------------------------------------------------
// IMPLEMENTATION
//------------------------------------------------------------------------------
// new
function uvm_reg_file::new(string name="");
super.new(name);
hdl_paths_pool = new("hdl_paths");
endfunction: new
// configure
function void uvm_reg_file::configure(uvm_reg_block blk_parent, uvm_reg_file regfile_parent, string hdl_path = "");
if (blk_parent == null) begin
`uvm_error("UVM/RFILE/CFG/NOBLK", {"uvm_reg_file::configure() called without a parent block for instance \"", get_name(), "\" of register file type \"", get_type_name(), "\"."})
return;
end
this.parent = blk_parent;
this.m_rf = regfile_parent;
this.add_hdl_path(hdl_path);
endfunction: configure
// get_block
function uvm_reg_block uvm_reg_file::get_block();
get_block = this.parent;
endfunction: get_block
// get_regfile
function uvm_reg_file uvm_reg_file::get_regfile();
return m_rf;
endfunction
// clear_hdl_path
function void uvm_reg_file::clear_hdl_path(string kind = "RTL");
if (kind == "ALL") begin
hdl_paths_pool = new("hdl_paths");
return;
end
if (kind == "") begin
if (m_rf != null)
kind = m_rf.get_default_hdl_path();
else
kind = parent.get_default_hdl_path();
end
if (!hdl_paths_pool.exists(kind)) begin
`uvm_warning("RegModel",{"Unknown HDL Abstraction '",kind,"'"})
return;
end
hdl_paths_pool.delete(kind);
endfunction
// add_hdl_path
function void uvm_reg_file::add_hdl_path(string path, string kind = "RTL");
uvm_queue #(string) paths;
paths = hdl_paths_pool.get(kind);
paths.push_back(path);
endfunction
// has_hdl_path
function bit uvm_reg_file::has_hdl_path(string kind = "");
if (kind == "") begin
if (m_rf != null)
kind = m_rf.get_default_hdl_path();
else
kind = parent.get_default_hdl_path();
end
return hdl_paths_pool.exists(kind);
endfunction
// get_hdl_path
function void uvm_reg_file::get_hdl_path(ref string paths[$], input string kind = "");
uvm_queue #(string) hdl_paths;
if (kind == "") begin
if (m_rf != null)
kind = m_rf.get_default_hdl_path();
else
kind = parent.get_default_hdl_path();
end
if (!has_hdl_path(kind)) begin
`uvm_error("RegModel",{"Register 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
// get_full_hdl_path
function void uvm_reg_file::get_full_hdl_path(ref string paths[$],
input string kind = "",
input string separator = ".");
if (kind == "")
kind = get_default_hdl_path();
if (!has_hdl_path(kind)) begin
`uvm_error("RegModel",{"Register file does not have hdl path defined for abstraction '",kind,"'"})
return;
end
paths.delete();
begin
uvm_queue #(string) hdl_paths = hdl_paths_pool.get(kind);
string parent_paths[$];
if (m_rf != null)
m_rf.get_full_hdl_path(parent_paths, kind, separator);
else if (parent != null)
parent.get_full_hdl_path(parent_paths, kind, separator);
for (int i=0; i<hdl_paths.size();i++) begin
string hdl_path = hdl_paths.get(i);
if (parent_paths.size() == 0) begin
if (hdl_path != "")
paths.push_back(hdl_path);
continue;
end
foreach (parent_paths[j]) begin
if (hdl_path == "")
paths.push_back(parent_paths[j]);
else
paths.push_back({ parent_paths[j], separator, hdl_path });
end
end
end
endfunction
// get_default_hdl_path
function string uvm_reg_file::get_default_hdl_path();
if (default_hdl_path == "") begin
if (m_rf != null)
return m_rf.get_default_hdl_path();
else
return parent.get_default_hdl_path();
end
return default_hdl_path;
endfunction
// set_default_hdl_path
function void uvm_reg_file::set_default_hdl_path(string kind);
if (kind == "") begin
if (m_rf != null)
kind = m_rf.get_default_hdl_path();
else if (parent == null)
kind = parent.get_default_hdl_path();
else begin
`uvm_error("RegModel",{"Register file has no parent. ",
"Must specify a valid HDL abstraction (kind)"})
return;
end
end
default_hdl_path = kind;
endfunction
// get_parent
function uvm_reg_block uvm_reg_file::get_parent();
return get_block();
endfunction
// get_full_name
function string uvm_reg_file::get_full_name();
uvm_reg_block blk;
get_full_name = this.get_name();
// Is there a parent register file?
if (m_rf != null)
return {m_rf.get_full_name(), ".", get_full_name};
// No: then prepend the full name of the parent block (if any)
if (this.parent == null)
return get_full_name;
get_full_name = {this.parent.get_full_name(), ".", get_full_name};
endfunction: get_full_name
//-------------
// STANDARD OPS
//-------------
// convert2string
function string uvm_reg_file::convert2string();
`uvm_fatal("RegModel","RegModel register files cannot be converted to strings")
return "";
endfunction: convert2string
// do_print
function void uvm_reg_file::do_print (uvm_printer printer);
super.do_print(printer);
endfunction
// clone
function uvm_object uvm_reg_file::clone();
`uvm_fatal("RegModel","RegModel register files cannot be cloned")
return null;
endfunction
// do_copy
function void uvm_reg_file::do_copy(uvm_object rhs);
`uvm_fatal("RegModel","RegModel register files cannot be copied")
endfunction
// do_compare
function bit uvm_reg_file::do_compare (uvm_object rhs,
uvm_comparer comparer);
`uvm_warning("RegModel","RegModel register files cannot be compared")
return 0;
endfunction
// do_pack
function void uvm_reg_file::do_pack (uvm_packer packer);
`uvm_warning("RegModel","RegModel register files cannot be packed")
endfunction
// do_unpack
function void uvm_reg_file::do_unpack (uvm_packer packer);
`uvm_warning("RegModel","RegModel register files cannot be unpacked")
endfunction