//
//------------------------------------------------------------------------------
// Copyright 2007-2011 Mentor Graphics Corporation
// Copyright 2007-2011 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// Copyright 2013 NVIDIA Corporation
// 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_root
//
// The ~uvm_root~ class serves as the implicit top-level and phase controller for
// all UVM components. Users do not directly instantiate ~uvm_root~. The UVM
// automatically creates a single instance of <uvm_root> that users can
// access via the global (uvm_pkg-scope) variable, ~uvm_top~.
//
// (see uvm_ref_root.gif)
//
// The ~uvm_top~ instance of ~uvm_root~ plays several key roles in the UVM.
//
// Implicit top-level - The ~uvm_top~ serves as an implicit top-level component.
// Any component whose parent is specified as ~null~ becomes a child of ~uvm_top~.
// Thus, all UVM components in simulation are descendants of ~uvm_top~.
//
// Phase control - ~uvm_top~ manages the phasing for all components.
//
// Search - Use ~uvm_top~ to search for components based on their
// hierarchical name. See <find> and <find_all>.
//
// Report configuration - Use ~uvm_top~ to globally configure
// report verbosity, log files, and actions. For example,
// ~uvm_top.set_report_verbosity_level_hier(UVM_FULL)~ would set
// full verbosity for all components in simulation.
//
// Global reporter - Because ~uvm_top~ is globally accessible (in uvm_pkg
// scope), UVM's reporting mechanism is accessible from anywhere
// outside ~uvm_component~, such as in modules and sequences.
// See <uvm_report_error>, <uvm_report_warning>, and other global
// methods.
//
//
// The ~uvm_top~ instance checks during the end_of_elaboration phase if any errors have
// been generated so far. If errors are found a UVM_FATAL error is being generated as result
// so that the simulation will not continue to the start_of_simulation_phase.
//
//------------------------------------------------------------------------------
typedef class [docs]uvm_test_done_objection;
typedef class [docs]uvm_cmdline_processor;
typedef class [docs]uvm_component_proxy;
typedef class [docs]uvm_top_down_visitor_adapter;
class [docs]uvm_root extends uvm_component;
// Function: get()
// Static accessor for <uvm_root>.
//
// The static accessor is provided as a convenience wrapper
// around retrieving the root via the <uvm_coreservice_t::get_root>
// method.
//
// | // Using the uvm_coreservice_t:
// | uvm_coreservice_t cs;
// | uvm_root r;
// | cs = uvm_coreservice_t::get();
// | r = cs.get_root();
// |
// | // Not using the uvm_coreservice_t:
// | uvm_root r;
// | r = uvm_root::get();
//
extern static function uvm_root [docs]get();
uvm_cmdline_processor clp;
virtual function string [docs]get_type_name();
return "uvm_root";
endfunction
//----------------------------------------------------------------------------
// Group: Simulation Control
//----------------------------------------------------------------------------
// Task: run_test
//
// Phases all components through all registered phases. If the optional
// test_name argument is provided, or if a command-line plusarg,
// +UVM_TESTNAME=TEST_NAME, is found, then the specified component is created
// just prior to phasing. The test may contain new verification components or
// the entire testbench, in which case the test and testbench can be chosen from
// the command line without forcing recompilation. If the global (package)
// variable, finish_on_completion, is set, then $finish is called after
// phasing completes.
extern virtual task [docs]run_test (string test_name="");
// Function: die
//
// This method is called by the report server if a report reaches the maximum
// quit count or has a UVM_EXIT action associated with it, e.g., as with
// fatal errors.
//
// Calls the <uvm_component::pre_abort()> method
// on the entire <uvm_component> hierarchy in a bottom-up fashion.
// It then calls <uvm_report_server::report_summarize> and terminates the simulation
// with ~$finish~.
virtual function void [docs]die();
uvm_report_server l_rs = uvm_report_server::get_server();
// do the pre_abort callbacks
m_do_pre_abort();
l_rs.report_summarize();
$finish;
endfunction
// Function: set_timeout
//
// Specifies the timeout for the simulation. Default is <`UVM_DEFAULT_TIMEOUT>
//
// The timeout is simply the maximum absolute simulation time allowed before a
// ~FATAL~ occurs. If the timeout is set to 20ns, then the simulation must end
// before 20ns, or a ~FATAL~ timeout will occur.
//
// This is provided so that the user can prevent the simulation from potentially
// consuming too many resources (Disk, Memory, CPU, etc) when the testbench is
// essentially hung.
//
//
extern function void [docs]set_timeout(time timeout, bit overridable=1);
// Variable: finish_on_completion
//
// If set, then run_test will call $finish after all phases are executed.
bit finish_on_completion = 1;
//----------------------------------------------------------------------------
// Group: Topology
//----------------------------------------------------------------------------
// Variable: top_levels
//
// This variable is a list of all of the top level components in UVM. It
// includes the uvm_test_top component that is created by <run_test> as
// well as any other top level components that have been instantiated
// anywhere in the hierarchy.
uvm_component top_levels[$];
// Function: find
extern function uvm_component [docs]find (string comp_match);
// Function: find_all
//
// Returns the component handle (find) or list of components handles
// (find_all) matching a given string. The string may contain the wildcards,
// * and ?. Strings beginning with '.' are absolute path names. If the optional
// argument comp is provided, then search begins from that component down
// (default=all components).
extern function void [docs]find_all (string comp_match,
ref uvm_component comps[$],
input uvm_component comp=null);
// Function: print_topology
//
// Print the verification environment's component topology. The
// ~printer~ is a <uvm_printer> object that controls the format
// of the topology printout; a ~null~ printer prints with the
// default output.
extern function void [docs]print_topology (uvm_printer printer=null);
// Variable: enable_print_topology
//
// If set, then the entire testbench topology is printed just after completion
// of the end_of_elaboration phase.
bit enable_print_topology = 0;
// Variable- phase_timeout
//
// Specifies the timeout for the run phase. Default is `UVM_DEFAULT_TIMEOUT
time phase_timeout = `UVM_DEFAULT_TIMEOUT;
// PRIVATE members
extern function void m_find_all_recurse(string comp_match,
ref uvm_component comps[$],
input uvm_component comp=null);
extern protected function new ();
extern protected virtual function bit m_add_child (uvm_component child);
extern function void [docs]build_phase(uvm_phase phase);
extern local function void m_do_verbosity_settings();
extern local function void m_do_timeout_settings();
extern local function void m_do_factory_settings();
extern local function void m_process_inst_override(string ovr);
extern local function void m_process_type_override(string ovr);
extern local function void m_do_config_settings();
extern local function void m_do_max_quit_settings();
extern local function void m_do_dump_args();
extern local function void m_process_config(string cfg, bit is_int);
extern local function void m_process_default_sequence(string cfg);
extern function void m_check_verbosity();
extern virtual function void [docs]report_header(UVM_FILE file = 0);
// singleton handle
static local uvm_root m_inst;
// For error checking
extern virtual task [docs]run_phase (uvm_phase phase);
// phase_started
// -------------
// At end of elab phase we need to do tlm binding resolution.
function void [docs]phase_started(uvm_phase phase);
if (phase == end_of_elaboration_ph) begin
do_resolve_bindings();
if (enable_print_topology) print_topology();
begin
uvm_report_server srvr;
srvr = uvm_report_server::get_server();
if(srvr.get_severity_count(UVM_ERROR) > 0) begin
uvm_report_fatal("BUILDERR", "stopping due to build errors", UVM_NONE);
end
end
end
endfunction
bit m_phase_all_done;
// internal function not to be used
// get the initialized singleton instance of uvm_root
static function uvm_root m_uvm_get_root();
if (m_inst == null) begin
m_inst = new();
void'(uvm_domain::get_common_domain());
m_inst.m_domain = uvm_domain::get_uvm_domain();
end
return m_inst;
endfunction
`ifndef UVM_NO_DEPRECATED
// stop_request
// ------------
// backward compat only
// call global_stop_request() or uvm_test_done.stop_request() instead
function void [docs]stop_request();
uvm_test_done_objection tdo;
tdo = uvm_test_done_objection::get();
tdo.stop_request();
endfunction
`endif
static local bit m_relnotes_done=0;
function void [docs]end_of_elaboration_phase(uvm_phase phase);
uvm_component_proxy p = new("proxy");
uvm_top_down_visitor_adapter#(uvm_component) adapter = new("adapter");
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_visitor#(uvm_component) v = cs.get_component_visitor();
adapter.accept(this, v, p);
endfunction
endclass
//----------------------------------------------------------------------------
// Group: Global Variables
//----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Variable: uvm_top
//
// This is the top-level that governs phase execution and provides component
// search interface. See <uvm_root> for more information.
//------------------------------------------------------------------------------
const uvm_root uvm_top = uvm_root::get();
//-----------------------------------------------------------------------------
// IMPLEMENTATION
//-----------------------------------------------------------------------------
// get
// ---
function uvm_root uvm_root::get();
uvm_coreservice_t cs = uvm_coreservice_t::get();
return cs.get_root();
endfunction
// new
// ---
function uvm_root::new();
super.new("__top__", null);
m_rh.set_name("reporter");
clp = uvm_cmdline_processor::get_inst();
report_header();
// This sets up the global verbosity. Other command line args may
// change individual component verbosity.
m_check_verbosity();
endfunction
function void uvm_root::report_header(UVM_FILE file = 0);
string q[$];
uvm_report_server srvr;
uvm_cmdline_processor clp;
string args[$];
srvr = uvm_report_server::get_server();
clp = uvm_cmdline_processor::get_inst();
if (clp.get_arg_matches("+UVM_NO_RELNOTES", args)) return;
q.push_back("\n----------------------------------------------------------------\n");
q.push_back({uvm_revision_string(),"\n"});
q.push_back({uvm_mgc_copyright,"\n"});
q.push_back({uvm_cdn_copyright,"\n"});
q.push_back({uvm_snps_copyright,"\n"});
q.push_back({uvm_cy_copyright,"\n"});
q.push_back({uvm_nv_copyright,"\n"});
q.push_back("----------------------------------------------------------------\n");
`ifndef UVM_NO_DEPRECATED
if(!m_relnotes_done)
q.push_back("\n *********** IMPORTANT RELEASE NOTES ************\n");
q.push_back("\n You are using a version of the UVM library that has been compiled\n");
q.push_back(" with `UVM_NO_DEPRECATED undefined.\n");
q.push_back(" See http://www.eda.org/svdb/view.php?id=3313 for more details.\n");
m_relnotes_done=1;
`endif
`ifndef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR
if(!m_relnotes_done)
q.push_back("\n *********** IMPORTANT RELEASE NOTES ************\n");
q.push_back("\n You are using a version of the UVM library that has been compiled\n");
q.push_back(" with `UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR undefined.\n");
q.push_back(" See http://www.eda.org/svdb/view.php?id=3770 for more details.\n");
m_relnotes_done=1;
`endif
if(m_relnotes_done)
q.push_back("\n (Specify +UVM_NO_RELNOTES to turn off this notice)\n");
`uvm_info("UVM/RELNOTES",`UVM_STRING_QUEUE_STREAMING_PACK(q),UVM_LOW)
endfunction
// run_test
// --------
task uvm_root::run_test(string test_name="");
uvm_report_server l_rs;
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
bit testname_plusarg;
int test_name_count;
string test_names[$];
string msg;
uvm_component uvm_test_top;
process phase_runner_proc; // store thread forked below for final cleanup
testname_plusarg = 0;
// Set up the process that decouples the thread that drops objections from
// the process that processes drop/all_dropped objections. Thus, if the
// original calling thread (the "dropper") gets killed, it does not affect
// drain-time and propagation of the drop up the hierarchy.
// Needs to be done in run_test since it needs to be in an
// initial block to fork a process.
uvm_objection::m_init_objections();
`ifndef UVM_NO_DPI
// Retrieve the test names provided on the command line. Command line
// overrides the argument.
test_name_count = clp.get_arg_values("+UVM_TESTNAME=", test_names);
// If at least one, use first in queue.
if (test_name_count > 0) begin
test_name = test_names[0];
testname_plusarg = 1;
end
// If multiple, provided the warning giving the number, which one will be
// used and the complete list.
if (test_name_count > 1) begin
string test_list;
string sep;
for (int i = 0; i < test_names.size(); i++) begin
if (i != 0)
sep = ", ";
test_list = {test_list, sep, test_names[i]};
end
uvm_report_warning("MULTTST",
$sformatf("Multiple (%0d) +UVM_TESTNAME arguments provided on the command line. '%s' will be used. Provided list: %s.", test_name_count, test_name, test_list), UVM_NONE);
end
`else
// plusarg overrides argument
if ($value$plusargs("UVM_TESTNAME=%s", test_name)) begin
`uvm_info("NO_DPI_TSTNAME", "UVM_NO_DPI defined--getting UVM_TESTNAME directly, without DPI", UVM_NONE)
testname_plusarg = 1;
end
`endif
// if test now defined, create it using common factory
if (test_name != "") begin
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
if(m_children.exists("uvm_test_top")) begin
uvm_report_fatal("TTINST",
"An uvm_test_top already exists via a previous call to run_test", UVM_NONE);
#0; // forces shutdown because $finish is forked
end
$cast(uvm_test_top, factory.create_component_by_name(test_name,
"", "uvm_test_top", null));
if (uvm_test_top == null) begin
msg = testname_plusarg ? {"command line +UVM_TESTNAME=",test_name} :
{"call to run_test(",test_name,")"};
uvm_report_fatal("INVTST",
{"Requested test from ",msg, " not found." }, UVM_NONE);
end
end
if (m_children.num() == 0) begin
uvm_report_fatal("NOCOMP",
{"No components instantiated. You must either instantiate",
" at least one component before calling run_test or use",
" run_test to do so. To run a test using run_test,",
" use +UVM_TESTNAME or supply the test name in",
" the argument to run_test(). Exiting simulation."}, UVM_NONE);
return;
end
begin
if(test_name=="")
uvm_report_info("RNTST", "Running test ...", UVM_LOW);
else if (test_name == uvm_test_top.get_type_name())
uvm_report_info("RNTST", {"Running test ",test_name,"..."}, UVM_LOW);
else
uvm_report_info("RNTST", {"Running test ",uvm_test_top.get_type_name()," (via factory override for test \"",test_name,"\")..."}, UVM_LOW);
end
// phase runner, isolated from calling process
fork begin
// spawn the phase runner task
phase_runner_proc = process::self();
uvm_phase::m_run_phases();
end
join_none
#0; // let the phase runner start
wait (m_phase_all_done == 1);
// clean up after ourselves
phase_runner_proc.kill();
l_rs = uvm_report_server::get_server();
l_rs.report_summarize();
if (finish_on_completion)
$finish;
endtask
// find_all
// --------
function void uvm_root::find_all(string comp_match, ref uvm_component comps[$],
input uvm_component comp=null);
if (comp==null)
comp = this;
m_find_all_recurse(comp_match, comps, comp);
endfunction
// find
// ----
function uvm_component uvm_root::find (string comp_match);
uvm_component comp_list[$];
find_all(comp_match,comp_list);
if (comp_list.size() > 1)
uvm_report_warning("MMATCH",
$sformatf("Found %0d components matching '%s'. Returning first match, %0s.",
comp_list.size(),comp_match,comp_list[0].get_full_name()), UVM_NONE);
if (comp_list.size() == 0) begin
uvm_report_warning("CMPNFD",
{"Component matching '",comp_match,
"' was not found in the list of uvm_components"}, UVM_NONE);
return null;
end
return comp_list[0];
endfunction
// print_topology
// --------------
function void uvm_root::print_topology(uvm_printer printer=null);
string s;
if (m_children.num()==0) begin
uvm_report_warning("EMTCOMP", "print_topology - No UVM components to print.", UVM_NONE);
return;
end
if (printer==null)
printer = uvm_default_printer;
foreach (m_children[c]) begin
if(m_children[c].print_enabled) begin
printer.print_object("", m_children[c]);
end
end
`uvm_info("UVMTOP",{"UVM testbench topology:\n",printer.emit()},UVM_NONE)
endfunction
// set_timeout
// -----------
function void uvm_root::set_timeout(time timeout, bit overridable=1);
static bit m_uvm_timeout_overridable = 1;
if (m_uvm_timeout_overridable == 0) begin
uvm_report_info("NOTIMOUTOVR",
$sformatf("The global timeout setting of %0d is not overridable to %0d due to a previous setting.",
phase_timeout, timeout), UVM_NONE);
return;
end
m_uvm_timeout_overridable = overridable;
phase_timeout = timeout;
endfunction
// m_find_all_recurse
// ------------------
function void uvm_root::m_find_all_recurse(string comp_match, ref uvm_component comps[$],
input uvm_component comp=null);
string name;
if (comp.get_first_child(name))
do begin
this.m_find_all_recurse(comp_match, comps, comp.get_child(name));
end
while (comp.get_next_child(name));
if (uvm_is_match(comp_match, comp.get_full_name()) &&
comp.get_name() != "") /* uvm_top */
comps.push_back(comp);
endfunction
// m_add_child
// -----------
// Add to the top levels array
function bit uvm_root::m_add_child (uvm_component child);
if(super.m_add_child(child)) begin
if(child.get_name() == "uvm_test_top")
top_levels.push_front(child);
else
top_levels.push_back(child);
return 1;
end
else
return 0;
endfunction
// build_phase
// -----
function void uvm_root::build_phase(uvm_phase phase);
super.build_phase(phase);
m_set_cl_msg_args();
m_do_verbosity_settings();
m_do_timeout_settings();
m_do_factory_settings();
m_do_config_settings();
m_do_max_quit_settings();
m_do_dump_args();
endfunction
// m_do_verbosity_settings
// -----------------------
function void uvm_root::m_do_verbosity_settings();
string set_verbosity_settings[$];
string split_vals[$];
uvm_verbosity tmp_verb;
// Retrieve them all into set_verbosity_settings
void'(clp.get_arg_values("+uvm_set_verbosity=", set_verbosity_settings));
for(int i = 0; i < set_verbosity_settings.size(); i++) begin
uvm_split_string(set_verbosity_settings[i], ",", split_vals);
if(split_vals.size() < 4 || split_vals.size() > 5) begin
uvm_report_warning("INVLCMDARGS",
$sformatf("Invalid number of arguments found on the command line for setting '+uvm_set_verbosity=%s'. Setting ignored.",
set_verbosity_settings[i]), UVM_NONE, "", "");
end
// Invalid verbosity
if(!clp.m_convert_verb(split_vals[2], tmp_verb)) begin
uvm_report_warning("INVLCMDVERB",
$sformatf("Invalid verbosity found on the command line for setting '%s'.",
set_verbosity_settings[i]), UVM_NONE, "", "");
end
end
endfunction
// m_do_timeout_settings
// ---------------------
function void uvm_root::m_do_timeout_settings();
string timeout_settings[$];
string timeout;
string split_timeout[$];
int timeout_count;
time timeout_int;
string override_spec;
timeout_count = clp.get_arg_values("+UVM_TIMEOUT=", timeout_settings);
if (timeout_count == 0)
return;
else begin
timeout = timeout_settings[0];
if (timeout_count > 1) begin
string timeout_list;
string sep;
for (int i = 0; i < timeout_settings.size(); i++) begin
if (i != 0)
sep = "; ";
timeout_list = {timeout_list, sep, timeout_settings[i]};
end
uvm_report_warning("MULTTIMOUT",
$sformatf("Multiple (%0d) +UVM_TIMEOUT arguments provided on the command line. '%s' will be used. Provided list: %s.",
timeout_count, timeout, timeout_list), UVM_NONE);
end
uvm_report_info("TIMOUTSET",
$sformatf("'+UVM_TIMEOUT=%s' provided on the command line is being applied.", timeout), UVM_NONE);
void'($sscanf(timeout,"%d,%s",timeout_int,override_spec));
case(override_spec)
"YES" : set_timeout(timeout_int, 1);
"NO" : set_timeout(timeout_int, 0);
default : set_timeout(timeout_int, 1);
endcase
end
endfunction
// m_do_factory_settings
// ---------------------
function void uvm_root::m_do_factory_settings();
string args[$];
void'(clp.get_arg_matches("/^\\+(UVM_SET_INST_OVERRIDE|uvm_set_inst_override)=/",args));
foreach(args[i]) begin
m_process_inst_override(args[i].substr(23, args[i].len()-1));
end
void'(clp.get_arg_matches("/^\\+(UVM_SET_TYPE_OVERRIDE|uvm_set_type_override)=/",args));
foreach(args[i]) begin
m_process_type_override(args[i].substr(23, args[i].len()-1));
end
endfunction
// m_process_inst_override
// -----------------------
function void uvm_root::m_process_inst_override(string ovr);
string split_val[$];
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
uvm_split_string(ovr, ",", split_val);
if(split_val.size() != 3 ) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid setting for +uvm_set_inst_override=", ovr,
", setting must specify <requested_type>,<override_type>,<instance_path>"}, UVM_NONE);
return;
end
uvm_report_info("INSTOVR", {"Applying instance override from the command line: +uvm_set_inst_override=", ovr}, UVM_NONE);
factory.set_inst_override_by_name(split_val[0], split_val[1], split_val[2]);
endfunction
// m_process_type_override
// -----------------------
function void uvm_root::m_process_type_override(string ovr);
string split_val[$];
int replace=1;
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
uvm_split_string(ovr, ",", split_val);
if(split_val.size() > 3 || split_val.size() < 2) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid setting for +uvm_set_type_override=", ovr,
", setting must specify <requested_type>,<override_type>[,<replace>]"}, UVM_NONE);
return;
end
// Replace arg is optional. If set, must be 0 or 1
if(split_val.size() == 3) begin
if(split_val[2]=="0") replace = 0;
else if (split_val[2] == "1") replace = 1;
else begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid replace arg for +uvm_set_type_override=", ovr ," value must be 0 or 1"}, UVM_NONE);
return;
end
end
uvm_report_info("UVM_CMDLINE_PROC", {"Applying type override from the command line: +uvm_set_type_override=", ovr}, UVM_NONE);
factory.set_type_override_by_name(split_val[0], split_val[1], replace);
endfunction
// m_process_config
// ----------------
function void uvm_root::m_process_config(string cfg, bit is_int);
uvm_bitstream_t v;
string split_val[$];
uvm_root m_uvm_top;
uvm_coreservice_t cs;
cs = uvm_coreservice_t::get();
m_uvm_top = cs.get_root();
uvm_split_string(cfg, ",", split_val);
if(split_val.size() == 1) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid +uvm_set_config command\"", cfg,
"\" missing field and value: component is \"", split_val[0], "\""}, UVM_NONE);
return;
end
if(split_val.size() == 2) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid +uvm_set_config command\"", cfg,
"\" missing value: component is \"", split_val[0], "\" field is \"", split_val[1], "\""}, UVM_NONE);
return;
end
if(split_val.size() > 3) begin
uvm_report_error("UVM_CMDLINE_PROC",
$sformatf("Invalid +uvm_set_config command\"%s\" : expected only 3 fields (component, field and value).", cfg), UVM_NONE);
return;
end
if(is_int) begin
if(split_val[2].len() > 2) begin
string base, extval;
base = split_val[2].substr(0,1);
extval = split_val[2].substr(2,split_val[2].len()-1);
case(base)
"'b" : v = extval.atobin();
"0b" : v = extval.atobin();
"'o" : v = extval.atooct();
"'d" : v = extval.atoi();
"'h" : v = extval.atohex();
"'x" : v = extval.atohex();
"0x" : v = extval.atohex();
default : v = split_val[2].atoi();
endcase
end
else begin
v = split_val[2].atoi();
end
uvm_report_info("UVM_CMDLINE_PROC", {"Applying config setting from the command line: +uvm_set_config_int=", cfg}, UVM_NONE);
uvm_config_int::set(m_uvm_top, split_val[0], split_val[1], v);
end
else begin
uvm_report_info("UVM_CMDLINE_PROC", {"Applying config setting from the command line: +uvm_set_config_string=", cfg}, UVM_NONE);
uvm_config_string::set(m_uvm_top, split_val[0], split_val[1], split_val[2]);
end
endfunction
// m_process_default_sequence
// ----------------
function void uvm_root::m_process_default_sequence(string cfg);
string split_val[$];
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_root m_uvm_top = cs.get_root();
uvm_factory f = cs.get_factory();
uvm_object_wrapper w;
uvm_split_string(cfg, ",", split_val);
if(split_val.size() == 1) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid +uvm_set_default_sequence command\"", cfg,
"\" missing phase and type: sequencer is \"", split_val[0], "\""}, UVM_NONE);
return;
end
if(split_val.size() == 2) begin
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid +uvm_set_default_sequence command\"", cfg,
"\" missing type: sequencer is \"", split_val[0], "\" phase is \"", split_val[1], "\""}, UVM_NONE);
return;
end
if(split_val.size() > 3) begin
uvm_report_error("UVM_CMDLINE_PROC",
$sformatf("Invalid +uvm_set_default_sequence command\"%s\" : expected only 3 fields (sequencer, phase and type).", cfg), UVM_NONE);
return;
end
w = f.find_wrapper_by_name(split_val[2]);
if (w == null) begin
uvm_report_error("UVM_CMDLINE_PROC",
$sformatf("Invalid type '%s' provided to +uvm_set_default_sequence", split_val[2]),
UVM_NONE);
return;
end
else begin
uvm_report_info("UVM_CMDLINE_PROC", {"Setting default sequence from the command line: +uvm_set_default_sequence=", cfg}, UVM_NONE);
uvm_config_db#(uvm_object_wrapper)::set(this, {split_val[0], ".", split_val[1]}, "default_sequence", w);
end
endfunction : m_process_default_sequence
// m_do_config_settings
// --------------------
function void uvm_root::m_do_config_settings();
string args[$];
void'(clp.get_arg_matches("/^\\+(UVM_SET_CONFIG_INT|uvm_set_config_int)=/",args));
foreach(args[i]) begin
m_process_config(args[i].substr(20, args[i].len()-1), 1);
end
void'(clp.get_arg_matches("/^\\+(UVM_SET_CONFIG_STRING|uvm_set_config_string)=/",args));
foreach(args[i]) begin
m_process_config(args[i].substr(23, args[i].len()-1), 0);
end
void'(clp.get_arg_matches("/^\\+(UVM_SET_DEFAULT_SEQUENCE|uvm_set_default_sequence)=/", args));
foreach(args[i]) begin
m_process_default_sequence(args[i].substr(26, args[i].len()-1));
end
endfunction
// m_do_max_quit_settings
// ----------------------
function void uvm_root::m_do_max_quit_settings();
uvm_report_server srvr;
string max_quit_settings[$];
int max_quit_count;
string max_quit;
string split_max_quit[$];
int max_quit_int;
srvr = uvm_report_server::get_server();
max_quit_count = clp.get_arg_values("+UVM_MAX_QUIT_COUNT=", max_quit_settings);
if (max_quit_count == 0)
return;
else begin
max_quit = max_quit_settings[0];
if (max_quit_count > 1) begin
string max_quit_list;
string sep;
for (int i = 0; i < max_quit_settings.size(); i++) begin
if (i != 0)
sep = "; ";
max_quit_list = {max_quit_list, sep, max_quit_settings[i]};
end
uvm_report_warning("MULTMAXQUIT",
$sformatf("Multiple (%0d) +UVM_MAX_QUIT_COUNT arguments provided on the command line. '%s' will be used. Provided list: %s.",
max_quit_count, max_quit, max_quit_list), UVM_NONE);
end
uvm_report_info("MAXQUITSET",
$sformatf("'+UVM_MAX_QUIT_COUNT=%s' provided on the command line is being applied.", max_quit), UVM_NONE);
uvm_split_string(max_quit, ",", split_max_quit);
max_quit_int = split_max_quit[0].atoi();
case(split_max_quit[1])
"YES" : srvr.set_max_quit_count(max_quit_int, 1);
"NO" : srvr.set_max_quit_count(max_quit_int, 0);
default : srvr.set_max_quit_count(max_quit_int, 1);
endcase
end
endfunction
// m_do_dump_args
// --------------
function void uvm_root::m_do_dump_args();
string dump_args[$];
string all_args[$];
string out_string;
if(clp.get_arg_matches("+UVM_DUMP_CMDLINE_ARGS", dump_args)) begin
clp.get_args(all_args);
for (int i = 0; i < all_args.size(); i++) begin
if (all_args[i] == "__-f__")
continue;
out_string = {out_string, all_args[i], " "};
end
uvm_report_info("DUMPARGS", out_string, UVM_NONE);
end
endfunction
// m_check_verbosity
// ----------------
function void uvm_root::m_check_verbosity();
string verb_string;
string verb_settings[$];
int verb_count;
int plusarg;
int verbosity = UVM_MEDIUM;
`ifndef UVM_CMDLINE_NO_DPI
// Retrieve the verbosities provided on the command line.
verb_count = clp.get_arg_values("+UVM_VERBOSITY=", verb_settings);
`else
verb_count = $value$plusargs("UVM_VERBOSITY=%s",verb_string);
if (verb_count)
verb_settings.push_back(verb_string);
`endif
// If none provided, provide message about the default being used.
//if (verb_count == 0)
// uvm_report_info("DEFVERB", ("No verbosity specified on the command line. Using the default: UVM_MEDIUM"), UVM_NONE);
// If at least one, use the first.
if (verb_count > 0) begin
verb_string = verb_settings[0];
plusarg = 1;
end
// If more than one, provide the warning stating how many, which one will
// be used and the complete list.
if (verb_count > 1) begin
string verb_list;
string sep;
for (int i = 0; i < verb_settings.size(); i++) begin
if (i != 0)
sep = ", ";
verb_list = {verb_list, sep, verb_settings[i]};
end
uvm_report_warning("MULTVERB",
$sformatf("Multiple (%0d) +UVM_VERBOSITY arguments provided on the command line. '%s' will be used. Provided list: %s.", verb_count, verb_string, verb_list), UVM_NONE);
end
if(plusarg == 1) begin
case(verb_string)
"UVM_NONE" : verbosity = UVM_NONE;
"NONE" : verbosity = UVM_NONE;
"UVM_LOW" : verbosity = UVM_LOW;
"LOW" : verbosity = UVM_LOW;
"UVM_MEDIUM" : verbosity = UVM_MEDIUM;
"MEDIUM" : verbosity = UVM_MEDIUM;
"UVM_HIGH" : verbosity = UVM_HIGH;
"HIGH" : verbosity = UVM_HIGH;
"UVM_FULL" : verbosity = UVM_FULL;
"FULL" : verbosity = UVM_FULL;
"UVM_DEBUG" : verbosity = UVM_DEBUG;
"DEBUG" : verbosity = UVM_DEBUG;
default : begin
verbosity = verb_string.atoi();
if(verbosity > 0)
uvm_report_info("NSTVERB", $sformatf("Non-standard verbosity value, using provided '%0d'.", verbosity), UVM_NONE);
if(verbosity == 0) begin
verbosity = UVM_MEDIUM;
uvm_report_warning("ILLVERB", "Illegal verbosity value, using default of UVM_MEDIUM.", UVM_NONE);
end
end
endcase
end
set_report_verbosity_level_hier(verbosity);
endfunction
// It is required that the run phase start at simulation time 0
// TBD this looks wrong - taking advantage of uvm_root not doing anything else?
// TBD move to phase_started callback?
task uvm_root::run_phase (uvm_phase phase);
// check that the commandline are took effect
foreach(m_uvm_applied_cl_action[idx])
if(m_uvm_applied_cl_action[idx].used==0) begin
`uvm_warning("INVLCMDARGS",$sformatf("\"+uvm_set_action=%s\" never took effect due to a mismatching component pattern",m_uvm_applied_cl_action[idx].arg))
end
foreach(m_uvm_applied_cl_sev[idx])
if(m_uvm_applied_cl_sev[idx].used==0) begin
`uvm_warning("INVLCMDARGS",$sformatf("\"+uvm_set_severity=%s\" never took effect due to a mismatching component pattern",m_uvm_applied_cl_sev[idx].arg))
end
if($time > 0)
`uvm_fatal("RUNPHSTIME", {"The run phase must start at time 0, current time is ",
$sformatf("%0t", $realtime), ". No non-zero delays are allowed before ",
"run_test(), and pre-run user defined phases may not consume ",
"simulation time before the start of the run phase."})
endtask