// DESCRIPTION: Verilator: Concatenated UVM header for internal testing // SPDX-License-Identifier: Apache-2.0 //------------------------------------------------------------------------------ // To recreate: // Using verilator_ext_tests // t/t_uvm_parse.pl --debug --no-dump-tree // Copy to here t/obj_vlt/Vt_uvm_parse/Vt_uvm_parse__inputs.vpp // M-x untabify // (global-replace-regexp "[ ]+$" "") // (global-replace-regexp ", +" ", ") // Add this header //------------------------------------------------------------------------------ // Copyright 2007-2011 Mentor Graphics Corporation // Copyright 2010 Synopsys, Inc. // Copyright 2007-2018 Cadence Design Systems, Inc. // Copyright 2010 AMD // Copyright 2017 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. //------------------------------------------------------------------------------ package uvm_pkg; parameter int UVM_HDL_MAX_WIDTH = 1024; typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t; function int uvm_hdl_check_path(string path); uvm_report_fatal("UVM_HDL_CHECK_PATH", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_deposit(string path, uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_DEPOSIT", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_force(string path, uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_FORCE", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time=0); uvm_report_fatal("UVM_HDL_FORCE_TIME", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); endtask function int uvm_hdl_release(string path, output uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_RELEASE", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_read(string path, output uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_READ", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function string uvm_dpi_get_next_arg(int init=0); return ""; endfunction function string uvm_dpi_get_tool_name(); return "?"; endfunction function string uvm_dpi_get_tool_version(); return "?"; endfunction function chandle uvm_dpi_regcomp(string regex); return null; endfunction function int uvm_dpi_regexec(chandle preg, string str); return 0; endfunction function void uvm_dpi_regfree(chandle preg); endfunction function int uvm_re_match(string re, string str); int e, es, s, ss; string tmp; e = 0; s = 0; es = 0; ss = 0; if(re.len() == 0) return 0; if(re[0] == "^") re = re.substr(1, re.len()-1); while (s != str.len() && re.getc(e) != "*") begin if ((re.getc(e) != str.getc(s)) && (re.getc(e) != "?")) return 1; e++; s++; end while (s != str.len()) begin if (re.getc(e) == "*") begin e++; if (e == re.len()) begin return 0; end es = e; ss = s+1; end else if (re.getc(e) == str.getc(s) || re.getc(e) == "?") begin e++; s++; end else begin e = es; s = ss++; end end while (e < re.len() && re.getc(e) == "*") e++; if(e == re.len()) begin return 0; end else begin return 1; end endfunction function string uvm_glob_to_re(string glob); return glob; endfunction typedef class uvm_cmdline_processor; parameter string UVM_VERSION_STRING = "Accellera:1800.2-2017:UVM:1.0"; function string uvm_revision_string(); return UVM_VERSION_STRING; endfunction parameter UVM_STREAMBITS = 4096; typedef logic signed [UVM_STREAMBITS-1:0] uvm_bitstream_t; typedef logic signed [63:0] uvm_integral_t; parameter UVM_FIELD_FLAG_RESERVED_BITS = 28; typedef bit [UVM_FIELD_FLAG_RESERVED_BITS-1 : 0] uvm_field_flag_t; typedef enum uvm_field_flag_t { UVM_BIN = 'h1000000, UVM_DEC = 'h2000000, UVM_UNSIGNED = 'h3000000, UVM_UNFORMAT2 = 'h4000000, UVM_UNFORMAT4 = 'h5000000, UVM_OCT = 'h6000000, UVM_HEX = 'h7000000, UVM_STRING = 'h8000000, UVM_TIME = 'h9000000, UVM_ENUM = 'ha000000, UVM_REAL = 'hb000000, UVM_REAL_DEC = 'hc000000, UVM_REAL_EXP = 'hd000000, UVM_NORADIX = 0 } uvm_radix_enum; parameter UVM_RADIX = 'hf000000; function string uvm_radix_to_string(uvm_radix_enum radix); case(radix) UVM_BIN: return "b"; UVM_OCT: return "o"; UVM_DEC: return "d"; UVM_HEX: return "h"; UVM_UNSIGNED: return "u"; UVM_UNFORMAT2: return "u"; UVM_UNFORMAT4: return "z"; UVM_STRING: return "s"; UVM_TIME: return "t"; UVM_ENUM: return "s"; UVM_REAL: return "g"; UVM_REAL_DEC: return "f"; UVM_REAL_EXP: return "e"; default: return "x"; endcase endfunction typedef enum uvm_field_flag_t { UVM_DEFAULT_POLICY = 0, UVM_DEEP = (1<<16), UVM_SHALLOW = (1<<17), UVM_REFERENCE = (1<<18) } uvm_recursion_policy_enum; parameter UVM_RECURSION = (UVM_DEEP|UVM_SHALLOW|UVM_REFERENCE); typedef enum bit { UVM_PASSIVE=0, UVM_ACTIVE=1 } uvm_active_passive_enum; parameter uvm_field_flag_t UVM_MACRO_NUMFLAGS = 19; parameter uvm_field_flag_t UVM_DEFAULT = 'b000010101010101; parameter uvm_field_flag_t UVM_ALL_ON = 'b000000101010101; parameter uvm_field_flag_t UVM_FLAGS_ON = 'b000000101010101; parameter uvm_field_flag_t UVM_FLAGS_OFF = 0; parameter uvm_field_flag_t UVM_COPY = (1<<0); parameter uvm_field_flag_t UVM_NOCOPY = (1<<1); parameter uvm_field_flag_t UVM_COMPARE = (1<<2); parameter uvm_field_flag_t UVM_NOCOMPARE = (1<<3); parameter uvm_field_flag_t UVM_PRINT = (1<<4); parameter uvm_field_flag_t UVM_NOPRINT = (1<<5); parameter uvm_field_flag_t UVM_RECORD = (1<<6); parameter uvm_field_flag_t UVM_NORECORD = (1<<7); parameter uvm_field_flag_t UVM_PACK = (1<<8); parameter uvm_field_flag_t UVM_NOPACK = (1<<9); parameter uvm_field_flag_t UVM_UNPACK = (1<<10); parameter uvm_field_flag_t UVM_NOUNPACK = UVM_NOPACK; parameter uvm_field_flag_t UVM_SET = (1<<11); parameter uvm_field_flag_t UVM_NOSET = (1<<12); parameter uvm_field_flag_t UVM_NODEFPRINT = (1<<15); parameter uvm_field_flag_t UVM_MACRO_EXTRAS = (1<"; uvm_object_value_str.itoa(v.get_inst_id()); uvm_object_value_str = {"@",uvm_object_value_str}; endfunction function string uvm_leaf_scope (string full_name, byte scope_separator = "."); byte bracket_match; int pos; int bmatches; bmatches = 0; case(scope_separator) "[": bracket_match = "]"; "(": bracket_match = ")"; "<": bracket_match = ">"; "{": bracket_match = "}"; default: bracket_match = ""; endcase if(bracket_match != "" && bracket_match != full_name[full_name.len()-1]) bracket_match = ""; for(pos=full_name.len()-1; pos>0; --pos) begin if(full_name[pos] == bracket_match) bmatches++; else if(full_name[pos] == scope_separator) begin bmatches--; if(!bmatches || (bracket_match == "")) break; end end if(pos) begin if(scope_separator != ".") pos--; uvm_leaf_scope = full_name.substr(pos+1,full_name.len()-1); end else begin uvm_leaf_scope = full_name; end endfunction function string uvm_bitstream_to_string (uvm_bitstream_t value, int size, uvm_radix_enum radix=UVM_NORADIX, string radix_str=""); if (radix == UVM_DEC && value[size-1] === 1) return $sformatf("%0d", value); if($isunknown(value)) begin uvm_bitstream_t _t; _t=0; for(int idx=0;idx 0 && (arg[i] != "[")) begin --i; if((arg[i] == "*") || (arg[i] == "?")) i=0; else if((arg[i] < "0") || (arg[i] > "9") && (arg[i] != "[")) begin uvm_get_array_index_int = -1; i=0; end end else begin is_wildcard = 0; return 0; end if(i>0) begin arg = arg.substr(i+1, arg.len()-2); uvm_get_array_index_int = arg.atoi(); is_wildcard = 0; end endfunction function string uvm_get_array_index_string(string arg, output bit is_wildcard); int i; uvm_get_array_index_string = ""; is_wildcard = 1; i = arg.len() - 1; if(arg[i] == "]") while(i > 0 && (arg[i] != "[")) begin if((arg[i] == "*") || (arg[i] == "?")) i=0; --i; end if(i>0) begin uvm_get_array_index_string = arg.substr(i+1, arg.len()-2); is_wildcard = 0; end endfunction function bit uvm_is_array(string arg); return arg[arg.len()-1] == "]"; endfunction function automatic bit uvm_has_wildcard (string arg); uvm_has_wildcard = 0; if( (arg.len() > 1) && (arg[0] == "/") && (arg[arg.len()-1] == "/") ) return 1; foreach(arg[i]) if( (arg[i] == "*") || (arg[i] == "+") || (arg[i] == "?") ) uvm_has_wildcard = 1; endfunction typedef class uvm_component; typedef class uvm_root; typedef class uvm_report_object; function automatic string m_uvm_string_queue_join(ref string i[$]); m_uvm_string_queue_join = {>>{i}}; endfunction typedef class uvm_factory; typedef class uvm_default_factory; typedef class uvm_report_server; typedef class uvm_default_report_server; typedef class uvm_root; typedef class uvm_visitor; typedef class uvm_component_name_check_visitor; typedef class uvm_component; typedef class uvm_comparer; typedef class uvm_copier; typedef class uvm_packer; typedef class uvm_printer; typedef class uvm_table_printer; typedef class uvm_tr_database; typedef class uvm_text_tr_database; typedef class uvm_resource_pool; typedef class uvm_default_coreservice_t; virtual class uvm_coreservice_t; pure virtual function uvm_factory get_factory(); pure virtual function void set_factory(uvm_factory f); pure virtual function uvm_report_server get_report_server(); pure virtual function void set_report_server(uvm_report_server server); pure virtual function uvm_tr_database get_default_tr_database(); pure virtual function void set_default_tr_database(uvm_tr_database db); pure virtual function void set_component_visitor(uvm_visitor#(uvm_component) v); pure virtual function uvm_visitor#(uvm_component) get_component_visitor(); pure virtual function uvm_root get_root(); pure virtual function void set_phase_max_ready_to_end(int max); pure virtual function int get_phase_max_ready_to_end(); pure virtual function void set_default_printer(uvm_printer printer); pure virtual function uvm_printer get_default_printer(); pure virtual function void set_default_packer(uvm_packer packer); pure virtual function uvm_packer get_default_packer(); pure virtual function void set_default_comparer(uvm_comparer comparer); pure virtual function uvm_comparer get_default_comparer(); pure virtual function int unsigned get_global_seed(); pure virtual function void set_default_copier(uvm_copier copier); pure virtual function uvm_copier get_default_copier(); pure virtual function bit get_uvm_seeding(); pure virtual function void set_uvm_seeding(bit enable); pure virtual function void set_resource_pool (uvm_resource_pool pool); pure virtual function uvm_resource_pool get_resource_pool(); pure virtual function void set_resource_pool_default_precedence(int unsigned precedence); pure virtual function int unsigned get_resource_pool_default_precedence(); local static uvm_coreservice_t inst; static function uvm_coreservice_t get(); if(inst==null) uvm_init(null); return inst; endfunction static function void set(uvm_coreservice_t cs); inst=cs; endfunction endclass class uvm_default_coreservice_t extends uvm_coreservice_t; local uvm_factory factory; virtual function uvm_factory get_factory(); if(factory==null) begin uvm_default_factory f; f=new; factory=f; end return factory; endfunction virtual function void set_factory(uvm_factory f); factory = f; endfunction local uvm_tr_database tr_database; virtual function uvm_tr_database get_default_tr_database(); if (tr_database == null) begin process p = process::self(); uvm_text_tr_database tx_db; string s; if(p != null) s = p.get_randstate(); tx_db = new("default_tr_database"); tr_database = tx_db; if(p != null) p.set_randstate(s); end return tr_database; endfunction : get_default_tr_database virtual function void set_default_tr_database(uvm_tr_database db); tr_database = db; endfunction : set_default_tr_database local uvm_report_server report_server; virtual function uvm_report_server get_report_server(); if(report_server==null) begin uvm_default_report_server f; f=new; report_server=f; end return report_server; endfunction virtual function void set_report_server(uvm_report_server server); report_server=server; endfunction virtual function uvm_root get_root(); return uvm_root::m_uvm_get_root(); endfunction local uvm_visitor#(uvm_component) _visitor; virtual function void set_component_visitor(uvm_visitor#(uvm_component) v); _visitor=v; endfunction virtual function uvm_visitor#(uvm_component) get_component_visitor(); if(_visitor==null) begin uvm_component_name_check_visitor v = new("name-check-visitor"); _visitor=v; end return _visitor; endfunction local uvm_printer m_printer ; virtual function void set_default_printer(uvm_printer printer); m_printer = printer ; endfunction virtual function uvm_printer get_default_printer(); if (m_printer == null) begin m_printer = uvm_table_printer::get_default() ; end return m_printer ; endfunction local uvm_packer m_packer ; virtual function void set_default_packer(uvm_packer packer); m_packer = packer ; endfunction virtual function uvm_packer get_default_packer(); if (m_packer == null) begin m_packer = new("uvm_default_packer") ; end return m_packer ; endfunction local uvm_comparer m_comparer ; virtual function void set_default_comparer(uvm_comparer comparer); m_comparer = comparer ; endfunction virtual function uvm_comparer get_default_comparer(); if (m_comparer == null) begin m_comparer = new("uvm_default_comparer") ; end return m_comparer ; endfunction local int m_default_max_ready_to_end_iters = 20; virtual function void set_phase_max_ready_to_end(int max); m_default_max_ready_to_end_iters = max; endfunction virtual function int get_phase_max_ready_to_end(); return m_default_max_ready_to_end_iters; endfunction local uvm_resource_pool m_rp ; virtual function void set_resource_pool (uvm_resource_pool pool); m_rp = pool; endfunction virtual function uvm_resource_pool get_resource_pool(); if(m_rp == null) m_rp = new(); return m_rp; endfunction local int unsigned m_default_precedence = 1000; virtual function void set_resource_pool_default_precedence(int unsigned precedence); m_default_precedence = precedence; endfunction virtual function int unsigned get_resource_pool_default_precedence(); return m_default_precedence; endfunction local int unsigned m_uvm_global_seed = $urandom; virtual function int unsigned get_global_seed(); return m_uvm_global_seed; endfunction local bit m_use_uvm_seeding = 1; virtual function bit get_uvm_seeding(); return m_use_uvm_seeding; endfunction : get_uvm_seeding virtual function void set_uvm_seeding(bit enable); m_use_uvm_seeding = enable; endfunction : set_uvm_seeding local uvm_copier m_copier ; virtual function void set_default_copier(uvm_copier copier); m_copier = copier ; endfunction virtual function uvm_copier get_default_copier(); if (m_copier == null) begin m_copier = new("uvm_default_copier") ; end return m_copier ; endfunction endclass typedef class uvm_root; typedef class uvm_report_object; typedef class uvm_report_message; task run_test (string test_name=""); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.run_test(test_name); endtask function uvm_report_object uvm_get_report_object(); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); return top; endfunction function int uvm_report_enabled (int verbosity, uvm_severity severity=UVM_INFO, string id=""); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); return top.uvm_report_enabled(verbosity,severity,id); endfunction function void uvm_report( uvm_severity severity, string id, string message, int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW : (severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_report(severity, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction export "DPI-C" function m__uvm_report_dpi; function void m__uvm_report_dpi(int severity, string id, string message, int verbosity, string filename, int line); uvm_report(uvm_severity'(severity), id, message, verbosity, filename, line); endfunction : m__uvm_report_dpi function void uvm_report_info(string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_report_info(id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction function void uvm_report_warning(string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_report_warning(id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction function void uvm_report_error(string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_report_error(id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction function void uvm_report_fatal(string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_report_fatal(id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction function void uvm_process_report_message(uvm_report_message report_message); uvm_root top; uvm_coreservice_t cs; process p; p = process::self(); cs = uvm_coreservice_t::get(); top = cs.get_root(); top.uvm_process_report_message(report_message); endfunction function bit uvm_string_to_severity (string sev_str, output uvm_severity sev); case (sev_str) "UVM_INFO": sev = UVM_INFO; "UVM_WARNING": sev = UVM_WARNING; "UVM_ERROR": sev = UVM_ERROR; "UVM_FATAL": sev = UVM_FATAL; default: return 0; endcase return 1; endfunction function automatic bit uvm_string_to_action (string action_str, output uvm_action action); string actions[$]; uvm_split_string(action_str,"|",actions); uvm_string_to_action = 1; action = 0; foreach(actions[i]) begin case (actions[i]) "UVM_NO_ACTION": action |= UVM_NO_ACTION; "UVM_DISPLAY": action |= UVM_DISPLAY; "UVM_LOG": action |= UVM_LOG; "UVM_COUNT": action |= UVM_COUNT; "UVM_EXIT": action |= UVM_EXIT; "UVM_CALL_HOOK": action |= UVM_CALL_HOOK; "UVM_STOP": action |= UVM_STOP; "UVM_RM_RECORD": action |= UVM_RM_RECORD; default: uvm_string_to_action = 0; endcase end endfunction function bit uvm_is_match (string expr, string str); string s; s = uvm_glob_to_re(expr); return (uvm_re_match(s, str) == 0); endfunction parameter UVM_LINE_WIDTH = 120; parameter UVM_NUM_LINES = 120; parameter UVM_SMALL_STRING = UVM_LINE_WIDTH*8-1; parameter UVM_LARGE_STRING = UVM_LINE_WIDTH*UVM_NUM_LINES*8-1; function logic[UVM_LARGE_STRING:0] uvm_string_to_bits(string str); $swrite(uvm_string_to_bits, "%0s", str); endfunction function uvm_core_state get_core_state(); return m_uvm_core_state; endfunction function void uvm_init(uvm_coreservice_t cs=null); uvm_default_coreservice_t dcs; if(get_core_state()!=UVM_CORE_UNINITIALIZED) begin if (get_core_state() == UVM_CORE_PRE_INIT) begin dcs = new(); uvm_coreservice_t::set(dcs); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"UVM/INIT/MULTI")) uvm_report_fatal ("UVM/INIT/MULTI", "Non-recoverable race during uvm_init", UVM_NONE, "t/uvm/src/base/uvm_globals.svh", 335, "", 1); end end else begin uvm_coreservice_t actual; actual = uvm_coreservice_t::get(); if ((cs != actual) && (cs != null)) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/INIT/MULTI")) uvm_report_warning ("UVM/INIT/MULTI", "uvm_init() called after library has already completed initialization, subsequent calls are ignored!", UVM_NONE, "t/uvm/src/base/uvm_globals.svh", 344, "", 1); end end return; end m_uvm_core_state=UVM_CORE_PRE_INIT; if(cs == null) begin dcs = new(); cs = dcs; end uvm_coreservice_t::set(cs); m_uvm_core_state=UVM_CORE_INITIALIZING; foreach(uvm_deferred_init[idx]) begin uvm_deferred_init[idx].initialize(); end uvm_deferred_init.delete(); begin uvm_root top; top = uvm_root::get(); top.report_header(); top.m_check_uvm_field_flag_size(); top.m_check_verbosity(); end m_uvm_core_state=UVM_CORE_INITIALIZED; endfunction function string uvm_bits_to_string(logic [UVM_LARGE_STRING:0] str); $swrite(uvm_bits_to_string, "%0s", str); endfunction task uvm_wait_for_nba_region; int nba; int next_nba; next_nba++; nba <= next_nba; @(nba); endtask function automatic void uvm_split_string (string str, byte sep, ref string values[$]); int s = 0, e = 0; values.delete(); while(e < str.len()) begin for(s=e; e"; endfunction virtual function uvm_object create (string name=""); return null; endfunction extern virtual function uvm_object clone (); extern function void print (uvm_printer printer=null); extern function string sprint (uvm_printer printer=null); extern virtual function void do_print (uvm_printer printer); extern virtual function string convert2string(); extern function void record (uvm_recorder recorder=null); extern virtual function void do_record (uvm_recorder recorder); extern function void copy (uvm_object rhs, uvm_copier copier=null); extern virtual function void do_copy (uvm_object rhs); extern function bit compare (uvm_object rhs, uvm_comparer comparer=null); extern virtual function bit do_compare (uvm_object rhs, uvm_comparer comparer); extern function int pack (ref bit bitstream[], input uvm_packer packer=null); extern function int pack_bytes (ref byte unsigned bytestream[], input uvm_packer packer=null); extern function int pack_ints (ref int unsigned intstream[], input uvm_packer packer=null); extern function int pack_longints (ref longint unsigned longintstream[], input uvm_packer packer=null); extern virtual function void do_pack (uvm_packer packer); extern function int unpack (ref bit bitstream[], input uvm_packer packer=null); extern function int unpack_bytes (ref byte unsigned bytestream[], input uvm_packer packer=null); extern function int unpack_ints (ref int unsigned intstream[], input uvm_packer packer=null); extern function int unpack_longints (ref longint unsigned longintstream[], input uvm_packer packer=null); extern virtual function void do_unpack (uvm_packer packer); extern virtual function void do_execute_op ( uvm_field_op op); extern virtual function void set_local(uvm_resource_base rsrc) ; extern local function void m_pack (inout uvm_packer packer); extern local function void m_unpack_pre (inout uvm_packer packer); extern local function int m_unpack_post (uvm_packer packer); extern virtual function void m_unsupported_set_local(uvm_resource_base rsrc); local string m_leaf_name; local int m_inst_id; static protected int m_inst_count; extern virtual function void __m_uvm_field_automation (uvm_object tmp_data__, uvm_field_flag_t what__, string str__); extern protected virtual function uvm_report_object m_get_report_object(); endclass function uvm_object::new (string name=""); m_inst_id = m_inst_count++; m_leaf_name = name; endfunction function bit uvm_object::get_uvm_seeding(); uvm_coreservice_t cs = uvm_coreservice_t::get(); return cs.get_uvm_seeding(); endfunction function void uvm_object::set_uvm_seeding(bit enable); uvm_coreservice_t cs = uvm_coreservice_t::get(); cs.set_uvm_seeding(enable); endfunction function void uvm_object::reseed (); if(get_uvm_seeding()) this.srandom(uvm_create_random_seed(get_type_name(), get_full_name())); endfunction function uvm_object_wrapper uvm_object::get_type(); uvm_report_error("NOTYPID", "get_type not implemented in derived class.", UVM_NONE); return null; endfunction function int uvm_object::get_inst_id(); return m_inst_id; endfunction function uvm_object_wrapper uvm_object::get_object_type(); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); if(get_type_name() == "") return null; return factory.find_wrapper_by_name(get_type_name()); endfunction function int uvm_object::get_inst_count(); return m_inst_count; endfunction function string uvm_object::get_name (); return m_leaf_name; endfunction function string uvm_object::get_full_name (); return get_name(); endfunction function void uvm_object::set_name (string name); m_leaf_name = name; endfunction function void uvm_object::print(uvm_printer printer=null); if (printer==null) printer = uvm_printer::get_default(); $fwrite(printer.get_file(),sprint(printer)); endfunction function string uvm_object::sprint(uvm_printer printer=null); string name; if(printer==null) printer = uvm_printer::get_default(); if (printer.get_active_object_depth() == 0) begin printer.flush() ; name = printer.get_root_enabled() ? get_full_name() : get_name(); end else begin name = get_name(); end printer.print_object(name,this); return printer.emit(); endfunction function string uvm_object::convert2string(); return ""; endfunction function void uvm_object::set_local(uvm_resource_base rsrc) ; if(rsrc==null) begin return ; end else begin begin uvm_field_op op; op = uvm_field_op::m_get_available_op(); op.set(UVM_SET,null,rsrc); this.do_execute_op(op); op.m_recycle(); end end endfunction function void uvm_object::m_unsupported_set_local(uvm_resource_base rsrc); return; endfunction function uvm_object uvm_object::clone(); uvm_object tmp; tmp = this.create(get_name()); if(tmp == null) uvm_report_warning("CRFLD", $sformatf("The create method failed for %s, object cannot be cloned", get_name()), UVM_NONE); else tmp.copy(this); return(tmp); endfunction function void uvm_object::copy (uvm_object rhs, uvm_copier copier=null); uvm_coreservice_t coreservice ; uvm_copier m_copier; if(rhs == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"OBJ/COPY")) uvm_report_error ("OBJ/COPY", "Passing a null object to be copied", UVM_NONE, "t/uvm/src/base/uvm_object.svh", 1138, "", 1); end return; end if(copier == null) begin coreservice = uvm_coreservice_t::get() ; m_copier = coreservice.get_default_copier() ; end else m_copier = copier; if(m_copier.get_active_object_depth() == 0) m_copier.flush(); m_copier.copy_object(this,rhs); endfunction function void uvm_object::do_copy (uvm_object rhs); return; endfunction function bit uvm_object::compare (uvm_object rhs, uvm_comparer comparer=null); if (comparer == null) comparer = uvm_comparer::get_default(); if (comparer.get_active_object_depth() == 0) comparer.flush() ; compare = comparer.compare_object(get_name(),this,rhs); endfunction function bit uvm_object::do_compare (uvm_object rhs, uvm_comparer comparer); return 1; endfunction function void uvm_object::__m_uvm_field_automation (uvm_object tmp_data__, uvm_field_flag_t what__, string str__ ); return; endfunction function void uvm_object::do_print(uvm_printer printer); return; endfunction function void uvm_object::m_pack (inout uvm_packer packer); if (packer == null) packer = uvm_packer::get_default(); if(packer.get_active_object_depth() == 0) packer.flush(); packer.pack_object(this); endfunction function int uvm_object::pack (ref bit bitstream [], input uvm_packer packer =null ); m_pack(packer); packer.get_packed_bits(bitstream); return packer.get_packed_size(); endfunction function int uvm_object::pack_bytes (ref byte unsigned bytestream [], input uvm_packer packer=null ); m_pack(packer); packer.get_packed_bytes(bytestream); return packer.get_packed_size(); endfunction function int uvm_object::pack_ints (ref int unsigned intstream [], input uvm_packer packer=null ); m_pack(packer); packer.get_packed_ints(intstream); return packer.get_packed_size(); endfunction function int uvm_object::pack_longints (ref longint unsigned longintstream [], input uvm_packer packer=null ); m_pack(packer); packer.get_packed_longints(longintstream); return packer.get_packed_size(); endfunction function void uvm_object::do_pack (uvm_packer packer ); if (packer == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/OBJ/PACK/NULL")) uvm_report_error ("UVM/OBJ/PACK/NULL", "uvm_object::do_pack called with null packer!", UVM_NONE, "t/uvm/src/base/uvm_object.svh", 1265, "", 1); end return; endfunction function void uvm_object::m_unpack_pre (inout uvm_packer packer); if (packer == null) packer = uvm_packer::get_default(); if(packer.get_active_object_depth() == 0) packer.flush(); endfunction function int uvm_object::m_unpack_post (uvm_packer packer); int size_before_unpack = packer.get_packed_size(); packer.unpack_object(this); return size_before_unpack - packer.get_packed_size(); endfunction function int uvm_object::unpack (ref bit bitstream [], input uvm_packer packer=null); m_unpack_pre(packer); packer.set_packed_bits(bitstream); return m_unpack_post(packer); endfunction function int uvm_object::unpack_bytes (ref byte unsigned bytestream [], input uvm_packer packer=null); m_unpack_pre(packer); packer.set_packed_bytes(bytestream); return m_unpack_post(packer); endfunction function int uvm_object::unpack_ints (ref int unsigned intstream [], input uvm_packer packer=null); m_unpack_pre(packer); packer.set_packed_ints(intstream); return m_unpack_post(packer); endfunction function int uvm_object::unpack_longints (ref longint unsigned longintstream [], input uvm_packer packer=null); m_unpack_pre(packer); packer.set_packed_longints(longintstream); return m_unpack_post(packer); endfunction function void uvm_object::do_execute_op ( uvm_field_op op); endfunction function void uvm_object::do_unpack (uvm_packer packer); if (packer == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/OBJ/UNPACK/NULL")) uvm_report_error ("UVM/OBJ/UNPACK/NULL", "uvm_object::do_unpack called with null packer!", UVM_NONE, "t/uvm/src/base/uvm_object.svh", 1345, "", 1); end return; endfunction function void uvm_object::record (uvm_recorder recorder=null); if(recorder == null) return; recorder.record_object(get_name(), this); endfunction function void uvm_object::do_record (uvm_recorder recorder); return; endfunction function uvm_report_object uvm_object::m_get_report_object(); return null; endfunction typedef class uvm_object; typedef class uvm_component; typedef class uvm_object_wrapper; typedef class uvm_factory_override; typedef struct {uvm_object_wrapper m_type; string m_type_name;} m_uvm_factory_type_pair_t; class uvm_factory_queue_class; uvm_factory_override queue[$]; endclass virtual class uvm_factory; static function uvm_factory get(); uvm_coreservice_t s; s = uvm_coreservice_t::get(); return s.get_factory(); endfunction static function void set(uvm_factory f); uvm_coreservice_t s; s = uvm_coreservice_t::get(); s.set_factory(f); endfunction pure virtual function void register (uvm_object_wrapper obj); pure virtual function void set_inst_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path); pure virtual function void set_inst_override_by_name (string original_type_name, string override_type_name, string full_inst_path); pure virtual function void set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1); pure virtual function void set_type_override_by_name (string original_type_name, string override_type_name, bit replace=1); pure virtual function uvm_object create_object_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); pure virtual function uvm_component create_component_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name, uvm_component parent); pure virtual function uvm_object create_object_by_name (string requested_type_name, string parent_inst_path="", string name=""); pure virtual function bit is_type_name_registered (string type_name); pure virtual function bit is_type_registered (uvm_object_wrapper obj); pure virtual function uvm_component create_component_by_name (string requested_type_name, string parent_inst_path="", string name, uvm_component parent); pure virtual function void set_type_alias(string alias_type_name, uvm_object_wrapper original_type); pure virtual function void set_inst_alias(string alias_type_name, uvm_object_wrapper original_type, string full_inst_path); pure virtual function void debug_create_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); pure virtual function void debug_create_by_name (string requested_type_name, string parent_inst_path="", string name=""); pure virtual function uvm_object_wrapper find_override_by_type (uvm_object_wrapper requested_type, string full_inst_path); pure virtual function uvm_object_wrapper find_override_by_name (string requested_type_name, string full_inst_path); pure virtual function uvm_object_wrapper find_wrapper_by_name (string type_name); pure virtual function void print (int all_types=1); endclass class uvm_default_factory extends uvm_factory; extern virtual function void register (uvm_object_wrapper obj); extern virtual function void set_inst_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path); extern virtual function void set_inst_override_by_name (string original_type_name, string override_type_name, string full_inst_path); extern virtual function void set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1); extern virtual function void set_type_override_by_name (string original_type_name, string override_type_name, bit replace=1); extern virtual function void set_type_alias(string alias_type_name, uvm_object_wrapper original_type); extern virtual function void set_inst_alias(string alias_type_name, uvm_object_wrapper original_type, string full_inst_path); extern virtual function uvm_object create_object_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); extern virtual function uvm_component create_component_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name, uvm_component parent); extern virtual function uvm_object create_object_by_name (string requested_type_name, string parent_inst_path="", string name=""); extern virtual function uvm_component create_component_by_name (string requested_type_name, string parent_inst_path="", string name, uvm_component parent); extern virtual function bit is_type_name_registered (string type_name); extern virtual function bit is_type_registered (uvm_object_wrapper obj); extern virtual function void debug_create_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); extern virtual function void debug_create_by_name (string requested_type_name, string parent_inst_path="", string name=""); extern virtual function uvm_object_wrapper find_override_by_type (uvm_object_wrapper requested_type, string full_inst_path); extern virtual function uvm_object_wrapper find_override_by_name (string requested_type_name, string full_inst_path); extern virtual function uvm_object_wrapper find_wrapper_by_name (string type_name); extern virtual function void print (int all_types=1); extern protected function void m_debug_create (string requested_type_name, uvm_object_wrapper requested_type, string parent_inst_path, string name); extern protected function void m_debug_display(string requested_type_name, uvm_object_wrapper result, string full_inst_path); extern function uvm_object_wrapper m_resolve_type_name(string requested_type_name); extern function uvm_object_wrapper m_resolve_type_name_by_inst(string requested_type_name, string full_inst_path); extern function bit m_matches_type_pair(m_uvm_factory_type_pair_t match_type_pair, uvm_object_wrapper requested_type, string requested_type_name); extern function bit m_matches_type_override(uvm_factory_override override, uvm_object_wrapper requested_type, string requested_type_name, string full_inst_path="", bit match_original_type = 1, bit resolve_null_type_by_inst=0); extern function bit m_matches_inst_override(uvm_factory_override override, uvm_object_wrapper requested_type, string requested_type_name, string full_inst_path=""); typedef struct { m_uvm_factory_type_pair_t orig; string alias_type_name; string full_inst_path; } m_inst_typename_alias_t; protected bit m_types[uvm_object_wrapper]; protected bit m_lookup_strs[string]; protected uvm_object_wrapper m_type_names[string]; protected m_inst_typename_alias_t m_inst_aliases[$]; protected uvm_factory_override m_type_overrides[$]; protected uvm_factory_override m_inst_overrides[$]; local uvm_factory_override m_override_info[$]; local static bit m_debug_pass; extern function bit check_inst_override_exists (uvm_object_wrapper original_type, string original_type_name, uvm_object_wrapper override_type, string override_type_name, string full_inst_path); endclass virtual class uvm_object_wrapper; virtual function uvm_object create_object (string name=""); return null; endfunction virtual function uvm_component create_component (string name, uvm_component parent); return null; endfunction pure virtual function string get_type_name(); virtual function void initialize(); endfunction endclass class uvm_factory_override; string full_inst_path; m_uvm_factory_type_pair_t orig; m_uvm_factory_type_pair_t ovrd; bit replace; bit selected; int unsigned used; bit has_wildcard; function new (string full_inst_path="", string orig_type_name="", uvm_object_wrapper orig_type=null, uvm_object_wrapper ovrd_type, string ovrd_type_name="", bit replace=0); this.full_inst_path= full_inst_path; this.orig.m_type_name = orig_type_name; this.orig.m_type = orig_type; this.ovrd.m_type_name = ovrd_type_name; this.ovrd.m_type = ovrd_type; this.replace = replace; this.has_wildcard = m_has_wildcard(full_inst_path); endfunction function bit m_has_wildcard(string nm); foreach (nm[i]) if(nm[i] == "*" || nm[i] == "?") return 1; return 0; endfunction endclass function void uvm_default_factory::register (uvm_object_wrapper obj); if (obj == null) begin uvm_report_fatal ("NULLWR", "Attempting to register a null object with the factory", UVM_NONE); end if (obj.get_type_name() != "" && obj.get_type_name() != "") begin if (m_type_names.exists(obj.get_type_name())) uvm_report_warning("TPRGED", {"Type name '",obj.get_type_name(), "' already registered with factory. No string-based lookup ", "support for multiple types with the same type name."}, UVM_NONE); else m_type_names[obj.get_type_name()] = obj; end if (m_types.exists(obj)) begin if (obj.get_type_name() != "" && obj.get_type_name() != "") uvm_report_warning("TPRGED", {"Object type '",obj.get_type_name(), "' already registered with factory. "}, UVM_NONE); end else begin uvm_factory_override overrides[$]; m_types[obj] = 1; overrides = {m_type_overrides, m_inst_overrides}; foreach (overrides[index]) begin if(m_matches_type_pair(.match_type_pair(overrides[index].orig), .requested_type(null), .requested_type_name(obj.get_type_name()))) begin overrides[index].orig.m_type = obj; end if(m_matches_type_pair(.match_type_pair(overrides[index].ovrd), .requested_type(null), .requested_type_name(obj.get_type_name()))) begin overrides[index].ovrd.m_type = obj; end end end endfunction function void uvm_default_factory::set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1); bit replaced; if (original_type == override_type) begin if (original_type.get_type_name() == "" || original_type.get_type_name() == "") uvm_report_warning("TYPDUP", {"Original and override type ", "arguments are identical"}, UVM_NONE); else uvm_report_warning("TYPDUP", {"Original and override type ", "arguments are identical: ", original_type.get_type_name()}, UVM_NONE); end if (!m_types.exists(original_type)) register(original_type); if (!m_types.exists(override_type)) register(override_type); foreach (m_type_overrides[index]) begin if(m_matches_type_override(.override(m_type_overrides[index]), .requested_type(original_type), .requested_type_name(original_type.get_type_name()))) begin string msg; msg = {"Original object type '",original_type.get_type_name(), "' already registered to produce '", m_type_overrides[index].ovrd.m_type_name,"'"}; if (!replace) begin msg = {msg, ". Set 'replace' argument to replace the existing entry."}; uvm_report_info("TPREGD", msg, UVM_MEDIUM); return; end msg = {msg, ". Replacing with override to produce type '", override_type.get_type_name(),"'."}; uvm_report_info("TPREGR", msg, UVM_MEDIUM); replaced = 1; m_type_overrides[index].orig.m_type = original_type; m_type_overrides[index].orig.m_type_name = original_type.get_type_name(); m_type_overrides[index].ovrd.m_type = override_type; m_type_overrides[index].ovrd.m_type_name = override_type.get_type_name(); m_type_overrides[index].replace = replace; end else if (m_type_overrides[index].orig.m_type == null) begin break; end end if (!replaced) begin uvm_factory_override override; override = new(.orig_type(original_type), .orig_type_name(original_type.get_type_name()), .ovrd_type(override_type), .ovrd_type_name(override_type.get_type_name()), .replace(replace)); m_type_overrides.push_front(override); end endfunction function void uvm_default_factory::set_type_override_by_name (string original_type_name, string override_type_name, bit replace=1); bit replaced; uvm_object_wrapper original_type; uvm_object_wrapper override_type; if(m_type_names.exists(original_type_name)) original_type = m_type_names[original_type_name]; if(m_type_names.exists(override_type_name)) override_type = m_type_names[override_type_name]; if (original_type_name == override_type_name) begin uvm_report_warning("TYPDUP", {"Requested and actual type name ", " arguments are identical: ",original_type_name,". Ignoring this override."}, UVM_NONE); return; end foreach (m_type_overrides[index]) begin if(m_matches_type_override(.override(m_type_overrides[index]), .requested_type(original_type), .requested_type_name(original_type_name))) begin if (!replace) begin uvm_report_info("TPREGD", {"Original type '",original_type_name, "'/'",m_type_overrides[index].orig.m_type_name, "' already registered to produce '",m_type_overrides[index].ovrd.m_type_name, "'. Set 'replace' argument to replace the existing entry."}, UVM_MEDIUM); return; end uvm_report_info("TPREGR", {"Original object type '",original_type_name, "'/'",m_type_overrides[index].orig.m_type_name, "' already registered to produce '",m_type_overrides[index].ovrd.m_type_name, "'. Replacing with override to produce type '",override_type_name,"'."}, UVM_MEDIUM); replaced = 1; m_type_overrides[index].ovrd.m_type = override_type; m_type_overrides[index].ovrd.m_type_name = override_type_name; m_type_overrides[index].replace = replace; end else if ((m_type_overrides[index].orig.m_type == null) || (original_type == null)) begin break; end end if (original_type == null) m_lookup_strs[original_type_name] = 1; if (!replaced) begin uvm_factory_override override; override = new(.orig_type(original_type), .orig_type_name(original_type_name), .ovrd_type(override_type), .ovrd_type_name(override_type_name), .replace(replace) ); m_type_overrides.push_front(override); end endfunction function bit uvm_default_factory::check_inst_override_exists (uvm_object_wrapper original_type, string original_type_name, uvm_object_wrapper override_type, string override_type_name, string full_inst_path); uvm_factory_override override; foreach (m_inst_overrides[i]) begin override = m_inst_overrides[i]; if (override.full_inst_path == full_inst_path && override.orig.m_type == original_type && override.orig.m_type_name == original_type_name && override.ovrd.m_type == override_type && override.ovrd.m_type_name == override_type_name) begin uvm_report_info("DUPOVRD",{"Instance override for '", original_type_name,"' already exists: override type '", override_type_name,"' with full_inst_path '", full_inst_path,"'"},UVM_HIGH); return 1; end end return 0; endfunction function void uvm_default_factory::set_inst_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path); uvm_factory_override override; if (!m_types.exists(original_type)) register(original_type); if (!m_types.exists(override_type)) register(override_type); if (check_inst_override_exists(original_type, original_type.get_type_name(), override_type, override_type.get_type_name(), full_inst_path)) return; override = new(.full_inst_path(full_inst_path), .orig_type(original_type), .orig_type_name(original_type.get_type_name()), .ovrd_type(override_type), .ovrd_type_name(override_type.get_type_name())); m_inst_overrides.push_back(override); endfunction function void uvm_default_factory::set_inst_override_by_name (string original_type_name, string override_type_name, string full_inst_path); uvm_factory_override override; uvm_object_wrapper original_type; uvm_object_wrapper override_type; if(m_type_names.exists(original_type_name)) original_type = m_type_names[original_type_name]; if(m_type_names.exists(override_type_name)) override_type = m_type_names[override_type_name]; if (original_type == null) m_lookup_strs[original_type_name] = 1; override = new(.full_inst_path(full_inst_path), .orig_type(original_type), .orig_type_name(original_type_name), .ovrd_type(override_type), .ovrd_type_name(override_type_name)); if (check_inst_override_exists(original_type, original_type_name, override_type, override_type_name, full_inst_path)) return; m_inst_overrides.push_back(override); endfunction function void uvm_default_factory::set_type_alias(string alias_type_name, uvm_object_wrapper original_type); if (!is_type_registered(original_type)) uvm_report_warning("BDTYP",{"Cannot define alias of type '", original_type.get_type_name(),"' because it is not registered with the factory."}, UVM_NONE); else begin if (!m_type_names.exists(alias_type_name)) begin uvm_factory_override overrides[$]; m_type_names[alias_type_name] = original_type; overrides = {m_type_overrides, m_inst_overrides}; foreach (overrides[index]) begin if(m_matches_type_pair(.match_type_pair(overrides[index].orig), .requested_type(null), .requested_type_name(alias_type_name))) begin overrides[index].orig.m_type = original_type; end if(m_matches_type_pair(.match_type_pair(overrides[index].ovrd), .requested_type(null), .requested_type_name(alias_type_name))) begin overrides[index].ovrd.m_type = original_type; end end end end endfunction function void uvm_default_factory::set_inst_alias(string alias_type_name, uvm_object_wrapper original_type, string full_inst_path); string original_type_name; m_inst_typename_alias_t orig_type_alias_per_inst; original_type_name = original_type.get_type_name(); if (!is_type_registered(original_type)) uvm_report_warning("BDTYP",{"Cannot define alias of type '", original_type_name,"' because it is not registered with the factory."}, UVM_NONE); else begin orig_type_alias_per_inst.alias_type_name = alias_type_name; orig_type_alias_per_inst.full_inst_path = full_inst_path; orig_type_alias_per_inst.orig.m_type_name = original_type_name; orig_type_alias_per_inst.orig.m_type = original_type; m_inst_aliases.push_back(orig_type_alias_per_inst); end endfunction function uvm_object uvm_default_factory::create_object_by_name (string requested_type_name, string parent_inst_path="", string name=""); uvm_object_wrapper wrapper; string inst_path; if (parent_inst_path == "") inst_path = name; else if (name != "") inst_path = {parent_inst_path,".",name}; else inst_path = parent_inst_path; m_override_info.delete(); wrapper = find_override_by_name(requested_type_name, inst_path); if (wrapper==null) begin wrapper = m_resolve_type_name_by_inst(requested_type_name,inst_path); if(wrapper == null) begin uvm_report_warning("BDTYP",{"Cannot create an object of type '", requested_type_name,"' because it is not registered with the factory."}, UVM_NONE); return null; end end return wrapper.create_object(name); endfunction function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); string full_inst_path; if (parent_inst_path == "") full_inst_path = name; else if (name != "") full_inst_path = {parent_inst_path,".",name}; else full_inst_path = parent_inst_path; m_override_info.delete(); requested_type = find_override_by_type(requested_type, full_inst_path); return requested_type.create_object(name); endfunction function bit uvm_default_factory::is_type_name_registered (string type_name); return (m_type_names.exists(type_name)); endfunction function bit uvm_default_factory::is_type_registered (uvm_object_wrapper obj); return (m_types.exists(obj)); endfunction function uvm_component uvm_default_factory::create_component_by_name (string requested_type_name, string parent_inst_path="", string name, uvm_component parent); uvm_object_wrapper wrapper; string inst_path; if (parent_inst_path == "") inst_path = name; else if (name != "") inst_path = {parent_inst_path,".",name}; else inst_path = parent_inst_path; m_override_info.delete(); wrapper = find_override_by_name(requested_type_name, inst_path); if (wrapper == null) begin if(!m_type_names.exists(requested_type_name)) begin uvm_report_warning("BDTYP",{"Cannot create a component of type '", requested_type_name,"' because it is not registered with the factory."}, UVM_NONE); return null; end wrapper = m_type_names[requested_type_name]; end return wrapper.create_component(name, parent); endfunction function uvm_component uvm_default_factory::create_component_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name, uvm_component parent); string full_inst_path; if (parent_inst_path == "") full_inst_path = name; else if (name != "") full_inst_path = {parent_inst_path,".",name}; else full_inst_path = parent_inst_path; m_override_info.delete(); requested_type = find_override_by_type(requested_type, full_inst_path); return requested_type.create_component(name, parent); endfunction function uvm_object_wrapper uvm_default_factory::find_wrapper_by_name(string type_name); uvm_object_wrapper wrapper = m_resolve_type_name(type_name); if (wrapper != null) return wrapper; uvm_report_warning("UnknownTypeName", {"find_wrapper_by_name: Type name '",type_name, "' not registered with the factory."}, UVM_NONE); endfunction function uvm_object_wrapper uvm_default_factory::find_override_by_name (string requested_type_name, string full_inst_path); uvm_object_wrapper rtype; uvm_factory_override lindex; rtype = m_resolve_type_name_by_inst(requested_type_name,full_inst_path); if(full_inst_path != "") begin foreach(m_inst_overrides[i]) begin if(m_matches_inst_override(.override(m_inst_overrides[i]), .requested_type(rtype), .requested_type_name(requested_type_name), .full_inst_path(full_inst_path))) begin m_override_info.push_back(m_inst_overrides[i]); if (lindex == null) begin lindex = m_inst_overrides[i]; if (!m_debug_pass) begin break; end end end end end if ((lindex == null) || m_debug_pass) begin uvm_factory_override matched_overrides[$]; foreach (m_type_overrides[index]) begin if(m_matches_type_override(.override(m_type_overrides[index]), .requested_type(rtype), .requested_type_name(requested_type_name), .full_inst_path(full_inst_path), .resolve_null_type_by_inst(1))) begin matched_overrides.push_back(m_type_overrides[index]); if ((lindex == null) || (lindex.replace == 0)) begin lindex = m_type_overrides[index]; if (!m_debug_pass && lindex.replace) begin break; end end end end if(matched_overrides.size() != 0) begin if (m_debug_pass) begin m_override_info = {m_override_info,matched_overrides}; end else begin m_override_info.push_back(matched_overrides[$]); end end end if (lindex != null) begin uvm_object_wrapper override = lindex.ovrd.m_type; lindex.used++; if (m_debug_pass) begin lindex.selected = 1; end if(!m_matches_type_override(.override(lindex), .requested_type(rtype), .requested_type_name(requested_type_name), .full_inst_path(full_inst_path), .match_original_type(0), .resolve_null_type_by_inst(1))) begin if(override == null) begin override = find_override_by_name(lindex.ovrd.m_type_name,full_inst_path); end else begin override = find_override_by_type(override,full_inst_path); end end else if(override == null) begin override = m_resolve_type_name_by_inst(lindex.ovrd.m_type_name,full_inst_path); end if(override == null) begin uvm_report_error("TYPNTF", {"Cannot resolve override for original type '", lindex.orig.m_type_name,"' because the override type '", lindex.ovrd.m_type_name, "' is not registered with the factory."}, UVM_NONE); end return override; end return null; endfunction function uvm_object_wrapper uvm_default_factory::find_override_by_type(uvm_object_wrapper requested_type, string full_inst_path); uvm_object_wrapper override; uvm_factory_override lindex; uvm_factory_queue_class qc; foreach (m_override_info[index]) begin if ( m_override_info[index].orig.m_type == requested_type) begin uvm_report_error("OVRDLOOP", "Recursive loop detected while finding override.", UVM_NONE); m_override_info[index].used++; if (!m_debug_pass) debug_create_by_type (requested_type, full_inst_path); return requested_type; end end if(full_inst_path != "") begin foreach(m_inst_overrides[i]) begin if(m_matches_inst_override(.override(m_inst_overrides[i]), .requested_type(requested_type), .requested_type_name(requested_type.get_type_name()), .full_inst_path(full_inst_path))) begin m_override_info.push_back(m_inst_overrides[i]); if (lindex == null) begin lindex = m_inst_overrides[i]; if (!m_debug_pass) begin break; end end end end end if ((lindex == null) || m_debug_pass) begin uvm_factory_override matched_overrides[$]; foreach (m_type_overrides[index]) begin if(m_matches_type_override(.override(m_type_overrides[index]), .requested_type(requested_type), .requested_type_name(requested_type.get_type_name()), .full_inst_path(full_inst_path), .resolve_null_type_by_inst(1))) begin matched_overrides.push_back(m_type_overrides[index]); if ((lindex == null) || (lindex.replace == 0)) begin lindex = m_type_overrides[index]; if (!m_debug_pass && lindex.replace) begin break; end end end end if(matched_overrides.size() != 0) begin if (m_debug_pass) begin m_override_info = {m_override_info,matched_overrides}; end else begin m_override_info.push_back(matched_overrides[$]); end end end if (lindex != null) begin uvm_object_wrapper override = lindex.ovrd.m_type; lindex.used++; if (m_debug_pass) begin lindex.selected = 1; end if(!m_matches_type_override(.override(lindex), .requested_type(requested_type), .requested_type_name(requested_type.get_type_name()), .full_inst_path(full_inst_path), .match_original_type(0), .resolve_null_type_by_inst(1))) begin if(override == null) begin override = find_override_by_name(lindex.ovrd.m_type_name,full_inst_path); end else begin override = find_override_by_type(override,full_inst_path); end end else if(override == null) begin override = m_resolve_type_name_by_inst(lindex.ovrd.m_type_name,full_inst_path); end if(override == null) begin uvm_report_error("TYPNTF", {"Cannot resolve override for original type '", lindex.orig.m_type_name,"' because the override type '", lindex.ovrd.m_type_name, "' is not registered with the factory."}, UVM_NONE); end return override; end return requested_type; endfunction function void uvm_default_factory::print (int all_types=1); string key; string qs[$]; qs.push_back("\n#### Factory Configuration (*)\n\n"); if(!m_type_overrides.size() && !m_inst_overrides.size()) qs.push_back(" No instance or type overrides are registered with this factory\n"); else begin int max1,max2,max3; string dash = "---------------------------------------------------------------------------------------------------"; string space= " "; if(!m_inst_overrides.size()) qs.push_back("No instance overrides are registered with this factory\n"); else begin foreach(m_inst_overrides[j]) begin if (m_inst_overrides[j].orig.m_type_name.len() > max1) max1=m_inst_overrides[j].orig.m_type_name.len(); if (m_inst_overrides[j].full_inst_path.len() > max2) max2=m_inst_overrides[j].full_inst_path.len(); if (m_inst_overrides[j].ovrd.m_type_name.len() > max3) max3=m_inst_overrides[j].ovrd.m_type_name.len(); end if (max1 < 14) max1 = 14; if (max2 < 13) max2 = 13; if (max3 < 13) max3 = 13; qs.push_back("Instance Overrides:\n\n"); qs.push_back($sformatf(" %0s%0s %0s%0s %0s%0s\n","Requested Type",space.substr(1,max1-14), "Override Path", space.substr(1,max2-13), "Override Type", space.substr(1,max3-13))); qs.push_back($sformatf(" %0s %0s %0s\n",dash.substr(1,max1), dash.substr(1,max2), dash.substr(1,max3))); foreach(m_inst_overrides[j]) begin qs.push_back($sformatf(" %0s%0s %0s%0s",m_inst_overrides[j].orig.m_type_name, space.substr(1,max1-m_inst_overrides[j].orig.m_type_name.len()), m_inst_overrides[j].full_inst_path, space.substr(1,max2-m_inst_overrides[j].full_inst_path.len()))); qs.push_back($sformatf(" %0s\n", m_inst_overrides[j].ovrd.m_type_name)); end end if (!m_type_overrides.size()) qs.push_back("\nNo type overrides are registered with this factory\n"); else begin if (max1 < 14) max1 = 14; if (max2 < 13) max2 = 13; if (max3 < 13) max3 = 13; foreach (m_type_overrides[i]) begin if (m_type_overrides[i].orig.m_type_name.len() > max1) max1=m_type_overrides[i].orig.m_type_name.len(); if (m_type_overrides[i].ovrd.m_type_name.len() > max2) max2=m_type_overrides[i].ovrd.m_type_name.len(); end if (max1 < 14) max1 = 14; if (max2 < 13) max2 = 13; qs.push_back("\nType Overrides:\n\n"); qs.push_back($sformatf(" %0s%0s %0s%0s\n","Requested Type",space.substr(1,max1-14), "Override Type", space.substr(1,max2-13))); qs.push_back($sformatf(" %0s %0s\n",dash.substr(1,max1), dash.substr(1,max2))); for (int index=m_type_overrides.size()-1; index>=0; index--) qs.push_back($sformatf(" %0s%0s %0s\n", m_type_overrides[index].orig.m_type_name, space.substr(1,max1-m_type_overrides[index].orig.m_type_name.len()), m_type_overrides[index].ovrd.m_type_name)); end end if (all_types >= 1 && m_type_names.first(key)) begin bit banner; qs.push_back($sformatf("\nAll types registered with the factory: %0d total\n",m_types.num())); do begin if (!(all_types < 2 && uvm_is_match("uvm_*", m_type_names[key].get_type_name())) && key == m_type_names[key].get_type_name()) begin if (!banner) begin qs.push_back(" Type Name\n"); qs.push_back(" ---------\n"); banner=1; end qs.push_back($sformatf(" %s\n", m_type_names[key].get_type_name())); end end while(m_type_names.next(key)); end qs.push_back("(*) Types with no associated type name will be printed as \n\n####\n\n"); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/FACTORY/PRINT")) uvm_report_info ("UVM/FACTORY/PRINT", uvm_pkg::m_uvm_string_queue_join(qs), UVM_NONE, "t/uvm/src/base/uvm_factory.svh", 1875, "", 1); end endfunction function void uvm_default_factory::debug_create_by_name (string requested_type_name, string parent_inst_path="", string name=""); m_debug_create(requested_type_name, null, parent_inst_path, name); endfunction function void uvm_default_factory::debug_create_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name=""); m_debug_create("", requested_type, parent_inst_path, name); endfunction function void uvm_default_factory::m_debug_create (string requested_type_name, uvm_object_wrapper requested_type, string parent_inst_path, string name); string full_inst_path; uvm_object_wrapper result; if (parent_inst_path == "") full_inst_path = name; else if (name != "") full_inst_path = {parent_inst_path,".",name}; else full_inst_path = parent_inst_path; m_override_info.delete(); if (requested_type == null) begin if (!m_type_names.exists(requested_type_name) && !m_lookup_strs.exists(requested_type_name)) begin uvm_report_warning("Factory Warning", {"The factory does not recognize '", requested_type_name,"' as a registered type."}, UVM_NONE); return; end m_debug_pass = 1; result = find_override_by_name(requested_type_name,full_inst_path); end else begin m_debug_pass = 1; if (!m_types.exists(requested_type)) register(requested_type); result = find_override_by_type(requested_type,full_inst_path); if (requested_type_name == "") requested_type_name = requested_type.get_type_name(); end m_debug_display(requested_type_name, result, full_inst_path); m_debug_pass = 0; foreach (m_override_info[index]) m_override_info[index].selected = 0; endfunction function void uvm_default_factory::m_debug_display (string requested_type_name, uvm_object_wrapper result, string full_inst_path); int max1,max2,max3; string dash = "---------------------------------------------------------------------------------------------------"; string space= " "; string qs[$]; qs.push_back("\n#### Factory Override Information (*)\n\n"); qs.push_back( $sformatf("Given a request for an object of type '%s' with an instance\npath of '%s' the factory encountered\n\n", requested_type_name,full_inst_path)); if (m_override_info.size() == 0) qs.push_back("no relevant overrides.\n\n"); else begin qs.push_back("the following relevant overrides. An 'x' next to a match indicates a\nmatch that was ignored.\n\n"); foreach (m_override_info[i]) begin if (m_override_info[i].orig.m_type_name.len() > max1) max1=m_override_info[i].orig.m_type_name.len(); if (m_override_info[i].full_inst_path.len() > max2) max2=m_override_info[i].full_inst_path.len(); if (m_override_info[i].ovrd.m_type_name.len() > max3) max3=m_override_info[i].ovrd.m_type_name.len(); end if (max1 < 13) max1 = 13; if (max2 < 13) max2 = 13; if (max3 < 13) max3 = 13; qs.push_back($sformatf("Original Type%0s Instance Path%0s Override Type%0s\n", space.substr(1,max1-13),space.substr(1,max2-13),space.substr(1,max3-13))); qs.push_back($sformatf(" %0s %0s %0s\n",dash.substr(1,max1), dash.substr(1,max2), dash.substr(1,max3))); foreach (m_override_info[i]) begin qs.push_back($sformatf("%s%0s%0s\n", m_override_info[i].selected ? " " : "x ", m_override_info[i].orig.m_type_name, space.substr(1,max1-m_override_info[i].orig.m_type_name.len()))); qs.push_back($sformatf(" %0s%0s", m_override_info[i].full_inst_path, space.substr(1,max2-m_override_info[i].full_inst_path.len()))); qs.push_back($sformatf(" %0s%0s", m_override_info[i].ovrd.m_type_name, space.substr(1,max3-m_override_info[i].ovrd.m_type_name.len()))); if (m_override_info[i].full_inst_path == "*") qs.push_back(" "); else qs.push_back("\n"); end qs.push_back("\n"); end qs.push_back("Result:\n\n"); qs.push_back($sformatf(" The factory will produce an object of type '%0s'\n", result == null ? requested_type_name : result.get_type_name())); qs.push_back("\n(*) Types with no associated type name will be printed as \n\n####\n\n"); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/FACTORY/DUMP")) uvm_report_info ("UVM/FACTORY/DUMP", uvm_pkg::m_uvm_string_queue_join(qs), UVM_NONE, "t/uvm/src/base/uvm_factory.svh", 2015, "", 1); end endfunction function uvm_object_wrapper uvm_default_factory::m_resolve_type_name(string requested_type_name); uvm_object_wrapper wrapper=null; if(m_type_names.exists(requested_type_name)) wrapper = m_type_names[requested_type_name]; return wrapper; endfunction function uvm_object_wrapper uvm_default_factory::m_resolve_type_name_by_inst(string requested_type_name, string full_inst_path); uvm_object_wrapper wrapper=null; m_inst_typename_alias_t type_alias_inst[$]; type_alias_inst = m_inst_aliases.find(i) with ((i.alias_type_name == requested_type_name) && uvm_is_match(i.full_inst_path,full_inst_path)); if (type_alias_inst.size() > 0) begin wrapper = type_alias_inst[0].orig.m_type; end else begin wrapper = m_resolve_type_name(requested_type_name); end return wrapper; endfunction function bit uvm_default_factory::m_matches_type_pair(m_uvm_factory_type_pair_t match_type_pair, uvm_object_wrapper requested_type, string requested_type_name); return ((match_type_pair.m_type != null) && (match_type_pair.m_type == requested_type) || (match_type_pair.m_type_name != "" && match_type_pair.m_type_name != "" && match_type_pair.m_type_name == requested_type_name)); endfunction function bit uvm_default_factory::m_matches_inst_override(uvm_factory_override override, uvm_object_wrapper requested_type, string requested_type_name, string full_inst_path=""); m_uvm_factory_type_pair_t match_type_pair = override.orig ; if(match_type_pair.m_type == null) begin match_type_pair.m_type = m_resolve_type_name_by_inst(match_type_pair.m_type_name, full_inst_path); end if (m_matches_type_pair(.match_type_pair(match_type_pair), .requested_type(requested_type), .requested_type_name(requested_type_name))) begin if(override.has_wildcard) begin return (override.full_inst_path == "*" || uvm_is_match(override.full_inst_path,full_inst_path)); end else begin return (override.full_inst_path == full_inst_path); end end return 0; endfunction function bit uvm_default_factory::m_matches_type_override(uvm_factory_override override, uvm_object_wrapper requested_type, string requested_type_name, string full_inst_path="", bit match_original_type = 1, bit resolve_null_type_by_inst=0); m_uvm_factory_type_pair_t match_type_pair = match_original_type ? override.orig : override.ovrd; if(match_type_pair.m_type == null) begin if(resolve_null_type_by_inst) begin match_type_pair.m_type = m_resolve_type_name_by_inst(match_type_pair.m_type_name,full_inst_path); end else begin match_type_pair.m_type = m_resolve_type_name(match_type_pair.m_type_name); end end return m_matches_type_pair(.match_type_pair(match_type_pair), .requested_type(requested_type), .requested_type_name(requested_type_name)); endfunction typedef class uvm_registry_common; typedef class uvm_registry_component_creator; typedef class uvm_registry_object_creator; class uvm_component_registry #(type T=uvm_component, string Tname="") extends uvm_object_wrapper; typedef uvm_component_registry #(T,Tname) this_type; typedef uvm_registry_common#( this_type, uvm_registry_component_creator, T, Tname ) common_type; virtual function uvm_component create_component (string name, uvm_component parent); T obj; obj = new(name, parent); return obj; endfunction static function string type_name(); return common_type::type_name(); endfunction : type_name virtual function string get_type_name(); common_type common = common_type::get(); return common.get_type_name(); endfunction static function this_type get(); static this_type m_inst; if (m_inst == null) m_inst = new(); return m_inst; endfunction virtual function void initialize(); common_type common = common_type::get(); common.initialize(); endfunction static function T create(string name, uvm_component parent, string contxt=""); return common_type::create( name, parent, contxt ); endfunction static function void set_type_override (uvm_object_wrapper override_type, bit replace=1); common_type::set_type_override( override_type, replace ); endfunction static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component parent=null); common_type::set_inst_override( override_type, inst_path, parent ); endfunction static function bit set_type_alias(string alias_name); common_type::set_type_alias( alias_name ); return 1; endfunction endclass class uvm_object_registry #(type T=uvm_object, string Tname="") extends uvm_object_wrapper; typedef uvm_object_registry #(T,Tname) this_type; typedef uvm_registry_common#( this_type, uvm_registry_object_creator, T, Tname ) common_type; virtual function uvm_object create_object(string name=""); T obj; if (name=="") obj = new(); else obj = new(name); return obj; endfunction static function string type_name(); return common_type::type_name(); endfunction : type_name virtual function string get_type_name(); common_type common = common_type::get(); return common.get_type_name(); endfunction static function this_type get(); static this_type m_inst; if (m_inst == null) m_inst = new(); return m_inst; endfunction static function T create (string name="", uvm_component parent=null, string contxt=""); return common_type::create( name, parent, contxt ); endfunction static function void set_type_override (uvm_object_wrapper override_type, bit replace=1); common_type::set_type_override( override_type, replace ); endfunction static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component parent=null); common_type::set_inst_override( override_type, inst_path, parent ); endfunction static function bit set_type_alias(string alias_name); common_type::set_type_alias( alias_name ); return 1; endfunction virtual function void initialize(); common_type common = common_type::get(); common.initialize(); endfunction endclass class uvm_abstract_component_registry #(type T=uvm_component, string Tname="") extends uvm_object_wrapper; typedef uvm_abstract_component_registry #(T,Tname) this_type; typedef uvm_registry_common#( this_type, uvm_registry_component_creator, T, Tname ) common_type; virtual function uvm_component create_component (string name, uvm_component parent); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/ABST_RGTRY/CREATE_ABSTRACT_CMPNT")) uvm_report_error ("UVM/ABST_RGTRY/CREATE_ABSTRACT_CMPNT", $sformatf( "Cannot create an instance of abstract class %s (with name %s and parent %s). Check for missing factory overrides for %s.", this.get_type_name(), name, parent.get_full_name(), this.get_type_name() ), UVM_NONE, "t/uvm/src/base/uvm_registry.svh", 308, "", 1); end return null; endfunction static function string type_name(); return common_type::type_name(); endfunction : type_name virtual function string get_type_name(); common_type common = common_type::get(); return common.get_type_name(); endfunction static function this_type get(); static this_type m_inst; if (m_inst == null) m_inst = new(); return m_inst; endfunction static function T create(string name, uvm_component parent, string contxt=""); return common_type::create( name, parent, contxt ); endfunction static function void set_type_override (uvm_object_wrapper override_type, bit replace=1); common_type::set_type_override( override_type, replace ); endfunction static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component parent=null); common_type::set_inst_override( override_type, inst_path, parent ); endfunction static function bit set_type_alias(string alias_name); common_type::set_type_alias( alias_name ); return 1; endfunction virtual function void initialize(); common_type common = common_type::get(); common.initialize(); endfunction endclass class uvm_abstract_object_registry #(type T=uvm_object, string Tname="") extends uvm_object_wrapper; typedef uvm_abstract_object_registry #(T,Tname) this_type; typedef uvm_registry_common#( this_type, uvm_registry_object_creator, T, Tname ) common_type; virtual function uvm_object create_object(string name=""); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/ABST_RGTRY/CREATE_ABSTRACT_OBJ")) uvm_report_error ("UVM/ABST_RGTRY/CREATE_ABSTRACT_OBJ", $sformatf( "Cannot create an instance of abstract class %s (with name %s). Check for missing factory overrides for %s.", this.get_type_name(), name, this.get_type_name() ), UVM_NONE, "t/uvm/src/base/uvm_registry.svh", 428, "", 1); end return null; endfunction static function string type_name(); return common_type::type_name(); endfunction : type_name virtual function string get_type_name(); common_type common = common_type::get(); return common.get_type_name(); endfunction static function this_type get(); static this_type m_inst; if (m_inst == null) m_inst = new(); return m_inst; endfunction static function T create (string name="", uvm_component parent=null, string contxt=""); return common_type::create( name, parent, contxt ); endfunction static function void set_type_override (uvm_object_wrapper override_type, bit replace=1); common_type::set_type_override( override_type, replace ); endfunction static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component parent=null); common_type::set_inst_override( override_type, inst_path, parent ); endfunction static function bit set_type_alias(string alias_name); common_type::set_type_alias( alias_name ); return 1; endfunction virtual function void initialize(); common_type common = common_type::get(); common.initialize(); endfunction endclass class uvm_registry_common #( type Tregistry=int, type Tcreator=int, type Tcreated=int, string Tname="" ); typedef uvm_registry_common#(Tregistry,Tcreator,Tcreated,Tname) this_type; local static string m__type_aliases[$]; static function string type_name(); if((Tname == "") && (m__type_aliases.size() != 0)) begin return m__type_aliases[0]; end return Tname; endfunction : type_name virtual function string get_type_name(); return type_name(); endfunction static function this_type get(); static this_type m_inst; if (m_inst == null) m_inst = new(); return m_inst; endfunction : get static function Tcreated create(string name, uvm_component parent, string contxt); uvm_object obj; if (contxt == "" && parent != null) contxt = parent.get_full_name(); obj = Tcreator::create_by_type( Tregistry::get(), contxt, name, parent ); if (!$cast(create, obj)) begin string msg; msg = {"Factory did not return a ", Tcreator::base_type_name(), " of type '",Tregistry::type_name, "'. A component of type '",obj == null ? "null" : obj.get_type_name(), "' was returned instead. Name=",name," Parent=", parent==null?"null":parent.get_type_name()," contxt=",contxt}; uvm_report_fatal("FCTTYP", msg, UVM_NONE); end endfunction static function void set_type_override (uvm_object_wrapper override_type, bit replace); uvm_factory factory=uvm_factory::get(); factory.set_type_override_by_type(Tregistry::get(),override_type,replace); endfunction static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component parent); string full_inst_path; uvm_factory factory=uvm_factory::get(); if (parent != null) begin if (inst_path == "") inst_path = parent.get_full_name(); else inst_path = {parent.get_full_name(),".",inst_path}; end factory.set_inst_override_by_type(Tregistry::get(),override_type,inst_path); endfunction static function void set_type_alias(string alias_name); m__type_aliases.push_back(alias_name); m__type_aliases.sort(); if (uvm_pkg::get_core_state() != UVM_CORE_UNINITIALIZED) begin uvm_factory factory = uvm_factory::get(); Tregistry rgtry = Tregistry::get(); if (factory.is_type_registered(rgtry)) begin factory.set_type_alias(alias_name,rgtry); end end endfunction static function bit __deferred_init(); Tregistry rgtry = Tregistry::get(); if (uvm_pkg::get_core_state() == UVM_CORE_UNINITIALIZED) begin uvm_pkg::uvm_deferred_init.push_back(rgtry); end else begin rgtry.initialize(); end return 1; endfunction local static bit m__initialized=__deferred_init(); virtual function void initialize(); uvm_factory factory =uvm_factory::get(); Tregistry rgtry = Tregistry::get(); factory.register(rgtry); foreach(m__type_aliases[i]) begin factory.set_type_alias(m__type_aliases[i],rgtry); end endfunction endclass virtual class uvm_registry_component_creator; static function uvm_component create_by_type( uvm_object_wrapper obj_wrpr, string contxt, string name, uvm_component parent ); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory = cs.get_factory(); return factory.create_component_by_type( obj_wrpr, contxt, name, parent ); endfunction static function string base_type_name(); return "component"; endfunction endclass virtual class uvm_registry_object_creator; static function uvm_object create_by_type( uvm_object_wrapper obj_wrpr, string contxt, string name, uvm_object unused ); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory = cs.get_factory(); unused = unused; return factory.create_object_by_type( obj_wrpr, contxt, name ); endfunction static function string base_type_name(); return "object"; endfunction endclass class uvm_pool #(type KEY=int, T=uvm_void) extends uvm_object; typedef uvm_pool #(KEY,T) this_type; static protected this_type m_global_pool; protected T pool[KEY]; typedef uvm_object_registry #(uvm_pool #(KEY,T)) type_id; static function uvm_pool #(KEY,T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_pool #(KEY,T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_pool"; endfunction : type_name virtual function string get_type_name(); return "uvm_pool"; endfunction : get_type_name function new (string name=""); super.new(name); endfunction static function this_type get_global_pool (); if (m_global_pool==null) m_global_pool = new("pool"); return m_global_pool; endfunction static function T get_global (KEY key); this_type gpool; gpool = get_global_pool(); return gpool.get(key); endfunction virtual function T get (KEY key); if (!pool.exists(key)) begin T default_value; pool[key] = default_value; end return pool[key]; endfunction virtual function void add (KEY key, T item); pool[key] = item; endfunction virtual function int num (); return pool.num(); endfunction virtual function void delete (KEY key); if (!exists(key)) begin uvm_report_warning("POOLDEL", $sformatf("delete: pool key doesn't exist. Ignoring delete request")); return; end pool.delete(key); endfunction virtual function int exists (KEY key); return pool.exists(key); endfunction virtual function int first (ref KEY key); return pool.first(key); endfunction virtual function int last (ref KEY key); return pool.last(key); endfunction virtual function int next (ref KEY key); return pool.next(key); endfunction virtual function int prev (ref KEY key); return pool.prev(key); endfunction virtual function void do_copy (uvm_object rhs); this_type p; KEY key; super.do_copy(rhs); if (rhs==null || !$cast(p, rhs)) return; pool = p.pool; endfunction virtual function void do_print (uvm_printer printer); string v; int cnt; string item; KEY key; printer.print_array_header("pool",pool.num(),"aa_object_string"); if (pool.first(key)) do begin item.itoa(cnt); item = {"[-key",item,"--]"}; $swrite(v,pool[key]); printer.print_generic(item,"",-1,v,"["); end while (pool.next(key)); printer.print_array_footer(); endfunction endclass class uvm_object_string_pool #(type T=uvm_object) extends uvm_pool #(string,T); typedef uvm_object_string_pool #(T) this_type; static protected this_type m_global_pool; typedef uvm_object_registry #(uvm_object_string_pool#(T)) type_id; static function uvm_object_string_pool#(T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_object_string_pool#(T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_obj_str_pool"; endfunction : type_name virtual function string get_type_name(); return "uvm_obj_str_pool"; endfunction : get_type_name function new (string name=""); super.new(name); endfunction static function this_type get_global_pool (); if (m_global_pool==null) m_global_pool = new("global_pool"); return m_global_pool; endfunction static function T get_global (string key); this_type gpool; gpool = get_global_pool(); return gpool.get(key); endfunction virtual function T get (string key); if (!pool.exists(key)) pool[key] = new (key); return pool[key]; endfunction virtual function void delete (string key); if (!exists(key)) begin uvm_report_warning("POOLDEL", $sformatf("delete: key '%s' doesn't exist", key)); return; end pool.delete(key); endfunction virtual function void do_print (uvm_printer printer); string key; printer.print_array_header("pool",pool.num(),"aa_object_string"); if (pool.first(key)) do printer.print_object({"[",key,"]"}, pool[key],"["); while (pool.next(key)); printer.print_array_footer(); endfunction endclass typedef class uvm_barrier; typedef class uvm_event; typedef uvm_object_string_pool #(uvm_barrier) uvm_barrier_pool ; typedef uvm_object_string_pool #(uvm_event#(uvm_object)) uvm_event_pool ; class uvm_queue #(type T=int) extends uvm_object; typedef uvm_queue #(T) this_type; typedef uvm_object_registry #(uvm_queue#(T)) type_id; static function uvm_queue#(T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_queue#(T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_queue"; endfunction : type_name virtual function string get_type_name(); return "uvm_queue"; endfunction : get_type_name static local this_type m_global_queue; protected T queue[$]; function new (string name=""); super.new(name); endfunction static function this_type get_global_queue (); if (m_global_queue==null) m_global_queue = new("global_queue"); return m_global_queue; endfunction static function T get_global (int index); this_type gqueue; gqueue = get_global_queue(); return gqueue.get(index); endfunction virtual function T get (int index); T default_value; if (index >= size() || index < 0) begin uvm_report_warning("QUEUEGET", $sformatf("get: given index out of range for queue of size %0d. Ignoring get request",size())); return default_value; end return queue[index]; endfunction virtual function int size (); return queue.size(); endfunction virtual function void insert (int index, T item); if (index >= size() || index < 0) begin uvm_report_warning("QUEUEINS", $sformatf("insert: given index out of range for queue of size %0d. Ignoring insert request",size())); return; end queue.insert(index,item); endfunction virtual function void delete (int index=-1); if (index >= size() || index < -1) begin uvm_report_warning("QUEUEDEL", $sformatf("delete: given index out of range for queue of size %0d. Ignoring delete request",size())); return; end if (index == -1) queue.delete(); else queue.delete(index); endfunction virtual function T pop_front(); return queue.pop_front(); endfunction virtual function T pop_back(); return queue.pop_back(); endfunction virtual function void push_front(T item); queue.push_front(item); endfunction virtual function void push_back(T item); queue.push_back(item); endfunction virtual task wait_until_not_empty(); wait(queue.size() > 0); endtask virtual function void do_copy (uvm_object rhs); this_type p; super.do_copy(rhs); if (rhs == null || !$cast(p, rhs)) return; queue = p.queue; endfunction virtual function string convert2string(); return $sformatf("%p",queue); endfunction endclass class uvm_spell_chkr #(type T=int); typedef T tab_t[string]; static const int unsigned max = '1; static function bit check ( ref tab_t strtab, input string s); string key; int distance; int unsigned min; string min_key[$]; if(strtab.exists(s)) begin return 1; end min = max; foreach(strtab[key]) begin distance = levenshtein_distance(key, s); if(distance < 0) continue; if(distance < min) begin min = distance; min_key.delete(); min_key.push_back(key); continue; end if(distance == min) begin min_key.push_back(key); end end if(min == max) begin begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/CONFIGDB/SPELLCHK")) uvm_report_info ("UVM/CONFIGDB/SPELLCHK", $sformatf("%s not located, no alternatives to suggest", s), UVM_NONE, "t/uvm/src/base/uvm_spell_chkr.svh", 110, "", 1); end end else begin string q[$]; foreach(min_key[i]) begin q.push_back(min_key[i]); q.push_back("|"); end if(q.size()) void'(q.pop_back()); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/CONFIGDB/SPELLCHK")) uvm_report_info ("UVM/CONFIGDB/SPELLCHK", $sformatf("%s not located, did you mean %s", s, uvm_pkg::m_uvm_string_queue_join(q)), UVM_NONE, "t/uvm/src/base/uvm_spell_chkr.svh", 124, "", 1); end end return 0; endfunction static local function int levenshtein_distance(string s, string t); int k, i, j, n, m, cost, distance; int d[]; n = s.len() + 1; m = t.len() + 1; if(n == 1 || m == 1) return -1; d = new[m*n]; for(k = 0; k < n; k++) d[k] = k; for(k = 0; k < m; k++) d[k*n] = k; for(i = 1; i < n; i++) begin for(j = 1; j < m; j++) begin cost = !(s[i-1] == t[j-1]); d[j*n+i] = minimum(d[(j-1)*n+i]+1, d[j*n+i-1]+1, d[(j-1)*n+i-1]+cost); end end distance = d[n*m-1]; return distance; endfunction static local function int minimum(int a, int b, int c); int min = a; if(b < min) min = b; if(c < min) min = c; return min; endfunction endclass typedef class uvm_resource_base; class uvm_resource_types; typedef bit[1:0] override_t; typedef enum override_t { TYPE_OVERRIDE = 2'b01, NAME_OVERRIDE = 2'b10 } override_e; typedef uvm_queue#(uvm_resource_base) rsrc_q_t; typedef enum { PRI_HIGH, PRI_LOW } priority_e; typedef struct { time read_time; time write_time; int unsigned read_count; int unsigned write_count; } access_t; endclass class uvm_resource_options; static local bit auditing = 1; static function void turn_on_auditing(); auditing = 1; endfunction static function void turn_off_auditing(); auditing = 0; endfunction static function bit is_auditing(); return auditing; endfunction endclass virtual class uvm_resource_base extends uvm_object; protected bit modified; protected bit read_only; uvm_resource_types::access_t access[string]; function new(string name = ""); super.new(name); modified = 0; read_only = 0; endfunction pure virtual function uvm_resource_base get_type_handle(); function void set_read_only(); read_only = 1; endfunction function void set_read_write(); read_only = 0; endfunction function bit is_read_only(); return read_only; endfunction task wait_modified(); wait (modified == 1); modified = 0; endtask function string convert2string(); return $sformatf("(%s) %s", m_value_type_name(), m_value_as_string()); endfunction pure virtual function string m_value_type_name(); pure virtual function string m_value_as_string(); function void do_print(uvm_printer printer); super.do_print(printer); printer.print_generic_element("val", m_value_type_name(), "", m_value_as_string()); endfunction : do_print function void record_read_access(uvm_object accessor = null); string str; uvm_resource_types::access_t access_record; if(!uvm_resource_options::is_auditing()) return; if(accessor != null) str = accessor.get_full_name(); else str = ""; if(access.exists(str)) access_record = access[str]; else init_access_record(access_record); access_record.read_count++; access_record.read_time = $realtime; access[str] = access_record; endfunction function void record_write_access(uvm_object accessor = null); string str; if(uvm_resource_options::is_auditing()) begin if(accessor != null) begin uvm_resource_types::access_t access_record; string str; str = accessor.get_full_name(); if(access.exists(str)) access_record = access[str]; else init_access_record(access_record); access_record.write_count++; access_record.write_time = $realtime; access[str] = access_record; end end endfunction virtual function void print_accessors(); string str; uvm_component comp; uvm_resource_types::access_t access_record; string qs[$]; if(access.num() == 0) return; foreach (access[i]) begin str = i; access_record = access[str]; qs.push_back($sformatf("%s reads: %0d @ %0t writes: %0d @ %0t\n",str, access_record.read_count, access_record.read_time, access_record.write_count, access_record.write_time)); end begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/RESOURCE/ACCESSOR")) uvm_report_info ("UVM/RESOURCE/ACCESSOR", uvm_pkg::m_uvm_string_queue_join(qs), UVM_NONE, "t/uvm/src/base/uvm_resource_base.svh", 532, "", 1); end endfunction function void init_access_record (inout uvm_resource_types::access_t access_record); access_record.read_time = 0; access_record.write_time = 0; access_record.read_count = 0; access_record.write_count = 0; endfunction endclass class get_t; string name; string scope; uvm_resource_base rsrc; time t; endclass typedef class uvm_tree_printer ; class uvm_resource_pool; uvm_resource_types::rsrc_q_t rtab [string]; uvm_resource_types::rsrc_q_t ttab [uvm_resource_base]; typedef struct { string scope ; int unsigned precedence; } rsrc_info_t ; static rsrc_info_t ri_tab [uvm_resource_base]; get_t get_record [$]; function new(); endfunction static function uvm_resource_pool get(); uvm_resource_pool t_rp; uvm_coreservice_t cs = uvm_coreservice_t::get(); t_rp = cs.get_resource_pool(); return t_rp; endfunction function bit spell_check(string s); return uvm_spell_chkr#(uvm_resource_types::rsrc_q_t)::check(rtab, s); endfunction function void set_scope (uvm_resource_base rsrc, string scope); uvm_resource_types::rsrc_q_t rq; string name; uvm_resource_base type_handle; uvm_resource_base r; int unsigned i; if(rsrc == null) begin uvm_report_warning("NULLRASRC", "attempting to set scope of a null resource"); return; end name = rsrc.get_name(); if ((name != "") && rtab.exists(name)) begin rq = rtab[name]; for(i = 0; i < rq.size(); i++) begin r = rq.get(i); if(r == rsrc) begin ri_tab[rsrc].scope = uvm_glob_to_re(scope); return ; end end end if (rq == null) rq = new(name); rq.push_back(rsrc); rtab[name] = rq; type_handle = rsrc.get_type_handle(); if(ttab.exists(type_handle)) rq = ttab[type_handle]; else rq = new(); rq.push_back(rsrc); ttab[type_handle] = rq; ri_tab[rsrc].scope = uvm_glob_to_re(scope); ri_tab[rsrc].precedence = get_default_precedence(); endfunction function void set_override(uvm_resource_base rsrc, string scope = ""); string s = scope; set_scope(rsrc, s); set_priority(rsrc, uvm_resource_types::PRI_HIGH); endfunction function void set_name_override(uvm_resource_base rsrc, string scope = ""); string s = scope; set_scope(rsrc, s); set_priority_name(rsrc, uvm_resource_types::PRI_HIGH); endfunction function void set_type_override(uvm_resource_base rsrc, string scope = ""); string s = scope; set_scope(rsrc, s); set_priority_type(rsrc, uvm_resource_types::PRI_HIGH); endfunction virtual function bit get_scope(uvm_resource_base rsrc, output string scope); uvm_resource_types::rsrc_q_t rq; string name; uvm_resource_base r; int unsigned i; if(rsrc == null) return 0; name = rsrc.get_name(); if((name != "") && rtab.exists(name)) begin rq = rtab[name]; for(i = 0; i < rq.size(); i++) begin r = rq.get(i); if(r == rsrc) begin scope = ri_tab[rsrc].scope; return 1; end end end scope = ""; return 0; endfunction virtual function void delete ( uvm_resource_base rsrc ); string name; uvm_resource_base type_handle; if (rsrc != null) begin name = rsrc.get_name(); if(name != "") begin if(rtab.exists(name)) rtab.delete(name); end type_handle = rsrc.get_type_handle(); if(ttab.exists(type_handle)) begin int q_size = ttab[type_handle].size(); if (q_size == 1) ttab.delete(type_handle); else begin int i; for (i=0; i prec) begin rsrc = r; prec = c_prec; end end return rsrc; endfunction static function void sort_by_precedence(ref uvm_resource_types::rsrc_q_t q); uvm_resource_types::rsrc_q_t all[int]; uvm_resource_base r; int unsigned prec; for(int i=0; i", scope, null); return null; end rsrc = q.get(0); push_get_record("", scope, rsrc); return rsrc; endfunction function uvm_resource_types::rsrc_q_t lookup_regex_names(string scope, string name, uvm_resource_base type_handle = null); return lookup_name(scope, name, type_handle, 0); endfunction function uvm_resource_types::rsrc_q_t lookup_regex(string re, scope); uvm_resource_types::rsrc_q_t rq; uvm_resource_types::rsrc_q_t result_q; int unsigned i; uvm_resource_base r; string s; result_q = new(); foreach (rtab[name]) begin if ( ! uvm_is_match(re, name) ) continue; rq = rtab[name]; for(i = 0; i < rq.size(); i++) begin r = rq.get(i); if(ri_tab.exists(r) && uvm_is_match(ri_tab[r].scope, scope)) result_q.push_back(r); end end return result_q; endfunction function uvm_resource_types::rsrc_q_t lookup_scope(string scope); uvm_resource_types::rsrc_q_t rq; uvm_resource_base r; int unsigned i; int unsigned err; uvm_resource_types::rsrc_q_t q = new(); string name; if(rtab.last(name)) begin do begin rq = rtab[name]; for(int i = 0; i < rq.size(); ++i) begin r = rq.get(i); if(ri_tab.exists(r) && uvm_is_match(ri_tab[r].scope, scope)) begin q.push_back(r); end end end while(rtab.prev(name)); end return q; endfunction local function void set_priority_queue(uvm_resource_base rsrc, ref uvm_resource_types::rsrc_q_t q, uvm_resource_types::priority_e pri); uvm_resource_base r; int unsigned i; string msg; string name = rsrc.get_name(); for(i = 0; i < q.size(); i++) begin r = q.get(i); if(r == rsrc) break; end if(r != rsrc) begin $sformat(msg, "Handle for resource named %s is not in the name name; cannot change its priority", name); uvm_report_error("NORSRC", msg); return; end q.delete(i); case(pri) uvm_resource_types::PRI_HIGH: q.push_front(rsrc); uvm_resource_types::PRI_LOW: q.push_back(rsrc); endcase endfunction function void set_priority_type(uvm_resource_base rsrc, uvm_resource_types::priority_e pri); uvm_resource_base type_handle; string msg; uvm_resource_types::rsrc_q_t q; if(rsrc == null) begin uvm_report_warning("NULLRASRC", "attempting to change the serach priority of a null resource"); return; end type_handle = rsrc.get_type_handle(); if(!ttab.exists(type_handle)) begin $sformat(msg, "Type handle for resrouce named %s not found in type map; cannot change its search priority", rsrc.get_name()); uvm_report_error("RNFTYPE", msg); return; end q = ttab[type_handle]; set_priority_queue(rsrc, q, pri); endfunction function void set_priority_name(uvm_resource_base rsrc, uvm_resource_types::priority_e pri); string name; string msg; uvm_resource_types::rsrc_q_t q; if(rsrc == null) begin uvm_report_warning("NULLRASRC", "attempting to change the serach priority of a null resource"); return; end name = rsrc.get_name(); if(!rtab.exists(name)) begin $sformat(msg, "Resrouce named %s not found in name map; cannot change its search priority", name); uvm_report_error("RNFNAME", msg); return; end q = rtab[name]; set_priority_queue(rsrc, q, pri); endfunction function void set_priority (uvm_resource_base rsrc, uvm_resource_types::priority_e pri); set_priority_type(rsrc, pri); set_priority_name(rsrc, pri); endfunction static function void set_default_precedence( int unsigned precedence); uvm_coreservice_t cs = uvm_coreservice_t::get(); cs.set_resource_pool_default_precedence(precedence); endfunction static function int unsigned get_default_precedence(); uvm_coreservice_t cs = uvm_coreservice_t::get(); return cs.get_resource_pool_default_precedence(); endfunction virtual function void set_precedence(uvm_resource_base r, int unsigned p=uvm_resource_pool::get_default_precedence()); uvm_resource_types::rsrc_q_t q; string name; int unsigned i; uvm_resource_base rsrc; if(r == null) begin uvm_report_warning("NULLRASRC", "attempting to set precedence of a null resource"); return; end name = r.get_name(); if(rtab.exists(name)) begin q = rtab[name]; for(i = 0; i < q.size(); i++) begin rsrc = q.get(i); if(rsrc == r) break; end end if(r != rsrc) begin uvm_report_warning("NORSRC", $sformatf("resource named %s is not placed within the pool", name)); return; end ri_tab[r].precedence = p; endfunction virtual function int unsigned get_precedence(uvm_resource_base r); uvm_resource_types::rsrc_q_t q; string name; int unsigned i; uvm_resource_base rsrc; if(r == null) begin uvm_report_warning("NULLRASRC", "attempting to get precedence of a null resource"); return uvm_resource_pool::get_default_precedence(); end name = r.get_name(); if(rtab.exists(name)) begin q = rtab[name]; for(i = 0; i < q.size(); i++) begin rsrc = q.get(i); if(rsrc == r) break; end end if(r != rsrc) begin uvm_report_warning("NORSRC", $sformatf("resource named %s is not placed within the pool", name)); return uvm_resource_pool::get_default_precedence(); end return ri_tab[r].precedence; endfunction function void m_print_resources(uvm_printer printer, uvm_resource_types::rsrc_q_t rq, bit audit = 0); printer.push_element(rq.get_name(), "uvm_queue#(uvm_resource_base)", $sformatf("%0d",rq.size()), uvm_object_value_str(rq)); for(int i=0; i"); else m_print_resources(printer, rq, audit); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/RESOURCE_POOL/PRINT_QUEUE")) uvm_report_info ("UVM/RESOURCE_POOL/PRINT_QUEUE", printer.emit(), UVM_NONE, "t/uvm/src/base/uvm_resource.svh", 1071, "", 1); end endfunction function void dump(bit audit = 0, uvm_printer printer = null); string name; static uvm_tree_printer m_printer; if (m_printer == null) begin m_printer = new(); m_printer.set_type_name_enabled(1); end if (printer == null) printer = m_printer; printer.flush(); printer.push_element("uvm_resource_pool", "", $sformatf("%0d",rtab.size()), ""); foreach (rtab[name]) begin m_print_resources(printer, rtab[name], audit); end printer.pop_element(); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/RESOURCE/DUMP")) uvm_report_info ("UVM/RESOURCE/DUMP", printer.emit(), UVM_NONE, "t/uvm/src/base/uvm_resource.svh", 1108, "", 1); end endfunction endclass class uvm_resource #(type T=int) extends uvm_resource_base; typedef uvm_resource#(T) this_type; static this_type my_type = get_type(); protected T val; typedef uvm_object_registry#(this_type) type_id; virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction : get_object_type virtual function uvm_object create (string name=""); this_type tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction : create static function string type_name(); return $sformatf("uvm_resource#(%s)", $typename(T)); endfunction : type_name virtual function string get_type_name(); return $sformatf("uvm_resource#(%s)", $typename(T)); endfunction : get_type_name function new(string name=""); super.new(name); endfunction virtual function string m_value_type_name(); return $typename(T); endfunction : m_value_type_name virtual function string m_value_as_string(); return $sformatf("%0p", val); endfunction : m_value_as_string static function this_type get_type(); if(my_type == null) my_type = new(); return my_type; endfunction function uvm_resource_base get_type_handle(); return get_type(); endfunction function T read(uvm_object accessor = null); record_read_access(accessor); return val; endfunction function void write(T t, uvm_object accessor = null); if(is_read_only()) begin uvm_report_error("resource", $sformatf("resource %s is read only -- cannot modify", get_name())); return; end if(val == t) return; record_write_access(accessor); val = t; modified = 1; endfunction static function this_type get_highest_precedence(ref uvm_resource_types::rsrc_q_t q); this_type rsrc; this_type r; uvm_resource_types::rsrc_q_t tq; uvm_resource_base rb; uvm_resource_pool rp = uvm_resource_pool::get(); if(q.size() == 0) return null; tq = new(); rsrc = null; for(int i = 0; i < q.size(); ++i) begin if($cast(r, q.get(i))) begin tq.push_back(r) ; end end rb = rp.get_highest_precedence(tq); if (!$cast(rsrc, rb)) return null; return rsrc; endfunction endclass class uvm_int_rsrc extends uvm_resource #(int); typedef uvm_int_rsrc this_subtype; function new(string name, string s = "*"); uvm_resource_pool rp; super.new(name); rp = uvm_resource_pool::get(); rp.set_scope(this, s); endfunction function string convert2string(); string s; $sformat(s, "%0d", read()); return s; endfunction endclass class uvm_string_rsrc extends uvm_resource #(string); typedef uvm_string_rsrc this_subtype; function new(string name, string s = "*"); uvm_resource_pool rp; super.new(name); rp = uvm_resource_pool::get(); rp.set_scope(this, s); endfunction function string convert2string(); return read(); endfunction endclass class uvm_obj_rsrc extends uvm_resource #(uvm_object); typedef uvm_obj_rsrc this_subtype; function new(string name, string s = "*"); uvm_resource_pool rp; super.new(name); rp = uvm_resource_pool::get(); rp.set_scope(this, s); endfunction endclass class uvm_bit_rsrc #(int unsigned N=1) extends uvm_resource #(bit[N-1:0]); typedef uvm_bit_rsrc#(N) this_subtype; function new(string name, string s = "*"); uvm_resource_pool rp; super.new(name); rp = uvm_resource_pool::get(); rp.set_scope(this, s); endfunction function string convert2string(); string s; $sformat(s, "%0b", read()); return s; endfunction endclass class uvm_byte_rsrc #(int unsigned N=1) extends uvm_resource #(bit[7:0][N-1:0]); typedef uvm_byte_rsrc#(N) this_subtype; function new(string name, string s = "*"); uvm_resource_pool rp; super.new(name); rp = uvm_resource_pool::get(); rp.set_scope(this, s); endfunction function string convert2string(); string s; $sformat(s, "%0x", read()); return s; endfunction endclass typedef class uvm_resource_db_options; typedef class uvm_cmdline_processor; class uvm_resource_db #(type T=uvm_object); typedef uvm_resource #(T) rsrc_t; protected function new(); endfunction static function rsrc_t get_by_type(string scope); uvm_resource_pool rp = uvm_resource_pool::get(); uvm_resource_base rsrc_base; rsrc_t rsrc; string msg; uvm_resource_base type_handle = rsrc_t::get_type(); if(type_handle == null) return null; rsrc_base = rp.get_by_type(scope, type_handle); if(!$cast(rsrc, rsrc_base)) begin $sformat(msg, "Resource with specified type handle in scope %s was not located", scope); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RSRCNF")) uvm_report_warning ("RSRCNF", msg, UVM_NONE, "t/uvm/src/base/uvm_resource_db.svh", 84, "", 1); end return null; end return rsrc; endfunction static function rsrc_t get_by_name(string scope, string name, bit rpterr=1); uvm_resource_pool rp = uvm_resource_pool::get(); uvm_resource_base rsrc_base; rsrc_t rsrc; string msg; rsrc_base = rp.get_by_name(scope, name, rsrc_t::get_type(), rpterr); if(rsrc_base == null) return null; if(!$cast(rsrc, rsrc_base)) begin if(rpterr) begin $sformat(msg, "Resource with name %s in scope %s has incorrect type", name, scope); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RSRCTYPE")) uvm_report_warning ("RSRCTYPE", msg, UVM_NONE, "t/uvm/src/base/uvm_resource_db.svh", 115, "", 1); end end return null; end return rsrc; endfunction static function rsrc_t set_default(string scope, string name); rsrc_t r; uvm_resource_pool rp = uvm_resource_pool::get(); r = new(name); rp.set_scope(r, scope); return r; endfunction protected static function void m_show_msg( input string id, input string rtype, input string action, input string scope, input string name, input uvm_object accessor, input rsrc_t rsrc); T foo; string msg=$typename(foo); $sformat(msg, "%s scope='%s' name='%s' (type %s) %s accessor=%s = %s", rtype,scope,name, msg,action, (accessor != null) ? accessor.get_full_name() : "", rsrc==null?"null (failed lookup)":rsrc.convert2string()); begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,id)) uvm_report_info (id, msg, UVM_LOW, "t/uvm/src/base/uvm_resource_db.svh", 161, "", 1); end endfunction static function void set(input string scope, input string name, T val, input uvm_object accessor = null); uvm_resource_pool rp = uvm_resource_pool::get(); rsrc_t rsrc = new(name); rsrc.write(val, accessor); rp.set_scope(rsrc, scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/SET", "Resource","set", scope, name, accessor, rsrc); endfunction static function void set_anonymous(input string scope, T val, input uvm_object accessor = null); uvm_resource_pool rp = uvm_resource_pool::get(); rsrc_t rsrc = new(""); rsrc.write(val, accessor); rp.set_scope(rsrc, scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/SETANON","Resource", "set", scope, "", accessor, rsrc); endfunction static function void set_override(input string scope, input string name, T val, uvm_object accessor = null); uvm_resource_pool rp = uvm_resource_pool::get(); rsrc_t rsrc = new(name); rsrc.write(val, accessor); rp.set_override(rsrc, scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/SETOVRD", "Resource","set", scope, name, accessor, rsrc); endfunction static function void set_override_type(input string scope, input string name, T val, uvm_object accessor = null); uvm_resource_pool rp = uvm_resource_pool::get(); rsrc_t rsrc = new(name); rsrc.write(val, accessor); rp.set_type_override(rsrc, scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/SETOVRDTYP","Resource", "set", scope, name, accessor, rsrc); endfunction static function void set_override_name(input string scope, input string name, T val, uvm_object accessor = null); uvm_resource_pool rp = uvm_resource_pool::get(); rsrc_t rsrc = new(name); rsrc.write(val, accessor); rp.set_name_override(rsrc, scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/SETOVRDNAM","Resource", "set", scope, name, accessor, rsrc); endfunction static function bit read_by_name(input string scope, input string name, inout T val, input uvm_object accessor = null); rsrc_t rsrc = get_by_name(scope, name); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/RDBYNAM","Resource", "read", scope, name, accessor, rsrc); if(rsrc == null) return 0; val = rsrc.read(accessor); return 1; endfunction static function bit read_by_type(input string scope, inout T val, input uvm_object accessor = null); rsrc_t rsrc = get_by_type(scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/RDBYTYP", "Resource","read", scope, "", accessor, rsrc); if(rsrc == null) return 0; val = rsrc.read(accessor); return 1; endfunction static function bit write_by_name(input string scope, input string name, input T val, input uvm_object accessor = null); rsrc_t rsrc = get_by_name(scope, name); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/WR","Resource", "written", scope, name, accessor, rsrc); if(rsrc == null) return 0; rsrc.write(val, accessor); return 1; endfunction static function bit write_by_type(input string scope, input T val, input uvm_object accessor = null); rsrc_t rsrc = get_by_type(scope); if(uvm_resource_db_options::is_tracing()) m_show_msg("RSRCDB/WRTYP", "Resource","written", scope, "", accessor, rsrc); if(rsrc == null) return 0; rsrc.write(val, accessor); return 1; endfunction static function void dump(); uvm_resource_pool rp = uvm_resource_pool::get(); rp.dump(); endfunction endclass class uvm_resource_db_options; static local bit ready; static local bit tracing; static function void turn_on_tracing(); if (!ready) init(); tracing = 1; endfunction static function void turn_off_tracing(); if (!ready) init(); tracing = 0; endfunction static function bit is_tracing(); if (!ready) init(); return tracing; endfunction static local function void init(); uvm_cmdline_processor clp; string trace_args[$]; clp = uvm_cmdline_processor::get_inst(); if (clp.get_arg_matches("+UVM_RESOURCE_DB_TRACE", trace_args)) begin tracing = 1; end ready = 1; endfunction endclass typedef class uvm_phase; class m_uvm_waiter; string inst_name; string field_name; event trigger; function new (string inst_name, string field_name); this.inst_name = inst_name; this.field_name = field_name; endfunction endclass typedef class uvm_root; typedef class uvm_config_db_options; class uvm_config_db#(type T=int) extends uvm_resource_db#(T); static uvm_pool#(string,uvm_resource#(T)) m_rsc[uvm_component]; static local uvm_queue#(m_uvm_waiter) m_waiters[string]; static function bit get(uvm_component cntxt, string inst_name, string field_name, inout T value); uvm_resource#(T) r; uvm_resource_pool rp = uvm_resource_pool::get(); uvm_resource_types::rsrc_q_t rq; uvm_coreservice_t cs = uvm_coreservice_t::get(); if(cntxt == null) cntxt = cs.get_root(); if(inst_name == "") inst_name = cntxt.get_full_name(); else if(cntxt.get_full_name() != "") inst_name = {cntxt.get_full_name(), ".", inst_name}; rq = rp.lookup_regex_names(inst_name, field_name, uvm_resource#(T)::get_type()); r = uvm_resource#(T)::get_highest_precedence(rq); if(uvm_config_db_options::is_tracing()) m_show_msg("CFGDB/GET", "Configuration","read", inst_name, field_name, cntxt, r); if(r == null) return 0; value = r.read(cntxt); return 1; endfunction static function void set(uvm_component cntxt, string inst_name, string field_name, T value); uvm_root top; uvm_phase curr_phase; uvm_resource#(T) r; bit exists; string lookup; uvm_pool#(string,uvm_resource#(T)) pool; string rstate; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_resource_pool rp = cs.get_resource_pool(); int unsigned precedence; process p = process::self(); if(p != null) rstate = p.get_randstate(); top = cs.get_root(); curr_phase = top.m_current_phase; if(cntxt == null) cntxt = top; if(inst_name == "") inst_name = cntxt.get_full_name(); else if(cntxt.get_full_name() != "") inst_name = {cntxt.get_full_name(), ".", inst_name}; if(!m_rsc.exists(cntxt)) begin m_rsc[cntxt] = new; end pool = m_rsc[cntxt]; lookup = {inst_name, "__M_UVM__", field_name}; if(!pool.exists(lookup)) begin r = new(field_name); rp.set_scope(r, inst_name); pool.add(lookup, r); end else begin r = pool.get(lookup); exists = 1; end if(curr_phase != null && curr_phase.get_name() == "build") precedence = cs.get_resource_pool_default_precedence() - (cntxt.get_depth()); else precedence = cs.get_resource_pool_default_precedence(); rp.set_precedence(r, precedence); r.write(value, cntxt); rp.set_priority_name(r, uvm_resource_types::PRI_HIGH); if(m_waiters.exists(field_name)) begin m_uvm_waiter w; for(int i=0; iw.trigger; end end if(p != null) p.set_randstate(rstate); if(uvm_config_db_options::is_tracing()) m_show_msg("CFGDB/SET", "Configuration","set", inst_name, field_name, cntxt, r); endfunction static function bit exists(uvm_component cntxt, string inst_name, string field_name, bit spell_chk=0); uvm_coreservice_t cs = uvm_coreservice_t::get(); if(cntxt == null) cntxt = cs.get_root(); if(inst_name == "") inst_name = cntxt.get_full_name(); else if(cntxt.get_full_name() != "") inst_name = {cntxt.get_full_name(), ".", inst_name}; return (uvm_resource_db#(T)::get_by_name(inst_name,field_name,spell_chk) != null); endfunction static task wait_modified(uvm_component cntxt, string inst_name, string field_name); process p = process::self(); string rstate = p.get_randstate(); m_uvm_waiter waiter; uvm_coreservice_t cs = uvm_coreservice_t::get(); if(cntxt == null) cntxt = cs.get_root(); if(cntxt != cs.get_root()) begin if(inst_name != "") inst_name = {cntxt.get_full_name(),".",inst_name}; else inst_name = cntxt.get_full_name(); end waiter = new(inst_name, field_name); if(!m_waiters.exists(field_name)) m_waiters[field_name] = new; m_waiters[field_name].push_back(waiter); p.set_randstate(rstate); @waiter.trigger; for(int i=0; i 1) begin string msg_queue[$]; msg_queue.push_back("("); foreach (matching_ops[i]) begin msg_queue.push_back(matching_ops[i]); if (i != matching_ops.size() - 1) msg_queue.push_back(","); end msg_queue.push_back(")"); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/SET_BAD_OP_TYPE")) uvm_report_error ("UVM/FIELD_OP/SET_BAD_OP_TYPE", {"set() was passed op_type matching multiple operations: ", uvm_pkg::m_uvm_string_queue_join(msg_queue)}, UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 88, "", 1); end end if(m_is_set == 0) begin m_op_type = op_type; m_policy = policy; m_object = rhs; m_is_set = 1'b1; end else begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/SET")) uvm_report_error ("UVM/FIELD_OP/SET", "Attempting to set values in policy without flushing", UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 98, "", 1); end endfunction virtual function string get_op_name(); case(m_op_type) UVM_COPY : return "copy"; UVM_COMPARE : return "compare"; UVM_PRINT : return "print"; UVM_RECORD : return "record"; UVM_PACK : return "pack"; UVM_UNPACK : return "unpack"; UVM_SET : return "set"; default: return ""; endcase endfunction virtual function uvm_field_flag_t get_op_type(); if(m_is_set == 1'b1) return m_op_type; else begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/GET_OP_TYPE")) uvm_report_error ("UVM/FIELD_OP/GET_OP_TYPE", "Calling get_op_type() before calling set() is not allowed", UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 120, "", 1); end endfunction virtual function uvm_policy get_policy(); if(m_is_set == 1'b1) return m_policy; else begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/GET_POLICY")) uvm_report_error ("UVM/FIELD_OP/GET_POLICY", "Attempting to call get_policy() before calling set() is not allowed", UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 129, "", 1); end endfunction virtual function uvm_object get_rhs(); if(m_is_set == 1'b1) return m_object; else begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/GET_RHS")) uvm_report_error ("UVM/FIELD_OP/GET_RHS", "Calling get_rhs() before calling set() is not allowed", UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 137, "", 1); end endfunction function bit user_hook_enabled(); if(m_is_set == 1'b1) return m_user_hook; else begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/FIELD_OP/GET_USER_HOOK")) uvm_report_error ("UVM/FIELD_OP/GET_USER_HOOK", "Attempting to get_user_hook before calling set() is not allowed", UVM_NONE, "t/uvm/src/base/uvm_field_op.svh", 145, "", 1); end endfunction function void disable_user_hook(); m_user_hook = 1'b0; endfunction static uvm_field_op m_recycled_op[$] ; virtual function void flush(); m_policy = null; m_object = null; m_user_hook = 1'b1; m_is_set = 0; endfunction function void m_recycle(); this.flush(); m_recycled_op.push_back(this); endfunction : m_recycle static function uvm_field_op m_get_available_op() ; uvm_field_op field_op ; if (m_recycled_op.size() > 0) field_op = m_recycled_op.pop_back() ; else field_op = uvm_field_op::type_id_create("field_op"); return field_op ; endfunction endclass class uvm_copier extends uvm_policy; typedef uvm_object_registry#(uvm_copier,"uvm_copier") type_id; static function uvm_copier type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_copier tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_copier"; endfunction : type_name virtual function string get_type_name(); return "uvm_copier"; endfunction : get_type_name uvm_recursion_policy_enum policy = UVM_DEFAULT_POLICY; function new(string name="uvm_copier") ; super.new(name); endfunction recursion_state_e m_recur_states[uvm_object ][uvm_object ][uvm_recursion_policy_enum ]; virtual function void copy_object ( uvm_object lhs, uvm_object rhs); uvm_field_op field_op; if (get_recursion_policy() == UVM_REFERENCE) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM_COPY_POLICY")) uvm_report_error ("UVM_COPY_POLICY", "Attempting to make a copy of a object which is a reference", UVM_NONE, "t/uvm/src/base/uvm_copier.svh", 82, "", 1); end return; end if (rhs == null || lhs == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM_COPY_NULL_OBJ")) uvm_report_error ("UVM_COPY_NULL_OBJ", "Attempting to make a copy of a object with null src/target", UVM_NONE, "t/uvm/src/base/uvm_copier.svh", 87, "", 1); end return; end push_active_object(lhs); m_recur_states[rhs][lhs][get_recursion_policy()] = uvm_policy::STARTED; field_op = uvm_field_op::m_get_available_op() ; field_op.set(UVM_COPY,this,rhs); lhs.do_execute_op(field_op); if (field_op.user_hook_enabled()) begin lhs.do_copy(rhs); end field_op.m_recycle(); m_recur_states[rhs][lhs][get_recursion_policy()] = uvm_policy::FINISHED; void'(pop_active_object()); endfunction virtual function recursion_state_e object_copied( uvm_object lhs, uvm_object rhs, uvm_recursion_policy_enum recursion ); if (!m_recur_states.exists(rhs)) return NEVER ; else if (!m_recur_states[rhs].exists(lhs)) return NEVER ; else if (!m_recur_states[rhs][lhs].exists(recursion)) return NEVER ; else begin return m_recur_states[rhs][lhs][recursion]; end endfunction function void flush(); m_recur_states.delete(); endfunction virtual function void set_recursion_policy (uvm_recursion_policy_enum policy); this.policy = policy; endfunction virtual function uvm_recursion_policy_enum get_recursion_policy(); return policy; endfunction function int unsigned get_num_copies(uvm_object rhs); if (m_recur_states.exists(rhs)) return m_recur_states[rhs].size(); return 0; endfunction : get_num_copies function int get_first_copy(uvm_object rhs, ref uvm_object lhs); if (m_recur_states.exists(rhs)) return m_recur_states[rhs].first(lhs); return 0; endfunction : get_first_copy function int get_next_copy(uvm_object rhs, ref uvm_object lhs); if (m_recur_states.exists(rhs)) return m_recur_states[rhs].next(lhs); return 0; endfunction : get_next_copy function int get_last_copy(uvm_object rhs, ref uvm_object lhs); if (m_recur_states.exists(rhs)) return m_recur_states[rhs].last(lhs); return 0; endfunction : get_last_copy function int get_prev_copy(uvm_object rhs, ref uvm_object lhs); if (m_recur_states.exists(rhs)) return m_recur_states[rhs].prev(lhs); return 0; endfunction : get_prev_copy static function void set_default (uvm_copier copier) ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; coreservice.set_default_copier(copier) ; endfunction static function uvm_copier get_default () ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; return coreservice.get_default_copier() ; endfunction endclass typedef class m_uvm_printer_knobs; typedef class uvm_printer_element; typedef class uvm_structure_proxy; virtual class uvm_printer extends uvm_policy; typedef uvm_abstract_object_registry#(uvm_printer,"uvm_printer") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_printer"; endfunction : type_name virtual function string get_type_name(); return "uvm_printer"; endfunction : get_type_name extern function new(string name="") ; bit m_flushed ; local m_uvm_printer_knobs knobs ; protected function m_uvm_printer_knobs get_knobs() ; return knobs; endfunction extern static function void set_default(uvm_printer printer) ; extern static function uvm_printer get_default() ; extern virtual function void print_field (string name, uvm_bitstream_t value, int size, uvm_radix_enum radix=UVM_NORADIX, byte scope_separator=".", string type_name=""); extern virtual function void print_field_int (string name, uvm_integral_t value, int size, uvm_radix_enum radix=UVM_NORADIX, byte scope_separator=".", string type_name=""); extern virtual function void print_object (string name, uvm_object value, byte scope_separator="."); extern virtual function void print_object_header (string name, uvm_object value, byte scope_separator="."); extern virtual function void print_string (string name, string value, byte scope_separator="."); uvm_policy::recursion_state_e m_recur_states[uvm_object][uvm_recursion_policy_enum ] ; extern virtual function uvm_policy::recursion_state_e object_printed ( uvm_object value, uvm_recursion_policy_enum recursion); extern virtual function void print_time (string name, time value, byte scope_separator="."); extern virtual function void print_real (string name, real value, byte scope_separator="."); extern virtual function void print_generic (string name, string type_name, int size, string value, byte scope_separator="."); extern virtual function void print_generic_element (string name, string type_name, string size, string value); extern virtual function string emit (); extern virtual function void flush (); extern virtual function void set_name_enabled (bit enabled); extern virtual function bit get_name_enabled (); extern virtual function void set_type_name_enabled (bit enabled); extern virtual function bit get_type_name_enabled (); extern virtual function void set_size_enabled (bit enabled); extern virtual function bit get_size_enabled (); extern virtual function void set_id_enabled (bit enabled); extern virtual function bit get_id_enabled (); extern virtual function void set_radix_enabled (bit enabled); extern virtual function bit get_radix_enabled (); extern virtual function void set_radix_string (uvm_radix_enum radix, string prefix); extern virtual function string get_radix_string (uvm_radix_enum radix); extern virtual function void set_default_radix (uvm_radix_enum radix); extern virtual function uvm_radix_enum get_default_radix (); extern virtual function void set_root_enabled (bit enabled); extern virtual function bit get_root_enabled (); extern virtual function void set_recursion_policy (uvm_recursion_policy_enum policy); extern virtual function uvm_recursion_policy_enum get_recursion_policy (); extern virtual function void set_max_depth (int depth); extern virtual function int get_max_depth (); extern virtual function void set_file (UVM_FILE fl); extern virtual function UVM_FILE get_file (); extern virtual function void set_line_prefix (string prefix); extern virtual function string get_line_prefix (); extern virtual function void set_begin_elements (int elements = 5); extern virtual function int get_begin_elements (); extern virtual function void set_end_elements (int elements = 5); extern virtual function int get_end_elements (); local uvm_printer_element m_element_stack[$] ; protected function int m_get_stack_size(); return m_element_stack.size(); endfunction extern protected virtual function uvm_printer_element get_bottom_element (); extern protected virtual function uvm_printer_element get_top_element (); extern virtual function void push_element ( string name, string type_name, string size, string value="" ); extern virtual function void pop_element (); extern function uvm_printer_element get_unused_element() ; uvm_printer_element m_recycled_elements[$]; extern virtual function void print_array_header(string name, int size, string arraytype="array", byte scope_separator="."); extern virtual function void print_array_range (int min, int max); extern virtual function void print_array_footer (int size = 0); extern function bit istop (); extern function string index_string (int index, string name=""); string m_string; endclass class uvm_printer_element extends uvm_object; extern function new (string name=""); extern virtual function void set (string element_name = "", string element_type_name = "", string element_size = "", string element_value = "" ); extern virtual function void set_element_name (string element_name); extern virtual function string get_element_name (); extern virtual function void set_element_type_name (string element_type_name); extern virtual function string get_element_type_name (); extern virtual function void set_element_size (string element_size); extern virtual function string get_element_size (); extern virtual function void set_element_value (string element_value); extern virtual function string get_element_value (); extern function void add_child(uvm_printer_element child) ; extern function void get_children(ref uvm_printer_element children[$], input bit recurse) ; extern function void clear_children() ; local string m_name ; local string m_type_name ; local string m_size ; local string m_value ; local uvm_printer_element m_children[$] ; endclass class uvm_printer_element_proxy extends uvm_structure_proxy#(uvm_printer_element); extern function new (string name=""); extern virtual function void get_immediate_children(uvm_printer_element s, ref uvm_printer_element children[$]); endclass : uvm_printer_element_proxy class uvm_table_printer extends uvm_printer; typedef uvm_object_registry#(uvm_table_printer,"uvm_table_printer") type_id; static function uvm_table_printer type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_table_printer tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_table_printer"; endfunction : type_name virtual function string get_type_name(); return "uvm_table_printer"; endfunction : get_type_name extern function new(string name=""); extern virtual function string emit(); extern virtual function string m_emit_element(uvm_printer_element element, int unsigned level); local static uvm_table_printer m_default_table_printer ; local static string m_space ; extern static function void set_default(uvm_table_printer printer) ; extern static function uvm_table_printer get_default() ; extern virtual function void set_indent(int indent) ; extern virtual function int get_indent() ; extern virtual function void flush() ; protected int m_max_name=4; protected int m_max_type=4; protected int m_max_size=4; protected int m_max_value=5; extern virtual function void pop_element(); endclass class uvm_tree_printer extends uvm_printer; protected string m_newline = "\n"; protected string m_linefeed ; typedef uvm_object_registry#(uvm_tree_printer,"uvm_tree_printer") type_id; static function uvm_tree_printer type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_tree_printer tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_tree_printer"; endfunction : type_name virtual function string get_type_name(); return "uvm_tree_printer"; endfunction : get_type_name extern function new(string name=""); local static uvm_tree_printer m_default_tree_printer ; extern static function void set_default(uvm_tree_printer printer) ; extern static function uvm_tree_printer get_default() ; extern virtual function void set_indent(int indent) ; extern virtual function int get_indent() ; extern virtual function void set_separators(string separators) ; extern virtual function string get_separators() ; extern virtual function void flush() ; extern virtual function string emit(); extern virtual function string m_emit_element(uvm_printer_element element, int unsigned level); endclass class uvm_line_printer extends uvm_tree_printer; typedef uvm_object_registry#(uvm_line_printer,"uvm_line_printer") type_id; static function uvm_line_printer type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_line_printer tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_line_printer"; endfunction : type_name virtual function string get_type_name(); return "uvm_line_printer"; endfunction : get_type_name extern function new(string name=""); local static uvm_line_printer m_default_line_printer ; extern static function void set_default(uvm_line_printer printer) ; extern static function uvm_line_printer get_default() ; extern virtual function void set_separators(string separators) ; extern virtual function string get_separators() ; extern virtual function void flush() ; endclass class m_uvm_printer_knobs; bit identifier = 1; bit type_name = 1; bit size = 1; int depth = -1; bit reference = 1; int begin_elements = 5; int end_elements = 5; string prefix = ""; int indent = 2; bit show_root = 0; int mcd = UVM_STDOUT; string separator = "{}"; bit show_radix = 1; uvm_radix_enum default_radix = UVM_HEX; string dec_radix = "'d"; string bin_radix = "'b"; string oct_radix = "'o"; string unsigned_radix = "'d"; string hex_radix = "'h"; uvm_recursion_policy_enum recursion_policy ; endclass function uvm_printer::new(string name=""); super.new(name); knobs = new ; flush(); endfunction function void uvm_printer::set_default(uvm_printer printer) ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; coreservice.set_default_printer(printer) ; endfunction function uvm_printer uvm_printer::get_default() ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; return coreservice.get_default_printer() ; endfunction function void uvm_printer::print_field (string name, uvm_bitstream_t value, int size, uvm_radix_enum radix=UVM_NORADIX, byte scope_separator=".", string type_name=""); string sz_str, val_str; if(type_name == "") begin if(radix == UVM_TIME) type_name ="time"; else if(radix == UVM_STRING) type_name ="string"; else type_name ="integral"; end sz_str.itoa(size); if(radix == UVM_NORADIX) radix = get_default_radix(); val_str = uvm_bitstream_to_string (value, size, radix, get_radix_string(radix)); name = uvm_leaf_scope(name,scope_separator); push_element(name,type_name,sz_str,val_str); pop_element() ; endfunction function void uvm_printer::print_field_int (string name, uvm_integral_t value, int size, uvm_radix_enum radix=UVM_NORADIX, byte scope_separator=".", string type_name=""); string sz_str, val_str; if(type_name == "") begin if(radix == UVM_TIME) type_name ="time"; else if(radix == UVM_STRING) type_name ="string"; else type_name ="integral"; end sz_str.itoa(size); if(radix == UVM_NORADIX) radix = get_default_radix(); val_str = uvm_integral_to_string (value, size, radix, get_radix_string(radix)); name = uvm_leaf_scope(name,scope_separator); push_element(name,type_name,sz_str,val_str); pop_element() ; endfunction function string uvm_printer::emit (); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_OVERRIDE")) uvm_report_error ("NO_OVERRIDE", "emit() method not overridden in printer subtype", UVM_NONE, "t/uvm/src/base/uvm_printer.svh", 999, "", 1); end return ""; endfunction function void uvm_printer::flush (); uvm_printer_element element = get_bottom_element() ; uvm_printer_element all_descendent_elements[$] ; element = get_bottom_element() ; if (element != null) begin element.get_children(all_descendent_elements,1) ; foreach (all_descendent_elements[i]) begin m_recycled_elements.push_back(all_descendent_elements[i]) ; all_descendent_elements[i].clear_children() ; end element.clear_children(); m_recycled_elements.push_back(element) ; m_element_stack.delete() ; end m_recur_states.delete(); m_flushed = 1 ; endfunction function void uvm_printer::set_name_enabled (bit enabled); knobs.identifier = enabled ; endfunction function bit uvm_printer::get_name_enabled (); return knobs.identifier ; endfunction function void uvm_printer::set_type_name_enabled (bit enabled); knobs.type_name = enabled ; endfunction function bit uvm_printer::get_type_name_enabled (); return knobs.type_name ; endfunction function void uvm_printer::set_size_enabled (bit enabled); knobs.size = enabled ; endfunction function bit uvm_printer::get_size_enabled (); return knobs.size ; endfunction function void uvm_printer::set_id_enabled (bit enabled); knobs.reference = enabled ; endfunction function bit uvm_printer::get_id_enabled (); return knobs.reference ; endfunction function void uvm_printer::set_radix_enabled (bit enabled); knobs.show_radix = enabled ; endfunction function bit uvm_printer::get_radix_enabled (); return knobs.show_radix ; endfunction function void uvm_printer::set_radix_string (uvm_radix_enum radix, string prefix); if (radix == UVM_DEC) knobs.dec_radix = prefix ; else if (radix == UVM_BIN) knobs.bin_radix = prefix ; else if (radix == UVM_OCT) knobs.oct_radix = prefix ; else if (radix == UVM_UNSIGNED) knobs.unsigned_radix = prefix ; else if (radix == UVM_HEX) knobs.hex_radix = prefix ; else begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"PRINTER_UNKNOWN_RADIX")) uvm_report_warning ("PRINTER_UNKNOWN_RADIX", $sformatf("set_radix_string called with unsupported radix %s",radix), UVM_NONE, "t/uvm/src/base/uvm_printer.svh", 1065, "", 1); end endfunction function string uvm_printer::get_radix_string (uvm_radix_enum radix); if (radix == UVM_DEC) return knobs.dec_radix ; else if (radix == UVM_BIN) return knobs.bin_radix ; else if (radix == UVM_OCT) return knobs.oct_radix ; else if (radix == UVM_UNSIGNED) return knobs.unsigned_radix ; else if (radix == UVM_HEX) return knobs.hex_radix ; else return ""; endfunction function void uvm_printer::set_default_radix (uvm_radix_enum radix); knobs.default_radix = radix ; endfunction function uvm_radix_enum uvm_printer::get_default_radix (); return knobs.default_radix ; endfunction function void uvm_printer::set_root_enabled (bit enabled); knobs.show_root = enabled ; endfunction function bit uvm_printer::get_root_enabled (); return knobs.show_root ; endfunction function void uvm_printer::set_recursion_policy (uvm_recursion_policy_enum policy); knobs.recursion_policy = policy ; endfunction function uvm_recursion_policy_enum uvm_printer::get_recursion_policy (); return knobs.recursion_policy ; endfunction function void uvm_printer::set_max_depth (int depth); knobs.depth = depth ; endfunction function int uvm_printer::get_max_depth (); return knobs.depth ; endfunction function void uvm_printer::set_file (UVM_FILE fl); knobs.mcd = fl ; endfunction function UVM_FILE uvm_printer::get_file (); return knobs.mcd ; endfunction function void uvm_printer::set_line_prefix (string prefix); knobs.prefix = prefix ; endfunction function string uvm_printer::get_line_prefix (); return knobs.prefix ; endfunction function void uvm_printer::set_begin_elements (int elements = 5); knobs.begin_elements = elements ; endfunction function int uvm_printer::get_begin_elements (); return knobs.begin_elements ; endfunction function void uvm_printer::set_end_elements (int elements = 5); knobs.end_elements = elements ; endfunction function int uvm_printer::get_end_elements (); return knobs.end_elements ; endfunction function uvm_printer_element uvm_printer::get_bottom_element (); if (m_element_stack.size() > 0) return m_element_stack[0] ; else return null ; endfunction function uvm_printer_element uvm_printer::get_top_element (); if (m_element_stack.size() > 0) return m_element_stack[$] ; else return null ; endfunction function uvm_printer_element_proxy::new (string name=""); super.new(name) ; endfunction function void uvm_printer_element_proxy::get_immediate_children(uvm_printer_element s, ref uvm_printer_element children[$]); s.get_children(children,0) ; endfunction function void uvm_printer::push_element ( string name, string type_name, string size, string value=""); uvm_printer_element element ; uvm_printer_element parent ; element = get_unused_element() ; parent = get_top_element() ; element.set(name,type_name,size,value); if (parent != null) parent.add_child(element) ; m_element_stack.push_back(element) ; endfunction function void uvm_printer::pop_element (); if (m_element_stack.size() > 1) begin void'(m_element_stack.pop_back()); end endfunction function uvm_printer_element uvm_printer::get_unused_element() ; uvm_printer_element element ; if (m_recycled_elements.size() > 0) begin element = m_recycled_elements.pop_back() ; end else begin element = new() ; end return element ; endfunction function void uvm_printer::print_array_header (string name, int size, string arraytype="array", byte scope_separator="."); push_element(name,arraytype,$sformatf("%0d",size),"-"); endfunction function void uvm_printer::print_array_footer (int size=0); pop_element() ; endfunction function void uvm_printer::print_array_range(int min, int max); string tmpstr; if(min == -1 && max == -1) return; if(min == -1) min = max; if(max == -1) max = min; if(max < min) return; print_generic_element("...", "...", "...", "..."); endfunction function void uvm_printer::print_object_header (string name, uvm_object value, byte scope_separator="."); if(name == "") name = ""; push_element(name, (value != null) ? value.get_type_name() : "object", "-", get_id_enabled() ? uvm_object_value_str(value) : "-"); endfunction function void uvm_printer::print_object (string name, uvm_object value, byte scope_separator="."); uvm_component comp, child_comp; uvm_field_op field_op ; uvm_recursion_policy_enum recursion_policy; recursion_policy = get_recursion_policy(); if ((value == null) || (recursion_policy == UVM_REFERENCE) || (get_max_depth() == get_active_object_depth())) begin print_object_header(name,value,scope_separator); pop_element(); end else begin push_active_object(value); m_recur_states[value][recursion_policy] = uvm_policy::STARTED ; print_object_header(name,value,scope_separator); if($cast(comp, value)) begin string name; if (comp.get_first_child(name)) do begin child_comp = comp.get_child(name); if(child_comp.print_enabled) this.print_object(name,child_comp); end while (comp.get_next_child(name)); end field_op = uvm_field_op::m_get_available_op() ; field_op.set(UVM_PRINT,this,null); value.do_execute_op(field_op); if (field_op.user_hook_enabled()) value.do_print(this); field_op.m_recycle(); pop_element() ; m_recur_states[value][recursion_policy] = uvm_policy::FINISHED ; void'(pop_active_object()); end endfunction function bit uvm_printer::istop (); return (get_active_object_depth() == 0); endfunction function void uvm_printer::print_generic (string name, string type_name, int size, string value, byte scope_separator="."); push_element(name, type_name, (size == -2 ? "..." : $sformatf("%0d",size)), value); pop_element(); endfunction function void uvm_printer::print_generic_element (string name, string type_name, string size, string value); push_element(name,type_name,size,value); pop_element() ; endfunction function void uvm_printer::print_time (string name, time value, byte scope_separator="."); print_field_int(name, value, 64, UVM_TIME, scope_separator); endfunction function void uvm_printer::print_string (string name, string value, byte scope_separator="."); push_element(name, "string", $sformatf("%0d",value.len()), (value == "" ? "\"\"" : value)); pop_element() ; endfunction function uvm_policy::recursion_state_e uvm_printer::object_printed (uvm_object value, uvm_recursion_policy_enum recursion); if (!m_recur_states.exists(value)) return NEVER ; if (!m_recur_states[value].exists(recursion)) return NEVER ; else return m_recur_states[value][recursion] ; endfunction function void uvm_printer::print_real (string name, real value, byte scope_separator="."); push_element(name,"real","64",$sformatf("%f",value)); pop_element() ; endfunction function string uvm_printer::index_string(int index, string name=""); index_string.itoa(index); index_string = { name, "[", index_string, "]" }; endfunction function uvm_printer_element::new (string name = ""); super.new(name) ; endfunction function void uvm_printer_element::set (string element_name = "", string element_type_name = "", string element_size = "", string element_value = "" ); m_name = element_name ; m_type_name = element_type_name ; m_size = element_size ; m_value = element_value ; endfunction function void uvm_printer_element::set_element_name (string element_name); m_name = element_name ; endfunction function string uvm_printer_element::get_element_name (); return m_name ; endfunction function void uvm_printer_element::set_element_type_name (string element_type_name); m_type_name = element_type_name ; endfunction function string uvm_printer_element::get_element_type_name (); return m_type_name ; endfunction function void uvm_printer_element::set_element_size (string element_size); m_size = element_size ; endfunction function string uvm_printer_element::get_element_size (); return m_size ; endfunction function void uvm_printer_element::set_element_value (string element_value); m_value = element_value ; endfunction function string uvm_printer_element::get_element_value (); return m_value ; endfunction function void uvm_printer_element::add_child(uvm_printer_element child) ; m_children.push_back(child) ; endfunction function void uvm_printer_element::get_children(ref uvm_printer_element children[$], input bit recurse) ; foreach (m_children[i]) begin children.push_back(m_children[i]) ; if (recurse) begin m_children[i].get_children(children,1) ; end end endfunction function void uvm_printer_element::clear_children() ; m_children.delete() ; endfunction function uvm_table_printer::new(string name=""); super.new(name); endfunction function void uvm_table_printer::pop_element(); int name_len; int level ; uvm_printer_element popped ; string name_str ; string type_name_str ; string size_str ; string value_str ; popped = get_top_element() ; level = m_get_stack_size() - 1 ; name_str = popped.get_element_name() ; type_name_str = popped.get_element_type_name() ; size_str = popped.get_element_size() ; value_str = popped.get_element_value() ; if ((name_str.len() + (get_indent() * level)) > m_max_name) m_max_name = (name_str.len() + (get_indent() * level)); if (type_name_str.len() > m_max_type) m_max_type = type_name_str.len(); if (size_str.len() > m_max_size) m_max_size = size_str.len(); if (value_str.len() > m_max_value) m_max_value = value_str.len(); super.pop_element() ; endfunction function string uvm_table_printer::emit(); string s; string user_format; static string dash; string dashes; string linefeed; if (!m_flushed) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/PRINT/NO_FLUSH")) uvm_report_error ("UVM/PRINT/NO_FLUSH", "printer emit() method called twice without intervening uvm_printer::flush()", UVM_NONE, "t/uvm/src/base/uvm_printer.svh", 1516, "", 1); end end else m_flushed = 0 ; linefeed = {"\n", get_line_prefix()}; begin int q[5]; int m; int qq[$]; q = '{m_max_name,m_max_type,m_max_size,m_max_value,100}; qq = q.max; m = qq[0]; if(dash.len() 0) && (value_str[0] == "@")) result = {result,"(",element.get_element_type_name(),value_str,") "}; else if (get_type_name_enabled() && (element.get_element_type_name() != "" || element.get_element_type_name() != "-" || element.get_element_type_name() != "...")) result = {result,"(",element.get_element_type_name(),") "}; if (get_size_enabled()) begin if (element.get_element_size() != "" || element.get_element_size() != "-") result = {result,"(",element.get_element_size(),") "}; end if (element_children.size() > 0) begin result = {result, string'(separators[0]), m_linefeed}; end else result = {result, value_str, " ", m_linefeed}; foreach (element_children[i]) begin result = {result, m_emit_element(element_children[i],level+1)} ; end if (element_children.size() > 0) begin result = {result, indent_str, string'(separators[1]), m_linefeed}; end end return result ; endfunction : m_emit_element function void uvm_table_printer::set_default(uvm_table_printer printer) ; m_default_table_printer = printer ; endfunction function uvm_table_printer uvm_table_printer::get_default() ; if (m_default_table_printer == null) begin m_default_table_printer = new("uvm_default_table_printer") ; end return m_default_table_printer ; endfunction function void uvm_table_printer::set_indent(int indent) ; m_uvm_printer_knobs _knobs = get_knobs(); _knobs.indent = indent ; endfunction function int uvm_table_printer::get_indent() ; m_uvm_printer_knobs _knobs = get_knobs(); return _knobs.indent ; endfunction function void uvm_table_printer::flush() ; super.flush() ; m_max_name=4; m_max_type=4; m_max_size=4; m_max_value=5; endfunction function void uvm_tree_printer::set_default(uvm_tree_printer printer) ; m_default_tree_printer = printer ; endfunction function uvm_tree_printer uvm_tree_printer::get_default() ; if (m_default_tree_printer == null) begin m_default_tree_printer = new("uvm_default_tree_printer") ; end return m_default_tree_printer ; endfunction function uvm_line_printer::new(string name="") ; super.new(name); m_newline = " "; set_indent(0); endfunction function void uvm_line_printer::set_default(uvm_line_printer printer) ; m_default_line_printer = printer ; endfunction function uvm_line_printer uvm_line_printer::get_default() ; if (m_default_line_printer == null) begin m_default_line_printer = new("uvm_default_line_printer") ; end return m_default_line_printer ; endfunction function void uvm_line_printer::set_separators(string separators) ; m_uvm_printer_knobs _knobs = get_knobs(); if (separators.len() < 2) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/PRINT/SHORT_SEP")) uvm_report_error ("UVM/PRINT/SHORT_SEP", $sformatf("Bad call: set_separators(%s) (Argument must have at least 2 characters)",separators), UVM_NONE, "t/uvm/src/base/uvm_printer.svh", 1888, "", 1); end end _knobs.separator = separators ; endfunction function string uvm_line_printer::get_separators() ; m_uvm_printer_knobs _knobs = get_knobs(); return _knobs.separator ; endfunction function void uvm_line_printer::flush() ; super.flush() ; endfunction class uvm_comparer extends uvm_policy; typedef uvm_object_registry#(uvm_comparer,"uvm_comparer") type_id; static function uvm_comparer type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_comparer tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_comparer"; endfunction : type_name virtual function string get_type_name(); return "uvm_comparer"; endfunction : get_type_name extern virtual function void flush(); extern virtual function uvm_policy::recursion_state_e object_compared( uvm_object lhs, uvm_object rhs, uvm_recursion_policy_enum recursion, output bit ret_val ); extern virtual function string get_miscompares(); extern virtual function int unsigned get_result(); extern virtual function void set_result(int unsigned result) ; extern virtual function void set_recursion_policy( uvm_recursion_policy_enum policy); extern virtual function uvm_recursion_policy_enum get_recursion_policy(); extern virtual function void set_check_type( bit enabled ); extern virtual function bit get_check_type(); extern virtual function void set_show_max (int unsigned show_max); extern virtual function int unsigned get_show_max (); extern virtual function void set_verbosity (int unsigned verbosity); extern virtual function int unsigned get_verbosity (); extern virtual function void set_severity (uvm_severity severity); extern virtual function uvm_severity get_severity (); extern virtual function void set_threshold (int unsigned threshold); extern virtual function int unsigned get_threshold (); typedef struct { recursion_state_e state; bit ret_val; } state_info_t ; state_info_t m_recur_states[uvm_object ][uvm_object ][uvm_recursion_policy_enum ]; local uvm_recursion_policy_enum policy = UVM_DEFAULT_POLICY; local int unsigned show_max = 1; local int unsigned verbosity = UVM_LOW; local uvm_severity sev = UVM_INFO; local string miscompares = ""; local bit check_type = 1; local int unsigned result = 0; local int unsigned m_threshold; function new(string name=""); super.new(name); m_threshold = 1; endfunction static function void set_default (uvm_comparer comparer) ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; coreservice.set_default_comparer(comparer) ; endfunction static function uvm_comparer get_default () ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; return coreservice.get_default_comparer() ; endfunction virtual function bit compare_field (string name, uvm_bitstream_t lhs, uvm_bitstream_t rhs, int size, uvm_radix_enum radix=UVM_NORADIX); uvm_bitstream_t mask; string msg; if(size <= 64) return compare_field_int(name, lhs, rhs, size, radix); mask = -1; mask >>= (UVM_STREAMBITS-size); if((lhs & mask) !== (rhs & mask)) begin case (radix) UVM_BIN: begin $swrite(msg, "%s: lhs = 'b%0b : rhs = 'b%0b", name, lhs&mask, rhs&mask); end UVM_OCT: begin $swrite(msg, "%s: lhs = 'o%0o : rhs = 'o%0o", name, lhs&mask, rhs&mask); end UVM_DEC: begin $swrite(msg, "%s: lhs = %0d : rhs = %0d", name, lhs&mask, rhs&mask); end UVM_TIME: begin $swrite(msg, "%s: lhs = %0t : rhs = %0t", name, lhs&mask, rhs&mask); end UVM_STRING: begin $swrite(msg, "%s: lhs = %0s : rhs = %0s", name, lhs&mask, rhs&mask); end UVM_ENUM: begin $swrite(msg, "%s: lhs = %0d : rhs = %0d", name, lhs&mask, rhs&mask); end default: begin $swrite(msg, "%s: lhs = 'h%0x : rhs = 'h%0x", name, lhs&mask, rhs&mask); end endcase print_msg(msg); return 0; end return 1; endfunction virtual function bit compare_field_int (string name, uvm_integral_t lhs, uvm_integral_t rhs, int size, uvm_radix_enum radix=UVM_NORADIX); logic [63:0] mask; string msg; mask = -1; mask >>= (64-size); if((lhs & mask) !== (rhs & mask)) begin case (radix) UVM_BIN: begin $swrite(msg, "%s: lhs = 'b%0b : rhs = 'b%0b", name, lhs&mask, rhs&mask); end UVM_OCT: begin $swrite(msg, "%s: lhs = 'o%0o : rhs = 'o%0o", name, lhs&mask, rhs&mask); end UVM_DEC: begin $swrite(msg, "%s: lhs = %0d : rhs = %0d", name, lhs&mask, rhs&mask); end UVM_TIME: begin $swrite(msg, "%s: lhs = %0t : rhs = %0t", name, lhs&mask, rhs&mask); end UVM_STRING: begin $swrite(msg, "%s: lhs = %0s : rhs = %0s", name, lhs&mask, rhs&mask); end UVM_ENUM: begin $swrite(msg, "%s: lhs = %0d : rhs = %0d", name, lhs&mask, rhs&mask); end default: begin $swrite(msg, "%s: lhs = 'h%0x : rhs = 'h%0x", name, lhs&mask, rhs&mask); end endcase print_msg(msg); return 0; end return 1; endfunction virtual function bit compare_field_real (string name, real lhs, real rhs); string msg; if(lhs != rhs) begin $swrite(msg, name, ": lhs = ", lhs, " : rhs = ", rhs); print_msg(msg); return 0; end return 1; endfunction local string m_object_names[$]; local function string m_current_context(string name=""); if (m_object_names.size() == 0) return name; else if ((m_object_names.size() == 1) && (name=="")) return m_object_names[0]; else begin string full_name; foreach(m_object_names[i]) begin if (i == m_object_names.size() - 1) full_name = {full_name, m_object_names[i]}; else full_name = {full_name, m_object_names[i], "."}; end if (name != "") return {full_name, ".", name}; else return full_name; end endfunction : m_current_context virtual function bit compare_object (string name, uvm_object lhs, uvm_object rhs); int old_result ; uvm_field_op field_op ; uvm_policy::recursion_state_e prev_state; bit ret_val = 1; if (rhs == lhs) return ret_val; m_object_names.push_back(name); if (policy == UVM_REFERENCE && lhs != rhs) begin print_msg_object(lhs, rhs); ret_val = 0; end if (ret_val && (rhs == null || lhs == null)) begin print_msg_object(lhs, rhs); ret_val = 0; end if (ret_val) begin prev_state = object_compared(lhs,rhs,get_recursion_policy(),ret_val); if (prev_state != uvm_policy::NEVER) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/COPIER/LOOP")) uvm_report_warning ("UVM/COPIER/LOOP", {"Possible loop when comparing '", lhs.get_full_name(), "' to '", rhs.get_full_name(), "'"}, UVM_NONE, "t/uvm/src/base/uvm_comparer.svh", 465, "", 1); end push_active_object(lhs); m_recur_states[lhs][rhs][get_recursion_policy()] = '{uvm_policy::STARTED,0}; old_result = get_result(); if (get_check_type() && (lhs.get_object_type() != rhs.get_object_type())) begin if(lhs.get_type_name() != rhs.get_type_name()) begin print_msg({"type: lhs = \"", lhs.get_type_name(), "\" : rhs = \"", rhs.get_type_name(), "\""}); end else begin print_msg({"get_object_type() for ",lhs.get_name()," does not match get_object_type() for ",rhs.get_name()}); end end field_op = uvm_field_op::m_get_available_op(); field_op.set(UVM_COMPARE,this,rhs); lhs.do_execute_op(field_op); if (field_op.user_hook_enabled()) begin ret_val = lhs.do_compare(rhs,this); end field_op.m_recycle(); if (ret_val && (get_result() > old_result)) ret_val = 0; m_recur_states[lhs][rhs][get_recursion_policy()] = '{uvm_policy::FINISHED,ret_val}; void'(pop_active_object()); end void'(m_object_names.pop_back()); if (!ret_val && (get_active_object_depth() == 0)) begin string msg ; if(get_result()) begin if (get_show_max() && (get_show_max() < get_result())) $swrite(msg, "%0d Miscompare(s) (%0d shown) for object ", result, show_max); else $swrite(msg, "%0d Miscompare(s) for object ", result); end uvm_pkg::uvm_report(sev, "MISCMP", $sformatf("%s%s@%0d vs. %s@%0d", msg, (lhs == null) ? "" : lhs.get_name(), (lhs == null) ? 0 : lhs.get_inst_id(), (rhs == null) ? "" : rhs.get_name(), (rhs == null) ? 0 : rhs.get_inst_id()), get_verbosity(), "t/uvm/src/base/uvm_comparer.svh", 525); end return ret_val; endfunction virtual function bit compare_string (string name, string lhs, string rhs); string msg; if(lhs != rhs) begin msg = { name, ": lhs = \"", lhs, "\" : rhs = \"", rhs, "\""}; print_msg(msg); return 0; end return 1; endfunction function void print_msg (string msg); string tmp = m_current_context(msg); result++; if((get_show_max() == 0) || (get_result() <= get_show_max())) begin msg = {"Miscompare for ", tmp}; uvm_pkg::uvm_report(sev, "MISCMP", msg, get_verbosity(), "t/uvm/src/base/uvm_comparer.svh", 573); end miscompares = { miscompares, tmp, "\n" }; endfunction function void print_msg_object(uvm_object lhs, uvm_object rhs); string tmp = $sformatf("%s: lhs = @%0d : rhs = @%0d", m_current_context(), (lhs != null ? lhs.get_inst_id() : 0), (rhs != null ? rhs.get_inst_id() : 0)); result++; if((get_show_max() == 0) || (get_result() <= get_show_max())) begin uvm_pkg::uvm_report(sev, "MISCMP", {"Miscompare for ", tmp}, get_verbosity(), "t/uvm/src/base/uvm_comparer.svh", 599); end miscompares = { miscompares, tmp, "\n" }; endfunction int depth; bit compare_map[uvm_object][uvm_object]; endclass function void uvm_comparer::flush(); miscompares = "" ; check_type = 1 ; result = 0 ; m_recur_states.delete(); endfunction function uvm_policy::recursion_state_e uvm_comparer::object_compared( uvm_object lhs, uvm_object rhs, uvm_recursion_policy_enum recursion, output bit ret_val ); if (!m_recur_states.exists(lhs)) return NEVER ; else if (!m_recur_states[lhs].exists(rhs)) return NEVER ; else if (!m_recur_states[lhs][rhs].exists(recursion)) return NEVER ; else begin if (m_recur_states[lhs][rhs][recursion].state == FINISHED) ret_val = m_recur_states[lhs][rhs][recursion].ret_val; return m_recur_states[lhs][rhs][recursion].state ; end endfunction function string uvm_comparer::get_miscompares(); return miscompares ; endfunction function int unsigned uvm_comparer::get_result(); return result ; endfunction function void uvm_comparer::set_result(int unsigned result); this.result = result ; endfunction function void uvm_comparer::set_recursion_policy( uvm_recursion_policy_enum policy); this.policy = policy ; endfunction function uvm_recursion_policy_enum uvm_comparer::get_recursion_policy(); return policy ; endfunction function void uvm_comparer::set_check_type( bit enabled ); check_type = enabled ; endfunction function bit uvm_comparer::get_check_type(); return check_type ; endfunction function void uvm_comparer::set_show_max (int unsigned show_max); this.show_max = show_max ; endfunction function int unsigned uvm_comparer::get_show_max(); return show_max ; endfunction function void uvm_comparer::set_verbosity (int unsigned verbosity); this.verbosity = verbosity ; endfunction function int unsigned uvm_comparer::get_verbosity(); return verbosity ; endfunction function void uvm_comparer::set_severity (uvm_severity severity); sev = severity ; endfunction function uvm_severity uvm_comparer::get_severity(); return sev ; endfunction function void uvm_comparer::set_threshold (int unsigned threshold); m_threshold = threshold; endfunction function int unsigned uvm_comparer::get_threshold(); return m_threshold; endfunction typedef bit signed [(4096*8)-1:0] uvm_pack_bitstream_t; class uvm_packer extends uvm_policy; typedef uvm_object_registry#(uvm_packer,"uvm_packer") type_id; static function uvm_packer type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_packer tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_packer"; endfunction : type_name virtual function string get_type_name(); return "uvm_packer"; endfunction : get_type_name uvm_factory m_factory; local uvm_object m_object_references[int]; extern virtual function void set_packed_bits (ref bit unsigned stream[]); extern virtual function void set_packed_bytes (ref byte unsigned stream[]); extern virtual function void set_packed_ints (ref int unsigned stream[]); extern virtual function void set_packed_longints (ref longint unsigned stream[]); extern virtual function void get_packed_bits (ref bit unsigned stream[]); extern virtual function void get_packed_bytes (ref byte unsigned stream[]); extern virtual function void get_packed_ints (ref int unsigned stream[]); extern virtual function void get_packed_longints (ref longint unsigned stream[]); static function void set_default (uvm_packer packer) ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; coreservice.set_default_packer(packer) ; endfunction static function uvm_packer get_default () ; uvm_coreservice_t coreservice ; coreservice = uvm_coreservice_t::get() ; return coreservice.get_default_packer() ; endfunction extern virtual function void flush (); extern virtual function void pack_field (uvm_bitstream_t value, int size); extern function new(string name=""); extern virtual function void pack_field_int (uvm_integral_t value, int size); extern virtual function void pack_bits(ref bit value[], input int size = -1); extern virtual function void pack_bytes(ref byte value[], input int size = -1); extern virtual function void pack_ints(ref int value[], input int size = -1); extern virtual function void pack_string (string value); extern virtual function void pack_time (time value); extern virtual function void pack_real (real value); extern virtual function void pack_object (uvm_object value); extern virtual function void pack_object_with_meta (uvm_object value); extern virtual function void pack_object_wrapper (uvm_object_wrapper value); extern virtual function bit is_null (); extern virtual function bit is_object_wrapper(); extern virtual function uvm_bitstream_t unpack_field (int size); extern virtual function uvm_integral_t unpack_field_int (int size); extern virtual function void unpack_bits(ref bit value[], input int size = -1); extern virtual function void unpack_bytes(ref byte value[], input int size = -1); extern virtual function void unpack_ints(ref int value[], input int size = -1); extern virtual function string unpack_string (); extern virtual function time unpack_time (); extern virtual function real unpack_real (); extern virtual function void unpack_object (uvm_object value); extern virtual function void unpack_object_with_meta (inout uvm_object value); extern virtual function uvm_object_wrapper unpack_object_wrapper(); extern virtual function int get_packed_size(); static bit bitstream[]; static bit fabitstream[]; int m_pack_iter; int m_unpack_iter; bit reverse_order; byte byte_size = 8; int word_size = 16; bit nopack; uvm_pack_bitstream_t m_bits; extern function void index_error(int index, string id, int sz); extern function bit enough_bits(int needed, string id); endclass function void uvm_packer::index_error(int index, string id, int sz); uvm_report_error("PCKIDX", $sformatf("index %0d for get_%0s too large; valid index range is 0-%0d.", index,id,((m_pack_iter+sz-1)/sz)-1), UVM_NONE); endfunction function bit uvm_packer::enough_bits(int needed, string id); if ((m_pack_iter - m_unpack_iter) < needed) begin uvm_report_error("PCKSZ", $sformatf("%0d bits needed to unpack %0s, yet only %0d available.", needed, id, (m_pack_iter - m_unpack_iter)), UVM_NONE); return 0; end return 1; endfunction function int uvm_packer::get_packed_size(); return m_pack_iter - m_unpack_iter; endfunction function void uvm_packer::flush(); m_pack_iter = 64; m_unpack_iter = 64; m_bits = 0; m_object_references.delete(); m_object_references[0] = null; m_factory = null; super.flush(); endfunction : flush function void uvm_packer::get_packed_bits(ref bit unsigned stream[]); stream = new[m_pack_iter]; m_bits[31:0] = m_pack_iter; m_bits[63:32] = m_unpack_iter; for (int i=0;i> ($bits(byte)-(m_pack_iter%$bits(byte)))); stream[i] = v; end endfunction function void uvm_packer::get_packed_ints (ref int unsigned stream[] ); int sz; int v; sz = (m_pack_iter + $high(v)) / $bits(int); m_bits[31:0] = m_pack_iter; m_bits[63:32] = m_unpack_iter; stream = new[sz]; foreach (stream[i]) begin if (i != sz-1 || (m_pack_iter % $bits(int)) == 0) v = m_bits[ i* $bits(int) +: $bits(int) ]; else v = m_bits[ i* $bits(int) +: $bits(int) ] & ({$bits(int){1'b1}} >> ($bits(int)-(m_pack_iter%$bits(int)))); stream[i] = v; end endfunction function void uvm_packer::get_packed_longints (ref longint unsigned stream[] ); int sz; longint v; sz = (m_pack_iter + $high(v)) / $bits(longint); m_bits[31:0] = m_pack_iter; m_bits[63:32] = m_unpack_iter; stream = new[sz]; foreach (stream[i]) begin if (i != sz-1 || (m_pack_iter % $bits(longint)) == 0) v = m_bits[ i* $bits(longint) +: $bits(longint) ]; else v = m_bits[ i* $bits(longint) +: $bits(longint) ] & ({$bits(longint){1'b1}} >> ($bits(longint)-(m_pack_iter%$bits(longint)))); stream[i] = v; end endfunction function void uvm_packer::set_packed_bits (ref bit stream []); int bit_size; bit_size = stream.size(); for (int i=0;i value.size()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("pack_bits called with size '%0d', which exceeds value.size() of '%0d'", size, value.size()), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 797, "", 1); end return; end for (int i=0; i max_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("pack_bytes called with size '%0d', which exceeds value size of '%0d'", size, max_size), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 824, "", 1); end return; end else begin int idx_select; for (int i=0; i max_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("pack_ints called with size '%0d', which exceeds value size of '%0d'", size, max_size), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 858, "", 1); end return; end else begin int idx_select; for (int i=0; i value.size()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("unpack_bits called with size '%0d', which exceeds value.size() of '%0d'", size, value.size()), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 1076, "", 1); end return; end if (enough_bits(size, "integral")) begin m_unpack_iter += size; for (int i=0; i max_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("unpack_bytes called with size '%0d', which exceeds value size of '%0d'", size, value.size()), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 1104, "", 1); end return; end else begin if (enough_bits(size, "integral")) begin m_unpack_iter += size; for (int i=0; i max_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/BAD_SIZE")) uvm_report_error ("UVM/BASE/PACKER/BAD_SIZE", $sformatf("unpack_ints called with size '%0d', which exceeds value size of '%0d'", size, value.size()), UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 1136, "", 1); end return; end else begin if (enough_bits(size, "integral")) begin m_unpack_iter += size; for (int i=0; i' is not supported in links for 'uvm_tr_database'", UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 158, "", 1); end return; end if (rhs == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK")) uvm_report_warning ("UVM/TR_DB/BAD_LINK", "right hand side '' is not supported in links for 'uvm_tr_database'", UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 163, "", 1); end return; end if (!$cast(s_lhs, lhs) && !$cast(r_lhs, lhs)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK")) uvm_report_warning ("UVM/TR_DB/BAD_LINK", $sformatf("left hand side of type '%s' not supported in links for 'uvm_tr_database'", lhs.get_type_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 171, "", 1); end return; end if (!$cast(s_rhs, rhs) && !$cast(r_rhs, rhs)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK")) uvm_report_warning ("UVM/TR_DB/BAD_LINK", $sformatf("right hand side of type '%s' not supported in links for 'uvm_record_datbasae'", rhs.get_type_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 178, "", 1); end return; end if (r_lhs != null) begin s_lhs = r_lhs.get_stream(); end if (r_rhs != null) begin s_rhs = r_rhs.get_stream(); end if ((s_lhs != null) && (s_lhs.get_db() != this)) begin db = s_lhs.get_db(); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK")) uvm_report_warning ("UVM/TR_DB/BAD_LINK", $sformatf("attempt to link stream from '%s' into '%s'", db.get_name(), this.get_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 193, "", 1); end return; end if ((s_rhs != null) && (s_rhs.get_db() != this)) begin db = s_rhs.get_db(); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK")) uvm_report_warning ("UVM/TR_DB/BAD_LINK", $sformatf("attempt to link stream from '%s' into '%s'", db.get_name(), this.get_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_database.svh", 200, "", 1); end return; end do_establish_link(link); endfunction : establish_link pure virtual protected function bit do_open_db(); pure virtual protected function bit do_close_db(); pure virtual protected function uvm_tr_stream do_open_stream(string name, string scope, string type_name); pure virtual protected function void do_establish_link(uvm_link_base link); endclass : uvm_tr_database typedef class uvm_recorder; typedef class uvm_tr_stream; typedef class uvm_link_base; typedef class uvm_simple_lock_dap; typedef class uvm_text_tr_stream; class uvm_text_tr_database extends uvm_tr_database; local uvm_simple_lock_dap#(string) m_filename_dap; UVM_FILE m_file; typedef uvm_object_registry#(uvm_text_tr_database,"uvm_text_tr_database") type_id; static function uvm_text_tr_database type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_text_tr_database tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_text_tr_database"; endfunction : type_name virtual function string get_type_name(); return "uvm_text_tr_database"; endfunction : get_type_name function new(string name="unnamed-uvm_text_tr_database"); super.new(name); m_filename_dap = new("filename_dap"); m_filename_dap.set("tr_db.log"); endfunction : new protected virtual function bit do_open_db(); if (m_file == 0) begin m_file = $fopen(m_filename_dap.get(), "a+"); if (m_file != 0) m_filename_dap.lock(); end return (m_file != 0); endfunction : do_open_db protected virtual function bit do_close_db(); if (m_file != 0) begin fork $fclose(m_file); join_none m_filename_dap.unlock(); end return 1; endfunction : do_close_db protected virtual function uvm_tr_stream do_open_stream(string name, string scope, string type_name); uvm_text_tr_stream m_stream = uvm_text_tr_stream::type_id_create(name); return m_stream; endfunction : do_open_stream protected virtual function void do_establish_link(uvm_link_base link); uvm_recorder r_lhs, r_rhs; uvm_object lhs = link.get_lhs(); uvm_object rhs = link.get_rhs(); void'($cast(r_lhs, lhs)); void'($cast(r_rhs, rhs)); if ((r_lhs == null) || (r_rhs == null)) return; else begin uvm_parent_child_link pc_link; uvm_related_link re_link; if ($cast(pc_link, link)) begin $fdisplay(m_file," LINK @%0t {TXH1:%0d TXH2:%0d RELATION=%0s}", $time, r_lhs.get_handle(), r_rhs.get_handle(), "child"); end else if ($cast(re_link, link)) begin $fdisplay(m_file," LINK @%0t {TXH1:%0d TXH2:%0d RELATION=%0s}", $time, r_lhs.get_handle(), r_rhs.get_handle(), ""); end end endfunction : do_establish_link function void set_file_name(string filename); if (filename == "") begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TXT_DB/EMPTY_NAME")) uvm_report_warning ("UVM/TXT_DB/EMPTY_NAME", "Ignoring attempt to set file name to ''!", UVM_NONE, "t/uvm/src/base/uvm_text_tr_database.svh", 195, "", 1); end return; end if (!m_filename_dap.try_set(filename)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TXT_DB/SET_AFTER_OPEN")) uvm_report_warning ("UVM/TXT_DB/SET_AFTER_OPEN", "Ignoring attempt to change file name after opening the db!", UVM_NONE, "t/uvm/src/base/uvm_text_tr_database.svh", 201, "", 1); end return; end endfunction : set_file_name endclass : uvm_text_tr_database class m_uvm_tr_stream_cfg; uvm_tr_database db; string scope; string stream_type_name; endclass : m_uvm_tr_stream_cfg typedef class uvm_set_before_get_dap; typedef class uvm_text_recorder; virtual class uvm_tr_stream extends uvm_object; local uvm_set_before_get_dap#(m_uvm_tr_stream_cfg) m_cfg_dap; local bit m_records[uvm_recorder]; local bit m_warn_null_cfg; local bit m_is_opened; local bit m_is_closed; function new(string name="unnamed-uvm_tr_stream"); super.new(name); m_cfg_dap = new("cfg_dap"); endfunction : new local static int m_ids_by_stream[uvm_tr_stream]; function uvm_tr_database get_db(); m_uvm_tr_stream_cfg m_cfg; if (!m_cfg_dap.try_get(m_cfg)) begin if (m_warn_null_cfg == 1) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REC_STR/NO_CFG")) uvm_report_warning ("UVM/REC_STR/NO_CFG", $sformatf("attempt to retrieve DB from '%s' before it was set!", get_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_stream.svh", 94, "", 1); end m_warn_null_cfg = 0; return null; end return m_cfg.db; endfunction : get_db function string get_scope(); m_uvm_tr_stream_cfg m_cfg; if (!m_cfg_dap.try_get(m_cfg)) begin if (m_warn_null_cfg == 1) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REC_STR/NO_CFG")) uvm_report_warning ("UVM/REC_STR/NO_CFG", $sformatf("attempt to retrieve scope from '%s' before it was set!", get_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_stream.svh", 109, "", 1); end m_warn_null_cfg = 0; return ""; end return m_cfg.scope; endfunction : get_scope function string get_stream_type_name(); m_uvm_tr_stream_cfg m_cfg; if (!m_cfg_dap.try_get(m_cfg)) begin if (m_warn_null_cfg == 1) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REC_STR/NO_CFG")) uvm_report_warning ("UVM/REC_STR/NO_CFG", $sformatf("attempt to retrieve STREAM_TYPE_NAME from '%s' before it was set!", get_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_stream.svh", 124, "", 1); end m_warn_null_cfg = 0; return ""; end return m_cfg.stream_type_name; endfunction : get_stream_type_name function void close(); if (!is_open()) return; do_close(); foreach (m_records[idx]) if (idx.is_open()) idx.close(); m_is_opened = 0; m_is_closed = 1; endfunction : close function void free(); process p; string s; uvm_tr_database db; if (!is_open() && !is_closed()) return; if (is_open()) close(); do_free(); foreach (m_records[idx]) idx.free(); db = get_db(); m_is_closed = 0; p = process::self(); if(p != null) s = p.get_randstate(); m_cfg_dap = new("cfg_dap"); if(p != null) p.set_randstate(s); m_warn_null_cfg = 1; if (m_ids_by_stream.exists(this)) m_free_id(m_ids_by_stream[this]); if (db != null) db.m_free_stream(this); endfunction : free function void m_do_open(uvm_tr_database db, string scope="", string stream_type_name=""); m_uvm_tr_stream_cfg m_cfg; uvm_tr_database m_db; if (db == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REC_STR/NULL_DB")) uvm_report_error ("UVM/REC_STR/NULL_DB", $sformatf("Illegal attempt to set DB for '%s' to ''", this.get_full_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_stream.svh", 217, "", 1); end return; end if (m_cfg_dap.try_get(m_cfg)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REC_STR/RE_CFG")) uvm_report_error ("UVM/REC_STR/RE_CFG", $sformatf("Illegal attempt to re-open '%s'", this.get_full_name()), UVM_NONE, "t/uvm/src/base/uvm_tr_stream.svh", 224, "", 1); end end else begin m_cfg = new(); m_cfg.db = db; m_cfg.scope = scope; m_cfg.stream_type_name = stream_type_name; m_cfg_dap.set(m_cfg); m_is_opened = 1; do_open(db, scope, stream_type_name); end endfunction : m_do_open function bit is_open(); return m_is_opened; endfunction : is_open function bit is_closed(); return m_is_closed; endfunction : is_closed function uvm_recorder open_recorder(string name, time open_time = 0, string type_name=""); time m_time = (open_time == 0) ? $time : open_time; if (!is_open()) return null; else begin process p = process::self(); string s; if (p != null) s = p.get_randstate(); open_recorder = do_open_recorder(name, m_time, type_name); if (open_recorder != null) begin m_records[open_recorder] = 1; open_recorder.m_do_open(this, m_time, type_name); end if (p != null) p.set_randstate(s); end endfunction : open_recorder function void m_free_recorder(uvm_recorder recorder); if (m_records.exists(recorder)) m_records.delete(recorder); endfunction : m_free_recorder function unsigned get_recorders(ref uvm_recorder q[$]); q.delete(); foreach (m_records[idx]) q.push_back(idx); return q.size(); endfunction : get_recorders local static uvm_tr_stream m_streams_by_id[int]; function int get_handle(); if (!is_open() && !is_closed()) begin return 0; end else begin int handle = get_inst_id(); if (m_ids_by_stream.exists(this) && m_ids_by_stream[this] != handle) m_streams_by_id.delete(m_ids_by_stream[this]); m_streams_by_id[handle] = this; m_ids_by_stream[this] = handle; return handle; end endfunction : get_handle static function uvm_tr_stream get_stream_from_handle(int id); if (id == 0) return null; if ($isunknown(id) || !m_streams_by_id.exists(id)) return null; return m_streams_by_id[id]; endfunction : get_stream_from_handle static function void m_free_id(int id); uvm_tr_stream stream; if (!$isunknown(id) && m_streams_by_id.exists(id)) stream = m_streams_by_id[id]; if (stream != null) begin m_streams_by_id.delete(id); m_ids_by_stream.delete(stream); end endfunction : m_free_id protected virtual function void do_open(uvm_tr_database db, string scope, string stream_type_name); endfunction : do_open protected virtual function void do_close(); endfunction : do_close protected virtual function void do_free(); endfunction : do_free protected virtual function uvm_recorder do_open_recorder(string name, time open_time, string type_name); return null; endfunction : do_open_recorder endclass : uvm_tr_stream class uvm_text_tr_stream extends uvm_tr_stream; local uvm_text_tr_database m_text_db; typedef uvm_object_registry#(uvm_text_tr_stream,"uvm_text_tr_stream") type_id; static function uvm_text_tr_stream type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_text_tr_stream tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_text_tr_stream"; endfunction : type_name virtual function string get_type_name(); return "uvm_text_tr_stream"; endfunction : get_type_name function void do_execute_op( uvm_field_op op ); super.do_execute_op(op); __m_uvm_execute_field_op(op); endfunction : do_execute_op local function void __m_uvm_execute_field_op( uvm_field_op __local_op__ ); uvm_field_flag_t local_op_type__; uvm_text_tr_stream local_rhs__; uvm_resource_base local_rsrc__; string local_rsrc_name__; uvm_object local_obj__; bit local_success__; typedef uvm_text_tr_stream __local_type__; int local_size__; uvm_printer __local_printer__; uvm_comparer __local_comparer__; uvm_recorder __local_recorder__; uvm_packer __local_packer__; uvm_copier __local_copier__; void'($cast(local_rhs__, __local_op__.get_rhs())); if (($cast(local_rsrc__, __local_op__.get_rhs())) && (local_rsrc__ != null)) local_rsrc_name__ = local_rsrc__.get_name(); local_op_type__ = __local_op__.get_op_type(); case (local_op_type__) UVM_PRINT: begin $cast(__local_printer__, __local_op__.get_policy()); end UVM_COMPARE: begin if (local_rhs__ == null) return; $cast(__local_comparer__, __local_op__.get_policy()); end UVM_RECORD: begin $cast(__local_recorder__, __local_op__.get_policy()); end UVM_PACK, UVM_UNPACK: begin $cast(__local_packer__, __local_op__.get_policy()); end UVM_COPY: begin if (local_rhs__ == null) return; $cast(__local_copier__, __local_op__.get_policy()); end UVM_SET: begin if (local_rsrc__ == null) return; end default: return; endcase endfunction : __m_uvm_execute_field_op function new(string name="unnamed-uvm_text_tr_stream"); super.new(name); endfunction : new protected virtual function void do_open(uvm_tr_database db, string scope, string stream_type_name); $cast(m_text_db, db); if (m_text_db.open_db()) $fdisplay(m_text_db.m_file, " CREATE_STREAM @%0t {NAME:%s T:%s SCOPE:%s STREAM:%0d}", $time, this.get_name(), stream_type_name, scope, this.get_handle()); endfunction : do_open protected virtual function void do_close(); if (m_text_db.open_db()) $fdisplay(m_text_db.m_file, " CLOSE_STREAM @%0t {NAME:%s T:%s SCOPE:%s STREAM:%0d}", $time, this.get_name(), this.get_stream_type_name(), this.get_scope(), this.get_handle()); endfunction : do_close protected virtual function void do_free(); if (m_text_db.open_db()) $fdisplay(m_text_db.m_file, " FREE_STREAM @%0t {NAME:%s T:%s SCOPE:%s STREAM:%0d}", $time, this.get_name(), this.get_stream_type_name(), this.get_scope(), this.get_handle()); m_text_db = null; return; endfunction : do_free protected virtual function uvm_recorder do_open_recorder(string name, time open_time, string type_name); if (m_text_db.open_db()) begin return uvm_text_recorder::type_id_create(name); end return null; endfunction : do_open_recorder endclass : uvm_text_tr_stream typedef class uvm_report_message; virtual class uvm_recorder extends uvm_policy; typedef uvm_abstract_object_registry#(uvm_recorder,"uvm_recorder") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_recorder"; endfunction : type_name virtual function string get_type_name(); return "uvm_recorder"; endfunction : get_type_name local uvm_set_before_get_dap#(uvm_tr_stream) m_stream_dap; local bit m_warn_null_stream; local bit m_is_opened; local bit m_is_closed; local time m_open_time; local time m_close_time; int recording_depth; uvm_radix_enum default_radix = UVM_HEX; bit identifier = 1; local uvm_recursion_policy_enum policy = UVM_DEFAULT_POLICY; virtual function void set_recursion_policy(uvm_recursion_policy_enum policy); this.policy = policy; endfunction : set_recursion_policy virtual function uvm_recursion_policy_enum get_recursion_policy(); return this.policy; endfunction : get_recursion_policy virtual function void flush(); policy = UVM_DEFAULT_POLICY; identifier = 1; free(); endfunction : flush local static int m_ids_by_recorder[uvm_recorder]; function new(string name = "uvm_recorder"); super.new(name); m_stream_dap = new("stream_dap"); m_warn_null_stream = 1; endfunction function uvm_tr_stream get_stream(); if (!m_stream_dap.try_get(get_stream)) begin if (m_warn_null_stream == 1) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REC/NO_CFG")) uvm_report_warning ("UVM/REC/NO_CFG", $sformatf("attempt to retrieve STREAM from '%s' before it was set!", get_name()), UVM_NONE, "t/uvm/src/base/uvm_recorder.svh", 178, "", 1); end m_warn_null_stream = 0; end endfunction : get_stream function void close(time close_time = 0); if (close_time == 0) close_time = $realtime; if (!is_open()) return; do_close(close_time); m_is_opened = 0; m_is_closed = 1; m_close_time = close_time; endfunction : close function void free(time close_time = 0); process p=process::self(); string s; uvm_tr_stream stream; if (!is_open() && !is_closed()) return; if (is_open()) begin close(close_time); end do_free(); stream = get_stream(); m_is_closed = 0; if(p != null) s=p.get_randstate(); m_stream_dap = new("stream_dap"); if(p != null) p.set_randstate(s); m_warn_null_stream = 1; if (m_ids_by_recorder.exists(this)) m_free_id(m_ids_by_recorder[this]); if (stream != null) stream.m_free_recorder(this); endfunction : free function bit is_open(); return m_is_opened; endfunction : is_open function time get_open_time(); return m_open_time; endfunction : get_open_time function bit is_closed(); return m_is_closed; endfunction : is_closed function time get_close_time(); return m_close_time; endfunction : get_close_time function void m_do_open(uvm_tr_stream stream, time open_time, string type_name); uvm_tr_stream m_stream; if (stream == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REC/NULL_STREAM")) uvm_report_error ("UVM/REC/NULL_STREAM", $sformatf("Illegal attempt to set STREAM for '%s' to ''", this.get_name()), UVM_NONE, "t/uvm/src/base/uvm_recorder.svh", 287, "", 1); end return; end if (m_stream_dap.try_get(m_stream)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REC/RE_INIT")) uvm_report_error ("UVM/REC/RE_INIT", $sformatf("Illegal attempt to re-initialize '%s'", this.get_name()), UVM_NONE, "t/uvm/src/base/uvm_recorder.svh", 294, "", 1); end return; end m_stream_dap.set(stream); m_open_time = open_time; m_is_opened = 1; do_open(stream, open_time, type_name); endfunction : m_do_open local static uvm_recorder m_recorders_by_id[int]; local static int m_id; static function void m_free_id(int id); uvm_recorder recorder; if ((!$isunknown(id)) && (m_recorders_by_id.exists(id))) recorder = m_recorders_by_id[id]; if (recorder != null) begin m_recorders_by_id.delete(id); m_ids_by_recorder.delete(recorder); end endfunction : m_free_id function int get_handle(); if (!is_open() && !is_closed()) begin return 0; end else begin int handle = get_inst_id(); if (m_ids_by_recorder.exists(this) && m_ids_by_recorder[this] != handle) m_recorders_by_id.delete(m_ids_by_recorder[this]); m_recorders_by_id[handle] = this; m_ids_by_recorder[this] = handle; return handle; end endfunction : get_handle static function uvm_recorder get_recorder_from_handle(int id); if (id == 0) return null; if (($isunknown(id)) || (!m_recorders_by_id.exists(id))) return null; return m_recorders_by_id[id]; endfunction : get_recorder_from_handle function void record_field(string name, uvm_bitstream_t value, int size, uvm_radix_enum radix=UVM_NORADIX); if (get_stream() == null) begin return; end do_record_field(name, value, size, radix); endfunction : record_field function void record_field_int(string name, uvm_integral_t value, int size, uvm_radix_enum radix=UVM_NORADIX); if (get_stream() == null) begin return; end do_record_field_int(name, value, size, radix); endfunction : record_field_int function void record_field_real(string name, real value); if (get_stream() == null) begin return; end do_record_field_real(name, value); endfunction : record_field_real function void record_object(string name, uvm_object value); if (get_stream() == null) begin return; end if (value == null) do_record_object(name, value); else begin push_active_object(value); do_record_object(name, value); void'(pop_active_object()); end endfunction : record_object function void record_string(string name, string value); if (get_stream() == null) begin return; end do_record_string(name, value); endfunction : record_string function void record_time(string name, time value); if (get_stream() == null) begin return; end do_record_time(name, value); endfunction : record_time function void record_generic(string name, string value, string type_name=""); if (get_stream() == null) begin return; end do_record_generic(name, value, type_name); endfunction : record_generic virtual function bit use_record_attribute(); return 0; endfunction : use_record_attribute virtual function int get_record_attribute_handle(); return get_handle(); endfunction : get_record_attribute_handle protected virtual function void do_open(uvm_tr_stream stream, time open_time, string type_name); endfunction : do_open protected virtual function void do_close(time close_time); endfunction : do_close protected virtual function void do_free(); endfunction : do_free pure virtual protected function void do_record_field(string name, uvm_bitstream_t value, int size, uvm_radix_enum radix); pure virtual protected function void do_record_field_int(string name, uvm_integral_t value, int size, uvm_radix_enum radix); pure virtual protected function void do_record_field_real(string name, real value); virtual protected function void do_record_object(string name, uvm_object value); if ((get_recursion_policy() != UVM_REFERENCE) && (value != null)) begin uvm_field_op field_op = uvm_field_op::m_get_available_op(); field_op.set(UVM_RECORD, this, null); value.do_execute_op(field_op); if (field_op.user_hook_enabled()) value.do_record(this); field_op.m_recycle(); end endfunction : do_record_object pure virtual protected function void do_record_string(string name, string value); pure virtual protected function void do_record_time(string name, time value); pure virtual protected function void do_record_generic(string name, string value, string type_name); virtual function bit open_file(); return 0; endfunction virtual function int create_stream (string name, string t, string scope); return -1; endfunction virtual function void m_set_attribute (int txh, string nm, string value); endfunction virtual function void set_attribute (int txh, string nm, logic [1023:0] value, uvm_radix_enum radix, int numbits=1024); endfunction virtual function int check_handle_kind (string htype, int handle); return 0; endfunction virtual function int begin_tr(string txtype, int stream, string nm, string label="", string desc="", time begin_time=0); return -1; endfunction virtual function void end_tr (int handle, time end_time=0); endfunction virtual function void link_tr(int h1, int h2, string relation=""); endfunction virtual function void free_tr(int handle); endfunction endclass class uvm_text_recorder extends uvm_recorder; typedef uvm_object_registry#(uvm_text_recorder,"uvm_text_recorder") type_id; static function uvm_text_recorder type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_text_recorder tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_text_recorder"; endfunction : type_name virtual function string get_type_name(); return "uvm_text_recorder"; endfunction : get_type_name uvm_text_tr_database m_text_db; function new(string name="unnamed-uvm_text_recorder"); super.new(name); endfunction : new protected virtual function void do_open(uvm_tr_stream stream, time open_time, string type_name); $cast(m_text_db, stream.get_db()); if (m_text_db.open_db()) $fdisplay(m_text_db.m_file, " OPEN_RECORDER @%0t {TXH:%0d STREAM:%0d NAME:%s TIME:%0t TYPE=\"%0s\"}", $realtime, this.get_handle(), stream.get_handle(), this.get_name(), open_time, type_name); endfunction : do_open protected virtual function void do_close(time close_time); if (m_text_db.open_db()) begin $fdisplay(m_text_db.m_file, " CLOSE_RECORDER @%0t {TXH:%0d TIME=%0t}", $realtime, this.get_handle(), close_time); end endfunction : do_close protected virtual function void do_free(); if (m_text_db.open_db()) begin $fdisplay(m_text_db.m_file, " FREE_RECORDER @%0t {TXH:%0d}", $realtime, this.get_handle()); end m_text_db = null; endfunction : do_free protected virtual function void do_record_field(string name, uvm_bitstream_t value, int size, uvm_radix_enum radix); if (!radix) radix = default_radix; write_attribute(m_current_context(name), value, radix, size); endfunction : do_record_field protected virtual function void do_record_field_int(string name, uvm_integral_t value, int size, uvm_radix_enum radix); if (!radix) radix = default_radix; write_attribute_int(m_current_context(name), value, radix, size); endfunction : do_record_field_int protected virtual function void do_record_field_real(string name, real value); bit [63:0] ival = $realtobits(value); write_attribute_int(m_current_context(name), ival, UVM_REAL, 64); endfunction : do_record_field_real local string m_object_names[$]; local function string m_current_context(string name=""); if (m_object_names.size() == 0) return name; else if ((m_object_names.size() == 1) && (name=="")) return m_object_names[0]; else begin string full_name; foreach(m_object_names[i]) begin if (i == m_object_names.size() - 1) full_name = {full_name, m_object_names[i]}; else full_name = {full_name, m_object_names[i], "."}; end if (name != "") return {full_name, ".", name}; else return full_name; end endfunction : m_current_context protected virtual function void do_record_object(string name, uvm_object value); int v; string str; if(identifier) begin if(value != null) begin v = value.get_inst_id(); end write_attribute_int("inst_id", v, UVM_DEC, 32); end if (get_active_object_depth() > 1) m_object_names.push_back(name); super.do_record_object(name, value); if (get_active_object_depth() > 1) void'(m_object_names.pop_back()); endfunction : do_record_object protected virtual function void do_record_string(string name, string value); if (m_text_db.open_db()) begin $fdisplay(m_text_db.m_file, " SET_ATTR @%0t {TXH:%0d NAME:%s VALUE:%s RADIX:%s BITS=%0d}", $realtime, this.get_handle(), m_current_context(name), value, "UVM_STRING", 8+value.len()); end endfunction : do_record_string protected virtual function void do_record_time(string name, time value); write_attribute_int(m_current_context(name), value, UVM_TIME, 64); endfunction : do_record_time protected virtual function void do_record_generic(string name, string value, string type_name); write_attribute(m_current_context(name), uvm_string_to_bits(value), UVM_STRING, 8+value.len()); endfunction : do_record_generic function void write_attribute(string nm, uvm_bitstream_t value, uvm_radix_enum radix, int numbits=$bits(uvm_bitstream_t)); if (m_text_db.open_db()) begin $fdisplay(m_text_db.m_file, " SET_ATTR @%0t {TXH:%0d NAME:%s VALUE:%s RADIX:%s BITS=%0d}", $realtime, this.get_handle(), nm, uvm_bitstream_to_string(value, numbits, radix), radix.name(), numbits); end endfunction : write_attribute function void write_attribute_int(string nm, uvm_integral_t value, uvm_radix_enum radix, int numbits=$bits(uvm_bitstream_t)); if (m_text_db.open_db()) begin $fdisplay(m_text_db.m_file, " SET_ATTR @%0t {TXH:%0d NAME:%s VALUE:%s RADIX:%s BITS=%0d}", $realtime, this.get_handle(), nm, uvm_integral_to_string(value, numbits, radix), radix.name(), numbits); end endfunction : write_attribute_int string filename; bit filename_set; virtual function bit open_file(); if (!filename_set) begin m_text_db.set_file_name(filename); end return m_text_db.open_db(); endfunction virtual function int create_stream (string name, string t, string scope); uvm_text_tr_stream stream; if (open_file()) begin $cast(stream,m_text_db.open_stream(name, scope, t)); return stream.get_handle(); end return 0; endfunction virtual function void m_set_attribute (int txh, string nm, string value); if (open_file()) begin UVM_FILE file = m_text_db.m_file; $fdisplay(file," SET_ATTR @%0t {TXH:%0d NAME:%s VALUE:%s}", $realtime,txh,nm,value); end endfunction virtual function void set_attribute (int txh, string nm, logic [1023:0] value, uvm_radix_enum radix, int numbits=1024); if (open_file()) begin UVM_FILE file = m_text_db.m_file; $fdisplay(file, " SET_ATTR @%0t {TXH:%0d NAME:%s VALUE:%s RADIX:%s BITS=%0d}", $realtime, txh, nm, uvm_bitstream_to_string(value, numbits, radix), radix.name(), numbits); end endfunction virtual function int check_handle_kind (string htype, int handle); return ((uvm_recorder::get_recorder_from_handle(handle) != null) || (uvm_tr_stream::get_stream_from_handle(handle) != null)); endfunction virtual function int begin_tr(string txtype, int stream, string nm, string label="", string desc="", time begin_time=0); if (open_file()) begin uvm_tr_stream stream_obj = uvm_tr_stream::get_stream_from_handle(stream); uvm_recorder recorder; if (stream_obj == null) return -1; recorder = stream_obj.open_recorder(nm, begin_time, txtype); return recorder.get_handle(); end return -1; endfunction virtual function void end_tr (int handle, time end_time=0); if (open_file()) begin uvm_recorder record = uvm_recorder::get_recorder_from_handle(handle); if (record != null) begin record.close(end_time); end end endfunction virtual function void link_tr(int h1, int h2, string relation=""); if (open_file()) $fdisplay(m_text_db.m_file," LINK @%0t {TXH1:%0d TXH2:%0d RELATION=%0s}", $realtime,h1,h2,relation); endfunction virtual function void free_tr(int handle); if (open_file()) begin uvm_recorder record = uvm_recorder::get_recorder_from_handle(handle); if (record != null) begin record.free(); end end endfunction endclass : uvm_text_recorder typedef class uvm_object; typedef class uvm_event; typedef class uvm_callback; typedef class uvm_callbacks; virtual class uvm_event_callback#(type T=uvm_object) extends uvm_callback; function new (string name=""); super.new(name); endfunction virtual function bit pre_trigger (uvm_event#(T) e, T data); return 0; endfunction virtual function void post_trigger (uvm_event#(T) e, T data); return; endfunction virtual function uvm_object create (string name=""); return null; endfunction endclass virtual class uvm_event_base extends uvm_object; typedef uvm_abstract_object_registry#(uvm_event_base,"uvm_event_base") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_event_base"; endfunction : type_name virtual function string get_type_name(); return "uvm_event_base"; endfunction : get_type_name protected event m_event; protected int num_waiters; protected bit on; protected time trigger_time=0; function new (string name=""); super.new(name); endfunction virtual task wait_on (bit delta = 0); if (on) begin if (delta) #0; return; end num_waiters++; @on; endtask virtual task wait_off (bit delta = 0); if (!on) begin if (delta) #0; return; end num_waiters++; @on; endtask virtual task wait_trigger (); num_waiters++; @m_event; endtask virtual task wait_ptrigger (); if (m_event.triggered) return; num_waiters++; @m_event; endtask virtual function time get_trigger_time (); return trigger_time; endfunction virtual function bit is_on (); return (on == 1); endfunction virtual function bit is_off (); return (on == 0); endfunction virtual function void reset (bit wakeup = 0); event e; if (wakeup) ->m_event; m_event = e; num_waiters = 0; on = 0; trigger_time = 0; endfunction virtual function void cancel (); if (num_waiters > 0) num_waiters--; endfunction virtual function int get_num_waiters (); return num_waiters; endfunction virtual function void do_print (uvm_printer printer); printer.print_field_int("num_waiters", num_waiters, $bits(num_waiters), UVM_DEC, ".", "int"); printer.print_field_int("on", on, $bits(on), UVM_BIN, ".", "bit"); printer.print_time("trigger_time", trigger_time); endfunction virtual function void do_copy (uvm_object rhs); uvm_event_base e; super.do_copy(rhs); if(!$cast(e, rhs) || (e==null)) return; m_event = e.m_event; num_waiters = e.num_waiters; on = e.on; trigger_time = e.trigger_time; endfunction endclass class uvm_event#(type T=uvm_object) extends uvm_event_base; typedef uvm_event#(T) this_type; typedef uvm_event_callback#(T) cb_type; typedef uvm_callbacks#(this_type, cb_type) cbs_type; static local function bit m_register_cb(); return uvm_callbacks#(this_type,cb_type)::m_register_pair( "uvm_pkg::uvm_event#(T)", "uvm_pkg::uvm_event_callback#(T)" ); endfunction : m_register_cb static local bit m_cb_registered = m_register_cb(); typedef uvm_object_registry #(this_type) type_id; static function this_type type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); this_type tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction virtual function string get_type_name(); return "uvm_pkg::uvm_event#(T)"; endfunction : get_type_name local T trigger_data; local T default_data; function new (string name=""); super.new(name); endfunction virtual task wait_trigger_data (output T data); wait_trigger(); data = get_trigger_data(); endtask virtual task wait_ptrigger_data (output T data); wait_ptrigger(); data = get_trigger_data(); endtask virtual function void trigger (T data=get_default_data()); int skip; cb_type cb_q[$]; skip=0; cbs_type::get_all(cb_q, this); foreach (cb_q[i]) skip += cb_q[i].pre_trigger(this, data); if (skip==0) begin ->m_event; foreach (cb_q[i]) cb_q[i].post_trigger(this, data); num_waiters = 0; on = 1; trigger_time = $realtime; trigger_data = data; end endfunction virtual function T get_trigger_data (); return trigger_data; endfunction virtual function T get_default_data(); return default_data; endfunction : get_default_data virtual function void set_default_data(T data); default_data = data; endfunction : set_default_data virtual function void do_print (uvm_printer printer); uvm_event#(uvm_object) oe; cb_type cb_q[$]; super.do_print(printer); cbs_type::get_all(cb_q, this); printer.print_array_header("callbacks", cb_q.size(), "queue"); foreach(cb_q[e]) printer.print_object($sformatf("[%0d]", e), cb_q[e], "["); printer.print_array_footer(cb_q.size()); if ($cast(oe, this)) begin printer.print_object("trigger_data", oe.get_trigger_data()); end else begin uvm_event#(string) se; if ($cast(se, this)) printer.print_string("trigger_data", se.get_trigger_data()); end endfunction virtual function void do_copy (uvm_object rhs); this_type e; cb_type cb_q[$]; super.do_copy(rhs); if(!$cast(e, rhs) || (e==null)) return; trigger_data = e.trigger_data; begin cbs_type::get_all(cb_q, this); foreach(cb_q[i]) cbs_type::delete(this, cb_q[i]); cb_q.delete(); cbs_type::get_all(cb_q, e); foreach(cb_q[i]) cbs_type::add(this, cb_q[i]); end endfunction endclass class uvm_barrier extends uvm_object; local int threshold; local int num_waiters; local bit at_threshold; local bit auto_reset; local uvm_event#(uvm_object) m_event; typedef uvm_object_registry#(uvm_barrier,"uvm_barrier") type_id; static function uvm_barrier type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_barrier tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_barrier"; endfunction : type_name virtual function string get_type_name(); return "uvm_barrier"; endfunction : get_type_name function new (string name="", int threshold=0); super.new(name); m_event = new({"barrier_",name}); this.threshold = threshold; num_waiters = 0; auto_reset = 1; at_threshold = 0; endfunction virtual task wait_for(); if (at_threshold) return; num_waiters++; if (num_waiters >= threshold) begin if (!auto_reset) at_threshold=1; m_trigger(); return; end m_event.wait_trigger(); endtask virtual function void reset (bit wakeup=1); at_threshold = 0; if (num_waiters) begin if (wakeup) m_event.trigger(); else m_event.reset(); end num_waiters = 0; endfunction virtual function void set_auto_reset (bit value=1); at_threshold = 0; auto_reset = value; endfunction virtual function void set_threshold (int threshold); this.threshold = threshold; if (threshold <= num_waiters) reset(1); endfunction virtual function int get_threshold (); return threshold; endfunction virtual function int get_num_waiters (); return num_waiters; endfunction virtual function void cancel (); m_event.cancel(); num_waiters = m_event.get_num_waiters(); endfunction local task m_trigger(); m_event.trigger(); num_waiters=0; #0; endtask virtual function void do_print (uvm_printer printer); printer.print_field_int("threshold", threshold, $bits(threshold), UVM_DEC, ".", "int"); printer.print_field_int("num_waiters", num_waiters, $bits(num_waiters), UVM_DEC, ".", "int"); printer.print_field_int("at_threshold", at_threshold, $bits(at_threshold), UVM_BIN, ".", "bit"); printer.print_field_int("auto_reset", auto_reset, $bits(auto_reset), UVM_BIN, ".", "bit"); endfunction virtual function void do_copy (uvm_object rhs); uvm_barrier b; super.do_copy(rhs); if(!$cast(b, rhs) || (b==null)) return; threshold = b.threshold; num_waiters = b.num_waiters; at_threshold = b.at_threshold; auto_reset = b.auto_reset; m_event = b.m_event; endfunction endclass typedef class uvm_root; typedef class uvm_callback; typedef class uvm_callbacks_base; class uvm_typeid_base; static string typename; static uvm_callbacks_base typeid_map[uvm_typeid_base]; static uvm_typeid_base type_map[uvm_callbacks_base]; endclass class uvm_typeid#(type T=uvm_object) extends uvm_typeid_base; static uvm_typeid#(T) m_b_inst; static function uvm_typeid#(T) get(); if(m_b_inst == null) m_b_inst = new; return m_b_inst; endfunction endclass class uvm_callbacks_base extends uvm_object; typedef uvm_callbacks_base this_type; static bit m_tracing = 1; static this_type m_b_inst; static uvm_pool#(uvm_object,uvm_queue#(uvm_callback)) m_pool; static function this_type m_initialize(); if(m_b_inst == null) begin m_b_inst = new; m_pool = new; end return m_b_inst; endfunction this_type m_this_type[$]; uvm_typeid_base m_super_type; uvm_typeid_base m_derived_types[$]; virtual function bit m_am_i_a(uvm_object obj); return 0; endfunction virtual function bit m_is_for_me(uvm_callback cb); return 0; endfunction virtual function bit m_is_registered(uvm_object obj, uvm_callback cb); return 0; endfunction virtual function uvm_queue#(uvm_callback) m_get_tw_cb_q(uvm_object obj); return null; endfunction virtual function void m_add_tw_cbs(uvm_callback cb, uvm_apprepend ordering); endfunction virtual function bit m_delete_tw_cbs(uvm_callback cb); return 0; endfunction function bit check_registration(uvm_object obj, uvm_callback cb); this_type dt; if (m_is_registered(obj,cb)) return 1; foreach(m_this_type[i]) if(m_b_inst != m_this_type[i] && m_this_type[i].m_is_registered(obj,cb)) return 1; if(obj == null) begin foreach(m_derived_types[i]) begin dt = uvm_typeid_base::typeid_map[m_derived_types[i] ]; if(dt != null && dt.check_registration(null,cb)) return 1; end end return 0; endfunction endclass class uvm_typed_callbacks#(type T=uvm_object) extends uvm_callbacks_base; static uvm_queue#(uvm_callback) m_tw_cb_q; static string m_typename; typedef uvm_typed_callbacks#(T) this_type; typedef uvm_callbacks_base super_type; static this_type m_t_inst; static function this_type m_initialize(); if(m_t_inst == null) begin void'(super_type::m_initialize()); m_t_inst = new; m_t_inst.m_tw_cb_q = new("typewide_queue"); end return m_t_inst; endfunction virtual function bit m_am_i_a(uvm_object obj); T casted_obj; if (obj == null) return 1; return($cast(casted_obj,obj)); endfunction virtual function uvm_queue#(uvm_callback) m_get_tw_cb_q(uvm_object obj); if(m_am_i_a(obj)) begin foreach(m_derived_types[i]) begin super_type dt; dt = uvm_typeid_base::typeid_map[m_derived_types[i] ]; if(dt != null && dt != this) begin m_get_tw_cb_q = dt.m_get_tw_cb_q(obj); if(m_get_tw_cb_q != null) return m_get_tw_cb_q; end end return m_t_inst.m_tw_cb_q; end else return null; endfunction static function int m_cb_find(uvm_queue#(uvm_callback) q, uvm_callback cb); for(int i=0; i str.len() ? max_cb_name : str.len(); str = "(*)"; max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len(); end if(obj ==null) begin if(m_t_inst.m_pool.first(bobj)) begin do if($cast(me,bobj)) break; while(m_t_inst.m_pool.next(bobj)); end if(me != null || m_t_inst.m_tw_cb_q.size()) begin qs.push_back($sformatf("Registered callbacks for all instances of %s\n", tname)); qs.push_back("---------------------------------------------------------------\n"); end if(me != null) begin do begin if($cast(me,bobj)) begin q = m_t_inst.m_pool.get(bobj); if (q==null) begin q=new; m_t_inst.m_pool.add(bobj,q); end for(int i=0; i str.len() ? max_cb_name : str.len(); str = bobj.get_full_name(); max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len(); end end end while (m_t_inst.m_pool.next(bobj)); end else begin qs.push_back($sformatf("No callbacks registered for any instances of type %s\n", tname)); end end else begin if(m_t_inst.m_pool.exists(bobj) || m_t_inst.m_tw_cb_q.size()) begin qs.push_back($sformatf("Registered callbacks for instance %s of %s\n", obj.get_full_name(), tname)); qs.push_back("---------------------------------------------------------------\n"); end if(m_t_inst.m_pool.exists(bobj)) begin q = m_t_inst.m_pool.get(bobj); if(q==null) begin q=new; m_t_inst.m_pool.add(bobj,q); end for(int i=0; i str.len() ? max_cb_name : str.len(); str = bobj.get_full_name(); max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len(); end end end if(!cbq.size()) begin if(obj == null) str = "*"; else str = obj.get_full_name(); qs.push_back($sformatf("No callbacks registered for instance %s of type %s\n", str, tname)); end foreach (cbq[i]) begin qs.push_back($sformatf("%s %s %s on %s %s\n", cbq[i], blanks.substr(0,max_cb_name-cbq[i].len()-1), inst_q[i], blanks.substr(0,max_inst_name - inst_q[i].len()-1), mode_q[i])); end begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/CB/DISPLAY")) uvm_report_info ("UVM/CB/DISPLAY", uvm_pkg::m_uvm_string_queue_join(qs), UVM_NONE, "t/uvm/src/base/uvm_callback.svh", 435, "", 1); end m_tracing = 1; endfunction endclass class uvm_callbacks #(type T=uvm_object, type CB=uvm_callback) extends uvm_typed_callbacks#(T); typedef uvm_typed_callbacks#(T) super_type; typedef uvm_callbacks#(T,CB) this_type; local static this_type m_inst; static uvm_typeid_base m_typeid; static uvm_typeid_base m_cb_typeid; static string m_typename; static string m_cb_typename; static uvm_callbacks#(T,uvm_callback) m_base_inst; bit m_registered; static function this_type get(); if (m_inst == null) begin uvm_typeid_base cb_base_type; void'(super_type::m_initialize()); cb_base_type = uvm_typeid#(uvm_callback)::get(); m_cb_typeid = uvm_typeid#(CB)::get(); m_typeid = uvm_typeid#(T)::get(); m_inst = new; if (cb_base_type == m_cb_typeid) begin $cast(m_base_inst, m_inst); m_t_inst = m_base_inst; uvm_typeid_base::typeid_map[m_typeid] = m_inst; uvm_typeid_base::type_map[m_b_inst] = m_typeid; end else begin m_base_inst = uvm_callbacks#(T,uvm_callback)::get(); m_base_inst.m_this_type.push_back(m_inst); end if (m_inst == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"CB/INTERNAL")) uvm_report_fatal ("CB/INTERNAL", "get(): m_inst is null", UVM_NONE, "t/uvm/src/base/uvm_callback.svh", 547, "", 1); end end return m_inst; endfunction static function bit m_register_pair(string tname="", cbname=""); this_type inst = get(); m_typename = tname; super_type::m_typename = tname; m_typeid.typename = tname; m_cb_typename = cbname; m_cb_typeid.typename = cbname; inst.m_registered = 1; return 1; endfunction virtual function bit m_is_registered(uvm_object obj, uvm_callback cb); if(m_is_for_me(cb) && m_am_i_a(obj)) begin return m_registered; end endfunction virtual function bit m_is_for_me(uvm_callback cb); CB this_cb; return($cast(this_cb,cb)); endfunction static function void add(T obj, uvm_callback cb, uvm_apprepend ordering=UVM_APPEND); uvm_queue#(uvm_callback) q; string nm,tnm; void'(get()); if (cb==null) begin if (obj==null) nm = "(*)"; else nm = obj.get_full_name(); if (m_base_inst.m_typename!="") tnm = m_base_inst.m_typename; else if (obj != null) tnm = obj.get_type_name(); else tnm = "uvm_object"; uvm_report_error("CBUNREG", {"Null callback object cannot be registered with object ", nm, " (", tnm, ")"}, UVM_NONE); return; end if (!m_base_inst.check_registration(obj,cb)) begin if (obj==null) nm = "(*)"; else nm = obj.get_full_name(); if (m_base_inst.m_typename!="") tnm = m_base_inst.m_typename; else if(obj != null) tnm = obj.get_type_name(); else tnm = "uvm_object"; uvm_report_warning("CBUNREG", {"Callback ", cb.get_name(), " cannot be registered with object ", nm, " because callback type ", cb.get_type_name(), " is not registered with object type ", tnm }, UVM_NONE); end if(obj == null) begin if (m_cb_find(m_t_inst.m_tw_cb_q,cb) != -1) begin if (m_base_inst.m_typename!="") tnm = m_base_inst.m_typename; else tnm = "uvm_object"; uvm_report_warning("CBPREG", {"Callback object ", cb.get_name(), " is already registered with type ", tnm }, UVM_NONE); end else begin m_t_inst.m_add_tw_cbs(cb,ordering); end end else begin q = m_base_inst.m_pool.get(obj); if (q==null) begin q=new; m_base_inst.m_pool.add(obj,q); end if(q.size() == 0) begin uvm_report_object o; if($cast(o,obj)) begin uvm_queue#(uvm_callback) qr; void'(uvm_callbacks#(uvm_report_object, uvm_callback)::get()); qr = uvm_callbacks#(uvm_report_object,uvm_callback)::m_t_inst.m_tw_cb_q; for(int i=0; i=0; --itr) if ($cast(cb, q.get(itr)) && cb.callback_mode()) return cb; return null; endfunction static function CB get_next (ref int itr, input T obj); uvm_queue#(uvm_callback) q; CB cb; void'(get()); m_get_q(q,obj); for(itr = itr+1; itr= 0; --itr) if($cast(cb, q.get(itr)) && cb.callback_mode()) return cb; return null; endfunction static function void get_all ( ref CB all_callbacks[$], input T obj=null ); uvm_queue#(uvm_callback) q; CB cb; CB callbacks_to_append[$]; CB unique_callbacks_to_append[$]; void'( get() ); if ((obj == null) || (!m_pool.exists(obj))) begin for (int qi=0; qi= m_max_quit_count); endfunction function int get_severity_count(uvm_severity severity); return m_severity_count[severity]; endfunction function void set_severity_count(uvm_severity severity, int count); m_severity_count[severity] = count < 0 ? 0 : count; endfunction function void incr_severity_count(uvm_severity severity); m_severity_count[severity]++; endfunction function void reset_severity_counts(); uvm_severity s; s = s.first(); forever begin m_severity_count[s] = 0; if(s == s.last()) break; s = s.next(); end endfunction function int get_id_count(string id); if(m_id_count.exists(id)) return m_id_count[id]; return 0; endfunction function void set_id_count(string id, int count); m_id_count[id] = count < 0 ? 0 : count; endfunction function void incr_id_count(string id); if(m_id_count.exists(id)) m_id_count[id]++; else m_id_count[id] = 1; endfunction virtual function void set_message_database(uvm_tr_database database); m_message_db = database; endfunction : set_message_database virtual function uvm_tr_database get_message_database(); return m_message_db; endfunction : get_message_database virtual function void get_severity_set(output uvm_severity q[$]); foreach(m_severity_count[idx]) q.push_back(idx); endfunction virtual function void get_id_set(output string q[$]); foreach(m_id_count[idx]) q.push_back(idx); endfunction function void f_display(UVM_FILE file, string str); if (file == 0) $display("%s", str); else $fdisplay(file, "%s", str); endfunction virtual function void process_report_message(uvm_report_message report_message); uvm_report_handler l_report_handler = report_message.get_report_handler(); process p = process::self(); bit report_ok = 1; report_message.set_report_server(this); if(report_ok) report_ok = uvm_report_catcher::process_all_report_catchers(report_message); if(uvm_action_type'(report_message.get_action()) == UVM_NO_ACTION) report_ok = 0; if(report_ok) begin string m; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_report_server svr = cs.get_report_server(); if (report_message.get_action() & (UVM_LOG|UVM_DISPLAY)) m = svr.compose_report_message(report_message); svr.execute_report_message(report_message, m); end endfunction virtual function void execute_report_message(uvm_report_message report_message, string composed_message); process p = process::self(); incr_severity_count(report_message.get_severity()); incr_id_count(report_message.get_id()); if (record_all_messages) report_message.set_action(report_message.get_action() | UVM_RM_RECORD); if(report_message.get_action() & UVM_RM_RECORD) begin uvm_tr_stream stream; uvm_report_object ro = report_message.get_report_object(); uvm_report_handler rh = report_message.get_report_handler(); if (m_streams.exists(ro.get_name()) && (m_streams[ro.get_name()].exists(rh.get_name()))) stream = m_streams[ro.get_name()][rh.get_name()]; if (stream == null) begin uvm_tr_database db; db = get_message_database(); if (db == null) begin uvm_coreservice_t cs = uvm_coreservice_t::get(); db = cs.get_default_tr_database(); end if (db != null) begin stream = db.open_stream(ro.get_name(), rh.get_name(), "MESSAGES"); m_streams[ro.get_name()][rh.get_name()] = stream; end end if (stream != null) begin uvm_recorder recorder = stream.open_recorder(report_message.get_name(),,report_message.get_type_name()); if (recorder != null) begin report_message.record(recorder); recorder.free(); end end end if(report_message.get_action() & UVM_DISPLAY) $display("%s", composed_message); if(report_message.get_action() & UVM_LOG) if( (report_message.get_file() == 0) || (report_message.get_file() != 32'h8000_0001) ) begin UVM_FILE tmp_file = report_message.get_file(); if((report_message.get_file() & 32'h8000_0000) == 0) begin tmp_file = report_message.get_file() & 32'hffff_fffe; end f_display(tmp_file, composed_message); end if(report_message.get_action() & UVM_COUNT) begin if(get_max_quit_count() != 0) begin incr_quit_count(); if(is_quit_count_reached()) begin report_message.set_action(report_message.get_action() | UVM_EXIT); end end end if(report_message.get_action() & UVM_EXIT) begin uvm_root l_root; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); l_root = cs.get_root(); l_root.die(); end if (report_message.get_action() & UVM_STOP) $stop; endfunction virtual function string compose_report_message(uvm_report_message report_message, string report_object_name = ""); string sev_string; uvm_severity l_severity; uvm_verbosity l_verbosity; string filename_line_string; string time_str; string line_str; string context_str; string verbosity_str; string terminator_str; string msg_body_str; uvm_report_message_element_container el_container; string prefix; uvm_report_handler l_report_handler; l_severity = report_message.get_severity(); sev_string = l_severity.name(); if (report_message.get_filename() != "") begin line_str.itoa(report_message.get_line()); filename_line_string = {report_message.get_filename(), "(", line_str, ") "}; end $swrite(time_str, "%0t", $time); if (report_message.get_context() != "") context_str = {"@@", report_message.get_context()}; if (show_verbosity) begin if ($cast(l_verbosity, report_message.get_verbosity())) verbosity_str = l_verbosity.name(); else verbosity_str.itoa(report_message.get_verbosity()); verbosity_str = {"(", verbosity_str, ")"}; end if (show_terminator) terminator_str = {" -",sev_string}; el_container = report_message.get_element_container(); if (el_container.size() == 0) msg_body_str = report_message.get_message(); else begin uvm_printer uvm_default_printer = uvm_printer::get_default() ; prefix = uvm_default_printer.get_line_prefix(); uvm_default_printer.set_line_prefix(" +"); msg_body_str = {report_message.get_message(), "\n", el_container.sprint()}; uvm_default_printer.set_line_prefix(prefix); end if (report_object_name == "") begin l_report_handler = report_message.get_report_handler(); report_object_name = l_report_handler.get_full_name(); end compose_report_message = {sev_string, verbosity_str, " ", filename_line_string, "@ ", time_str, ": ", report_object_name, context_str, " [", report_message.get_id(), "] ", msg_body_str, terminator_str}; endfunction virtual function void report_summarize(UVM_FILE file = UVM_STDOUT); string id; string name; string output_str; string q[$]; uvm_report_catcher::summarize(); q.push_back("\n--- UVM Report Summary ---\n\n"); if(m_max_quit_count != 0) begin if ( m_quit_count >= m_max_quit_count ) q.push_back("Quit count reached!\n"); q.push_back($sformatf("Quit count : %5d of %5d\n",m_quit_count, m_max_quit_count)); end q.push_back("** Report counts by severity\n"); foreach(m_severity_count[s]) begin q.push_back($sformatf("%s :%5d\n", s.name(), m_severity_count[s])); end if (enable_report_id_count_summary) begin q.push_back("** Report counts by id\n"); foreach(m_id_count[id]) q.push_back($sformatf("[%s] %5d\n", id, m_id_count[id])); end begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/REPORT/SERVER")) uvm_report_info ("UVM/REPORT/SERVER", uvm_pkg::m_uvm_string_queue_join(q), UVM_NONE, "t/uvm/src/base/uvm_report_server.svh", 864, "", 1); end endfunction endclass typedef class uvm_report_object; typedef class uvm_report_server; typedef uvm_pool#(string, uvm_action) uvm_id_actions_array; typedef uvm_pool#(string, UVM_FILE) uvm_id_file_array; typedef uvm_pool#(string, int) uvm_id_verbosities_array; typedef uvm_pool#(uvm_severity, uvm_severity) uvm_sev_override_array; class uvm_report_handler extends uvm_object; int m_max_verbosity_level; uvm_id_verbosities_array id_verbosities; uvm_id_verbosities_array severity_id_verbosities[uvm_severity]; uvm_id_actions_array id_actions; uvm_action severity_actions[uvm_severity]; uvm_id_actions_array severity_id_actions[uvm_severity]; uvm_sev_override_array sev_overrides; uvm_sev_override_array sev_id_overrides [string]; UVM_FILE default_file_handle; uvm_id_file_array id_file_handles; UVM_FILE severity_file_handles[uvm_severity]; uvm_id_file_array severity_id_file_handles[uvm_severity]; typedef uvm_object_registry#(uvm_report_handler,"uvm_report_handler") type_id; static function uvm_report_handler type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_report_handler tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_report_handler"; endfunction : type_name virtual function string get_type_name(); return "uvm_report_handler"; endfunction : get_type_name function new(string name = "uvm_report_handler"); super.new(name); initialize(); endfunction virtual function void do_print (uvm_printer printer); uvm_verbosity l_verbosity; uvm_severity l_severity; string idx; int l_int; if ($cast(l_verbosity, m_max_verbosity_level)) printer.print_generic("max_verbosity_level", "uvm_verbosity", 32, l_verbosity.name()); else printer.print_field("max_verbosity_level", m_max_verbosity_level, 32, UVM_DEC, ".", "int"); if(id_verbosities.first(idx)) begin printer.print_array_header("id_verbosities",id_verbosities.num(), "uvm_pool"); do begin l_int = id_verbosities.get(idx); if ($cast(l_verbosity, l_int)) printer.print_generic($sformatf("[%s]", idx), "uvm_verbosity", 32, l_verbosity.name()); else begin string l_str; l_str.itoa(l_int); printer.print_generic($sformatf("[%s]", idx), "int", 32, l_str); end end while(id_verbosities.next(idx)); printer.print_array_footer(); end if(severity_id_verbosities.size() != 0) begin int _total_cnt; foreach (severity_id_verbosities[l_severity]) _total_cnt += severity_id_verbosities[l_severity].num(); printer.print_array_header("severity_id_verbosities", _total_cnt, "array"); if(severity_id_verbosities.first(l_severity)) begin do begin uvm_id_verbosities_array id_v_ary = severity_id_verbosities[l_severity]; if(id_v_ary.first(idx)) do begin l_int = id_v_ary.get(idx); if ($cast(l_verbosity, l_int)) printer.print_generic($sformatf("[%s:%s]", l_severity.name(), idx), "uvm_verbosity", 32, l_verbosity.name()); else begin string l_str; l_str.itoa(l_int); printer.print_generic($sformatf("[%s:%s]", l_severity.name(), idx), "int", 32, l_str); end end while(id_v_ary.next(idx)); end while(severity_id_verbosities.next(l_severity)); end printer.print_array_footer(); end if(id_actions.first(idx)) begin printer.print_array_header("id_actions",id_actions.num(), "uvm_pool"); do begin l_int = id_actions.get(idx); printer.print_generic($sformatf("[%s]", idx), "uvm_action", 32, format_action(l_int)); end while(id_actions.next(idx)); printer.print_array_footer(); end if(severity_actions.first(l_severity)) begin printer.print_array_header("severity_actions",4,"array"); do begin printer.print_generic($sformatf("[%s]", l_severity.name()), "uvm_action", 32, format_action(severity_actions[l_severity])); end while(severity_actions.next(l_severity)); printer.print_array_footer(); end if(severity_id_actions.size() != 0) begin int _total_cnt; foreach (severity_id_actions[l_severity]) _total_cnt += severity_id_actions[l_severity].num(); printer.print_array_header("severity_id_actions", _total_cnt, "array"); if(severity_id_actions.first(l_severity)) begin do begin uvm_id_actions_array id_a_ary = severity_id_actions[l_severity]; if(id_a_ary.first(idx)) do begin printer.print_generic($sformatf("[%s:%s]", l_severity.name(), idx), "uvm_action", 32, format_action(id_a_ary.get(idx))); end while(id_a_ary.next(idx)); end while(severity_id_actions.next(l_severity)); end printer.print_array_footer(); end if(sev_overrides.first(l_severity)) begin printer.print_array_header("sev_overrides",sev_overrides.num(), "uvm_pool"); do begin uvm_severity l_severity_new = sev_overrides.get(l_severity); printer.print_generic($sformatf("[%s]", l_severity.name()), "uvm_severity", 32, l_severity_new.name()); end while(sev_overrides.next(l_severity)); printer.print_array_footer(); end if(sev_id_overrides.size() != 0) begin int _total_cnt; foreach (sev_id_overrides[idx]) _total_cnt += sev_id_overrides[idx].num(); printer.print_array_header("sev_id_overrides", _total_cnt, "array"); if(sev_id_overrides.first(idx)) begin do begin uvm_sev_override_array sev_o_ary = sev_id_overrides[idx]; if(sev_o_ary.first(l_severity)) do begin uvm_severity new_sev = sev_o_ary.get(l_severity); printer.print_generic($sformatf("[%s:%s]", l_severity.name(), idx), "uvm_severity", 32, new_sev.name()); end while(sev_o_ary.next(l_severity)); end while(sev_id_overrides.next(idx)); end printer.print_array_footer(); end printer.print_field("default_file_handle", default_file_handle, 32, UVM_HEX, ".", "int"); if(id_file_handles.first(idx)) begin printer.print_array_header("id_file_handles",id_file_handles.num(), "uvm_pool"); do begin printer.print_field($sformatf("[%s]", idx), id_file_handles.get(idx), 32, UVM_HEX, ".", "UVM_FILE"); end while(id_file_handles.next(idx)); printer.print_array_footer(); end if(severity_file_handles.first(l_severity)) begin printer.print_array_header("severity_file_handles",4,"array"); do begin printer.print_field($sformatf("[%s]", l_severity.name()), severity_file_handles[l_severity], 32, UVM_HEX, ".", "UVM_FILE"); end while(severity_file_handles.next(l_severity)); printer.print_array_footer(); end if(severity_id_file_handles.size() != 0) begin int _total_cnt; foreach (severity_id_file_handles[l_severity]) _total_cnt += severity_id_file_handles[l_severity].num(); printer.print_array_header("severity_id_file_handles", _total_cnt, "array"); if(severity_id_file_handles.first(l_severity)) begin do begin uvm_id_file_array id_f_ary = severity_id_file_handles[l_severity]; if(id_f_ary.first(idx)) do begin printer.print_field($sformatf("[%s:%s]", l_severity.name(), idx), id_f_ary.get(idx), 32, UVM_HEX, ".", "UVM_FILE"); end while(id_f_ary.next(idx)); end while(severity_id_file_handles.next(l_severity)); end printer.print_array_footer(); end endfunction virtual function void process_report_message(uvm_report_message report_message); process p = process::self(); uvm_report_server srvr = uvm_report_server::get_server(); string id = report_message.get_id(); uvm_severity severity = report_message.get_severity(); if(sev_id_overrides.exists(id)) begin if(sev_id_overrides[id].exists(uvm_severity'(severity))) begin severity = sev_id_overrides[id].get(severity); report_message.set_severity(severity); end end else begin if(sev_overrides.exists(severity)) begin severity = sev_overrides.get(severity); report_message.set_severity(severity); end end report_message.set_file(get_file_handle(severity, id)); report_message.set_report_handler(this); report_message.set_action(get_action(severity, id)); srvr.process_report_message(report_message); endfunction static function string format_action(uvm_action action); string s; if(uvm_action_type'(action) == UVM_NO_ACTION) begin s = "NO ACTION"; end else begin s = ""; if(action & UVM_DISPLAY) s = {s, "DISPLAY "}; if(action & UVM_LOG) s = {s, "LOG "}; if(action & UVM_RM_RECORD) s = {s, "RM_RECORD "}; if(action & UVM_COUNT) s = {s, "COUNT "}; if(action & UVM_CALL_HOOK) s = {s, "CALL_HOOK "}; if(action & UVM_EXIT) s = {s, "EXIT "}; if(action & UVM_STOP) s = {s, "STOP "}; end return s; endfunction function void initialize(); set_default_file(0); m_max_verbosity_level = UVM_MEDIUM; id_actions=new(); id_verbosities=new(); id_file_handles=new(); sev_overrides=new(); set_severity_action(UVM_INFO, UVM_DISPLAY); set_severity_action(UVM_WARNING, UVM_DISPLAY); set_severity_action(UVM_ERROR, UVM_DISPLAY | UVM_COUNT); set_severity_action(UVM_FATAL, UVM_DISPLAY | UVM_EXIT); set_severity_file(UVM_INFO, default_file_handle); set_severity_file(UVM_WARNING, default_file_handle); set_severity_file(UVM_ERROR, default_file_handle); set_severity_file(UVM_FATAL, default_file_handle); endfunction local function UVM_FILE get_severity_id_file(uvm_severity severity, string id); uvm_id_file_array array; if(severity_id_file_handles.exists(severity)) begin array = severity_id_file_handles[severity]; if(array.exists(id)) return array.get(id); end if(id_file_handles.exists(id)) return id_file_handles.get(id); if(severity_file_handles.exists(severity)) return severity_file_handles[severity]; return default_file_handle; endfunction function void set_verbosity_level(int verbosity_level); m_max_verbosity_level = verbosity_level; endfunction function int get_verbosity_level(uvm_severity severity=UVM_INFO, string id="" ); uvm_id_verbosities_array array; if(severity_id_verbosities.exists(severity)) begin array = severity_id_verbosities[severity]; if(array.exists(id)) begin return array.get(id); end end if(id_verbosities.exists(id)) begin return id_verbosities.get(id); end return m_max_verbosity_level; endfunction function uvm_action get_action(uvm_severity severity, string id); uvm_id_actions_array array; if(severity_id_actions.exists(severity)) begin array = severity_id_actions[severity]; if(array.exists(id)) return array.get(id); end if(id_actions.exists(id)) return id_actions.get(id); return severity_actions[severity]; endfunction function UVM_FILE get_file_handle(uvm_severity severity, string id); UVM_FILE file; file = get_severity_id_file(severity, id); if (file != 0) return file; if (id_file_handles.exists(id)) begin file = id_file_handles.get(id); if (file != 0) return file; end if (severity_file_handles.exists(severity)) begin file = severity_file_handles[severity]; if(file != 0) return file; end return default_file_handle; endfunction function void set_severity_action(input uvm_severity severity, input uvm_action action); severity_actions[severity] = action; endfunction function void set_id_action(input string id, input uvm_action action); id_actions.add(id, action); endfunction function void set_severity_id_action(uvm_severity severity, string id, uvm_action action); if(!severity_id_actions.exists(severity)) severity_id_actions[severity] = new; severity_id_actions[severity].add(id,action); endfunction function void set_id_verbosity(input string id, input int verbosity); id_verbosities.add(id, verbosity); endfunction function void set_severity_id_verbosity(uvm_severity severity, string id, int verbosity); if(!severity_id_verbosities.exists(severity)) severity_id_verbosities[severity] = new; severity_id_verbosities[severity].add(id,verbosity); endfunction function void set_default_file (UVM_FILE file); default_file_handle = file; endfunction function void set_severity_file (uvm_severity severity, UVM_FILE file); severity_file_handles[severity] = file; endfunction function void set_id_file (string id, UVM_FILE file); id_file_handles.add(id, file); endfunction function void set_severity_id_file(uvm_severity severity, string id, UVM_FILE file); if(!severity_id_file_handles.exists(severity)) severity_id_file_handles[severity] = new; severity_id_file_handles[severity].add(id, file); endfunction function void set_severity_override(uvm_severity cur_severity, uvm_severity new_severity); sev_overrides.add(cur_severity, new_severity); endfunction function void set_severity_id_override(uvm_severity cur_severity, string id, uvm_severity new_severity); uvm_sev_override_array arr; if(!sev_id_overrides.exists(id)) sev_id_overrides[id] = new; sev_id_overrides[id].add(cur_severity, new_severity); endfunction virtual function void report( uvm_severity severity, string name, string id, string message, int verbosity_level=UVM_MEDIUM, string filename="", int line=0, uvm_report_object client=null ); bit l_report_enabled = 0; uvm_report_message l_report_message; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); if (!uvm_report_enabled(verbosity_level, UVM_INFO, id)) return; if (client==null) client = cs.get_root(); l_report_message = uvm_report_message::new_report_message(); l_report_message.set_report_message(severity, id, message, verbosity_level, filename, line, name); l_report_message.set_report_object(client); l_report_message.set_action(get_action(severity,id)); process_report_message(l_report_message); endfunction endclass : uvm_report_handler typedef class uvm_component; typedef class uvm_env; typedef class uvm_root; class uvm_report_object extends uvm_object; uvm_report_handler m_rh; local bit m_rh_set; local function void m_rh_init(); if (!m_rh_set) set_report_handler(uvm_report_handler::type_id_create(get_name())); endfunction : m_rh_init function new(string name = ""); super.new(name); endfunction function uvm_report_object uvm_get_report_object(); return this; endfunction function int uvm_report_enabled(int verbosity, uvm_severity severity = UVM_INFO, string id = ""); if (get_report_verbosity_level(severity, id) < verbosity) return 0; return 1; endfunction virtual function void uvm_report( uvm_severity severity, string id, string message, int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW : (severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked =0); uvm_report_message l_report_message; if ((severity == UVM_INFO) && (report_enabled_checked == 0)) begin if (!uvm_report_enabled(verbosity, severity, id)) return; end l_report_message = uvm_report_message::new_report_message(); l_report_message.set_report_message(severity, id, message, verbosity, filename, line, context_name); uvm_process_report_message(l_report_message); endfunction virtual function void uvm_report_info( string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_report (UVM_INFO, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_warning( string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_report (UVM_WARNING, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_error( string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_report (UVM_ERROR, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_fatal( string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_report (UVM_FATAL, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_process_report_message(uvm_report_message report_message); m_rh_init(); report_message.set_report_object(this); m_rh.process_report_message(report_message); endfunction function int get_report_verbosity_level(uvm_severity severity=UVM_INFO, string id=""); m_rh_init(); return m_rh.get_verbosity_level(severity, id); endfunction function int get_report_max_verbosity_level(); m_rh_init(); return m_rh.m_max_verbosity_level; endfunction function void set_report_verbosity_level (int verbosity_level); m_rh_init(); m_rh.set_verbosity_level(verbosity_level); endfunction function void set_report_id_verbosity (string id, int verbosity); m_rh_init(); m_rh.set_id_verbosity(id, verbosity); endfunction function void set_report_severity_id_verbosity (uvm_severity severity, string id, int verbosity); m_rh_init(); m_rh.set_severity_id_verbosity(severity, id, verbosity); endfunction function int get_report_action(uvm_severity severity, string id); m_rh_init(); return m_rh.get_action(severity,id); endfunction function void set_report_severity_action (uvm_severity severity, uvm_action action); m_rh_init(); m_rh.set_severity_action(severity, action); endfunction function void set_report_id_action (string id, uvm_action action); m_rh_init(); m_rh.set_id_action(id, action); endfunction function void set_report_severity_id_action (uvm_severity severity, string id, uvm_action action); m_rh_init(); m_rh.set_severity_id_action(severity, id, action); endfunction function int get_report_file_handle(uvm_severity severity, string id); m_rh_init(); return m_rh.get_file_handle(severity,id); endfunction function void set_report_default_file (UVM_FILE file); m_rh_init(); m_rh.set_default_file(file); endfunction function void set_report_id_file (string id, UVM_FILE file); m_rh_init(); m_rh.set_id_file(id, file); endfunction function void set_report_severity_file (uvm_severity severity, UVM_FILE file); m_rh_init(); m_rh.set_severity_file(severity, file); endfunction function void set_report_severity_id_file (uvm_severity severity, string id, UVM_FILE file); m_rh_init(); m_rh.set_severity_id_file(severity, id, file); endfunction function void set_report_severity_override(uvm_severity cur_severity, uvm_severity new_severity); m_rh_init(); m_rh.set_severity_override(cur_severity, new_severity); endfunction function void set_report_severity_id_override(uvm_severity cur_severity, string id, uvm_severity new_severity); m_rh_init(); m_rh.set_severity_id_override(cur_severity, id, new_severity); endfunction function void set_report_handler(uvm_report_handler handler); m_rh = handler; m_rh_set = 1; endfunction function uvm_report_handler get_report_handler(); m_rh_init(); return m_rh; endfunction function void reset_report_handler; m_rh_init(); m_rh.initialize(); endfunction endclass typedef class uvm_event; typedef class uvm_event_pool; typedef class uvm_component; typedef class uvm_parent_child_link; virtual class uvm_transaction extends uvm_object; extern function new (string name="", uvm_component initiator=null); extern function void accept_tr (time accept_time = 0); extern virtual protected function void do_accept_tr (); extern function int begin_tr (time begin_time = 0); extern function int begin_child_tr (time begin_time = 0, int parent_handle = 0); extern virtual protected function void do_begin_tr (); extern function void end_tr (time end_time=0, bit free_handle=1); extern virtual protected function void do_end_tr (); extern function int get_tr_handle (); extern function void disable_recording (); extern function void enable_recording (uvm_tr_stream stream); extern function bit is_recording_enabled(); extern function bit is_active (); extern function uvm_event_pool get_event_pool (); extern function void set_initiator (uvm_component initiator); extern function uvm_component get_initiator (); extern function time get_accept_time (); extern function time get_begin_time (); extern function time get_end_time (); extern function void set_transaction_id(int id); extern function int get_transaction_id(); const local uvm_event_pool events = new("events"); extern virtual function void do_print (uvm_printer printer); extern virtual function void do_record (uvm_recorder recorder); extern virtual function void do_copy (uvm_object rhs); extern protected function int m_begin_tr (time begin_time=0, int parent_handle=0); local int m_transaction_id = -1; local time begin_time=-1; local time end_time=-1; local time accept_time=-1; local uvm_component initiator; local uvm_tr_stream stream_handle; local uvm_recorder tr_recorder; endclass function uvm_transaction::new (string name="", uvm_component initiator = null); super.new(name); this.initiator = initiator; m_transaction_id = -1; endfunction function void uvm_transaction::set_transaction_id(int id); m_transaction_id = id; endfunction function int uvm_transaction::get_transaction_id(); return (m_transaction_id); endfunction function void uvm_transaction::set_initiator(uvm_component initiator); this.initiator = initiator; endfunction function uvm_component uvm_transaction::get_initiator(); return initiator; endfunction function uvm_event_pool uvm_transaction::get_event_pool(); return events; endfunction function bit uvm_transaction::is_active(); return (end_time == -1); endfunction function time uvm_transaction::get_begin_time (); return begin_time; endfunction function time uvm_transaction::get_end_time (); return end_time; endfunction function time uvm_transaction::get_accept_time (); return accept_time; endfunction function void uvm_transaction::do_accept_tr(); return; endfunction function void uvm_transaction::do_begin_tr(); return; endfunction function void uvm_transaction::do_end_tr(); return; endfunction function void uvm_transaction::do_print (uvm_printer printer); string str; uvm_component tmp_initiator; super.do_print(printer); if(accept_time != -1) printer.print_time("accept_time", accept_time); if(begin_time != -1) printer.print_time("begin_time", begin_time); if(end_time != -1) printer.print_time("end_time", end_time); if(initiator != null) begin tmp_initiator = initiator; $swrite(str,"@%0d", tmp_initiator.get_inst_id()); printer.print_generic("initiator", initiator.get_type_name(), -1, str); end endfunction function void uvm_transaction::do_copy (uvm_object rhs); uvm_transaction txn; super.do_copy(rhs); if(rhs == null) return; if(!$cast(txn, rhs) ) return; accept_time = txn.accept_time; begin_time = txn.begin_time; end_time = txn.end_time; initiator = txn.initiator; stream_handle = txn.stream_handle; tr_recorder = txn.tr_recorder; endfunction function void uvm_transaction::do_record (uvm_recorder recorder); string s; super.do_record(recorder); if(accept_time != -1) recorder.record_field("accept_time", accept_time, $bits(accept_time), UVM_TIME); if(initiator != null) begin uvm_recursion_policy_enum p = recorder.get_recursion_policy(); recorder.set_recursion_policy(UVM_REFERENCE); recorder.record_object("initiator", initiator); recorder.set_recursion_policy(p); end endfunction function int uvm_transaction::get_tr_handle (); if (tr_recorder != null) return tr_recorder.get_handle(); else return 0; endfunction function void uvm_transaction::disable_recording (); this.stream_handle = null; endfunction function void uvm_transaction::enable_recording (uvm_tr_stream stream); this.stream_handle = stream; endfunction : enable_recording function bit uvm_transaction::is_recording_enabled (); return (this.stream_handle != null); endfunction function void uvm_transaction::accept_tr (time accept_time = 0); uvm_event#(uvm_object) e; if(accept_time != 0) this.accept_time = accept_time; else this.accept_time = $realtime; do_accept_tr(); e = events.get("accept"); if(e!=null) e.trigger(); endfunction function int uvm_transaction::begin_tr (time begin_time=0); return m_begin_tr(begin_time); endfunction function int uvm_transaction::begin_child_tr (time begin_time=0, int parent_handle=0); return m_begin_tr(begin_time, parent_handle); endfunction function int uvm_transaction::m_begin_tr (time begin_time=0, int parent_handle=0); time tmp_time = (begin_time == 0) ? $realtime : begin_time; uvm_recorder parent_recorder; if (parent_handle != 0) parent_recorder = uvm_recorder::get_recorder_from_handle(parent_handle); if (tr_recorder != null) end_tr(tmp_time); if(is_recording_enabled()) begin uvm_tr_database db = stream_handle.get_db(); this.end_time = -1; this.begin_time = tmp_time; if(parent_recorder == null) tr_recorder = stream_handle.open_recorder(get_type_name(), this.begin_time, "Begin_No_Parent, Link"); else begin tr_recorder = stream_handle.open_recorder(get_type_name(), this.begin_time, "Begin_End, Link"); if (tr_recorder != null) db.establish_link(uvm_parent_child_link::get_link(parent_recorder, tr_recorder)); end if (tr_recorder != null) m_begin_tr = tr_recorder.get_handle(); else m_begin_tr = 0; end else begin tr_recorder = null; this.end_time = -1; this.begin_time = tmp_time; m_begin_tr = 0; end do_begin_tr(); begin uvm_event#(uvm_object) begin_event ; begin_event = events.get("begin"); begin_event.trigger(); end endfunction function void uvm_transaction::end_tr (time end_time=0, bit free_handle=1); this.end_time = (end_time == 0) ? $realtime : end_time; do_end_tr(); if(is_recording_enabled() && (tr_recorder != null)) begin record(tr_recorder); tr_recorder.close(this.end_time); if(free_handle) begin tr_recorder.free(); end end tr_recorder = null; begin uvm_event#(uvm_object) end_event ; end_event = events.get("end") ; end_event.trigger(); end endfunction typedef class uvm_sequencer_base; typedef class uvm_domain; typedef class uvm_task_phase; typedef class uvm_phase_cb; class uvm_phase extends uvm_object; static local bit m_register_cb_uvm_phase_cb = uvm_callbacks#(uvm_phase,uvm_phase_cb)::m_register_pair("uvm_phase","uvm_phase_cb"); extern function new(string name="uvm_phase", uvm_phase_type phase_type=UVM_PHASE_SCHEDULE, uvm_phase parent=null); extern function uvm_phase_type get_phase_type(); extern virtual function void set_max_ready_to_end_iterations(int max); extern virtual function int get_max_ready_to_end_iterations(); extern static function void set_default_max_ready_to_end_iterations(int max); extern static function int get_default_max_ready_to_end_iterations(); extern function uvm_phase_state get_state(); extern function int get_run_count(); extern function uvm_phase find_by_name(string name, bit stay_in_scope=1); extern function uvm_phase find(uvm_phase phase, bit stay_in_scope=1); extern function bit is(uvm_phase phase); extern function bit is_before(uvm_phase phase); extern function bit is_after(uvm_phase phase); virtual function void exec_func(uvm_component comp, uvm_phase phase); endfunction virtual task exec_task(uvm_component comp, uvm_phase phase); endtask extern function void add(uvm_phase phase, uvm_phase with_phase=null, uvm_phase after_phase=null, uvm_phase before_phase=null, uvm_phase start_with_phase=null, uvm_phase end_with_phase=null ); extern function uvm_phase get_parent(); extern virtual function string get_full_name(); extern function uvm_phase get_schedule(bit hier = 0); extern function string get_schedule_name(bit hier = 0); extern function uvm_domain get_domain(); extern function uvm_phase get_imp(); extern function string get_domain_name(); extern function void get_adjacent_predecessor_nodes(ref uvm_phase pred[]); extern function void get_adjacent_successor_nodes(ref uvm_phase succ[]); extern function void m_report_null_objection(uvm_object obj, string description, int count, string action); extern virtual function void raise_objection (uvm_object obj, string description="", int count=1); extern virtual function void drop_objection (uvm_object obj, string description="", int count=1); extern virtual function int get_objection_count( uvm_object obj=null ); extern function void sync(uvm_domain target, uvm_phase phase=null, uvm_phase with_phase=null); extern function void unsync(uvm_domain target, uvm_phase phase=null, uvm_phase with_phase=null); extern task wait_for_state(uvm_phase_state state, uvm_wait_op op=UVM_EQ); extern function void jump(uvm_phase phase); extern function void set_jump_phase(uvm_phase phase) ; extern function void end_prematurely() ; extern static function void jump_all(uvm_phase phase); extern function uvm_phase get_jump_target(); protected uvm_phase_type m_phase_type; protected uvm_phase m_parent; uvm_phase m_imp; local uvm_phase_state m_state; local int m_run_count; local process m_phase_proc; local static int m_default_max_ready_to_end_iters = 20; local int max_ready_to_end_iters = get_default_max_ready_to_end_iterations(); int m_num_procs_not_yet_returned; extern function uvm_phase m_find_predecessor(uvm_phase phase, bit stay_in_scope=1, uvm_phase orig_phase=null); extern function uvm_phase m_find_successor(uvm_phase phase, bit stay_in_scope=1, uvm_phase orig_phase=null); extern function uvm_phase m_find_predecessor_by_name(string name, bit stay_in_scope=1, uvm_phase orig_phase=null); extern function uvm_phase m_find_successor_by_name(string name, bit stay_in_scope=1, uvm_phase orig_phase=null); extern function void m_print_successors(); virtual function void traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state); endfunction virtual function void execute(uvm_component comp, uvm_phase phase); endfunction protected bit m_predecessors[uvm_phase]; protected bit m_successors[uvm_phase]; protected uvm_phase m_end_node; static protected bit m_executing_phases[uvm_phase]; function uvm_phase get_begin_node(); if (m_imp != null) return this; return null; endfunction function uvm_phase get_end_node(); return m_end_node; endfunction local uvm_phase m_sync[$]; local uvm_objection phase_done; local int unsigned m_ready_to_end_count; function int unsigned get_ready_to_end_count(); return m_ready_to_end_count; endfunction extern local function void get_predecessors_for_successors(output bit pred_of_succ[uvm_phase]); extern local task m_wait_for_pred(); local bit m_jump_bkwd; local bit m_jump_fwd; local uvm_phase m_jump_phase; local bit m_premature_end; extern function void clear(uvm_phase_state state = UVM_PHASE_DORMANT); extern function void clear_successors( uvm_phase_state state = UVM_PHASE_DORMANT, uvm_phase end_state=null); local static mailbox #(uvm_phase) m_phase_hopper = new(); extern static task m_run_phases(); extern local task execute_phase(); extern local function void m_terminate_phase(); extern local function void m_print_termination_state(); extern local task wait_for_self_and_siblings_to_drop(); extern function void kill(); extern function void kill_successors(); protected static bit m_phase_trace; local static bit m_use_ovm_run_semantic; function string convert2string(); string s; s = $sformatf("phase: %s parent=%s pred=%s succ=%s",get_name(), (m_parent==null) ? "null" : get_schedule_name(), m_aa2string(m_predecessors), m_aa2string(m_successors)); return s; endfunction local function string m_aa2string(bit aa[uvm_phase]); string s; int i; s = "'{ "; foreach (aa[ph]) begin uvm_phase n = ph; s = {s, (n == null) ? "null" : n.get_name(), (i == aa.num()-1) ? "" : ", "}; i++; end s = {s, " }"}; return s; endfunction function bit is_domain(); return (m_phase_type == UVM_PHASE_DOMAIN); endfunction virtual function void m_get_transitive_children(ref uvm_phase phases[$]); foreach (m_successors[succ]) begin phases.push_back(succ); succ.m_get_transitive_children(phases); end endfunction function uvm_objection get_objection(); uvm_phase imp; uvm_task_phase tp; imp = get_imp(); if ((get_phase_type() != UVM_PHASE_NODE) || (imp == null) || !$cast(tp, imp)) begin return null; end if (phase_done == null) begin phase_done = uvm_objection::type_id_create({get_name(), "_objection"}); end return phase_done; endfunction endclass class uvm_phase_state_change extends uvm_object; typedef uvm_object_registry#(uvm_phase_state_change,"uvm_phase_state_change") type_id; static function uvm_phase_state_change type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_phase_state_change tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_phase_state_change"; endfunction : type_name virtual function string get_type_name(); return "uvm_phase_state_change"; endfunction : get_type_name uvm_phase m_phase; uvm_phase_state m_prev_state; uvm_phase m_jump_to; function new(string name = "uvm_phase_state_change"); super.new(name); endfunction virtual function uvm_phase_state get_state(); return m_phase.get_state(); endfunction virtual function uvm_phase_state get_prev_state(); return m_prev_state; endfunction function uvm_phase jump_to(); return m_jump_to; endfunction endclass class uvm_phase_cb extends uvm_callback; function new(string name="unnamed-uvm_phase_cb"); super.new(name); endfunction : new virtual function void phase_state_change(uvm_phase phase, uvm_phase_state_change change); endfunction endclass typedef uvm_callbacks#(uvm_phase, uvm_phase_cb) uvm_phase_cb_pool ; typedef class uvm_cmdline_processor; function uvm_phase::new(string name="uvm_phase", uvm_phase_type phase_type=UVM_PHASE_SCHEDULE, uvm_phase parent=null); super.new(name); m_phase_type = phase_type; if ((name == "common") && (phase_type == UVM_PHASE_DOMAIN)) m_state = UVM_PHASE_DORMANT; m_run_count = 0; m_parent = parent; begin uvm_cmdline_processor clp = uvm_cmdline_processor::get_inst(); string val; if (clp.get_arg_value("+UVM_PHASE_TRACE", val)) m_phase_trace = 1; else m_phase_trace = 0; if (clp.get_arg_value("+UVM_USE_OVM_RUN_SEMANTIC", val)) m_use_ovm_run_semantic = 1; else m_use_ovm_run_semantic = 0; end if (parent == null && (phase_type == UVM_PHASE_SCHEDULE || phase_type == UVM_PHASE_DOMAIN )) begin m_end_node = new({name,"_end"}, UVM_PHASE_TERMINAL, this); this.m_successors[m_end_node] = 1; m_end_node.m_predecessors[this] = 1; end endfunction function void uvm_phase::add(uvm_phase phase, uvm_phase with_phase=null, uvm_phase after_phase=null, uvm_phase before_phase=null, uvm_phase start_with_phase=null, uvm_phase end_with_phase=null ); uvm_phase new_node, begin_node, end_node, tmp_node; uvm_phase_state_change state_chg; if (phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH/NULL")) uvm_report_fatal ("PH/NULL", "add: phase argument is null", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 762, "", 1); end if (with_phase != null && with_phase.get_phase_type() == UVM_PHASE_IMP) begin string nm = with_phase.get_name(); with_phase = find(with_phase); if (with_phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"cannot find with_phase '",nm,"' within node '",get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 769, "", 1); end end if (before_phase != null && before_phase.get_phase_type() == UVM_PHASE_IMP) begin string nm = before_phase.get_name(); before_phase = find(before_phase); if (before_phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"cannot find before_phase '",nm,"' within node '",get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 777, "", 1); end end if (after_phase != null && after_phase.get_phase_type() == UVM_PHASE_IMP) begin string nm = after_phase.get_name(); after_phase = find(after_phase); if (after_phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"cannot find after_phase '",nm,"' within node '",get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 785, "", 1); end end if (start_with_phase != null && start_with_phase.get_phase_type() == UVM_PHASE_IMP) begin string nm = start_with_phase.get_name(); start_with_phase = find(start_with_phase); if (start_with_phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"cannot find start_with_phase '",nm,"' within node '",get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 793, "", 1); end end if (end_with_phase != null && end_with_phase.get_phase_type() == UVM_PHASE_IMP) begin string nm = end_with_phase.get_name(); end_with_phase = find(end_with_phase); if (end_with_phase == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"cannot find end_with_phase '",nm,"' within node '",get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 801, "", 1); end end if (((with_phase != null) + (after_phase != null) + (start_with_phase != null)) > 1) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", "only one of with_phase/after_phase/start_with_phase may be specified as they all specify predecessor", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 806, "", 1); end if (((with_phase != null) + (before_phase != null) + (end_with_phase != null)) > 1) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", "only one of with_phase/before_phase/end_with_phase may be specified as they all specify successor", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 810, "", 1); end if (before_phase == this || after_phase == m_end_node || with_phase == m_end_node || start_with_phase == m_end_node || end_with_phase == m_end_node) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", "cannot add before begin node, after end node, or with end nodes", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 818, "", 1); end if (before_phase != null && after_phase != null) begin if (!after_phase.is_before(before_phase)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"Phase '",before_phase.get_name(), "' is not before phase '",after_phase.get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 823, "", 1); end end end if (before_phase != null && start_with_phase != null) begin if (!start_with_phase.is_before(before_phase)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"Phase '",before_phase.get_name(), "' is not before phase '",start_with_phase.get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 830, "", 1); end end end if (end_with_phase != null && after_phase != null) begin if (!after_phase.is_before(end_with_phase)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BAD_ADD")) uvm_report_fatal ("PH_BAD_ADD", {"Phase '",end_with_phase.get_name(), "' is not before phase '",after_phase.get_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 837, "", 1); end end end if (phase.get_phase_type() == UVM_PHASE_IMP) begin uvm_task_phase tp; new_node = new(phase.get_name(),UVM_PHASE_NODE,this); new_node.m_imp = phase; begin_node = new_node; end_node = new_node; end else begin begin_node = phase; end_node = phase.m_end_node; phase.m_parent = this; end if (with_phase==null && after_phase==null && before_phase==null && start_with_phase==null && end_with_phase==null) begin before_phase = m_end_node; end if (m_phase_trace) begin uvm_phase_type typ = phase.get_phase_type(); begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH/TRC/ADD_PH")) uvm_report_info ("PH/TRC/ADD_PH", {get_name()," (",m_phase_type.name(),") ADD_PHASE: phase=",phase.get_full_name()," (", typ.name(),", inst_id=",$sformatf("%0d",phase.get_inst_id()),")", " with_phase=", (with_phase == null) ? "null" : with_phase.get_name(), " start_with_phase=", (start_with_phase == null) ? "null" : start_with_phase.get_name(), " end_with_phase=", (end_with_phase == null) ? "null" : end_with_phase.get_name(), " after_phase=", (after_phase == null) ? "null" : after_phase.get_name(), " before_phase=", (before_phase == null) ? "null" : before_phase.get_name(), " new_node=", (new_node == null) ? "null" : {new_node.get_name(), " inst_id=", $sformatf("%0d",new_node.get_inst_id())}, " begin_node=", (begin_node == null) ? "null" : begin_node.get_name(), " end_node=", (end_node == null) ? "null" : end_node.get_name()}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 886, "", 1); end end if (with_phase != null) begin begin_node.m_predecessors = with_phase.m_predecessors; foreach (with_phase.m_predecessors[pred]) pred.m_successors[begin_node] = 1; end_node.m_successors = with_phase.m_successors; foreach (with_phase.m_successors[succ]) succ.m_predecessors[end_node] = 1; end if (start_with_phase != null) begin begin_node.m_predecessors = start_with_phase.m_predecessors; foreach (start_with_phase.m_predecessors[pred]) begin pred.m_successors[begin_node] = 1; end if (before_phase == null && end_with_phase == null) begin end_node.m_successors = m_end_node.m_successors ; foreach (m_end_node.m_successors[succ]) begin succ.m_predecessors[end_node] = 1; end end end if (end_with_phase != null) begin end_node.m_successors = end_with_phase.m_successors; foreach (end_with_phase.m_successors[succ]) begin succ.m_predecessors[end_node] = 1; end if (after_phase == null && start_with_phase == null) begin begin_node.m_predecessors = this.m_predecessors ; foreach (this.m_predecessors[pred]) begin pred.m_successors[begin_node] = 1; end end end if (before_phase != null) begin if (after_phase == null && start_with_phase == null) begin foreach (before_phase.m_predecessors[pred]) begin pred.m_successors.delete(before_phase); pred.m_successors[begin_node] = 1; end begin_node.m_predecessors = before_phase.m_predecessors; before_phase.m_predecessors.delete(); end else if (before_phase.m_predecessors.exists(after_phase)) begin before_phase.m_predecessors.delete(after_phase); end before_phase.m_predecessors[end_node] = 1; end_node.m_successors.delete() ; end_node.m_successors[before_phase] = 1; end if (after_phase != null) begin if (before_phase == null && end_with_phase == null) begin foreach (after_phase.m_successors[succ]) begin succ.m_predecessors.delete(after_phase); succ.m_predecessors[end_node] = 1; end end_node.m_successors = after_phase.m_successors; after_phase.m_successors.delete(); end else if (after_phase.m_successors.exists(before_phase)) begin after_phase.m_successors.delete(before_phase); end after_phase.m_successors[begin_node] = 1; begin_node.m_predecessors.delete(); begin_node.m_predecessors[after_phase] = 1; end if (new_node == null) tmp_node = phase; else tmp_node = new_node; state_chg = uvm_phase_state_change::type_id_create(tmp_node.get_name()); state_chg.m_phase = tmp_node; state_chg.m_jump_to = null; state_chg.m_prev_state = tmp_node.m_state; tmp_node.m_state = UVM_PHASE_DORMANT; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(tmp_node, state_chg); cb = iter.next(); end end endfunction function uvm_phase uvm_phase::get_parent(); return m_parent; endfunction function uvm_phase uvm_phase::get_imp(); return m_imp; endfunction function uvm_phase uvm_phase::get_schedule(bit hier=0); uvm_phase sched; sched = this; if (hier) while (sched.m_parent != null && (sched.m_parent.get_phase_type() == UVM_PHASE_SCHEDULE)) sched = sched.m_parent; if (sched.m_phase_type == UVM_PHASE_SCHEDULE) return sched; if (sched.m_phase_type == UVM_PHASE_NODE) if (m_parent != null && m_parent.m_phase_type != UVM_PHASE_DOMAIN) return m_parent; return null; endfunction function uvm_domain uvm_phase::get_domain(); uvm_phase phase; phase = this; while (phase != null && phase.m_phase_type != UVM_PHASE_DOMAIN) phase = phase.m_parent; if (phase == null) return null; if(!$cast(get_domain,phase)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH/INTERNAL")) uvm_report_fatal ("PH/INTERNAL", "get_domain: m_phase_type is DOMAIN but $cast to uvm_domain fails", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1047, "", 1); end endfunction function string uvm_phase::get_domain_name(); uvm_domain domain; domain = get_domain(); if (domain == null) return "unknown"; return domain.get_name(); endfunction function string uvm_phase::get_schedule_name(bit hier=0); uvm_phase sched; string s; sched = get_schedule(hier); if (sched == null) return ""; s = sched.get_name(); while (sched.m_parent != null && sched.m_parent != sched && (sched.m_parent.get_phase_type() == UVM_PHASE_SCHEDULE)) begin sched = sched.m_parent; s = {sched.get_name(),(s.len()>0?".":""),s}; end return s; endfunction function string uvm_phase::get_full_name(); string dom, sch; if (m_phase_type == UVM_PHASE_IMP) return get_name(); get_full_name = get_domain_name(); sch = get_schedule_name(); if (sch != "") get_full_name = {get_full_name, ".", sch}; if (m_phase_type != UVM_PHASE_DOMAIN && m_phase_type != UVM_PHASE_SCHEDULE) get_full_name = {get_full_name, ".", get_name()}; endfunction function uvm_phase_type uvm_phase::get_phase_type(); return m_phase_type; endfunction function void uvm_phase::set_max_ready_to_end_iterations(int max); max_ready_to_end_iters = max; endfunction function int uvm_phase::get_max_ready_to_end_iterations(); return max_ready_to_end_iters; endfunction function void uvm_phase::set_default_max_ready_to_end_iterations(int max); m_default_max_ready_to_end_iters = max; endfunction function int uvm_phase::get_default_max_ready_to_end_iterations(); return m_default_max_ready_to_end_iters; endfunction function uvm_phase_state uvm_phase::get_state(); return m_state; endfunction function int uvm_phase::get_run_count(); return m_run_count; endfunction function void uvm_phase::m_print_successors(); uvm_phase found; static string spaces = " "; static int level; if (m_phase_type == UVM_PHASE_DOMAIN) level = 0; begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/PHASE/SUCC")) uvm_report_info ("UVM/PHASE/SUCC", $sformatf("%s%s (%s) id=%0d",spaces.substr(0,level*2),get_name(), m_phase_type.name(),get_inst_id()), UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1162, "", 1); end level++; foreach (m_successors[succ]) begin succ.m_print_successors(); end level--; endfunction function uvm_phase uvm_phase::m_find_predecessor(uvm_phase phase, bit stay_in_scope=1, uvm_phase orig_phase=null); uvm_phase found; if (phase == null) begin return null ; end if (phase == m_imp || phase == this) return this; foreach (m_predecessors[pred]) begin uvm_phase orig; orig = (orig_phase==null) ? this : orig_phase; if (!stay_in_scope || (pred.get_schedule() == orig.get_schedule()) || (pred.get_domain() == orig.get_domain())) begin found = pred.m_find_predecessor(phase,stay_in_scope,orig); if (found != null) return found; end end return null; endfunction function uvm_phase uvm_phase::m_find_predecessor_by_name(string name, bit stay_in_scope=1, uvm_phase orig_phase=null); uvm_phase found; if (get_name() == name) return this; foreach (m_predecessors[pred]) begin uvm_phase orig; orig = (orig_phase==null) ? this : orig_phase; if (!stay_in_scope || (pred.get_schedule() == orig.get_schedule()) || (pred.get_domain() == orig.get_domain())) begin found = pred.m_find_predecessor_by_name(name,stay_in_scope,orig); if (found != null) return found; end end return null; endfunction function uvm_phase uvm_phase::m_find_successor(uvm_phase phase, bit stay_in_scope=1, uvm_phase orig_phase=null); uvm_phase found; if (phase == null) begin return null ; end if (phase == m_imp || phase == this) begin return this; end foreach (m_successors[succ]) begin uvm_phase orig; orig = (orig_phase==null) ? this : orig_phase; if (!stay_in_scope || (succ.get_schedule() == orig.get_schedule()) || (succ.get_domain() == orig.get_domain())) begin found = succ.m_find_successor(phase,stay_in_scope,orig); if (found != null) begin return found; end end end return null; endfunction function uvm_phase uvm_phase::m_find_successor_by_name(string name, bit stay_in_scope=1, uvm_phase orig_phase=null); uvm_phase found; if (get_name() == name) return this; foreach (m_successors[succ]) begin uvm_phase orig; orig = (orig_phase==null) ? this : orig_phase; if (!stay_in_scope || (succ.get_schedule() == orig.get_schedule()) || (succ.get_domain() == orig.get_domain())) begin found = succ.m_find_successor_by_name(name,stay_in_scope,orig); if (found != null) return found; end end return null; endfunction function uvm_phase uvm_phase::find(uvm_phase phase, bit stay_in_scope=1); if (phase == m_imp || phase == this) return phase; find = m_find_predecessor(phase,stay_in_scope,this); if (find == null) find = m_find_successor(phase,stay_in_scope,this); endfunction function uvm_phase uvm_phase::find_by_name(string name, bit stay_in_scope=1); if (get_name() == name) return this; find_by_name = m_find_predecessor_by_name(name,stay_in_scope,this); if (find_by_name == null) find_by_name = m_find_successor_by_name(name,stay_in_scope,this); endfunction function bit uvm_phase::is(uvm_phase phase); return (m_imp == phase || this == phase); endfunction function bit uvm_phase::is_before(uvm_phase phase); return (!is(phase) && m_find_successor(phase,0,this) != null); endfunction function bit uvm_phase::is_after(uvm_phase phase); return (!is(phase) && m_find_predecessor(phase,0,this) != null); endfunction task uvm_phase::execute_phase(); uvm_task_phase task_phase; uvm_root top; uvm_phase_state_change state_chg; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); foreach (m_predecessors[pred]) wait (pred.m_state == UVM_PHASE_DONE); if (m_state == UVM_PHASE_DONE) return; state_chg = uvm_phase_state_change::type_id_create(get_name()); state_chg.m_phase = this; state_chg.m_jump_to = null; state_chg.m_prev_state = m_state; m_state = UVM_PHASE_SYNCING; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end #0; if (m_sync.size()) begin foreach (m_sync[i]) begin wait (m_sync[i].m_state >= UVM_PHASE_SYNCING); end end m_run_count++; if (m_phase_trace) begin begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/STRT")) uvm_report_info ("PH/TRC/STRT", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"Starting phase"}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1382, "", 1); end end if (m_phase_type != UVM_PHASE_NODE) begin state_chg.m_prev_state = m_state; m_state = UVM_PHASE_STARTED; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end #0; state_chg.m_prev_state = m_state; m_state = UVM_PHASE_EXECUTING; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end #0; end else begin state_chg.m_prev_state = m_state; m_state = UVM_PHASE_STARTED; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end m_imp.traverse(top,this,UVM_PHASE_STARTED); m_ready_to_end_count = 0 ; #0; if (!$cast(task_phase,m_imp)) begin state_chg.m_prev_state = m_state; m_state = UVM_PHASE_EXECUTING; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end #0; m_imp.traverse(top,this,UVM_PHASE_EXECUTING); end else begin m_executing_phases[this] = 1; state_chg.m_prev_state = m_state; m_state = UVM_PHASE_EXECUTING; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end fork : master_phase_process begin m_phase_proc = process::self(); task_phase.traverse(top,this,UVM_PHASE_EXECUTING); wait(0); end join_none uvm_wait_for_nba_region(); fork begin fork begin wait (m_premature_end); begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH/TRC/EXE/JUMP")) uvm_report_info ("PH/TRC/EXE/JUMP", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE EXIT ON JUMP REQUEST"}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 1462, "", 1); end end begin bit do_ready_to_end ; uvm_objection phase_done; phase_done = get_objection(); if (phase_done.get_objection_total(top) || m_use_ovm_run_semantic && m_imp.get_name() == "run") begin if (!phase_done.m_top_all_dropped) phase_done.wait_for(UVM_ALL_DROPPED, top); begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH/TRC/EXE/ALLDROP")) uvm_report_info ("PH/TRC/EXE/ALLDROP", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE EXIT ALL_DROPPED"}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 1475, "", 1); end end else begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/SKIP")) uvm_report_info ("PH/TRC/SKIP", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"No objections raised, skipping phase"}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1478, "", 1); end end wait_for_self_and_siblings_to_drop() ; do_ready_to_end = 1; while (do_ready_to_end) begin uvm_wait_for_nba_region(); begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_READY_TO_END")) uvm_report_info ("PH_READY_TO_END", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE READY TO END"}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 1490, "", 1); end m_ready_to_end_count++; if (m_phase_trace) begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH_READY_TO_END_CB")) uvm_report_info ("PH_READY_TO_END_CB", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"CALLING READY_TO_END CB"}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1493, "", 1); end state_chg.m_prev_state = m_state; m_state = UVM_PHASE_READY_TO_END; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end if (m_imp != null) m_imp.traverse(top,this,UVM_PHASE_READY_TO_END); uvm_wait_for_nba_region(); wait_for_self_and_siblings_to_drop(); do_ready_to_end = (m_state == UVM_PHASE_EXECUTING) && (m_ready_to_end_count < get_max_ready_to_end_iterations()) ; end end begin if (this.get_name() == "run") begin if (top.phase_timeout == 0) wait(top.phase_timeout != 0); if (m_phase_trace) begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH/TRC/TO_WAIT")) uvm_report_info ("PH/TRC/TO_WAIT", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),$sformatf("STARTING PHASE TIMEOUT WATCHDOG (timeout == %t)", top.phase_timeout)}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1513, "", 1); end #(top.phase_timeout); if ($time == 9200s) begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/TIMEOUT")) uvm_report_info ("PH/TRC/TIMEOUT", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE TIMEOUT WATCHDOG EXPIRED"}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1517, "", 1); end foreach (m_executing_phases[p]) begin uvm_objection p_phase_done; p_phase_done = p.get_objection(); if ((p_phase_done != null) && (p_phase_done.get_objection_total() > 0)) begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/TIMEOUT/OBJCTN")) uvm_report_info ("PH/TRC/TIMEOUT/OBJCTN", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),$sformatf("Phase '%s' has outstanding objections:\n%s", p.get_full_name(), p_phase_done.convert2string())}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1526, "", 1); end end end begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_TIMEOUT")) uvm_report_fatal ("PH_TIMEOUT", $sformatf("Default timeout of %0t hit, indicating a probable testbench issue", 9200s), UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1532, "", 1); end end else begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/TIMEOUT")) uvm_report_info ("PH/TRC/TIMEOUT", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE TIMEOUT WATCHDOG EXPIRED"}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1536, "", 1); end foreach (m_executing_phases[p]) begin uvm_objection p_phase_done; p_phase_done = p.get_objection(); if ((p_phase_done != null) && (p_phase_done.get_objection_total() > 0)) begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/TIMEOUT/OBJCTN")) uvm_report_info ("PH/TRC/TIMEOUT/OBJCTN", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),$sformatf("Phase '%s' has outstanding objections:\n%s", p.get_full_name(), p_phase_done.convert2string())}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1545, "", 1); end end end begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_TIMEOUT")) uvm_report_fatal ("PH_TIMEOUT", $sformatf("Explicit timeout of %0t hit, indicating a probable testbench issue", top.phase_timeout), UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1551, "", 1); end end if (m_phase_trace) begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH/TRC/EXE/3")) uvm_report_info ("PH/TRC/EXE/3", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"PHASE EXIT TIMEOUT"}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 1554, "", 1); end end else begin wait (0); end end join_any disable fork; end join end end m_executing_phases.delete(this); if (m_phase_type == UVM_PHASE_NODE) begin if(m_premature_end) begin if(m_jump_phase != null) begin state_chg.m_jump_to = m_jump_phase; begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"PH_JUMP")) uvm_report_info ("PH_JUMP", $sformatf("phase %s (schedule %s, domain %s) is jumping to phase %s", get_name(), get_schedule_name(), get_domain_name(), m_jump_phase.get_name()), UVM_MEDIUM, "t/uvm/src/base/uvm_phase.svh", 1598, "", 1); end end else begin begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"PH_JUMP")) uvm_report_info ("PH_JUMP", $sformatf("phase %s (schedule %s, domain %s) is ending prematurely", get_name(), get_schedule_name(), get_domain_name()), UVM_MEDIUM, "t/uvm/src/base/uvm_phase.svh", 1604, "", 1); end end #0; if (m_phase_trace) begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH_END")) uvm_report_info ("PH_END", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"ENDING PHASE PREMATURELY"}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1610, "", 1); end end else begin if (task_phase == null) m_wait_for_pred(); end if (m_phase_trace) begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH_END")) uvm_report_info ("PH_END", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"ENDING PHASE"}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1624, "", 1); end state_chg.m_prev_state = m_state; m_state = UVM_PHASE_ENDED; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end if (m_imp != null) m_imp.traverse(top,this,UVM_PHASE_ENDED); #0; state_chg.m_prev_state = m_state; if(m_premature_end) m_state = UVM_PHASE_JUMPING; else m_state = UVM_PHASE_CLEANUP ; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end if (m_phase_proc != null) begin m_phase_proc.kill(); m_phase_proc = null; end #0; begin uvm_objection objection = get_objection(); if (objection != null) objection.clear(); end end m_premature_end = 0 ; if(m_jump_fwd || m_jump_bkwd) begin if(m_jump_fwd) begin clear_successors(UVM_PHASE_DONE,m_jump_phase); end m_jump_phase.clear_successors(); end else begin if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/DONE")) uvm_report_info ("PH/TRC/DONE", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"Completed phase"}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1666, "", 1); end state_chg.m_prev_state = m_state; m_state = UVM_PHASE_DONE; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(this, state_chg); cb = iter.next(); end end m_phase_proc = null; #0; end #0; begin uvm_objection objection; objection = get_objection(); if (objection != null) objection.clear(); end if(m_jump_fwd || m_jump_bkwd) begin void'(m_phase_hopper.try_put(m_jump_phase)); m_jump_phase = null; m_jump_fwd = 0; m_jump_bkwd = 0; end else if (m_successors.size() == 0) begin top.m_phase_all_done=1; end else begin foreach (m_successors[succ]) begin if(succ.m_state < UVM_PHASE_SCHEDULED) begin state_chg.m_prev_state = succ.m_state; state_chg.m_phase = succ; succ.m_state = UVM_PHASE_SCHEDULED; begin uvm_callback_iter#(uvm_phase,uvm_phase_cb) iter = new(this); uvm_phase_cb cb = iter.first(); while(cb != null) begin cb.phase_state_change(succ, state_chg); cb = iter.next(); end end #0; void'(m_phase_hopper.try_put(succ)); if (m_phase_trace) begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"PH/TRC/SCHEDULED")) uvm_report_info ("PH/TRC/SCHEDULED", {$sformatf("Phase '%0s' (id=%0d) ", succ.get_full_name(), succ.get_inst_id()),{"Scheduled from phase ",get_full_name()}}, UVM_LOW, "t/uvm/src/base/uvm_phase.svh", 1705, "", 1); end end end end endtask function void uvm_phase::get_adjacent_predecessor_nodes(ref uvm_phase pred[]); bit done; bit predecessors[uvm_phase]; int idx; foreach (m_predecessors[p]) predecessors[p] = 1; do begin done = 1; foreach (predecessors[p]) begin if (p.get_phase_type() != UVM_PHASE_NODE) begin predecessors.delete(p); foreach (p.m_predecessors[next_p]) predecessors[next_p] = 1; done = 0; end end end while (!done); pred = new [predecessors.size()]; foreach (predecessors[p]) begin pred[idx++] = p; end endfunction : get_adjacent_predecessor_nodes function void uvm_phase::get_adjacent_successor_nodes(ref uvm_phase succ[]); bit done; bit successors[uvm_phase]; int idx; foreach (m_successors[s]) successors[s] = 1; do begin done = 1; foreach (successors[s]) begin if (s.get_phase_type() != UVM_PHASE_NODE) begin successors.delete(s); foreach (s.m_successors[next_s]) successors[next_s] = 1; done = 0; end end end while (!done); succ = new [successors.size()]; foreach (successors[s]) begin succ[idx++] = s; end endfunction : get_adjacent_successor_nodes function void uvm_phase::get_predecessors_for_successors(output bit pred_of_succ[uvm_phase]); bit done; uvm_phase successors[]; get_adjacent_successor_nodes(successors); foreach (successors[s]) foreach (successors[s].m_predecessors[pred]) pred_of_succ[pred] = 1; do begin done=1; foreach (pred_of_succ[pred]) begin if (pred.get_phase_type() != UVM_PHASE_NODE) begin pred_of_succ.delete(pred); foreach (pred.m_predecessors[next_pred]) pred_of_succ[next_pred] = 1; done =0; end end end while (!done); pred_of_succ.delete(this); endfunction task uvm_phase::m_wait_for_pred(); bit pred_of_succ[uvm_phase]; get_predecessors_for_successors(pred_of_succ); foreach (pred_of_succ[sibling]) begin if (m_phase_trace) begin string s; s = $sformatf("Waiting for phase '%s' (%0d) to be READY_TO_END. Current state is %s", sibling.get_name(),sibling.get_inst_id(),sibling.m_state.name()); begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH/TRC/WAIT_PRED_OF_SUCC")) uvm_report_info ("PH/TRC/WAIT_PRED_OF_SUCC", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),s}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1819, "", 1); end end sibling.wait_for_state(UVM_PHASE_READY_TO_END, UVM_GTE); if (m_phase_trace) begin string s; s = $sformatf("Phase '%s' (%0d) is now READY_TO_END. Releasing phase", sibling.get_name(),sibling.get_inst_id()); begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH/TRC/WAIT_PRED_OF_SUCC")) uvm_report_info ("PH/TRC/WAIT_PRED_OF_SUCC", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),s}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1828, "", 1); end end end if (m_phase_trace) begin if (pred_of_succ.num()) begin string s = "( "; foreach (pred_of_succ[pred]) s = {s, pred.get_full_name()," "}; s = {s, ")"}; begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH/TRC/WAIT_PRED_OF_SUCC")) uvm_report_info ("PH/TRC/WAIT_PRED_OF_SUCC", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),{"*** All pred to succ ",s," in READY_TO_END state, so ending phase ***"}}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1840, "", 1); end end else begin begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"PH/TRC/WAIT_PRED_OF_SUCC")) uvm_report_info ("PH/TRC/WAIT_PRED_OF_SUCC", {$sformatf("Phase '%0s' (id=%0d) ", this.get_full_name(), this.get_inst_id()),"*** No pred to succ other than myself, so ending phase ***"}, UVM_HIGH, "t/uvm/src/base/uvm_phase.svh", 1844, "", 1); end end end #0; endtask function void uvm_phase::m_report_null_objection(uvm_object obj, string description, int count, string action); string m_action; string m_addon; string m_obj_name = (obj == null) ? "uvm_top" : obj.get_full_name(); if ((action == "raise") || (action == "drop")) begin if (count != 1) m_action = $sformatf("%s %0d objections", action, count); else m_action = $sformatf("%s an objection", action); end else if (action == "get_objection_count") begin m_action = "call get_objection_count"; end if (this.get_phase_type() == UVM_PHASE_IMP) begin m_addon = " (This is a UVM_PHASE_IMP, you have to query the schedule to find the UVM_PHASE_NODE)"; end begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/PH/NULL_OBJECTION")) uvm_report_error ("UVM/PH/NULL_OBJECTION", $sformatf("'%s' attempted to %s on '%s', however '%s' is not a task-based phase node! %s", m_obj_name, m_action, get_name(), get_name(), m_addon), UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1885, "", 1); end endfunction : m_report_null_objection function void uvm_phase::raise_objection (uvm_object obj, string description="", int count=1); uvm_objection phase_done; phase_done = get_objection(); if (phase_done != null) phase_done.raise_objection(obj,description,count); else m_report_null_objection(obj, description, count, "raise"); endfunction function void uvm_phase::drop_objection (uvm_object obj, string description="", int count=1); uvm_objection phase_done; phase_done = get_objection(); if (phase_done != null) phase_done.drop_objection(obj,description,count); else m_report_null_objection(obj, description, count, "drop"); endfunction function int uvm_phase::get_objection_count (uvm_object obj=null); uvm_objection phase_done; phase_done = get_objection(); if (phase_done != null) return phase_done.get_objection_count(obj); else begin m_report_null_objection(obj, "" , 0, "get_objection_count"); return 0; end endfunction : get_objection_count function void uvm_phase::sync(uvm_domain target, uvm_phase phase=null, uvm_phase with_phase=null); if (!this.is_domain()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "sync() called from a non-domain phase schedule node", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1939, "", 1); end end else if (target == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "sync() called with a null target domain", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1942, "", 1); end end else if (!target.is_domain()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "sync() called with a non-domain phase schedule node as target", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1945, "", 1); end end else if (phase == null && with_phase != null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "sync() called with null phase and non-null with phase", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1948, "", 1); end end else if (phase == null) begin int visited[uvm_phase]; uvm_phase queue[$]; queue.push_back(this); visited[this] = 1; while (queue.size()) begin uvm_phase node; node = queue.pop_front(); if (node.m_imp != null) begin sync(target, node.m_imp); end foreach (node.m_successors[succ]) begin if (!visited.exists(succ)) begin queue.push_back(succ); visited[succ] = 1; end end end end else begin uvm_phase from_node, to_node; int found_to[$], found_from[$]; if(with_phase == null) with_phase = phase; from_node = find(phase); to_node = target.find(with_phase); if(from_node == null || to_node == null) return; found_to = from_node.m_sync.find_index(node) with (node == to_node); found_from = to_node.m_sync.find_index(node) with (node == from_node); if (found_to.size() == 0) from_node.m_sync.push_back(to_node); if (found_from.size() == 0) to_node.m_sync.push_back(from_node); end endfunction function void uvm_phase::unsync(uvm_domain target, uvm_phase phase=null, uvm_phase with_phase=null); if (!this.is_domain()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "unsync() called from a non-domain phase schedule node", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1993, "", 1); end end else if (target == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "unsync() called with a null target domain", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1995, "", 1); end end else if (!target.is_domain()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "unsync() called with a non-domain phase schedule node as target", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1997, "", 1); end end else if (phase == null && with_phase != null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADSYNC")) uvm_report_fatal ("PH_BADSYNC", "unsync() called with null phase and non-null with phase", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 1999, "", 1); end end else if (phase == null) begin int visited[uvm_phase]; uvm_phase queue[$]; queue.push_back(this); visited[this] = 1; while (queue.size()) begin uvm_phase node; node = queue.pop_front(); if (node.m_imp != null) unsync(target,node.m_imp); foreach (node.m_successors[succ]) begin if (!visited.exists(succ)) begin queue.push_back(succ); visited[succ] = 1; end end end end else begin uvm_phase from_node, to_node; int found_to[$], found_from[$]; if(with_phase == null) with_phase = phase; from_node = find(phase); to_node = target.find(with_phase); if(from_node == null || to_node == null) return; found_to = from_node.m_sync.find_index(node) with (node == to_node); found_from = to_node.m_sync.find_index(node) with (node == from_node); if (found_to.size()) from_node.m_sync.delete(found_to[0]); if (found_from.size()) to_node.m_sync.delete(found_from[0]); end endfunction task uvm_phase::wait_for_state(uvm_phase_state state, uvm_wait_op op=UVM_EQ); case (op) UVM_EQ: wait((state&m_state) != 0); UVM_NE: wait((state&m_state) == 0); UVM_LT: wait(m_state < state); UVM_LTE: wait(m_state <= state); UVM_GT: wait(m_state > state); UVM_GTE: wait(m_state >= state); endcase endtask function void uvm_phase::set_jump_phase(uvm_phase phase) ; uvm_phase d; if ((m_state < UVM_PHASE_STARTED) || (m_state > UVM_PHASE_ENDED) ) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"JMPPHIDL")) uvm_report_error ("JMPPHIDL", { "Attempting to jump from phase \"", get_name(), "\" which is not currently active (current state is ", m_state.name(), "). The jump will not happen until the phase becomes ", "active."}, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 2067, "", 1); end end d = m_find_predecessor(phase,0); if (d == null) begin d = m_find_successor(phase,0); if (d == null) begin string msg; $sformat(msg,{"phase %s is neither a predecessor or successor of ", "phase %s or is non-existant, so we cannot jump to it. ", "Phase control flow is now undefined so the simulation ", "must terminate"}, phase.get_name(), get_name()); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADJUMP")) uvm_report_fatal ("PH_BADJUMP", msg, UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 2093, "", 1); end end else begin m_jump_fwd = 1; begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_JUMPF")) uvm_report_info ("PH_JUMPF", $sformatf("jumping forward to phase %s", phase.get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 2098, "", 1); end end end else begin m_jump_bkwd = 1; begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_JUMPB")) uvm_report_info ("PH_JUMPB", $sformatf("jumping backward to phase %s", phase.get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 2104, "", 1); end end m_jump_phase = d; endfunction function void uvm_phase::end_prematurely() ; m_premature_end = 1 ; endfunction function void uvm_phase::jump(uvm_phase phase); set_jump_phase(phase) ; end_prematurely() ; endfunction function void uvm_phase::jump_all(uvm_phase phase); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"NOTIMPL")) uvm_report_warning ("NOTIMPL", "uvm_phase::jump_all is not implemented and has been replaced by uvm_domain::jump_all", UVM_NONE, "t/uvm/src/base/uvm_phase.svh", 2136, "", 1); end endfunction function uvm_phase uvm_phase::get_jump_target(); return m_jump_phase; endfunction function void uvm_phase::clear(uvm_phase_state state = UVM_PHASE_DORMANT); uvm_objection phase_done; phase_done = get_objection(); m_state = state; m_phase_proc = null; if (phase_done != null) phase_done.clear(this); endfunction function void uvm_phase::clear_successors(uvm_phase_state state = UVM_PHASE_DORMANT, uvm_phase end_state=null); if(this == end_state) return; clear(state); foreach(m_successors[succ]) begin succ.clear_successors(state, end_state); end endfunction task uvm_phase::wait_for_self_and_siblings_to_drop() ; bit need_to_check_all = 1 ; uvm_root top; uvm_coreservice_t cs; bit siblings[uvm_phase]; cs = uvm_coreservice_t::get(); top = cs.get_root(); get_predecessors_for_successors(siblings); foreach (m_sync[i]) begin siblings[m_sync[i]] = 1; end while (need_to_check_all) begin uvm_objection phase_done; phase_done = get_objection(); need_to_check_all = 0 ; if ((phase_done != null) && (phase_done.get_objection_total(top) != 0)) begin m_state = UVM_PHASE_EXECUTING ; phase_done.wait_for(UVM_ALL_DROPPED, top); need_to_check_all = 1 ; end foreach(siblings[sib]) begin uvm_objection sib_phase_done; sib_phase_done = sib.get_objection(); sib.wait_for_state(UVM_PHASE_EXECUTING, UVM_GTE); if ((sib_phase_done != null) && (sib_phase_done.get_objection_total(top) != 0)) begin m_state = UVM_PHASE_EXECUTING ; sib_phase_done.wait_for(UVM_ALL_DROPPED, top); need_to_check_all = 1 ; end end end endtask function void uvm_phase::kill(); begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_KILL")) uvm_report_info ("PH_KILL", {"killing phase '", get_name(),"'"}, UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 2230, "", 1); end if (m_phase_proc != null) begin m_phase_proc.kill(); m_phase_proc = null; end endfunction function void uvm_phase::kill_successors(); foreach (m_successors[succ]) succ.kill_successors(); kill(); endfunction task uvm_phase::m_run_phases(); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); begin uvm_phase ph = uvm_domain::get_common_domain(); void'(m_phase_hopper.try_put(ph)); end m_uvm_core_state=UVM_CORE_RUNNING; forever begin uvm_phase phase; m_phase_hopper.get(phase); fork begin phase.execute_phase(); end join_none #0; end endtask function void uvm_phase::m_terminate_phase(); uvm_objection phase_done; phase_done = get_objection(); if (phase_done != null) phase_done.clear(this); endfunction function void uvm_phase::m_print_termination_state(); uvm_root top; uvm_coreservice_t cs; uvm_objection phase_done; phase_done = get_objection(); cs = uvm_coreservice_t::get(); top = cs.get_root(); if (phase_done != null) begin begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_TERMSTATE")) uvm_report_info ("PH_TERMSTATE", $sformatf("phase %s outstanding objections = %0d", get_name(), phase_done.get_objection_total(top)), UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 2309, "", 1); end end else begin begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_TERMSTATE")) uvm_report_info ("PH_TERMSTATE", $sformatf("phase %s has no outstanding objections", get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_phase.svh", 2315, "", 1); end end endfunction typedef class uvm_build_phase; typedef class uvm_connect_phase; typedef class uvm_end_of_elaboration_phase; typedef class uvm_start_of_simulation_phase; typedef class uvm_run_phase; typedef class uvm_extract_phase; typedef class uvm_check_phase; typedef class uvm_report_phase; typedef class uvm_final_phase; typedef class uvm_pre_reset_phase; typedef class uvm_reset_phase; typedef class uvm_post_reset_phase; typedef class uvm_pre_configure_phase; typedef class uvm_configure_phase; typedef class uvm_post_configure_phase; typedef class uvm_pre_main_phase; typedef class uvm_main_phase; typedef class uvm_post_main_phase; typedef class uvm_pre_shutdown_phase; typedef class uvm_shutdown_phase; typedef class uvm_post_shutdown_phase; uvm_phase build_ph; uvm_phase connect_ph; uvm_phase end_of_elaboration_ph; uvm_phase start_of_simulation_ph; uvm_phase run_ph; uvm_phase extract_ph; uvm_phase check_ph; uvm_phase report_ph; class uvm_domain extends uvm_phase; static local uvm_domain m_uvm_domain; static local uvm_domain m_domains[string]; static local uvm_phase m_uvm_schedule; static function void get_domains(output uvm_domain domains[string]); domains = m_domains; endfunction static function uvm_phase get_uvm_schedule(); void'(get_uvm_domain()); return m_uvm_schedule; endfunction static function uvm_domain get_common_domain(); uvm_domain domain; if(m_domains.exists("common")) domain = m_domains["common"]; if (domain != null) return domain; domain = new("common"); domain.add(uvm_build_phase::get()); domain.add(uvm_connect_phase::get()); domain.add(uvm_end_of_elaboration_phase::get()); domain.add(uvm_start_of_simulation_phase::get()); domain.add(uvm_run_phase::get()); domain.add(uvm_extract_phase::get()); domain.add(uvm_check_phase::get()); domain.add(uvm_report_phase::get()); domain.add(uvm_final_phase::get()); build_ph = domain.find(uvm_build_phase::get()); connect_ph = domain.find(uvm_connect_phase::get()); end_of_elaboration_ph = domain.find(uvm_end_of_elaboration_phase::get()); start_of_simulation_ph = domain.find(uvm_start_of_simulation_phase::get()); run_ph = domain.find(uvm_run_phase::get()); extract_ph = domain.find(uvm_extract_phase::get()); check_ph = domain.find(uvm_check_phase::get()); report_ph = domain.find(uvm_report_phase::get()); domain = get_uvm_domain(); m_domains["common"].add(domain, .with_phase(m_domains["common"].find(uvm_run_phase::get()))); return m_domains["common"]; endfunction static function void add_uvm_phases(uvm_phase schedule); schedule.add(uvm_pre_reset_phase::get()); schedule.add(uvm_reset_phase::get()); schedule.add(uvm_post_reset_phase::get()); schedule.add(uvm_pre_configure_phase::get()); schedule.add(uvm_configure_phase::get()); schedule.add(uvm_post_configure_phase::get()); schedule.add(uvm_pre_main_phase::get()); schedule.add(uvm_main_phase::get()); schedule.add(uvm_post_main_phase::get()); schedule.add(uvm_pre_shutdown_phase::get()); schedule.add(uvm_shutdown_phase::get()); schedule.add(uvm_post_shutdown_phase::get()); endfunction static function uvm_domain get_uvm_domain(); if (m_uvm_domain == null) begin m_uvm_domain = new("uvm"); m_uvm_schedule = new("uvm_sched", UVM_PHASE_SCHEDULE); add_uvm_phases(m_uvm_schedule); m_uvm_domain.add(m_uvm_schedule); end return m_uvm_domain; endfunction function new(string name); super.new(name,UVM_PHASE_DOMAIN); if (m_domains.exists(name)) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UNIQDOMNAM")) uvm_report_error ("UNIQDOMNAM", $sformatf("Domain created with non-unique name '%s'", name), UVM_NONE, "t/uvm/src/base/uvm_domain.svh", 183, "", 1); end m_domains[name] = this; endfunction function void jump(uvm_phase phase); uvm_phase phases[$]; m_get_transitive_children(phases); phases = phases.find(item) with (item.get_state() inside {[UVM_PHASE_STARTED:UVM_PHASE_CLEANUP]}); foreach(phases[idx]) if(phases[idx].is_before(phase) || phases[idx].is_after(phase)) phases[idx].jump(phase); endfunction static function void jump_all(uvm_phase phase); uvm_domain domains[string]; uvm_domain::get_domains(domains); foreach(domains[idx]) domains[idx].jump(phase); endfunction endclass virtual class uvm_bottomup_phase extends uvm_phase; function new(string name); super.new(name,UVM_PHASE_IMP); endfunction virtual function void traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state); string name; uvm_domain phase_domain =phase.get_domain(); uvm_domain comp_domain = comp.get_domain(); if (comp.get_first_child(name)) do traverse(comp.get_child(name), phase, state); while(comp.get_next_child(name)); if (m_phase_trace) begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_TRACE")) uvm_report_info ("PH_TRACE", $sformatf("bottomup-phase phase=%s state=%s comp=%s comp.domain=%s phase.domain=%s", phase.get_name(), state.name(), comp.get_full_name(),comp_domain.get_name(),phase_domain.get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_bottomup_phase.svh", 64, "", 1); end if (phase_domain == uvm_domain::get_common_domain() || phase_domain == comp_domain) begin case (state) UVM_PHASE_STARTED: begin comp.m_current_phase = phase; comp.m_apply_verbosity_settings(phase); comp.phase_started(phase); end UVM_PHASE_EXECUTING: begin uvm_phase ph = this; if (comp.m_phase_imps.exists(this)) ph = comp.m_phase_imps[this]; ph.execute(comp, phase); end UVM_PHASE_READY_TO_END: begin comp.phase_ready_to_end(phase); end UVM_PHASE_ENDED: begin comp.phase_ended(phase); comp.m_current_phase = null; end default: begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADEXEC")) uvm_report_fatal ("PH_BADEXEC", "bottomup phase traverse internal error", UVM_NONE, "t/uvm/src/base/uvm_bottomup_phase.svh", 88, "", 1); end endcase end endfunction virtual function void execute(uvm_component comp, uvm_phase phase); process proc = process::self(); proc.srandom(uvm_create_random_seed(phase.get_type_name(), comp.get_full_name())); comp.m_current_phase = phase; exec_func(comp,phase); endfunction endclass virtual class uvm_topdown_phase extends uvm_phase; function new(string name); super.new(name,UVM_PHASE_IMP); endfunction virtual function void traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state); string name; uvm_domain phase_domain = phase.get_domain(); uvm_domain comp_domain = comp.get_domain(); if (m_phase_trace) begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_TRACE")) uvm_report_info ("PH_TRACE", $sformatf("topdown-phase phase=%s state=%s comp=%s comp.domain=%s phase.domain=%s", phase.get_name(), state.name(), comp.get_full_name(),comp_domain.get_name(),phase_domain.get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_topdown_phase.svh", 59, "", 1); end if (phase_domain == uvm_domain::get_common_domain() || phase_domain == comp_domain) begin case (state) UVM_PHASE_STARTED: begin comp.m_current_phase = phase; comp.m_apply_verbosity_settings(phase); comp.phase_started(phase); end UVM_PHASE_EXECUTING: begin if (!(phase.get_name() == "build" && comp.m_build_done)) begin uvm_phase ph = this; comp.m_phasing_active++; if (comp.m_phase_imps.exists(this)) ph = comp.m_phase_imps[this]; ph.execute(comp, phase); comp.m_phasing_active--; end end UVM_PHASE_READY_TO_END: begin comp.phase_ready_to_end(phase); end UVM_PHASE_ENDED: begin comp.phase_ended(phase); comp.m_current_phase = null; end default: begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADEXEC")) uvm_report_fatal ("PH_BADEXEC", "topdown phase traverse internal error", UVM_NONE, "t/uvm/src/base/uvm_topdown_phase.svh", 87, "", 1); end endcase end if(comp.get_first_child(name)) do traverse(comp.get_child(name), phase, state); while(comp.get_next_child(name)); endfunction virtual function void execute(uvm_component comp, uvm_phase phase); process proc = process::self(); proc.srandom(uvm_create_random_seed(phase.get_type_name(), comp.get_full_name())); comp.m_current_phase = phase; exec_func(comp,phase); endfunction endclass virtual class uvm_task_phase extends uvm_phase; function new(string name); super.new(name,UVM_PHASE_IMP); endfunction virtual function void traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state); phase.m_num_procs_not_yet_returned = 0; m_traverse(comp, phase, state); endfunction function void m_traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state); string name; uvm_domain phase_domain =phase.get_domain(); uvm_domain comp_domain = comp.get_domain(); uvm_sequencer_base seqr; if (comp.get_first_child(name)) do m_traverse(comp.get_child(name), phase, state); while(comp.get_next_child(name)); if (m_phase_trace) begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"PH_TRACE")) uvm_report_info ("PH_TRACE", $sformatf("topdown-phase phase=%s state=%s comp=%s comp.domain=%s phase.domain=%s", phase.get_name(), state.name(), comp.get_full_name(),comp_domain.get_name(),phase_domain.get_name()), UVM_DEBUG, "t/uvm/src/base/uvm_task_phase.svh", 94, "", 1); end if (phase_domain == uvm_domain::get_common_domain() || phase_domain == comp_domain) begin case (state) UVM_PHASE_STARTED: begin comp.m_current_phase = phase; comp.m_apply_verbosity_settings(phase); comp.phase_started(phase); if ($cast(seqr, comp)) seqr.start_phase_sequence(phase); end UVM_PHASE_EXECUTING: begin uvm_phase ph = this; if (comp.m_phase_imps.exists(this)) ph = comp.m_phase_imps[this]; ph.execute(comp, phase); end UVM_PHASE_READY_TO_END: begin comp.phase_ready_to_end(phase); end UVM_PHASE_ENDED: begin if ($cast(seqr, comp)) seqr.stop_phase_sequence(phase); comp.phase_ended(phase); comp.m_current_phase = null; end default: begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PH_BADEXEC")) uvm_report_fatal ("PH_BADEXEC", "task phase traverse internal error", UVM_NONE, "t/uvm/src/base/uvm_task_phase.svh", 122, "", 1); end endcase end endfunction virtual function void execute(uvm_component comp, uvm_phase phase); fork begin process proc; proc = process::self(); proc.srandom(uvm_create_random_seed(phase.get_type_name(), comp.get_full_name())); phase.m_num_procs_not_yet_returned++; exec_task(comp,phase); phase.m_num_procs_not_yet_returned--; end join_none endfunction endclass class uvm_build_phase extends uvm_topdown_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.build_phase(phase); endfunction local static uvm_build_phase m_inst; static function string type_name(); return "uvm_build_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_build_phase"; endfunction : get_type_name static function uvm_build_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="build"); super.new(name); endfunction endclass class uvm_connect_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.connect_phase(phase); endfunction local static uvm_connect_phase m_inst; static function string type_name(); return "uvm_connect_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_connect_phase"; endfunction : get_type_name static function uvm_connect_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="connect"); super.new(name); endfunction endclass class uvm_end_of_elaboration_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.end_of_elaboration_phase(phase); endfunction local static uvm_end_of_elaboration_phase m_inst; static function string type_name(); return "uvm_end_of_elaboration_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_end_of_elaboration_phase"; endfunction : get_type_name static function uvm_end_of_elaboration_phase get(); if(m_inst == null) begin m_inst = new(); end return m_inst; endfunction protected function new(string name="end_of_elaboration"); super.new(name); endfunction endclass class uvm_start_of_simulation_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.start_of_simulation_phase(phase); endfunction local static uvm_start_of_simulation_phase m_inst; static function string type_name(); return "uvm_start_of_simulation_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_start_of_simulation_phase"; endfunction : get_type_name static function uvm_start_of_simulation_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="start_of_simulation"); super.new(name); endfunction endclass class uvm_run_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.run_phase(phase); endtask local static uvm_run_phase m_inst; static function string type_name(); return "uvm_run_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_run_phase"; endfunction : get_type_name static function uvm_run_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="run"); super.new(name); endfunction endclass class uvm_extract_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.extract_phase(phase); endfunction local static uvm_extract_phase m_inst; static function string type_name(); return "uvm_extract_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_extract_phase"; endfunction : get_type_name static function uvm_extract_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="extract"); super.new(name); endfunction endclass class uvm_check_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.check_phase(phase); endfunction local static uvm_check_phase m_inst; static function string type_name(); return "uvm_check_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_check_phase"; endfunction : get_type_name static function uvm_check_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="check"); super.new(name); endfunction endclass class uvm_report_phase extends uvm_bottomup_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.report_phase(phase); endfunction local static uvm_report_phase m_inst; static function string type_name(); return "uvm_report_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_report_phase"; endfunction : get_type_name static function uvm_report_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="report"); super.new(name); endfunction endclass class uvm_final_phase extends uvm_topdown_phase; virtual function void exec_func(uvm_component comp, uvm_phase phase); comp.final_phase(phase); endfunction local static uvm_final_phase m_inst; static function string type_name(); return "uvm_final_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_final_phase"; endfunction : get_type_name static function uvm_final_phase get(); if(m_inst == null) m_inst = new(); return m_inst; endfunction protected function new(string name="final"); super.new(name); endfunction endclass class uvm_pre_reset_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.pre_reset_phase(phase); endtask local static uvm_pre_reset_phase m_inst; static function string type_name(); return "uvm_pre_reset_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_pre_reset_phase"; endfunction : get_type_name static function uvm_pre_reset_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="pre_reset"); super.new(name); endfunction endclass class uvm_reset_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.reset_phase(phase); endtask local static uvm_reset_phase m_inst; static function string type_name(); return "uvm_reset_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_reset_phase"; endfunction : get_type_name static function uvm_reset_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="reset"); super.new(name); endfunction endclass class uvm_post_reset_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.post_reset_phase(phase); endtask local static uvm_post_reset_phase m_inst; static function string type_name(); return "uvm_post_reset_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_post_reset_phase"; endfunction : get_type_name static function uvm_post_reset_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="post_reset"); super.new(name); endfunction endclass class uvm_pre_configure_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.pre_configure_phase(phase); endtask local static uvm_pre_configure_phase m_inst; static function string type_name(); return "uvm_pre_configure_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_pre_configure_phase"; endfunction : get_type_name static function uvm_pre_configure_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="pre_configure"); super.new(name); endfunction endclass class uvm_configure_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.configure_phase(phase); endtask local static uvm_configure_phase m_inst; static function string type_name(); return "uvm_configure_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_configure_phase"; endfunction : get_type_name static function uvm_configure_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="configure"); super.new(name); endfunction endclass class uvm_post_configure_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.post_configure_phase(phase); endtask local static uvm_post_configure_phase m_inst; static function string type_name(); return "uvm_post_configure_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_post_configure_phase"; endfunction : get_type_name static function uvm_post_configure_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="post_configure"); super.new(name); endfunction endclass class uvm_pre_main_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.pre_main_phase(phase); endtask local static uvm_pre_main_phase m_inst; static function string type_name(); return "uvm_pre_main_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_pre_main_phase"; endfunction : get_type_name static function uvm_pre_main_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="pre_main"); super.new(name); endfunction endclass class uvm_main_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.main_phase(phase); endtask local static uvm_main_phase m_inst; static function string type_name(); return "uvm_main_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_main_phase"; endfunction : get_type_name static function uvm_main_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="main"); super.new(name); endfunction endclass class uvm_post_main_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.post_main_phase(phase); endtask local static uvm_post_main_phase m_inst; static function string type_name(); return "uvm_post_main_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_post_main_phase"; endfunction : get_type_name static function uvm_post_main_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="post_main"); super.new(name); endfunction endclass class uvm_pre_shutdown_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.pre_shutdown_phase(phase); endtask local static uvm_pre_shutdown_phase m_inst; static function string type_name(); return "uvm_pre_shutdown_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_pre_shutdown_phase"; endfunction : get_type_name static function uvm_pre_shutdown_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="pre_shutdown"); super.new(name); endfunction endclass class uvm_shutdown_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.shutdown_phase(phase); endtask local static uvm_shutdown_phase m_inst; static function string type_name(); return "uvm_shutdown_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_shutdown_phase"; endfunction : get_type_name static function uvm_shutdown_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="shutdown"); super.new(name); endfunction endclass class uvm_post_shutdown_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.post_shutdown_phase(phase); endtask local static uvm_post_shutdown_phase m_inst; static function string type_name(); return "uvm_post_shutdown_phase"; endfunction : type_name virtual function string get_type_name(); return "uvm_post_shutdown_phase"; endfunction : get_type_name static function uvm_post_shutdown_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction protected function new(string name="post_shutdown"); super.new(name); endfunction endclass virtual class uvm_run_test_callback extends uvm_callback; extern function new( string name="uvm_run_test_callback"); virtual function void pre_run_test(); endfunction virtual function void post_run_test(); endfunction virtual function void pre_abort(); endfunction extern static function bit add( uvm_run_test_callback cb ); extern static function bit delete( uvm_run_test_callback cb ); extern static function void m_do_pre_run_test(); extern static function void m_do_post_run_test(); extern static function void m_do_pre_abort(); local static uvm_run_test_callback m_registered_cbs[$]; endclass : uvm_run_test_callback function uvm_run_test_callback::new( string name="uvm_run_test_callback"); super.new( name ); endfunction function bit uvm_run_test_callback::add( uvm_run_test_callback cb ); bit found; int unsigned i; if ( cb == null ) begin return 0; end found = 0; i = 0; while ( ! found && ( i < m_registered_cbs.size() ) ) begin if ( m_registered_cbs[ i ] == cb ) begin found = 1; end ++i; end if ( ! found ) begin m_registered_cbs.push_back( cb ); end return ! found; endfunction function bit uvm_run_test_callback::delete( uvm_run_test_callback cb ); int cb_idxs[$]; if ( cb == null ) begin return 0; end cb_idxs = m_registered_cbs.find_index( item ) with ( item == cb ); foreach ( cb_idxs[ i ] ) begin m_registered_cbs.delete( i ); end return ( cb_idxs.size() > 0 ); endfunction function void uvm_run_test_callback::m_do_pre_run_test(); foreach ( m_registered_cbs[ i ] ) begin m_registered_cbs[ i ].pre_run_test(); end endfunction function void uvm_run_test_callback::m_do_post_run_test(); foreach ( m_registered_cbs[ i ] ) begin m_registered_cbs[ i ].post_run_test(); end endfunction function void uvm_run_test_callback::m_do_pre_abort(); foreach ( m_registered_cbs[ i ] ) begin m_registered_cbs[ i ].pre_abort(); end endfunction typedef class uvm_objection; typedef class uvm_sequence_base; typedef class uvm_sequence_item; virtual class uvm_component extends uvm_report_object; extern function new (string name, uvm_component parent); extern virtual function uvm_component get_parent (); extern virtual function string get_full_name (); extern function void get_children(ref uvm_component children[$]); extern function uvm_component get_child (string name); extern function int get_next_child (ref string name); extern function int get_first_child (ref string name); extern function int get_num_children (); extern function int has_child (string name); extern virtual function void set_name (string name); extern function uvm_component lookup (string name); extern function int unsigned get_depth(); extern virtual function void build_phase(uvm_phase phase); extern virtual function void connect_phase(uvm_phase phase); extern virtual function void end_of_elaboration_phase(uvm_phase phase); extern virtual function void start_of_simulation_phase(uvm_phase phase); extern virtual task run_phase(uvm_phase phase); extern virtual task pre_reset_phase(uvm_phase phase); extern virtual task reset_phase(uvm_phase phase); extern virtual task post_reset_phase(uvm_phase phase); extern virtual task pre_configure_phase(uvm_phase phase); extern virtual task configure_phase(uvm_phase phase); extern virtual task post_configure_phase(uvm_phase phase); extern virtual task pre_main_phase(uvm_phase phase); extern virtual task main_phase(uvm_phase phase); extern virtual task post_main_phase(uvm_phase phase); extern virtual task pre_shutdown_phase(uvm_phase phase); extern virtual task shutdown_phase(uvm_phase phase); extern virtual task post_shutdown_phase(uvm_phase phase); extern virtual function void extract_phase(uvm_phase phase); extern virtual function void check_phase(uvm_phase phase); extern virtual function void report_phase(uvm_phase phase); extern virtual function void final_phase(uvm_phase phase); extern virtual function void phase_started (uvm_phase phase); extern virtual function void phase_ready_to_end (uvm_phase phase); extern virtual function void phase_ended (uvm_phase phase); extern function void set_domain(uvm_domain domain, int hier=1); extern function uvm_domain get_domain(); extern virtual protected function void define_domain(uvm_domain domain); extern virtual task suspend (); extern virtual task resume (); extern virtual function void resolve_bindings (); extern function string massage_scope(string scope); extern virtual function void apply_config_settings (bit verbose = 0); extern virtual function bit use_automatic_config(); extern function void print_config(bit recurse = 0, bit audit = 0); extern function void print_config_with_audit(bit recurse = 0); static bit print_config_matches; virtual function void raised (uvm_objection objection, uvm_object source_obj, string description, int count); endfunction virtual function void dropped (uvm_objection objection, uvm_object source_obj, string description, int count); endfunction virtual task all_dropped (uvm_objection objection, uvm_object source_obj, string description, int count); endtask extern function uvm_component create_component (string requested_type_name, string name); extern function uvm_object create_object (string requested_type_name, string name=""); extern static function void set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1); extern function void set_inst_override_by_type(string relative_inst_path, uvm_object_wrapper original_type, uvm_object_wrapper override_type); extern static function void set_type_override(string original_type_name, string override_type_name, bit replace=1); extern function void set_inst_override(string relative_inst_path, string original_type_name, string override_type_name); extern function void print_override_info(string requested_type_name, string name=""); extern function void set_report_id_verbosity_hier (string id, int verbosity); extern function void set_report_severity_id_verbosity_hier(uvm_severity severity, string id, int verbosity); extern function void set_report_severity_action_hier (uvm_severity severity, uvm_action action); extern function void set_report_id_action_hier (string id, uvm_action action); extern function void set_report_severity_id_action_hier(uvm_severity severity, string id, uvm_action action); extern function void set_report_default_file_hier (UVM_FILE file); extern function void set_report_severity_file_hier (uvm_severity severity, UVM_FILE file); extern function void set_report_id_file_hier (string id, UVM_FILE file); extern function void set_report_severity_id_file_hier(uvm_severity severity, string id, UVM_FILE file); extern function void set_report_verbosity_level_hier (int verbosity); virtual function void pre_abort; endfunction extern function void accept_tr (uvm_transaction tr, time accept_time = 0); extern virtual protected function void do_accept_tr (uvm_transaction tr); extern function int begin_tr (uvm_transaction tr, string stream_name="main", string label="", string desc="", time begin_time=0, int parent_handle=0); extern virtual protected function void do_begin_tr (uvm_transaction tr, string stream_name, int tr_handle); extern function void end_tr (uvm_transaction tr, time end_time=0, bit free_handle=1); extern virtual protected function void do_end_tr (uvm_transaction tr, int tr_handle); extern function int record_error_tr (string stream_name="main", uvm_object info=null, string label="error_tr", string desc="", time error_time=0, bit keep_active=0); extern function int record_event_tr (string stream_name="main", uvm_object info=null, string label="event_tr", string desc="", time event_time=0, bit keep_active=0); extern virtual function uvm_tr_stream get_tr_stream(string name, string stream_type_name=""); extern virtual function void free_tr_stream(uvm_tr_stream stream); bit print_enabled = 1; uvm_tr_database tr_database; extern virtual function uvm_tr_database get_tr_database(); extern virtual function void set_tr_database(uvm_tr_database db); protected uvm_domain m_domain; uvm_phase m_phase_imps[uvm_phase]; uvm_phase m_current_phase; protected process m_phase_process; bit m_build_done; int m_phasing_active; extern function void set_local(uvm_resource_base rsrc) ; uvm_component m_parent; protected uvm_component m_children[string]; protected uvm_component m_children_by_handle[uvm_component]; extern protected virtual function bit m_add_child(uvm_component child); extern local virtual function void m_set_full_name(); extern function void do_resolve_bindings(); extern function void do_flush(); extern virtual function void flush (); extern local function void m_extract_name(string name , output string leaf , output string remainder ); extern virtual function uvm_object create (string name=""); extern virtual function uvm_object clone (); local uvm_tr_stream m_streams[string][string]; local uvm_recorder m_tr_h[uvm_transaction]; extern protected function int m_begin_tr (uvm_transaction tr, int parent_handle=0, string stream_name="main", string label="", string desc="", time begin_time=0); string m_name; typedef uvm_abstract_component_registry#(uvm_component, "uvm_component") type_id; static function string type_name(); return "uvm_component"; endfunction : type_name virtual function string get_type_name(); return "uvm_component"; endfunction : get_type_name protected uvm_event_pool event_pool; int unsigned recording_detail = UVM_NONE; extern function void do_print(uvm_printer printer); extern function void m_set_cl_msg_args; extern function void m_set_cl_verb; extern function void m_set_cl_action; extern function void m_set_cl_sev; extern function void m_apply_verbosity_settings(uvm_phase phase); typedef struct { string comp; string phase; time offset; uvm_verbosity verbosity; string id; } m_verbosity_setting; m_verbosity_setting m_verbosity_settings[$]; static m_verbosity_setting m_time_settings[$]; extern function void m_do_pre_abort; uvm_resource_base m_unsupported_resource_base = null; extern function void m_unsupported_set_local(uvm_resource_base rsrc); typedef struct { string arg; string args[$]; int unsigned used; } uvm_cmdline_parsed_arg_t; static uvm_cmdline_parsed_arg_t m_uvm_applied_cl_action[$]; static uvm_cmdline_parsed_arg_t m_uvm_applied_cl_sev[$]; endclass : uvm_component typedef class uvm_cmdline_processor; typedef class uvm_component_proxy; typedef class uvm_top_down_visitor_adapter; typedef class uvm_report_message; typedef class uvm_report_object; typedef class uvm_report_handler; typedef class uvm_default_report_server; class uvm_root extends uvm_component; extern static function uvm_root get(); uvm_cmdline_processor clp; virtual function string get_type_name(); return "uvm_root"; endfunction extern virtual task run_test (string test_name=""); virtual function void die(); uvm_report_server l_rs = uvm_report_server::get_server(); m_uvm_core_state=UVM_CORE_PRE_ABORT; m_do_pre_abort(); uvm_run_test_callback::m_do_pre_abort(); l_rs.report_summarize(); m_uvm_core_state=UVM_CORE_ABORTED; $finish; endfunction extern function void set_timeout(time timeout, bit overridable=1); local bit finish_on_completion = 1; virtual function bit get_finish_on_completion(); return finish_on_completion; endfunction : get_finish_on_completion virtual function void set_finish_on_completion(bit f); finish_on_completion = f; endfunction : set_finish_on_completion extern function uvm_component find (string comp_match); extern function void find_all (string comp_match, ref uvm_component comps[$], input uvm_component comp=null); extern function void print_topology (uvm_printer printer=null); bit enable_print_topology = 0; extern function void set_enable_print_topology (bit enable); extern function bit get_enable_print_topology (); time phase_timeout = 9200s; 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 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 function void m_check_uvm_field_flag_size(); extern virtual function void report_header(UVM_FILE file = 0); static local uvm_root m_inst; extern virtual task run_phase (uvm_phase phase); function void 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; extern static function uvm_root m_uvm_get_root(); static local bit m_relnotes_done=0; function void 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 function uvm_root uvm_root::get(); uvm_coreservice_t cs = uvm_coreservice_t::get(); return cs.get_root(); endfunction function uvm_root::new(); uvm_report_handler rh; super.new("__top__", null); rh = new("reporter"); set_report_handler(rh); if (m_inst != null) begin begin if (m_inst.uvm_report_enabled(UVM_NONE,UVM_FATAL,"UVM/ROOT/MULTI")) m_inst.uvm_report_fatal ("UVM/ROOT/MULTI", "Attempting to construct multiple roots", UVM_NONE, "t/uvm/src/base/uvm_root.svh", 378, "", 1); end return; end m_inst = this; clp = uvm_cmdline_processor::get_inst(); endfunction function uvm_root uvm_root::m_uvm_get_root(); if (m_inst == null) begin uvm_root top; top = new(); if (top != m_inst) return null; top.m_domain = uvm_domain::get_uvm_domain(); end return m_inst; 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; if (!m_relnotes_done) begin q.push_back("\n *********** IMPORTANT RELEASE NOTES ************\n"); m_relnotes_done = 1; q.push_back("\n This implementation of the UVM Library deviates from the 1800.2-2017\n"); q.push_back(" standard. See the DEVIATIONS.md file contained in the release\n"); q.push_back(" for more details.\n"); end q.push_back("\n----------------------------------------------------------------\n"); q.push_back({uvm_revision_string(),"\n"}); q.push_back("\n"); q.push_back("All copyright owners for this kit are listed in NOTICE.txt\n"); q.push_back("All Rights Reserved Worldwide\n"); q.push_back("----------------------------------------------------------------\n"); if(m_relnotes_done) q.push_back("\n (Specify +UVM_NO_RELNOTES to turn off this notice)\n"); begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"UVM/RELNOTES")) uvm_report_info ("UVM/RELNOTES", uvm_pkg::m_uvm_string_queue_join(q), UVM_LOW, "t/uvm/src/base/uvm_root.svh", 449, "", 1); end endfunction task uvm_root::run_test(string test_name=""); uvm_report_server l_rs; uvm_factory factory; bit testname_plusarg; int test_name_count; string test_names[$]; string msg; uvm_component uvm_test_top; process phase_runner_proc; uvm_run_test_callback::m_do_pre_run_test(); factory=uvm_factory::get(); m_uvm_core_state=UVM_CORE_PRE_RUN; testname_plusarg = 0; uvm_objection::m_init_objections(); m_do_dump_args(); if ($value$plusargs("UVM_TESTNAME=%s", test_name)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"NO_DPI_TSTNAME")) uvm_report_info ("NO_DPI_TSTNAME", "UVM_NO_DPI defined--getting UVM_TESTNAME directly, without DPI", UVM_NONE, "t/uvm/src/base/uvm_root.svh", 517, "", 1); end testname_plusarg = 1; end if (test_name != "") begin 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; 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 fork begin phase_runner_proc = process::self(); uvm_phase::m_run_phases(); end join_none #0; wait (m_phase_all_done == 1); m_uvm_core_state=UVM_CORE_POST_RUN; phase_runner_proc.kill(); l_rs = uvm_report_server::get_server(); uvm_run_test_callback::m_do_post_run_test(); l_rs.report_summarize(); m_uvm_core_state=UVM_CORE_FINISHED; if (get_finish_on_completion()) $finish; endtask 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 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 function void uvm_root::print_topology(uvm_printer printer=null); 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_printer::get_default(); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVMTOP")) uvm_report_info ("UVMTOP", "UVM testbench topology:", UVM_NONE, "t/uvm/src/base/uvm_root.svh", 640, "", 1); end print(printer) ; endfunction 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 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() != "") comps.push_back(comp); endfunction function bit uvm_root::m_add_child (uvm_component child); if(super.m_add_child(child)) begin return 1; end else return 0; endfunction 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(); endfunction function void uvm_root::m_do_verbosity_settings(); string set_verbosity_settings[$]; string split_vals[$]; uvm_verbosity tmp_verb; 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 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 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 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 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 ,,"}, 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 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 ,[,]"}, UVM_NONE); return; end 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 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 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 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 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 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); foreach (all_args[idx]) begin uvm_report_info("DUMPARGS", $sformatf("idx=%0d arg=[%s]",idx,all_args[idx]), UVM_NONE); end end endfunction function void uvm_root::m_check_verbosity(); string verb_string; string verb_settings[$]; int verb_count; int plusarg; int verbosity = UVM_MEDIUM; verb_count = $value$plusargs("UVM_VERBOSITY=%s",verb_string); if (verb_count) verb_settings.push_back(verb_string); if (verb_count > 0) begin verb_string = verb_settings[0]; plusarg = 1; end 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 function void uvm_root::m_check_uvm_field_flag_size(); if ( (UVM_FIELD_FLAG_RESERVED_BITS) < UVM_FIELD_FLAG_RESERVED_BITS ) begin uvm_report_fatal( "BAD_FIELD_FLAG_SZ", $sformatf( "Macro UVM_FIELD_FLAG_SIZE is set to %0d which is less than the required minimum of UVM_FIELD_FLAG_RESERVED_BITS (%0d).", UVM_FIELD_FLAG_RESERVED_BITS, UVM_FIELD_FLAG_RESERVED_BITS ) ); end endfunction task uvm_root::run_phase (uvm_phase phase); foreach(m_uvm_applied_cl_action[idx]) if(m_uvm_applied_cl_action[idx].used==0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("\"+uvm_set_action=%s\" never took effect due to a mismatching component pattern",m_uvm_applied_cl_action[idx].arg), UVM_NONE, "t/uvm/src/base/uvm_root.svh", 1130, "", 1); end end foreach(m_uvm_applied_cl_sev[idx]) if(m_uvm_applied_cl_sev[idx].used==0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("\"+uvm_set_severity=%s\" never took effect due to a mismatching component pattern",m_uvm_applied_cl_sev[idx].arg), UVM_NONE, "t/uvm/src/base/uvm_root.svh", 1134, "", 1); end end if($time > 0) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RUNPHSTIME")) uvm_report_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."}, UVM_NONE, "t/uvm/src/base/uvm_root.svh", 1141, "", 1); end endtask function void uvm_root::set_enable_print_topology (bit enable); enable_print_topology = enable; endfunction function bit uvm_root::get_enable_print_topology(); return enable_print_topology; endfunction function uvm_component::new (string name, uvm_component parent); string error_str; uvm_root top; uvm_coreservice_t cs; super.new(name); if (parent==null && name == "__top__") begin set_name(""); return; end cs = uvm_coreservice_t::get(); top = cs.get_root(); begin uvm_phase bld; uvm_domain common; common = uvm_domain::get_common_domain(); bld = common.find(uvm_build_phase::get()); if (bld == null) uvm_report_fatal("COMP/INTERNAL", "attempt to find build phase object failed",UVM_NONE); if (bld.get_state() == UVM_PHASE_DONE) begin uvm_report_fatal("ILLCRT", {"It is illegal to create a component ('", name,"' under '", (parent == null ? top.get_full_name() : parent.get_full_name()), "') after the build phase has ended."}, UVM_NONE); end end if (name == "") begin name.itoa(m_inst_count); name = {"COMP_", name}; end if(parent == this) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"THISPARENT")) uvm_report_fatal ("THISPARENT", "cannot set the parent of a component to itself", UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1635, "", 1); end end if (parent == null) parent = top; if(uvm_report_enabled(UVM_MEDIUM+1, UVM_INFO, "NEWCOMP")) begin if (uvm_report_enabled(UVM_MEDIUM+1,UVM_INFO,"NEWCOMP")) uvm_report_info ("NEWCOMP", {"Creating ", (parent==top?"uvm_top":parent.get_full_name()),".",name}, UVM_MEDIUM+1, "t/uvm/src/base/uvm_component.svh", 1643, "", 1); end if (parent.has_child(name) && this != parent.get_child(name)) begin if (parent == top) begin error_str = {"Name '",name,"' is not unique to other top-level ", "instances. If parent is a module, build a unique name by combining the ", "the module name and component name: $sformatf(\"\%m.\%s\",\"",name,"\")."}; begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"CLDEXT")) uvm_report_fatal ("CLDEXT", error_str, UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1650, "", 1); end end else begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"CLDEXT")) uvm_report_fatal ("CLDEXT", $sformatf("Cannot set '%s' as a child of '%s', %s", name, parent.get_full_name(), "which already has a child by that name."), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1656, "", 1); end return; end m_parent = parent; set_name(name); if (!m_parent.m_add_child(this)) m_parent = null; event_pool = new("event_pool"); m_domain = parent.m_domain; reseed(); if (!uvm_config_db #(uvm_bitstream_t)::get(this, "", "recording_detail", recording_detail)) void'(uvm_config_db #(int)::get(this, "", "recording_detail", recording_detail)); m_rh.set_name(get_full_name()); set_report_verbosity_level(parent.get_report_verbosity_level()); m_set_cl_msg_args(); endfunction function bit uvm_component::m_add_child(uvm_component child); if (m_children.exists(child.get_name()) && m_children[child.get_name()] != child) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"BDCLD")) uvm_report_warning ("BDCLD", $sformatf("A child with the name '%0s' (type=%0s) already exists.", child.get_name(), m_children[child.get_name()].get_type_name()), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1695, "", 1); end return 0; end if (m_children_by_handle.exists(child)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"BDCHLD")) uvm_report_warning ("BDCHLD", $sformatf("A child with the name '%0s' %0s %0s'", child.get_name(), "already exists in parent under name '", m_children_by_handle[child].get_name()), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1704, "", 1); end return 0; end m_children[child.get_name()] = child; m_children_by_handle[child] = child; return 1; endfunction function void uvm_component::get_children(ref uvm_component children[$]); foreach(m_children[i]) children.push_back(m_children[i]); endfunction function int uvm_component::get_first_child(ref string name); return m_children.first(name); endfunction function int uvm_component::get_next_child(ref string name); return m_children.next(name); endfunction function uvm_component uvm_component::get_child(string name); if (m_children.exists(name)) return m_children[name]; begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"NOCHILD")) uvm_report_warning ("NOCHILD", {"Component with name '",name, "' is not a child of component '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1754, "", 1); end return null; endfunction function int uvm_component::has_child(string name); return m_children.exists(name); endfunction function int uvm_component::get_num_children(); return m_children.num(); endfunction function string uvm_component::get_full_name (); if(m_name == "") return get_name(); else return m_name; endfunction function uvm_component uvm_component::get_parent (); return m_parent; endfunction function void uvm_component::set_name (string name); if(m_name != "") begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"INVSTNM")) uvm_report_error ("INVSTNM", $sformatf("It is illegal to change the name of a component. The component name will not be changed to \"%s\"", name), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1801, "", 1); end return; end super.set_name(name); m_set_full_name(); endfunction function void uvm_component::m_set_full_name(); uvm_root top; if ($cast(top, m_parent) || m_parent==null) m_name = get_name(); else m_name = {m_parent.get_full_name(), ".", get_name()}; foreach (m_children[c]) begin uvm_component tmp; tmp = m_children[c]; tmp.m_set_full_name(); end endfunction function uvm_component uvm_component::lookup( string name ); string leaf , remainder; uvm_component comp; uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); comp = this; m_extract_name(name, leaf, remainder); if (leaf == "") begin comp = top; m_extract_name(remainder, leaf, remainder); end if (!comp.has_child(leaf)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"Lookup Error")) uvm_report_warning ("Lookup Error", $sformatf("Cannot find child %0s",leaf), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1852, "", 1); end return null; end if( remainder != "" ) return comp.m_children[leaf].lookup(remainder); return comp.m_children[leaf]; endfunction function int unsigned uvm_component::get_depth(); if(m_name == "") return 0; get_depth = 1; foreach(m_name[i]) if(m_name[i] == ".") ++get_depth; endfunction function void uvm_component::m_extract_name(input string name , output string leaf , output string remainder ); int i , len; len = name.len(); for( i = 0; i < name.len(); i++ ) begin if( name[i] == "." ) begin break; end end if( i == len ) begin leaf = name; remainder = ""; return; end leaf = name.substr( 0 , i - 1 ); remainder = name.substr( i + 1 , len - 1 ); return; endfunction function void uvm_component::flush(); return; endfunction function void uvm_component::do_flush(); foreach( m_children[s] ) m_children[s].do_flush(); flush(); endfunction function uvm_object uvm_component::create (string name =""); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"ILLCRT")) uvm_report_error ("ILLCRT", "create cannot be called on a uvm_component. Use create_component instead.", UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1934, "", 1); end return null; endfunction function uvm_object uvm_component::clone (); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"ILLCLN")) uvm_report_error ("ILLCLN", $sformatf("Attempting to clone '%s'. Clone cannot be called on a uvm_component. The clone target variable will be set to null.", get_full_name()), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 1943, "", 1); end return null; endfunction function void uvm_component::print_override_info (string requested_type_name, string name=""); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); factory.debug_create_by_name(requested_type_name, get_full_name(), name); endfunction function uvm_component uvm_component::create_component (string requested_type_name, string name); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); return factory.create_component_by_name(requested_type_name, get_full_name(), name, this); endfunction function uvm_object uvm_component::create_object (string requested_type_name, string name=""); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); return factory.create_object_by_name(requested_type_name, get_full_name(), name); endfunction function void uvm_component::set_type_override (string original_type_name, string override_type_name, bit replace=1); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); factory.set_type_override_by_name(original_type_name,override_type_name, replace); endfunction function void uvm_component::set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); factory.set_type_override_by_type(original_type, override_type, replace); endfunction function void uvm_component::set_inst_override (string relative_inst_path, string original_type_name, string override_type_name); string full_inst_path; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); if (relative_inst_path == "") full_inst_path = get_full_name(); else full_inst_path = {get_full_name(), ".", relative_inst_path}; factory.set_inst_override_by_name( original_type_name, override_type_name, full_inst_path); endfunction function void uvm_component::set_inst_override_by_type (string relative_inst_path, uvm_object_wrapper original_type, uvm_object_wrapper override_type); string full_inst_path; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); if (relative_inst_path == "") full_inst_path = get_full_name(); else full_inst_path = {get_full_name(), ".", relative_inst_path}; factory.set_inst_override_by_type(original_type, override_type, full_inst_path); endfunction function void uvm_component::set_report_id_verbosity_hier( string id, int verbosity); set_report_id_verbosity(id, verbosity); foreach( m_children[c] ) m_children[c].set_report_id_verbosity_hier(id, verbosity); endfunction function void uvm_component::set_report_severity_id_verbosity_hier( uvm_severity severity, string id, int verbosity); set_report_severity_id_verbosity(severity, id, verbosity); foreach( m_children[c] ) m_children[c].set_report_severity_id_verbosity_hier(severity, id, verbosity); endfunction function void uvm_component::set_report_severity_action_hier( uvm_severity severity, uvm_action action); set_report_severity_action(severity, action); foreach( m_children[c] ) m_children[c].set_report_severity_action_hier(severity, action); endfunction function void uvm_component::set_report_id_action_hier( string id, uvm_action action); set_report_id_action(id, action); foreach( m_children[c] ) m_children[c].set_report_id_action_hier(id, action); endfunction function void uvm_component::set_report_severity_id_action_hier( uvm_severity severity, string id, uvm_action action); set_report_severity_id_action(severity, id, action); foreach( m_children[c] ) m_children[c].set_report_severity_id_action_hier(severity, id, action); endfunction function void uvm_component::set_report_severity_file_hier( uvm_severity severity, UVM_FILE file); set_report_severity_file(severity, file); foreach( m_children[c] ) m_children[c].set_report_severity_file_hier(severity, file); endfunction function void uvm_component::set_report_default_file_hier( UVM_FILE file); set_report_default_file(file); foreach( m_children[c] ) m_children[c].set_report_default_file_hier(file); endfunction function void uvm_component::set_report_id_file_hier( string id, UVM_FILE file); set_report_id_file(id, file); foreach( m_children[c] ) m_children[c].set_report_id_file_hier(id, file); endfunction function void uvm_component::set_report_severity_id_file_hier ( uvm_severity severity, string id, UVM_FILE file); set_report_severity_id_file(severity, id, file); foreach( m_children[c] ) m_children[c].set_report_severity_id_file_hier(severity, id, file); endfunction function void uvm_component::set_report_verbosity_level_hier(int verbosity); set_report_verbosity_level(verbosity); foreach( m_children[c] ) m_children[c].set_report_verbosity_level_hier(verbosity); endfunction function void uvm_component::build_phase(uvm_phase phase); m_build_done = 1; if (use_automatic_config()) apply_config_settings(print_config_matches); endfunction function void uvm_component::connect_phase(uvm_phase phase); return; endfunction function void uvm_component::start_of_simulation_phase(uvm_phase phase); return; endfunction function void uvm_component::end_of_elaboration_phase(uvm_phase phase); return; endfunction task uvm_component::run_phase(uvm_phase phase); return; endtask function void uvm_component::extract_phase(uvm_phase phase); return; endfunction function void uvm_component::check_phase(uvm_phase phase); return; endfunction function void uvm_component::report_phase(uvm_phase phase); return; endfunction function void uvm_component::final_phase(uvm_phase phase); return; endfunction task uvm_component::pre_reset_phase(uvm_phase phase); return; endtask task uvm_component::reset_phase(uvm_phase phase); return; endtask task uvm_component::post_reset_phase(uvm_phase phase); return; endtask task uvm_component::pre_configure_phase(uvm_phase phase); return; endtask task uvm_component::configure_phase(uvm_phase phase); return; endtask task uvm_component::post_configure_phase(uvm_phase phase); return; endtask task uvm_component::pre_main_phase(uvm_phase phase); return; endtask task uvm_component::main_phase(uvm_phase phase); return; endtask task uvm_component::post_main_phase(uvm_phase phase); return; endtask task uvm_component::pre_shutdown_phase(uvm_phase phase); return; endtask task uvm_component::shutdown_phase(uvm_phase phase); return; endtask task uvm_component::post_shutdown_phase(uvm_phase phase); return; endtask function void uvm_component::phase_started(uvm_phase phase); endfunction function void uvm_component::phase_ended(uvm_phase phase); endfunction function void uvm_component::phase_ready_to_end (uvm_phase phase); endfunction function void uvm_component::define_domain(uvm_domain domain); uvm_phase schedule; schedule = domain.find_by_name("uvm_sched"); if (schedule == null) begin uvm_domain common; schedule = new("uvm_sched", UVM_PHASE_SCHEDULE); uvm_domain::add_uvm_phases(schedule); domain.add(schedule); common = uvm_domain::get_common_domain(); if (common.find(domain,0) == null) common.add(domain,.with_phase(uvm_run_phase::get())); end endfunction function void uvm_component::set_domain(uvm_domain domain, int hier=1); m_domain = domain; define_domain(domain); if (hier) foreach (m_children[c]) m_children[c].set_domain(domain); endfunction function uvm_domain uvm_component::get_domain(); return m_domain; endfunction task uvm_component::suspend(); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"COMP/SPND/UNIMP")) uvm_report_warning ("COMP/SPND/UNIMP", "suspend() not implemented", UVM_NONE, "t/uvm/src/base/uvm_component.svh", 2395, "", 1); end endtask task uvm_component::resume(); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"COMP/RSUM/UNIMP")) uvm_report_warning ("COMP/RSUM/UNIMP", "resume() not implemented", UVM_NONE, "t/uvm/src/base/uvm_component.svh", 2403, "", 1); end endtask function void uvm_component::resolve_bindings(); return; endfunction function void uvm_component::do_resolve_bindings(); foreach( m_children[s] ) m_children[s].do_resolve_bindings(); resolve_bindings(); endfunction function void uvm_component::accept_tr (uvm_transaction tr, time accept_time=0); uvm_event#(uvm_object) e; if(tr == null) return; tr.accept_tr(accept_time); do_accept_tr(tr); e = event_pool.get("accept_tr"); if(e!=null) e.trigger(); endfunction function int uvm_component::begin_tr (uvm_transaction tr, string stream_name="main", string label="", string desc="", time begin_time=0, int parent_handle=0); return m_begin_tr(tr, parent_handle, stream_name, label, desc, begin_time); endfunction function uvm_tr_database uvm_component::get_tr_database(); if (tr_database == null) begin uvm_coreservice_t cs = uvm_coreservice_t::get(); tr_database = cs.get_default_tr_database(); end return tr_database; endfunction : get_tr_database function void uvm_component::set_tr_database(uvm_tr_database db); tr_database = db; endfunction : set_tr_database function uvm_tr_stream uvm_component::get_tr_stream( string name, string stream_type_name="" ); uvm_tr_database db = get_tr_database(); if (!m_streams.exists(name) || !m_streams[name].exists(stream_type_name)) m_streams[name][stream_type_name] = db.open_stream(name, this.get_full_name(), stream_type_name); return m_streams[name][stream_type_name]; endfunction : get_tr_stream function void uvm_component::free_tr_stream(uvm_tr_stream stream); if (stream == null) return; if (!m_streams.exists(stream.get_name()) || !m_streams[stream.get_name()].exists(stream.get_stream_type_name())) return; if (m_streams[stream.get_name()][stream.get_stream_type_name()] != stream) return; m_streams[stream.get_name()].delete(stream.get_type_name()); if (m_streams[stream.get_name()].size() == 0) m_streams.delete(stream.get_name()); if (stream.is_open() || stream.is_closed()) begin stream.free(); end endfunction : free_tr_stream function int uvm_component::m_begin_tr (uvm_transaction tr, int parent_handle=0, string stream_name="main", string label="", string desc="", time begin_time=0); uvm_event#(uvm_object) e; string name; string kind; uvm_tr_database db; int handle, link_handle; uvm_tr_stream stream; uvm_recorder recorder, parent_recorder, link_recorder; if (tr == null) return 0; db = get_tr_database(); if (parent_handle != 0) parent_recorder = uvm_recorder::get_recorder_from_handle(parent_handle); if (parent_recorder == null) begin uvm_sequence_item seq; if ($cast(seq,tr)) begin uvm_sequence_base parent_seq = seq.get_parent_sequence(); if (parent_seq != null) begin parent_recorder = parent_seq.m_tr_recorder; end end end if(parent_recorder != null) begin link_handle = tr.begin_child_tr(begin_time, parent_recorder.get_handle()); end else begin link_handle = tr.begin_tr(begin_time); end if (link_handle != 0) link_recorder = uvm_recorder::get_recorder_from_handle(link_handle); if (tr.get_name() != "") name = tr.get_name(); else name = tr.get_type_name(); if (uvm_verbosity'(recording_detail) != UVM_NONE) begin if (stream_name == "") stream_name = "main"; stream = get_tr_stream(stream_name, "TVM"); if (stream != null ) begin kind = (parent_recorder == null) ? "Begin_No_Parent, Link" : "Begin_End, Link"; recorder = stream.open_recorder(name, begin_time, kind); if (recorder != null) begin if (label != "") recorder.record_string("label", label); if (desc != "") recorder.record_string("desc", desc); if (parent_recorder != null) begin tr_database.establish_link(uvm_parent_child_link::get_link(parent_recorder, recorder)); end if (link_recorder != null) begin tr_database.establish_link(uvm_related_link::get_link(recorder, link_recorder)); end m_tr_h[tr] = recorder; end end handle = (recorder == null) ? 0 : recorder.get_handle(); do_begin_tr(tr, stream_name, handle); end e = event_pool.get("begin_tr"); if (e!=null) e.trigger(tr); return handle; endfunction function void uvm_component::end_tr (uvm_transaction tr, time end_time=0, bit free_handle=1); uvm_event#(uvm_object) e; uvm_recorder recorder; if (tr == null) return; tr.end_tr(end_time,free_handle); if (uvm_verbosity'(recording_detail) != UVM_NONE) begin if (m_tr_h.exists(tr)) begin recorder = m_tr_h[tr]; do_end_tr(tr, recorder.get_handle()); m_tr_h.delete(tr); tr.record(recorder); recorder.close(end_time); if (free_handle) recorder.free(); end else begin do_end_tr(tr, 0); end end e = event_pool.get("end_tr"); if(e!=null) e.trigger(); endfunction function int uvm_component::record_error_tr (string stream_name="main", uvm_object info=null, string label="error_tr", string desc="", time error_time=0, bit keep_active=0); uvm_recorder recorder; string etype; uvm_tr_stream stream; int handle; if(keep_active) etype = "Error, Link"; else etype = "Error"; if(error_time == 0) error_time = $realtime; if (stream_name == "") stream_name = "main"; stream = get_tr_stream(stream_name, "TVM"); handle = 0; if (stream != null) begin recorder = stream.open_recorder(label, error_time, etype); if (recorder != null) begin if (label != "") recorder.record_string("label", label); if (desc != "") recorder.record_string("desc", desc); if (info!=null) info.record(recorder); recorder.close(error_time); if (keep_active == 0) begin recorder.free(); end else begin handle = recorder.get_handle(); end end end return handle; endfunction function int uvm_component::record_event_tr (string stream_name="main", uvm_object info=null, string label="event_tr", string desc="", time event_time=0, bit keep_active=0); uvm_recorder recorder; string etype; int handle; uvm_tr_stream stream; if(keep_active) etype = "Event, Link"; else etype = "Event"; if(event_time == 0) event_time = $realtime; if (stream_name == "") stream_name = "main"; stream = get_tr_stream(stream_name, "TVM"); handle = 0; if (stream != null) begin recorder = stream.open_recorder(label, event_time, etype); if (recorder != null) begin if (label != "") recorder.record_string("label", label); if (desc != "") recorder.record_string("desc", desc); if (info!=null) info.record(recorder); recorder.close(event_time); if (keep_active == 0) begin recorder.free(); end else begin handle = recorder.get_handle(); end end end return handle; endfunction function void uvm_component::do_accept_tr (uvm_transaction tr); return; endfunction function void uvm_component::do_begin_tr (uvm_transaction tr, string stream_name, int tr_handle); return; endfunction function void uvm_component::do_end_tr (uvm_transaction tr, int tr_handle); return; endfunction function string uvm_component::massage_scope(string scope); if(scope == "") return "^$"; if(scope == "*") return {get_full_name(), ".*"}; if(scope == "uvm_test_top") return "uvm_test_top"; if(scope[0] == ".") return {get_full_name(), scope}; return {get_full_name(), ".", scope}; endfunction function bit uvm_component::use_automatic_config(); return 1; endfunction function void uvm_component::apply_config_settings (bit verbose=0); uvm_resource_pool rp = uvm_resource_pool::get(); uvm_queue#(uvm_resource_base) rq; uvm_resource_base r; rq = rp.lookup_scope(get_full_name()); rp.sort_by_precedence(rq); for(int i=rq.size()-1; i>=0; --i) begin r = rq.get(i); if(verbose) uvm_report_info("CFGAPL",$sformatf("applying configuration to field %s", r.get_name()),UVM_NONE); set_local(r); end endfunction function void uvm_component::print_config(bit recurse = 0, audit = 0); uvm_resource_pool rp = uvm_resource_pool::get(); uvm_report_info("CFGPRT","visible resources:",UVM_INFO); rp.print_resources(rp.lookup_scope(get_full_name()), audit); if(recurse) begin uvm_component c; foreach(m_children[name]) begin c = m_children[name]; c.print_config(recurse, audit); end end endfunction function void uvm_component::print_config_with_audit(bit recurse = 0); print_config(recurse, 1); endfunction function void uvm_component::do_print(uvm_printer printer); super.do_print(printer); if(uvm_verbosity'(recording_detail) != UVM_NONE) case (recording_detail) UVM_LOW : printer.print_generic("recording_detail", "uvm_verbosity", $bits(recording_detail), "UVM_LOW"); UVM_MEDIUM : printer.print_generic("recording_detail", "uvm_verbosity", $bits(recording_detail), "UVM_MEDIUM"); UVM_HIGH : printer.print_generic("recording_detail", "uvm_verbosity", $bits(recording_detail), "UVM_HIGH"); UVM_FULL : printer.print_generic("recording_detail", "uvm_verbosity", $bits(recording_detail), "UVM_FULL"); default : printer.print_field_int("recording_detail", recording_detail, $bits(recording_detail), UVM_DEC, , "integral"); endcase endfunction function void uvm_component::set_local(uvm_resource_base rsrc) ; bit success; if((rsrc != null) && (rsrc.get_name() == "recording_detail")) begin begin begin uvm_resource#(uvm_integral_t) __tmp_rsrc__; success = $cast(__tmp_rsrc__, rsrc); if (success) begin recording_detail = __tmp_rsrc__.read(this); end end if (!success) begin uvm_resource#(uvm_bitstream_t) __tmp_rsrc__; success = $cast(__tmp_rsrc__, rsrc); if (success) begin recording_detail = __tmp_rsrc__.read(this); end end if (!success) begin uvm_resource#(int) __tmp_rsrc__; success = $cast(__tmp_rsrc__, rsrc); if (success) begin recording_detail = __tmp_rsrc__.read(this); end end if (!success) begin uvm_resource#(int unsigned) __tmp_rsrc__; success = $cast(__tmp_rsrc__, rsrc); if (success) begin recording_detail = __tmp_rsrc__.read(this); end end end end if (!success) super.set_local(rsrc); endfunction function void uvm_component::m_unsupported_set_local(uvm_resource_base rsrc); m_unsupported_resource_base = rsrc; endfunction typedef class uvm_cmdline_processor; function void uvm_component::m_set_cl_msg_args; string s_; process p_; p_=process::self(); if(p_!=null) s_=p_.get_randstate(); else begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM")) uvm_report_warning ("UVM", "run_test() invoked from a non process context", UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3043, "", 1); end m_set_cl_verb(); m_set_cl_action(); m_set_cl_sev(); if(p_!=null) p_.set_randstate(s_); endfunction function void uvm_component::m_set_cl_verb; static string values[$]; static bit first = 1; string args[$]; uvm_cmdline_processor clp = uvm_cmdline_processor::get_inst(); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); if(first) begin string t[$]; m_verbosity_setting setting; void'(clp.get_arg_values("+uvm_set_verbosity=",values)); foreach(values[i]) begin args.delete(); uvm_split_string(values[i], ",", args); if(((args.size() == 4) || (args.size() == 5)) && (clp.m_convert_verb(args[2], setting.verbosity) == 1) ) t.push_back(values[i]); else uvm_report_warning("UVM/CMDLINE",$sformatf("argument %s not recognized and therefore dropped",values[i])); end values=t; first=0; end foreach(values[i]) begin m_verbosity_setting setting; args.delete(); uvm_split_string(values[i], ",", args); begin setting.comp = args[0]; setting.id = args[1]; void'(clp.m_convert_verb(args[2],setting.verbosity)); setting.phase = args[3]; setting.offset = 0; if(args.size() == 5) setting.offset = args[4].atoi(); if((setting.phase == "time") && (this == top)) begin m_time_settings.push_back(setting); end if (uvm_is_match(setting.comp, get_full_name()) ) begin if((setting.phase == "" || setting.phase == "build" || setting.phase == "time") && (setting.offset == 0) ) begin if(setting.id == "_ALL_") set_report_verbosity_level(setting.verbosity); else set_report_id_verbosity(setting.id, setting.verbosity); end else begin if(setting.phase != "time") begin m_verbosity_settings.push_back(setting); end end end end end if(this == top) begin fork begin time last_time = 0; if (m_time_settings.size() > 0) m_time_settings.sort() with ( item.offset ); foreach(m_time_settings[i]) begin uvm_component comps[$]; top.find_all(m_time_settings[i].comp,comps); #(m_time_settings[i].offset - last_time); last_time = m_time_settings[i].offset; if(m_time_settings[i].id == "_ALL_") begin foreach(comps[j]) begin comps[j].set_report_verbosity_level(m_time_settings[i].verbosity); end end else begin foreach(comps[j]) begin comps[j].set_report_id_verbosity(m_time_settings[i].id, m_time_settings[i].verbosity); end end end end join_none end endfunction function void uvm_component::m_set_cl_action; static bit initialized = 0; uvm_severity sev; uvm_action action; uvm_cmdline_processor uvm_cmdline_proc = uvm_cmdline_processor::get_inst(); if(!initialized) begin string values[$]; void'(uvm_cmdline_proc.get_arg_values("+uvm_set_action=",values)); foreach(values[idx]) begin uvm_cmdline_parsed_arg_t t; string args[$]; uvm_split_string(values[idx], ",", args); if(args.size() != 4) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("+uvm_set_action requires 4 arguments, but %0d given for command +uvm_set_action=%s, Usage: +uvm_set_action=,,,", args.size(), values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3169, "", 1); end continue; end if((args[2] != "_ALL_") && !uvm_string_to_severity(args[2], sev)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("Bad severity argument \"%s\" given to command +uvm_set_action=%s, Usage: +uvm_set_action=,,,", args[2], values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3173, "", 1); end continue; end if(!uvm_string_to_action(args[3], action)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("Bad action argument \"%s\" given to command +uvm_set_action=%s, Usage: +uvm_set_action=,,,", args[3], values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3177, "", 1); end continue; end t.args=args; t.arg=values[idx]; m_uvm_applied_cl_action.push_back(t); end initialized=1; end foreach(m_uvm_applied_cl_action[i]) begin string args[$] = m_uvm_applied_cl_action[i].args; if (!uvm_is_match(args[0], get_full_name()) ) continue; void'(uvm_string_to_severity(args[2], sev)); void'(uvm_string_to_action(args[3], action)); m_uvm_applied_cl_action[i].used++; if(args[1] == "_ALL_") begin if(args[2] == "_ALL_") begin set_report_severity_action(UVM_INFO, action); set_report_severity_action(UVM_WARNING, action); set_report_severity_action(UVM_ERROR, action); set_report_severity_action(UVM_FATAL, action); end else begin set_report_severity_action(sev, action); end end else begin if(args[2] == "_ALL_") begin set_report_id_action(args[1], action); end else begin set_report_severity_id_action(sev, args[1], action); end end end endfunction function void uvm_component::m_set_cl_sev; static bit initialized; uvm_severity orig_sev, sev; uvm_cmdline_processor uvm_cmdline_proc = uvm_cmdline_processor::get_inst(); if(!initialized) begin string values[$]; void'(uvm_cmdline_proc.get_arg_values("+uvm_set_severity=",values)); foreach(values[idx]) begin uvm_cmdline_parsed_arg_t t; string args[$]; uvm_split_string(values[idx], ",", args); if(args.size() != 4) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("+uvm_set_severity requires 4 arguments, but %0d given for command +uvm_set_severity=%s, Usage: +uvm_set_severity=,,,", args.size(), values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3240, "", 1); end continue; end if(args[2] != "_ALL_" && !uvm_string_to_severity(args[2], orig_sev)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("Bad severity argument \"%s\" given to command +uvm_set_severity=%s, Usage: +uvm_set_severity=,,,", args[2], values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3244, "", 1); end continue; end if(!uvm_string_to_severity(args[3], sev)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"INVLCMDARGS")) uvm_report_warning ("INVLCMDARGS", $sformatf("Bad severity argument \"%s\" given to command +uvm_set_severity=%s, Usage: +uvm_set_severity=,,,", args[3], values[idx]), UVM_NONE, "t/uvm/src/base/uvm_component.svh", 3248, "", 1); end continue; end t.args=args; t.arg=values[idx]; m_uvm_applied_cl_sev.push_back(t); end initialized=1; end foreach(m_uvm_applied_cl_sev[i]) begin string args[$]=m_uvm_applied_cl_sev[i].args; if (!uvm_is_match(args[0], get_full_name()) ) continue; void'(uvm_string_to_severity(args[2], orig_sev)); void'(uvm_string_to_severity(args[3], sev)); m_uvm_applied_cl_sev[i].used++; if(args[1] == "_ALL_" && args[2] == "_ALL_") begin set_report_severity_override(UVM_INFO,sev); set_report_severity_override(UVM_WARNING,sev); set_report_severity_override(UVM_ERROR,sev); set_report_severity_override(UVM_FATAL,sev); end else if(args[1] == "_ALL_") begin set_report_severity_override(orig_sev,sev); end else if(args[2] == "_ALL_") begin set_report_severity_id_override(UVM_INFO,args[1],sev); set_report_severity_id_override(UVM_WARNING,args[1],sev); set_report_severity_id_override(UVM_ERROR,args[1],sev); set_report_severity_id_override(UVM_FATAL,args[1],sev); end else begin set_report_severity_id_override(orig_sev,args[1],sev); end end endfunction function void uvm_component::m_apply_verbosity_settings(uvm_phase phase); int i; while (i < m_verbosity_settings.size()) begin if(phase.get_name() == m_verbosity_settings[i].phase) begin if( m_verbosity_settings[i].offset == 0 ) begin if(m_verbosity_settings[i].id == "_ALL_") set_report_verbosity_level(m_verbosity_settings[i].verbosity); else set_report_id_verbosity(m_verbosity_settings[i].id, m_verbosity_settings[i].verbosity); end else begin process p = process::self(); string p_rand = p.get_randstate(); fork begin m_verbosity_setting setting = m_verbosity_settings[i]; #(setting.offset); if(setting.id == "_ALL_") set_report_verbosity_level(setting.verbosity); else set_report_id_verbosity(setting.id, setting.verbosity); end join_none p.set_randstate(p_rand); end m_verbosity_settings.delete(i); continue; end i++; end endfunction function void uvm_component::m_do_pre_abort; foreach(m_children[i]) m_children[i].m_do_pre_abort(); pre_abort(); endfunction typedef class uvm_objection_context_object; typedef class uvm_objection; typedef class uvm_sequence_base; typedef class uvm_objection_callback; typedef uvm_callbacks #(uvm_objection,uvm_objection_callback) uvm_objection_cbs_t; typedef class uvm_cmdline_processor; class uvm_objection_events; int waiters; event raised; event dropped; event all_dropped; endclass class uvm_objection extends uvm_report_object; static local bit m_register_cb_uvm_objection_callback = uvm_callbacks#(uvm_objection,uvm_objection_callback)::m_register_pair("uvm_objection","uvm_objection_callback"); protected bit m_trace_mode; protected int m_source_count[uvm_object]; protected int m_total_count [uvm_object]; protected time m_drain_time [uvm_object]; protected uvm_objection_events m_events [uvm_object]; bit m_top_all_dropped; protected uvm_root m_top; static uvm_objection m_objections[$]; local static uvm_objection_context_object m_context_pool[$]; local process m_drain_proc[uvm_object]; local static uvm_objection_context_object m_scheduled_list[$]; local uvm_objection_context_object m_scheduled_contexts[uvm_object]; local uvm_objection_context_object m_forked_list[$]; local uvm_objection_context_object m_forked_contexts[uvm_object]; protected bit m_prop_mode = 1; protected bit m_cleared; function new(string name=""); uvm_cmdline_processor clp; uvm_coreservice_t cs_ ; string trace_args[$]; super.new(name); cs_ = uvm_coreservice_t::get(); m_top = cs_.get_root(); set_report_verbosity_level(m_top.get_report_verbosity_level()); clp = uvm_cmdline_processor::get_inst(); if(clp.get_arg_matches("+UVM_OBJECTION_TRACE", trace_args)) begin m_trace_mode=1; end m_objections.push_back(this); endfunction function bit trace_mode (int mode=-1); trace_mode = m_trace_mode; if(mode == 0) m_trace_mode = 0; else if(mode == 1) m_trace_mode = 1; endfunction function void m_report(uvm_object obj, uvm_object source_obj, string description, int count, string action); int _count = m_source_count.exists(obj) ? m_source_count[obj] : 0; int _total = m_total_count.exists(obj) ? m_total_count[obj] : 0; if (!uvm_report_enabled(UVM_NONE,UVM_INFO,"OBJTN_TRC") || !m_trace_mode) return; if (source_obj == obj) uvm_report_info("OBJTN_TRC", $sformatf("Object %0s %0s %0d objection(s)%s: count=%0d total=%0d", obj.get_full_name()==""?"uvm_top":obj.get_full_name(), action, count, description != ""? {" (",description,")"}:"", _count, _total), UVM_NONE); else begin int cpath = 0, last_dot=0; string sname = source_obj.get_full_name(), nm = obj.get_full_name(); int max = sname.len() > nm.len() ? nm.len() : sname.len(); while((sname[cpath] == nm[cpath]) && (cpath < max)) begin if(sname[cpath] == ".") last_dot = cpath; cpath++; end if(last_dot) sname = sname.substr(last_dot+1, sname.len()); uvm_report_info("OBJTN_TRC", $sformatf("Object %0s %0s %0d objection(s) %0s its total (%s from source object %s%s): count=%0d total=%0d", obj.get_full_name()==""?"uvm_top":obj.get_full_name(), action=="raised"?"added":"subtracted", count, action=="raised"?"to":"from", action, sname, description != ""?{", ",description}:"", _count, _total), UVM_NONE); end endfunction function uvm_object m_get_parent(uvm_object obj); uvm_component comp; uvm_sequence_base seq; if ($cast(comp, obj)) begin obj = comp.get_parent(); end else if ($cast(seq, obj)) begin obj = seq.get_sequencer(); end else obj = m_top; if (obj == null) obj = m_top; return obj; endfunction function void m_propagate (uvm_object obj, uvm_object source_obj, string description, int count, bit raise, int in_top_thread); if (obj != null && obj != m_top) begin obj = m_get_parent(obj); if(raise) m_raise(obj, source_obj, description, count); else m_drop(obj, source_obj, description, count, in_top_thread); end endfunction function void set_propagate_mode (bit prop_mode); if (!m_top_all_dropped && (get_objection_total() != 0)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/OBJTN/PROP_MODE")) uvm_report_error ("UVM/BASE/OBJTN/PROP_MODE", {"The propagation mode of '", this.get_full_name(), "' cannot be changed while the objection is raised ", "or draining!"}, UVM_NONE, "t/uvm/src/base/uvm_objection.svh", 265, "", 1); end return; end m_prop_mode = prop_mode; endfunction : set_propagate_mode function bit get_propagate_mode(); return m_prop_mode; endfunction : get_propagate_mode virtual function void raise_objection (uvm_object obj=null, string description="", int count=1); if(obj == null) obj = m_top; m_cleared = 0; m_top_all_dropped = 0; m_raise (obj, obj, description, count); endfunction function void m_raise (uvm_object obj, uvm_object source_obj, string description="", int count=1); int idx; uvm_objection_context_object ctxt; if (count == 0) return; if (m_total_count.exists(obj)) m_total_count[obj] += count; else m_total_count[obj] = count; if (source_obj==obj) begin if (m_source_count.exists(obj)) m_source_count[obj] += count; else m_source_count[obj] = count; end if (m_trace_mode) m_report(obj,source_obj,description,count,"raised"); raised(obj, source_obj, description, count); idx = 0; while (idx < m_scheduled_list.size()) begin if ((m_scheduled_list[idx].obj == obj) && (m_scheduled_list[idx].objection == this)) begin ctxt = m_scheduled_list[idx]; m_scheduled_list.delete(idx); break; end idx++; end if (ctxt == null) begin idx = 0; while (idx < m_forked_list.size()) begin if (m_forked_list[idx].obj == obj) begin ctxt = m_forked_list[idx]; m_forked_list.delete(idx); m_scheduled_contexts.delete(ctxt.obj); break; end idx++; end end if (ctxt == null) begin if (m_forked_contexts.exists(obj)) begin ctxt = m_forked_contexts[obj]; m_forked_contexts.delete(obj); m_drain_proc[obj].kill(); m_drain_proc.delete(obj); end end if (ctxt == null) begin if (!m_prop_mode && obj != m_top) m_raise(m_top,source_obj,description,count); else if (obj != m_top) m_propagate(obj, source_obj, description, count, 1, 0); end else begin int diff_count; diff_count = count - ctxt.count; if (diff_count != 0) begin if (diff_count > 0) begin if (!m_prop_mode && obj != m_top) m_raise(m_top, source_obj, description, diff_count); else if (obj != m_top) m_propagate(obj, source_obj, description, diff_count, 1, 0); end else begin diff_count = -diff_count; if (!m_prop_mode && obj != m_top) m_drop(m_top, source_obj, description, diff_count); else if (obj != m_top) m_propagate(obj, source_obj, description, diff_count, 0, 0); end end ctxt.clear(); m_context_pool.push_back(ctxt); end endfunction virtual function void drop_objection (uvm_object obj=null, string description="", int count=1); if(obj == null) obj = m_top; m_drop (obj, obj, description, count, 0); endfunction function void m_drop (uvm_object obj, uvm_object source_obj, string description="", int count=1, int in_top_thread=0); if (count == 0) return; if (!m_total_count.exists(obj) || (count > m_total_count[obj])) begin if(m_cleared) return; uvm_report_fatal("OBJTN_ZERO", {"Object \"", obj.get_full_name(), "\" attempted to drop objection '",this.get_name(),"' count below zero"}); return; end if (obj == source_obj) begin if (!m_source_count.exists(obj) || (count > m_source_count[obj])) begin if(m_cleared) return; uvm_report_fatal("OBJTN_ZERO", {"Object \"", obj.get_full_name(), "\" attempted to drop objection '",this.get_name(),"' count below zero"}); return; end m_source_count[obj] -= count; end m_total_count[obj] -= count; if (m_trace_mode) m_report(obj,source_obj,description,count,"dropped"); dropped(obj, source_obj, description, count); if (m_total_count[obj] != 0) begin if (!m_prop_mode && obj != m_top) m_drop(m_top,source_obj,description, count, in_top_thread); else if (obj != m_top) begin this.m_propagate(obj, source_obj, description, count, 0, in_top_thread); end end else begin uvm_objection_context_object ctxt; if (m_context_pool.size()) ctxt = m_context_pool.pop_front(); else ctxt = new; ctxt.obj = obj; ctxt.source_obj = source_obj; ctxt.description = description; ctxt.count = count; ctxt.objection = this; m_scheduled_list.push_back(ctxt); end endfunction virtual function void clear(uvm_object obj=null); string name; int idx; if (obj==null) obj=m_top; name = obj.get_full_name(); if (name == "") name = "uvm_top"; else name = obj.get_full_name(); if (!m_top_all_dropped && get_objection_total(m_top)) uvm_report_warning("OBJTN_CLEAR",{"Object '",name, "' cleared objection counts for ",get_name()}); m_source_count.delete(); m_total_count.delete(); idx = 0; while (idx < m_scheduled_list.size()) begin if (m_scheduled_list[idx].objection == this) begin m_scheduled_list[idx].clear(); m_context_pool.push_back(m_scheduled_list[idx]); m_scheduled_list.delete(idx); end else begin idx++; end end m_scheduled_contexts.delete(); while (m_forked_list.size()) begin m_forked_list[0].clear(); m_context_pool.push_back(m_forked_list[0]); void'(m_forked_list.pop_front()); end foreach (m_forked_contexts[o]) begin m_drain_proc[o].kill(); m_drain_proc.delete(o); m_forked_contexts[o].clear(); m_context_pool.push_back(m_forked_contexts[o]); m_forked_contexts.delete(o); end m_top_all_dropped = 0; m_cleared = 1; if (m_events.exists(m_top)) ->m_events[m_top].all_dropped; endfunction static task m_execute_scheduled_forks(); while(1) begin wait(m_scheduled_list.size() != 0); if(m_scheduled_list.size() != 0) begin uvm_objection_context_object c; c = m_scheduled_list.pop_front(); c.objection.m_scheduled_contexts[c.obj] = c; c.objection.m_forked_list.push_back(c); fork : guard automatic uvm_objection objection = c.objection; begin if (objection.m_forked_list.size() > 0) begin uvm_objection_context_object ctxt; ctxt = objection.m_forked_list.pop_front(); objection.m_scheduled_contexts.delete(ctxt.obj); objection.m_forked_contexts[ctxt.obj] = ctxt; objection.m_drain_proc[ctxt.obj] = process::self(); objection.m_forked_drain(ctxt.obj, ctxt.source_obj, ctxt.description, ctxt.count, 1); objection.m_drain_proc.delete(ctxt.obj); objection.m_forked_contexts.delete(ctxt.obj); ctxt.clear(); m_context_pool.push_back(ctxt); end end join_none : guard end end endtask task m_forked_drain (uvm_object obj, uvm_object source_obj, string description="", int count=1, int in_top_thread=0); if (m_drain_time.exists(obj)) #(m_drain_time[obj]); if (m_trace_mode) m_report(obj,source_obj,description,count,"all_dropped"); all_dropped(obj,source_obj,description, count); wait fork; if (m_source_count.exists(obj) && m_source_count[obj] == 0) m_source_count.delete(obj); if (m_total_count.exists(obj) && m_total_count[obj] == 0) m_total_count.delete(obj); if (!m_prop_mode && obj != m_top) m_drop(m_top,source_obj,description, count, 1); else if (obj != m_top) m_propagate(obj, source_obj, description, count, 0, 1); endtask static function void m_init_objections(); fork uvm_objection::m_execute_scheduled_forks(); join_none endfunction function void set_drain_time (uvm_object obj=null, time drain); if (obj==null) obj = m_top; m_drain_time[obj] = drain; endfunction virtual function void raised (uvm_object obj, uvm_object source_obj, string description, int count); uvm_component comp; if ($cast(comp,obj)) comp.raised(this, source_obj, description, count); begin uvm_callback_iter#(uvm_objection,uvm_objection_callback) iter = new(this); uvm_objection_callback cb = iter.first(); while(cb != null) begin cb.raised(this,obj,source_obj,description,count); cb = iter.next(); end end if (m_events.exists(obj)) ->m_events[obj].raised; endfunction virtual function void dropped (uvm_object obj, uvm_object source_obj, string description, int count); uvm_component comp; if($cast(comp,obj)) comp.dropped(this, source_obj, description, count); begin uvm_callback_iter#(uvm_objection,uvm_objection_callback) iter = new(this); uvm_objection_callback cb = iter.first(); while(cb != null) begin cb.dropped(this,obj,source_obj,description,count); cb = iter.next(); end end if (m_events.exists(obj)) ->m_events[obj].dropped; endfunction virtual task all_dropped (uvm_object obj, uvm_object source_obj, string description, int count); uvm_component comp; if($cast(comp,obj)) comp.all_dropped(this, source_obj, description, count); begin uvm_callback_iter#(uvm_objection,uvm_objection_callback) iter = new(this); uvm_objection_callback cb = iter.first(); while(cb != null) begin cb.all_dropped(this,obj,source_obj,description,count); cb = iter.next(); end end if (m_events.exists(obj)) ->m_events[obj].all_dropped; if (obj == m_top) m_top_all_dropped = 1; endtask function void get_objectors(ref uvm_object list[$]); list.delete(); foreach (m_source_count[obj]) list.push_back(obj); endfunction task wait_for(uvm_objection_event objt_event, uvm_object obj=null); if (obj==null) obj = m_top; if (!m_events.exists(obj)) begin m_events[obj] = new; end m_events[obj].waiters++; case (objt_event) UVM_RAISED: @(m_events[obj].raised); UVM_DROPPED: @(m_events[obj].dropped); UVM_ALL_DROPPED: @(m_events[obj].all_dropped); endcase m_events[obj].waiters--; if (m_events[obj].waiters == 0) m_events.delete(obj); endtask task wait_for_total_count(uvm_object obj=null, int count=0); if (obj==null) obj = m_top; if(!m_total_count.exists(obj) && count == 0) return; if (count == 0) wait (!m_total_count.exists(obj) && count == 0); else wait (m_total_count.exists(obj) && m_total_count[obj] == count); endtask function int get_objection_count (uvm_object obj=null); if (obj==null) obj = m_top; if (!m_source_count.exists(obj)) return 0; return m_source_count[obj]; endfunction function int get_objection_total (uvm_object obj=null); if (obj==null) obj = m_top; if (!m_total_count.exists(obj)) return 0; else return m_total_count[obj]; endfunction function time get_drain_time (uvm_object obj=null); if (obj==null) obj = m_top; if (!m_drain_time.exists(obj)) return 0; return m_drain_time[obj]; endfunction protected function string m_display_objections(uvm_object obj=null, bit show_header=1); static string blank=" "; string s; int total; uvm_object list[string]; uvm_object curr_obj; int depth; string name; string this_obj_name; string curr_obj_name; foreach (m_total_count[o]) begin uvm_object theobj = o; if ( m_total_count[o] > 0) list[theobj.get_full_name()] = theobj; end if (obj==null) obj = m_top; total = get_objection_total(obj); s = $sformatf("The total objection count is %0d\n",total); if (total == 0) return s; s = {s,"---------------------------------------------------------\n"}; s = {s,"Source Total \n"}; s = {s,"Count Count Object\n"}; s = {s,"---------------------------------------------------------\n"}; this_obj_name = obj.get_full_name(); curr_obj_name = this_obj_name; do begin curr_obj = list[curr_obj_name]; depth=0; foreach (curr_obj_name[i]) if (curr_obj_name[i] == ".") depth++; name = curr_obj_name; for (int i=curr_obj_name.len()-1;i >= 0; i--) if (curr_obj_name[i] == ".") begin name = curr_obj_name.substr(i+1,curr_obj_name.len()-1); break; end if (curr_obj_name == "") name = "uvm_top"; else depth++; s = {s, $sformatf("%-6d %-6d %s%s\n", m_source_count.exists(curr_obj) ? m_source_count[curr_obj] : 0, m_total_count.exists(curr_obj) ? m_total_count[curr_obj] : 0, blank.substr(0,2*depth), name)}; end while (list.next(curr_obj_name) && curr_obj_name.substr(0,this_obj_name.len()-1) == this_obj_name); s = {s,"---------------------------------------------------------\n"}; return s; endfunction function string convert2string(); return m_display_objections(m_top,1); endfunction function void display_objections(uvm_object obj=null, bit show_header=1); string m = m_display_objections(obj,show_header); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/OBJ/DISPLAY")) uvm_report_info ("UVM/OBJ/DISPLAY", m, UVM_NONE, "t/uvm/src/base/uvm_objection.svh", 1033, "", 1); end endfunction typedef uvm_object_registry#(uvm_objection,"uvm_objection") type_id; static function uvm_objection type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_objection tmp = new(name); return tmp; endfunction virtual function string get_type_name (); return "uvm_objection"; endfunction function void do_copy (uvm_object rhs); uvm_objection _rhs; $cast(_rhs, rhs); m_source_count = _rhs.m_source_count; m_total_count = _rhs.m_total_count; m_drain_time = _rhs.m_drain_time; m_prop_mode = _rhs.m_prop_mode; endfunction endclass typedef class uvm_cmdline_processor; class uvm_objection_context_object; uvm_object obj; uvm_object source_obj; string description; int count; uvm_objection objection; function void clear(); obj = null; source_obj = null; description = ""; count = 0; objection = null; endfunction : clear endclass typedef uvm_objection uvm_callbacks_objection; class uvm_objection_callback extends uvm_callback; function new(string name); super.new(name); endfunction virtual function void raised (uvm_objection objection, uvm_object obj, uvm_object source_obj, string description, int count); endfunction virtual function void dropped (uvm_objection objection, uvm_object obj, uvm_object source_obj, string description, int count); endfunction virtual task all_dropped (uvm_objection objection, uvm_object obj, uvm_object source_obj, string description, int count); endtask endclass typedef enum { UVM_ALL_ACTIVE, UVM_ONE_ACTIVE, UVM_ANY_ACTIVE, UVM_NO_HB_MODE } uvm_heartbeat_modes; typedef class uvm_heartbeat_callback; typedef uvm_callbacks #(uvm_objection,uvm_heartbeat_callback) uvm_heartbeat_cbs_t ; typedef class uvm_objection_callback; class uvm_heartbeat extends uvm_object; protected uvm_objection m_objection; protected uvm_heartbeat_callback m_cb; protected uvm_component m_cntxt; protected uvm_heartbeat_modes m_mode; protected uvm_component m_hblist[$]; protected uvm_event#(uvm_object) m_event; protected bit m_started; protected event m_stop_event; function new(string name, uvm_component cntxt, uvm_objection objection=null); uvm_coreservice_t cs; super.new(name); m_objection = objection; cs = uvm_coreservice_t::get(); if(cntxt != null) m_cntxt = cntxt; else m_cntxt = cs.get_root(); m_cb = new({name,"_cb"},m_cntxt); endfunction function uvm_heartbeat_modes set_mode (uvm_heartbeat_modes mode = UVM_NO_HB_MODE); set_mode = m_mode; if(mode == UVM_ANY_ACTIVE || mode == UVM_ONE_ACTIVE || mode == UVM_ALL_ACTIVE) m_mode = mode; endfunction function void set_heartbeat (uvm_event#(uvm_object) e, ref uvm_component comps[$]); uvm_object c; foreach(comps[i]) begin c = comps[i]; if(!m_cb.cnt.exists(c)) m_cb.cnt[c]=0; if(!m_cb.last_trigger.exists(c)) m_cb.last_trigger[c]=0; end if(e==null && m_event==null) return; start(e); endfunction function void add (uvm_component comp); uvm_object c = comp; if(m_cb.cnt.exists(c)) return; m_cb.cnt[c]=0; m_cb.last_trigger[c]=0; endfunction function void remove (uvm_component comp); uvm_object c = comp; if(m_cb.cnt.exists(c)) m_cb.cnt.delete(c); if(m_cb.last_trigger.exists(c)) m_cb.last_trigger.delete(c); endfunction function void start (uvm_event#(uvm_object) e=null); if(m_event == null && e == null) begin m_cntxt.uvm_report_warning("NOEVNT", { "start() was called for: ", get_name(), " with a null trigger and no currently set trigger" }, UVM_NONE); return; end if((m_event != null) && (e != m_event) && m_started) begin m_cntxt.uvm_report_error("ILHBVNT", { "start() was called for: ", get_name(), " with trigger ", e.get_name(), " which is different ", "from the original trigger ", m_event.get_name() }, UVM_NONE); return; end if(e != null) m_event = e; m_enable_cb(); m_start_hb_process(); endfunction function void stop (); m_started = 0; ->m_stop_event; m_disable_cb(); endfunction function void m_start_hb_process(); if(m_started) return; m_started = 1; fork m_hb_process; join_none endfunction protected bit m_added; function void m_enable_cb; void'(m_cb.callback_mode(1)); if(m_objection == null) return; if(!m_added) uvm_heartbeat_cbs_t::add(m_objection, m_cb); m_added = 1; endfunction function void m_disable_cb; void'(m_cb.callback_mode(0)); endfunction task m_hb_process; uvm_object obj; bit triggered; time last_trigger=0; fork begin while(1) begin m_event.wait_trigger(); if(triggered) begin case (m_mode) UVM_ALL_ACTIVE: begin foreach(m_cb.cnt[idx]) begin obj = idx; if(!m_cb.cnt[obj]) begin m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s for component %s since last event trigger at time %0t : last update time was %0t", m_objection.get_name(), obj.get_full_name(), last_trigger, m_cb.last_trigger[obj]), UVM_NONE); end end end UVM_ANY_ACTIVE: begin if(m_cb.cnt.num() && !m_cb.objects_triggered()) begin string s; foreach(m_cb.cnt[idx]) begin obj = idx; s={s,"\n ",obj.get_full_name()}; end m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s on any component since last event trigger at time %0t. The list of registered components is:%s", m_objection.get_name(), last_trigger, s), UVM_NONE); end end UVM_ONE_ACTIVE: begin if(m_cb.objects_triggered() > 1) begin string s; foreach(m_cb.cnt[idx]) begin obj = idx; if(m_cb.cnt[obj]) $swrite(s,"%s\n %s (updated: %0t)", s, obj.get_full_name(), m_cb.last_trigger[obj]); end m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Recieved update of %s from more than one component since last event trigger at time %0t. The list of triggered components is:%s", m_objection.get_name(), last_trigger, s), UVM_NONE); end if(m_cb.cnt.num() && !m_cb.objects_triggered()) begin string s; foreach(m_cb.cnt[idx]) begin obj = idx; s={s,"\n ",obj.get_full_name()}; end m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s on any component since last event trigger at time %0t. The list of registered components is:%s", m_objection.get_name(), last_trigger, s), UVM_NONE); end end endcase end m_cb.reset_counts(); last_trigger = $realtime; triggered = 1; end end @(m_stop_event); join_any disable fork; endtask endclass class uvm_heartbeat_callback extends uvm_objection_callback; int cnt [uvm_object]; time last_trigger [uvm_object]; uvm_object target; uvm_coreservice_t cs = uvm_coreservice_t::get(); function new(string name, uvm_object target); super.new(name); if (target != null) this.target = target; else this.target = cs.get_root(); endfunction virtual function void raised (uvm_objection objection, uvm_object obj, uvm_object source_obj, string description, int count); if(obj == target) begin if(!cnt.exists(source_obj)) cnt[source_obj] = 0; cnt[source_obj] = cnt[source_obj]+1; last_trigger[source_obj] = $realtime; end endfunction virtual function void dropped (uvm_objection objection, uvm_object obj, uvm_object source_obj, string description, int count); raised(objection,obj,source_obj,description,count); endfunction function void reset_counts; foreach(cnt[i]) cnt[i] = 0; endfunction function int objects_triggered; objects_triggered = 0; foreach(cnt[i]) if (cnt[i] != 0) objects_triggered++; endfunction endclass class uvm_cmd_line_verb; string comp_path; string id; uvm_verbosity verb; int exec_time; endclass typedef class uvm_cmdline_processor; uvm_cmdline_processor uvm_cmdline_proc; class uvm_cmdline_processor extends uvm_report_object; static local uvm_cmdline_processor m_inst; static function uvm_cmdline_processor get_inst(); if(m_inst == null) m_inst = new("uvm_cmdline_proc"); uvm_cmdline_proc = m_inst; return m_inst; endfunction protected string m_argv[$]; protected string m_plus_argv[$]; protected string m_uvm_argv[$]; function void get_args (output string args[$]); args = m_argv; endfunction function void get_plusargs (output string args[$]); args = m_plus_argv; endfunction function void get_uvm_args (output string args[$]); args = m_uvm_argv; endfunction function int get_arg_matches (string match, ref string args[$]); bit match_is_regex = (match.len() > 2) && (match[0] == "/") && (match[match.len()-1] == "/"); int len = match.len(); args.delete(); foreach (m_argv[i]) begin if ( match_is_regex && uvm_is_match( match, m_argv[i] ) ) begin args.push_back( m_argv[i] ); end else if((m_argv[i].len() >= len) && (m_argv[i].substr(0,len - 1) == match)) begin args.push_back(m_argv[i]); end end return args.size(); endfunction function int get_arg_value (string match, ref string value); int chars = match.len(); get_arg_value = 0; foreach (m_argv[i]) begin if(m_argv[i].len() >= chars) begin if(m_argv[i].substr(0,chars-1) == match) begin get_arg_value++; if(get_arg_value == 1) value = m_argv[i].substr(chars,m_argv[i].len()-1); end end end endfunction function int get_arg_values (string match, ref string values[$]); int chars = match.len(); values.delete(); foreach (m_argv[i]) begin if(m_argv[i].len() >= chars) begin if(m_argv[i].substr(0,chars-1) == match) values.push_back(m_argv[i].substr(chars,m_argv[i].len()-1)); end end return values.size(); endfunction function string get_tool_name (); return uvm_dpi_get_tool_name(); endfunction function string get_tool_version (); return uvm_dpi_get_tool_version(); endfunction function new(string name = ""); string s; string sub; int doInit=1; super.new(name); do begin s = uvm_dpi_get_next_arg(doInit); doInit=0; if(s!="") begin m_argv.push_back(s); if(s[0] == "+") begin m_plus_argv.push_back(s); end if(s.len() >= 4 && (s[0]=="-" || s[0]=="+")) begin sub = s.substr(1,3); sub = sub.toupper(); if(sub == "UVM") m_uvm_argv.push_back(s); end end end while(s!=""); endfunction function bit m_convert_verb(string verb_str, output uvm_verbosity verb_enum); case (verb_str) "NONE" : begin verb_enum = UVM_NONE; return 1; end "UVM_NONE" : begin verb_enum = UVM_NONE; return 1; end "LOW" : begin verb_enum = UVM_LOW; return 1; end "UVM_LOW" : begin verb_enum = UVM_LOW; return 1; end "MEDIUM" : begin verb_enum = UVM_MEDIUM; return 1; end "UVM_MEDIUM" : begin verb_enum = UVM_MEDIUM; return 1; end "HIGH" : begin verb_enum = UVM_HIGH; return 1; end "UVM_HIGH" : begin verb_enum = UVM_HIGH; return 1; end "FULL" : begin verb_enum = UVM_FULL; return 1; end "UVM_FULL" : begin verb_enum = UVM_FULL; return 1; end "DEBUG" : begin verb_enum = UVM_DEBUG; return 1; end "UVM_DEBUG" : begin verb_enum = UVM_DEBUG; return 1; end default : begin return 0; end endcase endfunction endclass virtual class uvm_visitor#(type NODE=uvm_component) extends uvm_object; function new (string name = ""); super.new(name); endfunction virtual function void begin_v(); endfunction virtual function void end_v(); endfunction pure virtual function void visit(NODE node); endclass virtual class uvm_structure_proxy#(type STRUCTURE=uvm_component) extends uvm_object; function new (string name = ""); super.new(name); endfunction pure virtual function void get_immediate_children(STRUCTURE s, ref STRUCTURE children[$]); endclass virtual class uvm_visitor_adapter#(type STRUCTURE=uvm_component,VISITOR=uvm_visitor#(STRUCTURE)) extends uvm_object; pure virtual function void accept(STRUCTURE s, VISITOR v,uvm_structure_proxy#(STRUCTURE) p, bit invoke_begin_end=1); function new (string name = ""); super.new(name); endfunction endclass class uvm_top_down_visitor_adapter#(type STRUCTURE=uvm_component,VISITOR=uvm_visitor#(STRUCTURE)) extends uvm_visitor_adapter#(STRUCTURE,VISITOR); function new (string name = ""); super.new(name); endfunction virtual function void accept(STRUCTURE s, VISITOR v,uvm_structure_proxy#(STRUCTURE) p, bit invoke_begin_end=1); STRUCTURE c[$]; if(invoke_begin_end) v.begin_v(); v.visit(s); p.get_immediate_children(s, c); foreach(c[idx]) accept(c[idx],v,p,0); if(invoke_begin_end) v.end_v(); endfunction endclass class uvm_bottom_up_visitor_adapter#(type STRUCTURE=uvm_component,VISITOR=uvm_visitor#(STRUCTURE)) extends uvm_visitor_adapter#(STRUCTURE,VISITOR); function new (string name = ""); super.new(name); endfunction virtual function void accept(STRUCTURE s, VISITOR v,uvm_structure_proxy#(STRUCTURE) p, bit invoke_begin_end=1); STRUCTURE c[$]; if(invoke_begin_end) v.begin_v(); p.get_immediate_children(s, c); foreach(c[idx]) accept(c[idx],v,p,0); v.visit(s); if(invoke_begin_end) v.end_v(); endfunction endclass class uvm_by_level_visitor_adapter#(type STRUCTURE=uvm_component,VISITOR=uvm_visitor#(STRUCTURE)) extends uvm_visitor_adapter#(STRUCTURE,VISITOR); function new (string name = ""); super.new(name); endfunction virtual function void accept(STRUCTURE s, VISITOR v,uvm_structure_proxy#(STRUCTURE) p, bit invoke_begin_end=1); STRUCTURE c[$]; c.push_back(s); if(invoke_begin_end) v.begin_v(); while(c.size() > 0) begin STRUCTURE q[$]; foreach(c[idx]) begin STRUCTURE t[$]; v.visit(c[idx]); p.get_immediate_children(c[idx], t); q = {q,t}; end c=q; end if(invoke_begin_end) v.end_v(); endfunction endclass class uvm_component_proxy extends uvm_structure_proxy#(uvm_component); virtual function void get_immediate_children(STRUCTURE s, ref STRUCTURE children[$]); s.get_children(children); endfunction function new (string name = ""); super.new(name); endfunction endclass class uvm_component_name_check_visitor extends uvm_visitor#(uvm_component); local uvm_root _root; virtual function string get_name_constraint(); return "/^[][[:alnum:](){}_:-]([][[:alnum:](){} _:-]*[][[:alnum:](){}_:-])?$/"; endfunction virtual function void visit(NODE node); if(_root != node) begin if ( ! uvm_is_match( get_name_constraint(), node.get_name() ) ) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/COMP/NAME")) uvm_report_warning ("UVM/COMP/NAME", $sformatf("the name \"%s\" of the component \"%s\" violates the uvm component name constraints",node.get_name(),node.get_full_name()), UVM_NONE, "t/uvm/src/base/uvm_traversal.svh", 274, "", 1); end end end endfunction function new (string name = ""); super.new(name); endfunction virtual function void begin_v(); uvm_coreservice_t cs = uvm_coreservice_t::get(); _root = cs.get_root(); begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/COMP/NAMECHECK")) uvm_report_info ("UVM/COMP/NAMECHECK", "This implementation of the component name checks requires DPI to be enabled", UVM_NONE, "t/uvm/src/base/uvm_traversal.svh", 289, "", 1); end endfunction endclass virtual class uvm_set_get_dap_base#(type T=int) extends uvm_object; typedef uvm_set_get_dap_base#(T) this_type; function new(string name="unnamed-uvm_set_get_dap_base#(T)"); super.new(name); endfunction : new pure virtual function void set(T value); pure virtual function bit try_set(T value); pure virtual function T get(); pure virtual function bit try_get(output T value); endclass : uvm_set_get_dap_base class uvm_simple_lock_dap#(type T=int) extends uvm_set_get_dap_base#(T); typedef uvm_simple_lock_dap#(T) this_type; typedef uvm_object_registry #(uvm_simple_lock_dap#(T)) type_id; static function uvm_simple_lock_dap#(T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_simple_lock_dap#(T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction local T m_value; local bit m_locked; function new(string name="unnamed-uvm_simple_lock_dap#(T)"); super.new(name); m_locked = 0; endfunction : new virtual function void set(T value); if (m_locked) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SIMPLE_LOCK_DAP/SAG")) uvm_report_error ("UVM/SIMPLE_LOCK_DAP/SAG", $sformatf("Attempt to set new value on '%s', but the data access policy forbids setting while locked!", get_full_name()), UVM_NONE, "t/uvm/src/dap/uvm_simple_lock_dap.svh", 68, "", 1); end else begin m_value = value; end endfunction : set virtual function bit try_set(T value); if (m_locked) return 0; else begin m_value = value; return 1; end endfunction : try_set virtual function T get(); return m_value; endfunction : get virtual function bit try_get(output T value); value = get(); return 1; endfunction : try_get function void lock(); m_locked = 1; endfunction : lock function void unlock(); m_locked = 0; endfunction : unlock function bit is_locked(); return m_locked; endfunction : is_locked virtual function void do_copy(uvm_object rhs); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SIMPLE_LOCK_DAP/CPY")) uvm_report_error ("UVM/SIMPLE_LOCK_DAP/CPY", "'copy()' is not supported for 'uvm_simple_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_simple_lock_dap.svh", 144, "", 1); end endfunction : do_copy virtual function void do_pack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SIMPLE_LOCK_DAP/PCK")) uvm_report_error ("UVM/SIMPLE_LOCK_DAP/PCK", "'pack()' is not supported for 'uvm_simple_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_simple_lock_dap.svh", 149, "", 1); end endfunction : do_pack virtual function void do_unpack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SIMPLE_LOCK_DAP/UPK")) uvm_report_error ("UVM/SIMPLE_LOCK_DAP/UPK", "'unpack()' is not supported for 'uvm_simple_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_simple_lock_dap.svh", 154, "", 1); end endfunction : do_unpack virtual function string convert2string(); if (m_locked) return $sformatf("(%s) %0p [LOCKED]", $typename(m_value), m_value); else return $sformatf("(%s) %0p [UNLOCKED]", $typename(m_value), m_value); endfunction : convert2string virtual function void do_print(uvm_printer printer); super.do_print(printer); printer.print_field("lock_state", m_locked, $bits(m_locked)); printer.print_generic("value", $typename(m_value), 0, $sformatf("%0p", m_value)); endfunction : do_print endclass class uvm_get_to_lock_dap#(type T=int) extends uvm_set_get_dap_base#(T); typedef uvm_get_to_lock_dap#(T) this_type; typedef uvm_object_registry #(uvm_get_to_lock_dap#(T)) type_id; static function uvm_get_to_lock_dap#(T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_get_to_lock_dap#(T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction local T m_value; local bit m_locked; function new(string name="unnamed-uvm_get_to_lock_dap#(T)"); super.new(name); m_locked = 0; endfunction : new virtual function void set(T value); if (m_locked) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/GET_TO_LOCK_DAP/SAG")) uvm_report_error ("UVM/GET_TO_LOCK_DAP/SAG", $sformatf("Attempt to set new value on '%s', but the data access policy forbids setting after a get!", get_full_name()), UVM_NONE, "t/uvm/src/dap/uvm_get_to_lock_dap.svh", 67, "", 1); end else begin m_value = value; end endfunction : set virtual function bit try_set(T value); if (m_locked) return 0; else begin m_value = value; return 1; end endfunction : try_set virtual function T get(); m_locked = 1; return m_value; endfunction : get virtual function bit try_get(output T value); value = get(); return 1; endfunction : try_get virtual function void do_copy(uvm_object rhs); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/GET_TO_LOCK_DAP/CPY")) uvm_report_error ("UVM/GET_TO_LOCK_DAP/CPY", "'copy()' is not supported for 'uvm_get_to_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_get_to_lock_dap.svh", 119, "", 1); end endfunction : do_copy virtual function void do_pack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/GET_TO_LOCK_DAP/PCK")) uvm_report_error ("UVM/GET_TO_LOCK_DAP/PCK", "'pack()' is not supported for 'uvm_get_to_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_get_to_lock_dap.svh", 124, "", 1); end endfunction : do_pack virtual function void do_unpack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/GET_TO_LOCK_DAP/UPK")) uvm_report_error ("UVM/GET_TO_LOCK_DAP/UPK", "'unpack()' is not supported for 'uvm_get_to_lock_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_get_to_lock_dap.svh", 129, "", 1); end endfunction : do_unpack virtual function string convert2string(); if (m_locked) return $sformatf("(%s) %0p [LOCKED]", $typename(m_value), m_value); else return $sformatf("(%s) %0p [UNLOCKED]", $typename(m_value), m_value); endfunction : convert2string virtual function void do_print(uvm_printer printer); super.do_print(printer); printer.print_field_int("lock_state", m_locked, $bits(m_locked)); printer.print_generic("value", $typename(m_value), 0, $sformatf("%0p", m_value)); endfunction : do_print endclass class uvm_set_before_get_dap#(type T=int) extends uvm_set_get_dap_base#(T); typedef uvm_set_before_get_dap#(T) this_type; typedef uvm_object_registry #(uvm_set_before_get_dap#(T)) type_id; static function uvm_set_before_get_dap#(T) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_set_before_get_dap#(T) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction local T m_value; local bit m_set; function new(string name="unnamed-uvm_set_before_get_dap#(T)"); super.new(name); m_set = 0; endfunction : new virtual function void set(T value); m_set = 1; m_value = value; endfunction : set virtual function bit try_set(T value); set(value); return 1; endfunction : try_set virtual function T get(); if (!m_set) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SET_BEFORE_GET_DAP/NO_SET")) uvm_report_error ("UVM/SET_BEFORE_GET_DAP/NO_SET", $sformatf("Attempt to get value on '%s', but the data access policy forbits calling 'get' prior to calling 'set' or 'try_set'!", get_full_name()), UVM_NONE, "t/uvm/src/dap/uvm_set_before_get_dap.svh", 117, "", 1); end end return m_value; endfunction : get virtual function bit try_get(output T value); if (!m_set) begin return 0; end else begin value = m_value; return 1; end endfunction : try_get virtual function void do_copy(uvm_object rhs); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SET_BEFORE_GET_DAP/CPY")) uvm_report_error ("UVM/SET_BEFORE_GET_DAP/CPY", "'copy()' is not supported for 'uvm_set_before_get_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_set_before_get_dap.svh", 149, "", 1); end endfunction : do_copy virtual function void do_pack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SET_BEFORE_GET_DAP/PCK")) uvm_report_error ("UVM/SET_BEFORE_GET_DAP/PCK", "'pack()' is not supported for 'uvm_set_before_get_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_set_before_get_dap.svh", 154, "", 1); end endfunction : do_pack virtual function void do_unpack(uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/SET_BEFORE_GET_DAP/UPK")) uvm_report_error ("UVM/SET_BEFORE_GET_DAP/UPK", "'unpack()' is not supported for 'uvm_set_before_get_dap#(T)'", UVM_NONE, "t/uvm/src/dap/uvm_set_before_get_dap.svh", 159, "", 1); end endfunction : do_unpack virtual function string convert2string(); if (m_set) return $sformatf("(%s) %0p [SET]", $typename(m_value), m_value); else return $sformatf("(%s) %0p [UNSET]", $typename(m_value), m_value); endfunction : convert2string virtual function void do_print(uvm_printer printer); super.do_print(printer); printer.print_field_int("set_state", m_set, $bits(m_set)); printer.print_generic("value", $typename(m_value), 0, $sformatf("%0p", m_value)); endfunction : do_print endclass virtual class uvm_tlm_if_base #(type T1=int, type T2=int); virtual task put( input T1 t ); uvm_report_error("put", "UVM TLM interface task not implemented", UVM_NONE); endtask virtual task get( output T2 t ); uvm_report_error("get", "UVM TLM interface task not implemented", UVM_NONE); endtask virtual task peek( output T2 t ); uvm_report_error("peek", "UVM TLM interface task not implemented", UVM_NONE); endtask virtual function bit try_put( input T1 t ); uvm_report_error("try_put", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_put(); uvm_report_error("can_put", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function bit try_get( output T2 t ); uvm_report_error("try_get", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_get(); uvm_report_error("can_get", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function bit try_peek( output T2 t ); uvm_report_error("try_peek", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_peek(); uvm_report_error("can_ppeek", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual task transport( input T1 req , output T2 rsp ); uvm_report_error("transport", "UVM TLM interface task not implemented", UVM_NONE); endtask virtual function bit nb_transport(input T1 req, output T2 rsp); uvm_report_error("nb_transport", "UVM TLM interface function not implemented", UVM_NONE); return 0; endfunction virtual function void write( input T1 t ); uvm_report_error("write", "UVM TLM interface function not implemented", UVM_NONE); endfunction endclass virtual class uvm_sqr_if_base #(type T1=uvm_object, T2=T1); virtual task get_next_item(output T1 t); uvm_report_error("get_next_item", "Sequencer interface task not implemented", UVM_NONE); endtask virtual task try_next_item(output T1 t); uvm_report_error("try_next_item", "Sequencer interface task not implemented", UVM_NONE); endtask virtual function void item_done(input T2 t = null); uvm_report_error("item_done", "Sequencer interface function not implemented", UVM_NONE); endfunction virtual task wait_for_sequences(); uvm_report_error("wait_for_sequences", "Sequencer interface task not implemented", UVM_NONE); endtask virtual function bit has_do_available(); uvm_report_error("has_do_available", "Sequencer interface function not implemented", UVM_NONE); return 0; endfunction virtual task get(output T1 t); uvm_report_error("get", "Sequencer interface task not implemented", UVM_NONE); endtask virtual task peek(output T1 t); uvm_report_error("peek", "Sequencer interface task not implemented", UVM_NONE); endtask virtual task put(input T2 t); uvm_report_error("put", "Sequencer interface task not implemented", UVM_NONE); endtask virtual function void put_response(input T2 t); uvm_report_error("put_response", "Sequencer interface function not implemented", UVM_NONE); endfunction virtual function void disable_auto_item_recording(); uvm_report_error("disable_auto_item_recording", "Sequencer interface function not implemented", UVM_NONE); endfunction virtual function bit is_auto_item_recording_enabled(); uvm_report_error("is_auto_item_recording_enabled", "Sequencer interface function not implemented", UVM_NONE); return 0; endfunction endclass const int UVM_UNBOUNDED_CONNECTIONS = -1; const string s_connection_error_id = "Connection Error"; const string s_connection_warning_id = "Connection Warning"; const string s_spaces = " "; typedef class uvm_port_component_base; typedef uvm_port_component_base uvm_port_list[string]; virtual class uvm_port_component_base extends uvm_component; function new (string name, uvm_component parent); super.new(name,parent); endfunction pure virtual function void get_connected_to(ref uvm_port_list list); pure virtual function bit is_port(); pure virtual function bit is_export(); pure virtual function bit is_imp(); virtual function bit use_automatic_config(); return 0; endfunction : use_automatic_config virtual task do_task_phase (uvm_phase phase); endtask endclass class uvm_port_component #(type PORT=uvm_object) extends uvm_port_component_base; PORT m_port; function new (string name, uvm_component parent, PORT port); super.new(name,parent); if (port == null) uvm_report_fatal("Bad usage", "Null handle to port", UVM_NONE); m_port = port; endfunction virtual function string get_type_name(); if(m_port == null) return "uvm_port_component"; return m_port.get_type_name(); endfunction virtual function void resolve_bindings(); m_port.resolve_bindings(); endfunction function PORT get_port(); return m_port; endfunction virtual function void get_connected_to(ref uvm_port_list list); PORT list1[string]; m_port.get_connected_to(list1); list.delete(); foreach(list1[name]) begin list[name] = list1[name].get_comp(); end endfunction function bit is_port (); return m_port.is_port(); endfunction function bit is_export (); return m_port.is_export(); endfunction function bit is_imp (); return m_port.is_imp(); endfunction endclass virtual class uvm_port_base #(type IF=uvm_void) extends IF; typedef uvm_port_base #(IF) this_type; protected int unsigned m_if_mask; protected this_type m_if; protected int unsigned m_def_index; uvm_port_component #(this_type) m_comp; local this_type m_provided_by[string]; local this_type m_provided_to[string]; local uvm_port_type_e m_port_type; local int m_min_size; local int m_max_size; local bit m_resolved; local this_type m_imp_list[string]; function new (string name, uvm_component parent, uvm_port_type_e port_type, int min_size=0, int max_size=1); uvm_component comp; int tmp; m_port_type = port_type; m_min_size = min_size; m_max_size = max_size; m_comp = new(name, parent, this); if (!uvm_config_int::get(m_comp, "", "check_connection_relationships",tmp)) m_comp.set_report_id_action(s_connection_warning_id, UVM_NO_ACTION); endfunction function string get_name(); return m_comp.get_name(); endfunction virtual function string get_full_name(); return m_comp.get_full_name(); endfunction virtual function uvm_component get_parent(); return m_comp.get_parent(); endfunction virtual function uvm_port_component_base get_comp(); return m_comp; endfunction virtual function string get_type_name(); case( m_port_type ) UVM_PORT : return "port"; UVM_EXPORT : return "export"; UVM_IMPLEMENTATION : return "implementation"; endcase endfunction function int max_size (); return m_max_size; endfunction function int min_size (); return m_min_size; endfunction function bit is_unbounded (); return (m_max_size == UVM_UNBOUNDED_CONNECTIONS); endfunction function bit is_port (); return m_port_type == UVM_PORT; endfunction function bit is_export (); return m_port_type == UVM_EXPORT; endfunction function bit is_imp (); return m_port_type == UVM_IMPLEMENTATION; endfunction function int size (); return m_imp_list.num(); endfunction function void set_if (int index=0); m_if = get_if(index); if (m_if != null) m_def_index = index; endfunction function int m_get_if_mask(); return m_if_mask; endfunction function void set_default_index (int index); m_def_index = index; endfunction virtual function void connect (this_type provider); uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); if (end_of_elaboration_ph.get_state() == UVM_PHASE_EXECUTING || end_of_elaboration_ph.get_state() == UVM_PHASE_DONE ) begin m_comp.uvm_report_warning("Late Connection", {"Attempt to connect ",this.get_full_name()," (of type ",this.get_type_name(), ") at or after end_of_elaboration phase. Ignoring."}); return; end if (provider == null) begin m_comp.uvm_report_error(s_connection_error_id, "Cannot connect to null port handle", UVM_NONE); return; end if (provider == this) begin m_comp.uvm_report_error(s_connection_error_id, "Cannot connect a port instance to itself", UVM_NONE); return; end if ((provider.m_if_mask & m_if_mask) != m_if_mask) begin m_comp.uvm_report_error(s_connection_error_id, {provider.get_full_name(), " (of type ",provider.get_type_name(), ") does not provide the complete interface required of this port (type ", get_type_name(),")"}, UVM_NONE); return; end if (is_imp()) begin m_comp.uvm_report_error(s_connection_error_id, $sformatf( "Cannot call an imp port's connect method. An imp is connected only to the component passed in its constructor. (You attempted to bind this imp to %s)", provider.get_full_name()), UVM_NONE); return; end if (is_export() && provider.is_port()) begin m_comp.uvm_report_error(s_connection_error_id, $sformatf( "Cannot connect exports to ports Try calling port.connect(export) instead. (You attempted to bind this export to %s).", provider.get_full_name()), UVM_NONE); return; end void'(m_check_relationship(provider)); m_provided_by[provider.get_full_name()] = provider; provider.m_provided_to[get_full_name()] = this; endfunction function void debug_connected_to (int level=0, int max_level=-1); int sz, num, curr_num; string s_sz; static string indent, save; this_type port; if (level < 0) level = 0; if (level == 0) begin save = ""; indent=" "; end if (max_level != -1 && level >= max_level) return; num = m_provided_by.num(); if (m_provided_by.num() != 0) begin foreach (m_provided_by[nm]) begin curr_num++; port = m_provided_by[nm]; save = {save, indent, " | \n"}; save = {save, indent, " |_",nm," (",port.get_type_name(),")\n"}; indent = (num > 1 && curr_num != num) ? {indent," | "}:{indent, " "}; port.debug_connected_to(level+1, max_level); indent = indent.substr(0,indent.len()-4-1); end end if (level == 0) begin if (save != "") save = {"This port's fanout network:\n\n ", get_full_name()," (",get_type_name(),")\n",save,"\n"}; if (m_imp_list.num() == 0) begin uvm_root top; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); top = cs.get_root(); if (end_of_elaboration_ph.get_state() == UVM_PHASE_EXECUTING || end_of_elaboration_ph.get_state() == UVM_PHASE_DONE ) save = {save," Connected implementations: none\n"}; else save = {save, " Connected implementations: not resolved until end-of-elab\n"}; end else begin save = {save," Resolved implementation list:\n"}; foreach (m_imp_list[nm]) begin port = m_imp_list[nm]; s_sz.itoa(sz); save = {save, indent, s_sz, ": ",nm," (",port.get_type_name(),")\n"}; sz++; end end m_comp.uvm_report_info("debug_connected_to", save); end endfunction function void debug_provided_to (int level=0, int max_level=-1); string nm; int num,curr_num; this_type port; static string indent, save; if (level < 0) level = 0; if (level == 0) begin save = ""; indent = " "; end if (max_level != -1 && level > max_level) return; num = m_provided_to.num(); if (num != 0) begin foreach (m_provided_to[nm]) begin curr_num++; port = m_provided_to[nm]; save = {save, indent, " | \n"}; save = {save, indent, " |_",nm," (",port.get_type_name(),")\n"}; indent = (num > 1 && curr_num != num) ? {indent," | "}:{indent, " "}; port.debug_provided_to(level+1, max_level); indent = indent.substr(0,indent.len()-4-1); end end if (level == 0) begin if (save != "") save = {"This port's fanin network:\n\n ", get_full_name()," (",get_type_name(),")\n",save,"\n"}; if (m_provided_to.num() == 0) save = {save,indent,"This port has not been bound\n"}; m_comp.uvm_report_info("debug_provided_to", save); end endfunction function void get_connected_to (ref uvm_port_base #(IF) list[string]); this_type port; list.delete(); foreach (m_provided_by[name]) begin port = m_provided_by[name]; list[name] = port; end endfunction function void get_provided_to (ref uvm_port_base #(IF) list[string]); this_type port; list.delete(); foreach (m_provided_to[name]) begin port = m_provided_to[name]; list[name] = port; end endfunction local function bit m_check_relationship (this_type provider); string s; this_type from; uvm_component from_parent; uvm_component to_parent; uvm_component from_gparent; uvm_component to_gparent; if (get_type_name() == "uvm_analysis_port") return 1; from = this; from_parent = get_parent(); to_parent = provider.get_parent(); if (from_parent == null || to_parent == null) return 1; from_gparent = from_parent.get_parent(); to_gparent = to_parent.get_parent(); if (from.is_port() && provider.is_port() && from_gparent != to_parent) begin s = {provider.get_full_name(), " (of type ",provider.get_type_name(), ") is not up one level of hierarchy from this port. ", "A port-to-port connection takes the form ", "child_component.child_port.connect(parent_port)"}; m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE); return 0; end else if (from.is_port() && (provider.is_export() || provider.is_imp()) && from_gparent != to_gparent) begin s = {provider.get_full_name(), " (of type ",provider.get_type_name(), ") is not at the same level of hierarchy as this port. ", "A port-to-export connection takes the form ", "component1.port.connect(component2.export)"}; m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE); return 0; end else if (from.is_export() && (provider.is_export() || provider.is_imp()) && from_parent != to_gparent) begin s = {provider.get_full_name(), " (of type ",provider.get_type_name(), ") is not down one level of hierarchy from this export. ", "An export-to-export or export-to-imp connection takes the form ", "parent_export.connect(child_component.child_export)"}; m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE); return 0; end return 1; endfunction local function void m_add_list (this_type provider); string sz; this_type imp; for (int i = 0; i < provider.size(); i++) begin imp = provider.get_if(i); if (!m_imp_list.exists(imp.get_full_name())) m_imp_list[imp.get_full_name()] = imp; end endfunction virtual function void resolve_bindings(); if (m_resolved) return; if (is_imp()) begin m_imp_list[get_full_name()] = this; end else begin foreach (m_provided_by[nm]) begin this_type port; port = m_provided_by[nm]; port.resolve_bindings(); m_add_list(port); end end m_resolved = 1; if (size() < min_size() ) begin m_comp.uvm_report_error(s_connection_error_id, $sformatf("connection count of %0d does not meet required minimum of %0d", size(), min_size()), UVM_NONE); end if (max_size() != UVM_UNBOUNDED_CONNECTIONS && size() > max_size() ) begin m_comp.uvm_report_error(s_connection_error_id, $sformatf("connection count of %0d exceeds maximum of %0d", size(), max_size()), UVM_NONE); end if (size()) set_if(0); endfunction function uvm_port_base #(IF) get_if(int index=0); string s; if (size()==0) begin m_comp.uvm_report_warning("get_if", "Port size is zero; cannot get interface at any index", UVM_NONE); return null; end if (index < 0 || index >= size()) begin $sformat(s, "Index %0d out of range [0,%0d]", index, size()-1); m_comp.uvm_report_warning(s_connection_error_id, s, UVM_NONE); return null; end foreach (m_imp_list[nm]) begin if (index == 0) return m_imp_list[nm]; index--; end endfunction endclass class uvm_blocking_put_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_blocking_put_imp"; endfunction task put (T t); m_imp.put(t); endtask endclass class uvm_nonblocking_put_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<4); endfunction virtual function string get_type_name(); return "uvm_nonblocking_put_imp"; endfunction function bit try_put (T t); return m_imp.try_put(t); endfunction function bit can_put(); return m_imp.can_put(); endfunction endclass class uvm_put_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<0) | (1<<4)); endfunction virtual function string get_type_name(); return "uvm_put_imp"; endfunction task put (T t); m_imp.put(t); endtask function bit try_put (T t); return m_imp.try_put(t); endfunction function bit can_put(); return m_imp.can_put(); endfunction endclass class uvm_blocking_get_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_blocking_get_imp"; endfunction task get (output T t); m_imp.get(t); endtask endclass class uvm_nonblocking_get_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<5); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_imp"; endfunction function bit try_get (output T t); return m_imp.try_get(t); endfunction function bit can_get(); return m_imp.can_get(); endfunction endclass class uvm_get_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<1) | (1<<5)); endfunction virtual function string get_type_name(); return "uvm_get_imp"; endfunction task get (output T t); m_imp.get(t); endtask function bit try_get (output T t); return m_imp.try_get(t); endfunction function bit can_get(); return m_imp.can_get(); endfunction endclass class uvm_blocking_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_blocking_peek_imp"; endfunction task peek (output T t); m_imp.peek(t); endtask endclass class uvm_nonblocking_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<6); endfunction virtual function string get_type_name(); return "uvm_nonblocking_peek_imp"; endfunction function bit try_peek (output T t); return m_imp.try_peek(t); endfunction function bit can_peek(); return m_imp.can_peek(); endfunction endclass class uvm_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<2) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_peek_imp"; endfunction task peek (output T t); m_imp.peek(t); endtask function bit try_peek (output T t); return m_imp.try_peek(t); endfunction function bit can_peek(); return m_imp.can_peek(); endfunction endclass class uvm_blocking_get_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<1) | (1<<2)); endfunction virtual function string get_type_name(); return "uvm_blocking_get_peek_imp"; endfunction task get (output T t); m_imp.get(t); endtask task peek (output T t); m_imp.peek(t); endtask endclass class uvm_nonblocking_get_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<5) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_peek_imp"; endfunction function bit try_get (output T t); return m_imp.try_get(t); endfunction function bit can_get(); return m_imp.can_get(); endfunction function bit try_peek (output T t); return m_imp.try_peek(t); endfunction function bit can_peek(); return m_imp.can_peek(); endfunction endclass class uvm_get_peek_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (((1<<1) | (1<<5)) | ((1<<2) | (1<<6))); endfunction virtual function string get_type_name(); return "uvm_get_peek_imp"; endfunction task get (output T t); m_imp.get(t); endtask task peek (output T t); m_imp.peek(t); endtask function bit try_get (output T t); return m_imp.try_get(t); endfunction function bit can_get(); return m_imp.can_get(); endfunction function bit try_peek (output T t); return m_imp.try_peek(t); endfunction function bit can_peek(); return m_imp.can_peek(); endfunction endclass class uvm_blocking_master_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_blocking_master_imp"; endfunction task put (REQ t); m_req_imp.put(t); endtask task get (output RSP t); m_rsp_imp.get(t); endtask task peek (output RSP t); m_rsp_imp.peek(t); endtask endclass class uvm_nonblocking_master_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_master_imp"; endfunction function bit try_put (REQ t); return m_req_imp.try_put(t); endfunction function bit can_put(); return m_req_imp.can_put(); endfunction function bit try_get (output RSP t); return m_rsp_imp.try_get(t); endfunction function bit can_get(); return m_rsp_imp.can_get(); endfunction function bit try_peek (output RSP t); return m_rsp_imp.try_peek(t); endfunction function bit can_peek(); return m_rsp_imp.can_peek(); endfunction endclass class uvm_master_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<9)) | ((1<<4) | (1<<5) | (1<<6) | (1<<9))); endfunction virtual function string get_type_name(); return "uvm_master_imp"; endfunction task put (REQ t); m_req_imp.put(t); endtask function bit try_put (REQ t); return m_req_imp.try_put(t); endfunction function bit can_put(); return m_req_imp.can_put(); endfunction task get (output RSP t); m_rsp_imp.get(t); endtask task peek (output RSP t); m_rsp_imp.peek(t); endtask function bit try_get (output RSP t); return m_rsp_imp.try_get(t); endfunction function bit can_get(); return m_rsp_imp.can_get(); endfunction function bit try_peek (output RSP t); return m_rsp_imp.try_peek(t); endfunction function bit can_peek(); return m_rsp_imp.can_peek(); endfunction endclass class uvm_blocking_slave_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_blocking_slave_imp"; endfunction task put (RSP t); m_rsp_imp.put(t); endtask task get (output REQ t); m_req_imp.get(t); endtask task peek (output REQ t); m_req_imp.peek(t); endtask endclass class uvm_nonblocking_slave_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_slave_imp"; endfunction function bit try_put (RSP t); return m_rsp_imp.try_put(t); endfunction function bit can_put(); return m_rsp_imp.can_put(); endfunction function bit try_get (output REQ t); return m_req_imp.try_get(t); endfunction function bit can_get(); return m_req_imp.can_get(); endfunction function bit try_peek (output REQ t); return m_req_imp.try_peek(t); endfunction function bit can_peek(); return m_req_imp.can_peek(); endfunction endclass class uvm_slave_imp #(type REQ=int, type RSP=REQ, type IMP=int, type REQ_IMP=IMP, type RSP_IMP=IMP) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); typedef IMP this_imp_type; typedef REQ_IMP this_req_type; typedef RSP_IMP this_rsp_type; local this_req_type m_req_imp; local this_rsp_type m_rsp_imp; function new (string name, this_imp_type imp, this_req_type req_imp = null, this_rsp_type rsp_imp = null); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); if(req_imp==null) $cast(req_imp, imp); if(rsp_imp==null) $cast(rsp_imp, imp); m_req_imp = req_imp; m_rsp_imp = rsp_imp; m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<10)) | ((1<<4) | (1<<5) | (1<<6) | (1<<10))); endfunction virtual function string get_type_name(); return "uvm_slave_imp"; endfunction task put (RSP t); m_rsp_imp.put(t); endtask function bit try_put (RSP t); return m_rsp_imp.try_put(t); endfunction function bit can_put(); return m_rsp_imp.can_put(); endfunction task get (output REQ t); m_req_imp.get(t); endtask task peek (output REQ t); m_req_imp.peek(t); endtask function bit try_get (output REQ t); return m_req_imp.try_get(t); endfunction function bit can_get(); return m_req_imp.can_get(); endfunction function bit try_peek (output REQ t); return m_req_imp.try_peek(t); endfunction function bit can_peek(); return m_req_imp.can_peek(); endfunction endclass class uvm_blocking_transport_imp #(type REQ=int, type RSP=REQ, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<3); endfunction virtual function string get_type_name(); return "uvm_blocking_transport_imp"; endfunction task transport (REQ req, output RSP rsp); m_imp.transport(req, rsp); endtask endclass class uvm_nonblocking_transport_imp #(type REQ=int, type RSP=REQ, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<7); endfunction virtual function string get_type_name(); return "uvm_nonblocking_transport_imp"; endfunction function bit nb_transport (REQ req, output RSP rsp); return m_imp.nb_transport(req, rsp); endfunction endclass class uvm_transport_imp #(type REQ=int, type RSP=REQ, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<3) | (1<<7)); endfunction virtual function string get_type_name(); return "uvm_transport_imp"; endfunction task transport (REQ req, output RSP rsp); m_imp.transport(req, rsp); endtask function bit nb_transport (REQ req, output RSP rsp); return m_imp.nb_transport(req, rsp); endfunction endclass class uvm_blocking_put_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_blocking_put_port"; endfunction task put (T t); this.m_if.put(t); endtask endclass class uvm_nonblocking_put_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<4); endfunction virtual function string get_type_name(); return "uvm_nonblocking_put_port"; endfunction function bit try_put (T t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction endclass class uvm_put_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<4)); endfunction virtual function string get_type_name(); return "uvm_put_port"; endfunction task put (T t); this.m_if.put(t); endtask function bit try_put (T t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction endclass class uvm_blocking_get_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_blocking_get_port"; endfunction task get (output T t); this.m_if.get(t); endtask endclass class uvm_nonblocking_get_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<5); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_port"; endfunction function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction endclass class uvm_get_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<1) | (1<<5)); endfunction virtual function string get_type_name(); return "uvm_get_port"; endfunction task get (output T t); this.m_if.get(t); endtask function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction endclass class uvm_blocking_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_blocking_peek_port"; endfunction task peek (output T t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<6); endfunction virtual function string get_type_name(); return "uvm_nonblocking_peek_port"; endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<2) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_peek_port"; endfunction task peek (output T t); this.m_if.peek(t); endtask function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_get_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<1) | (1<<2)); endfunction virtual function string get_type_name(); return "uvm_blocking_get_peek_port"; endfunction task get (output T t); this.m_if.get(t); endtask task peek (output T t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_get_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<5) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_peek_port"; endfunction function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_get_peek_port #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (((1<<1) | (1<<5)) | ((1<<2) | (1<<6))); endfunction virtual function string get_type_name(); return "uvm_get_peek_port"; endfunction task get (output T t); this.m_if.get(t); endtask task peek (output T t); this.m_if.peek(t); endtask function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_master_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_blocking_master_port"; endfunction task put (REQ t); this.m_if.put(t); endtask task get (output RSP t); this.m_if.get(t); endtask task peek (output RSP t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_master_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_master_port"; endfunction function bit try_put (REQ t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction function bit try_get (output RSP t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output RSP t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_master_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<9)) | ((1<<4) | (1<<5) | (1<<6) | (1<<9))); endfunction virtual function string get_type_name(); return "uvm_master_port"; endfunction task put (REQ t); this.m_if.put(t); endtask function bit try_put (REQ t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction task get (output RSP t); this.m_if.get(t); endtask task peek (output RSP t); this.m_if.peek(t); endtask function bit try_get (output RSP t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output RSP t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_slave_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_blocking_slave_port"; endfunction task put (RSP t); this.m_if.put(t); endtask task get (output REQ t); this.m_if.get(t); endtask task peek (output REQ t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_slave_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_slave_port"; endfunction function bit try_put (RSP t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction function bit try_get (output REQ t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output REQ t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_slave_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<10)) | ((1<<4) | (1<<5) | (1<<6) | (1<<10))); endfunction virtual function string get_type_name(); return "uvm_slave_port"; endfunction task put (RSP t); this.m_if.put(t); endtask function bit try_put (RSP t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction task get (output REQ t); this.m_if.get(t); endtask task peek (output REQ t); this.m_if.peek(t); endtask function bit try_get (output REQ t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output REQ t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_transport_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<3); endfunction virtual function string get_type_name(); return "uvm_blocking_transport_port"; endfunction task transport (REQ req, output RSP rsp); this.m_if.transport(req, rsp); endtask endclass class uvm_nonblocking_transport_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<7); endfunction virtual function string get_type_name(); return "uvm_nonblocking_transport_port"; endfunction function bit nb_transport (REQ req, output RSP rsp); return this.m_if.nb_transport(req, rsp); endfunction endclass class uvm_transport_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<3) | (1<<7)); endfunction virtual function string get_type_name(); return "uvm_transport_port"; endfunction task transport (REQ req, output RSP rsp); this.m_if.transport(req, rsp); endtask function bit nb_transport (REQ req, output RSP rsp); return this.m_if.nb_transport(req, rsp); endfunction endclass class uvm_blocking_put_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_blocking_put_export"; endfunction task put (T t); this.m_if.put(t); endtask endclass class uvm_nonblocking_put_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<4); endfunction virtual function string get_type_name(); return "uvm_nonblocking_put_export"; endfunction function bit try_put (T t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction endclass class uvm_put_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<4)); endfunction virtual function string get_type_name(); return "uvm_put_export"; endfunction task put (T t); this.m_if.put(t); endtask function bit try_put (T t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction endclass class uvm_blocking_get_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_blocking_get_export"; endfunction task get (output T t); this.m_if.get(t); endtask endclass class uvm_nonblocking_get_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<5); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_export"; endfunction function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction endclass class uvm_get_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<1) | (1<<5)); endfunction virtual function string get_type_name(); return "uvm_get_export"; endfunction task get (output T t); this.m_if.get(t); endtask function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction endclass class uvm_blocking_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_blocking_peek_export"; endfunction task peek (output T t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<6); endfunction virtual function string get_type_name(); return "uvm_nonblocking_peek_export"; endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<2) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_peek_export"; endfunction task peek (output T t); this.m_if.peek(t); endtask function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_get_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<1) | (1<<2)); endfunction virtual function string get_type_name(); return "uvm_blocking_get_peek_export"; endfunction task get (output T t); this.m_if.get(t); endtask task peek (output T t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_get_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<5) | (1<<6)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_get_peek_export"; endfunction function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_get_peek_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (((1<<1) | (1<<5)) | ((1<<2) | (1<<6))); endfunction virtual function string get_type_name(); return "uvm_get_peek_export"; endfunction task get (output T t); this.m_if.get(t); endtask task peek (output T t); this.m_if.peek(t); endtask function bit try_get (output T t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output T t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_master_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_blocking_master_export"; endfunction task put (REQ t); this.m_if.put(t); endtask task get (output RSP t); this.m_if.get(t); endtask task peek (output RSP t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_master_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<9)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_master_export"; endfunction function bit try_put (REQ t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction function bit try_get (output RSP t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output RSP t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_master_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<9)) | ((1<<4) | (1<<5) | (1<<6) | (1<<9))); endfunction virtual function string get_type_name(); return "uvm_master_export"; endfunction task put (REQ t); this.m_if.put(t); endtask function bit try_put (REQ t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction task get (output RSP t); this.m_if.get(t); endtask task peek (output RSP t); this.m_if.peek(t); endtask function bit try_get (output RSP t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output RSP t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_slave_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_blocking_slave_export"; endfunction task put (RSP t); this.m_if.put(t); endtask task get (output REQ t); this.m_if.get(t); endtask task peek (output REQ t); this.m_if.peek(t); endtask endclass class uvm_nonblocking_slave_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<4) | (1<<5) | (1<<6) | (1<<10)); endfunction virtual function string get_type_name(); return "uvm_nonblocking_slave_export"; endfunction function bit try_put (RSP t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction function bit try_get (output REQ t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output REQ t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_slave_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(RSP, REQ)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (((1<<0) | (1<<1) | (1<<2) | (1<<10)) | ((1<<4) | (1<<5) | (1<<6) | (1<<10))); endfunction virtual function string get_type_name(); return "uvm_slave_export"; endfunction task put (RSP t); this.m_if.put(t); endtask function bit try_put (RSP t); return this.m_if.try_put(t); endfunction function bit can_put(); return this.m_if.can_put(); endfunction task get (output REQ t); this.m_if.get(t); endtask task peek (output REQ t); this.m_if.peek(t); endtask function bit try_get (output REQ t); return this.m_if.try_get(t); endfunction function bit can_get(); return this.m_if.can_get(); endfunction function bit try_peek (output REQ t); return this.m_if.try_peek(t); endfunction function bit can_peek(); return this.m_if.can_peek(); endfunction endclass class uvm_blocking_transport_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<3); endfunction virtual function string get_type_name(); return "uvm_blocking_transport_export"; endfunction task transport (REQ req, output RSP rsp); this.m_if.transport(req, rsp); endtask endclass class uvm_nonblocking_transport_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<7); endfunction virtual function string get_type_name(); return "uvm_nonblocking_transport_export"; endfunction function bit nb_transport (REQ req, output RSP rsp); return this.m_if.nb_transport(req, rsp); endfunction endclass class uvm_transport_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_tlm_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<3) | (1<<7)); endfunction virtual function string get_type_name(); return "uvm_transport_export"; endfunction task transport (REQ req, output RSP rsp); this.m_if.transport(req, rsp); endtask function bit nb_transport (REQ req, output RSP rsp); return this.m_if.nb_transport(req, rsp); endfunction endclass class uvm_analysis_port # (type T = int) extends uvm_port_base # (uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent); super.new (name, parent, UVM_PORT, 0, UVM_UNBOUNDED_CONNECTIONS); m_if_mask = (1<<8); endfunction virtual function string get_type_name(); return "uvm_analysis_port"; endfunction function void write (input T t); uvm_tlm_if_base # (T, T) tif; for (int i = 0; i < this.size(); i++) begin tif = this.get_if (i); if ( tif == null ) uvm_report_fatal ("NTCONN", {"No uvm_tlm interface is connected to ", get_full_name(), " for executing write()"}, UVM_NONE); tif.write (t); end endfunction endclass class uvm_analysis_imp #(type T=int, type IMP=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<8); endfunction virtual function string get_type_name(); return "uvm_analysis_imp"; endfunction function void write (input T t); m_imp.write (t); endfunction endclass class uvm_analysis_export #(type T=int) extends uvm_port_base #(uvm_tlm_if_base #(T,T)); function new (string name, uvm_component parent = null); super.new (name, parent, UVM_EXPORT, 1, UVM_UNBOUNDED_CONNECTIONS); m_if_mask = (1<<8); endfunction virtual function string get_type_name(); return "uvm_analysis_export"; endfunction function void write (input T t); uvm_tlm_if_base #(T, T) tif; for (int i = 0; i < this.size(); i++) begin tif = this.get_if (i); if (tif == null) uvm_report_fatal ("NTCONN", {"No uvm_tlm interface is connected to ", get_full_name(), " for executing write()"}, UVM_NONE); tif.write (t); end endfunction endclass class uvm_tlm_event; event trigger; endclass virtual class uvm_tlm_fifo_base #(type T=int) extends uvm_component; typedef uvm_abstract_component_registry #(uvm_tlm_fifo_base #(T)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction typedef uvm_tlm_fifo_base #(T) this_type; uvm_put_imp #(T, this_type) put_export; uvm_get_peek_imp #(T, this_type) get_peek_export; uvm_analysis_port #(T) put_ap; uvm_analysis_port #(T) get_ap; uvm_put_imp #(T, this_type) blocking_put_export; uvm_put_imp #(T, this_type) nonblocking_put_export; uvm_get_peek_imp #(T, this_type) blocking_get_export; uvm_get_peek_imp #(T, this_type) nonblocking_get_export; uvm_get_peek_imp #(T, this_type) get_export; uvm_get_peek_imp #(T, this_type) blocking_peek_export; uvm_get_peek_imp #(T, this_type) nonblocking_peek_export; uvm_get_peek_imp #(T, this_type) peek_export; uvm_get_peek_imp #(T, this_type) blocking_get_peek_export; uvm_get_peek_imp #(T, this_type) nonblocking_get_peek_export; function new(string name, uvm_component parent = null); super.new(name, parent); put_export = new("put_export", this); blocking_put_export = put_export; nonblocking_put_export = put_export; get_peek_export = new("get_peek_export", this); blocking_get_peek_export = get_peek_export; nonblocking_get_peek_export = get_peek_export; blocking_get_export = get_peek_export; nonblocking_get_export = get_peek_export; get_export = get_peek_export; blocking_peek_export = get_peek_export; nonblocking_peek_export = get_peek_export; peek_export = get_peek_export; put_ap = new("put_ap", this); get_ap = new("get_ap", this); endfunction virtual function bit use_automatic_config(); return 0; endfunction : use_automatic_config virtual function void flush(); uvm_report_error("flush", "fifo channel function not implemented", UVM_NONE); endfunction virtual function int size(); uvm_report_error("size", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual task put(T t); uvm_report_error("put", "fifo channel task not implemented", UVM_NONE); endtask virtual task get(output T t); uvm_report_error("get", "fifo channel task not implemented", UVM_NONE); endtask virtual task peek(output T t); uvm_report_error("peek", "fifo channel task not implemented", UVM_NONE); endtask virtual function bit try_put(T t); uvm_report_error("try_put", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit try_get(output T t); uvm_report_error("try_get", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit try_peek(output T t); uvm_report_error("try_peek", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_put(); uvm_report_error("can_put", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_get(); uvm_report_error("can_get", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit can_peek(); uvm_report_error("can_peek", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function uvm_tlm_event ok_to_put(); uvm_report_error("ok_to_put", "fifo channel function not implemented", UVM_NONE); return null; endfunction virtual function uvm_tlm_event ok_to_get(); uvm_report_error("ok_to_get", "fifo channel function not implemented", UVM_NONE); return null; endfunction virtual function uvm_tlm_event ok_to_peek(); uvm_report_error("ok_to_peek", "fifo channel function not implemented", UVM_NONE); return null; endfunction virtual function bit is_empty(); uvm_report_error("is_empty", "fifo channel function not implemented", UVM_NONE); return 0; endfunction virtual function bit is_full(); uvm_report_error("is_full", "fifo channel function not implemented"); return 0; endfunction virtual function int used(); uvm_report_error("used", "fifo channel function not implemented", UVM_NONE); return 0; endfunction endclass typedef class uvm_tlm_event; class uvm_tlm_fifo #(type T=int) extends uvm_tlm_fifo_base #(T); typedef uvm_component_registry #(uvm_tlm_fifo#(T)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_tlm_fifo #(T)"; endfunction : type_name virtual function string get_type_name(); return "uvm_tlm_fifo #(T)"; endfunction : get_type_name local mailbox #( T ) m; local int m_size; protected int m_pending_blocked_gets; function new(string name, uvm_component parent = null, int size = 1); super.new(name, parent); m = new( size ); m_size = size; endfunction virtual function int size(); return m_size; endfunction virtual function int used(); return m.num(); endfunction virtual function bit is_empty(); return (m.num() == 0); endfunction virtual function bit is_full(); return (m_size != 0) && (m.num() == m_size); endfunction virtual task put( input T t ); m.put( t ); put_ap.write( t ); endtask virtual task get( output T t ); m_pending_blocked_gets++; m.get( t ); m_pending_blocked_gets--; get_ap.write( t ); endtask virtual task peek( output T t ); m.peek( t ); endtask virtual function bit try_get( output T t ); if( !m.try_get( t ) ) begin return 0; end get_ap.write( t ); return 1; endfunction virtual function bit try_peek( output T t ); if( !m.try_peek( t ) ) begin return 0; end return 1; endfunction virtual function bit try_put( input T t ); if( !m.try_put( t ) ) begin return 0; end put_ap.write( t ); return 1; endfunction virtual function bit can_put(); return m_size == 0 || m.num() < m_size; endfunction virtual function bit can_get(); return m.num() > 0 && m_pending_blocked_gets == 0; endfunction virtual function bit can_peek(); return m.num() > 0; endfunction virtual function void flush(); T t; bit r; r = 1; while( r ) r = try_get( t ) ; if( m.num() > 0 && m_pending_blocked_gets != 0 ) begin uvm_report_error("flush failed" , "there are blocked gets preventing the flush", UVM_NONE); end endfunction endclass class uvm_tlm_analysis_fifo #(type T = int) extends uvm_tlm_fifo #(T); typedef uvm_component_registry #(uvm_tlm_analysis_fifo#(T)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_tlm_analysis_fifo #(T)"; endfunction : type_name virtual function string get_type_name(); return "uvm_tlm_analysis_fifo #(T)"; endfunction : get_type_name uvm_analysis_imp #(T, uvm_tlm_analysis_fifo #(T)) analysis_export; function new(string name , uvm_component parent = null); super.new(name, parent, 0); analysis_export = new("analysis_export", this); endfunction function void write(input T t); void'(this.try_put(t)); endfunction endclass class uvm_tlm_req_rsp_channel #(type REQ=int, type RSP=REQ) extends uvm_component; typedef uvm_tlm_req_rsp_channel #(REQ, RSP) this_type; typedef uvm_component_registry #(uvm_tlm_req_rsp_channel#(REQ,RSP)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_tlm_req_rsp_channel #(REQ,RSP)"; endfunction : type_name virtual function string get_type_name(); return "uvm_tlm_req_rsp_channel #(REQ,RSP)"; endfunction : get_type_name uvm_put_export #(REQ) put_request_export; uvm_get_peek_export #(RSP) get_peek_response_export; uvm_get_peek_export #(REQ) get_peek_request_export; uvm_put_export #(RSP) put_response_export; uvm_analysis_port #(REQ) request_ap; uvm_analysis_port #(RSP) response_ap; uvm_master_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) master_export; uvm_slave_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) slave_export; uvm_put_export #(REQ) blocking_put_request_export, nonblocking_put_request_export; uvm_get_peek_export #(REQ) get_request_export, blocking_get_request_export, nonblocking_get_request_export, peek_request_export, blocking_peek_request_export, nonblocking_peek_request_export, blocking_get_peek_request_export, nonblocking_get_peek_request_export; uvm_put_export #(RSP) blocking_put_response_export, nonblocking_put_response_export; uvm_get_peek_export #(RSP) get_response_export, blocking_get_response_export, nonblocking_get_response_export, peek_response_export, blocking_peek_response_export, nonblocking_peek_response_export, blocking_get_peek_response_export, nonblocking_get_peek_response_export; uvm_master_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) blocking_master_export, nonblocking_master_export; uvm_slave_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) blocking_slave_export, nonblocking_slave_export; protected uvm_tlm_fifo #(REQ) m_request_fifo; protected uvm_tlm_fifo #(RSP) m_response_fifo; function new (string name, uvm_component parent=null, int request_fifo_size=1, int response_fifo_size=1); super.new (name, parent); m_request_fifo = new ("request_fifo", this, request_fifo_size); m_response_fifo = new ("response_fifo", this, response_fifo_size); request_ap = new ("request_ap", this); response_ap = new ("response_ap", this); put_request_export = new ("put_request_export", this); get_peek_request_export = new ("get_peek_request_export", this); put_response_export = new ("put_response_export", this); get_peek_response_export = new ("get_peek_response_export", this); master_export = new ("master_export", this, m_request_fifo, m_response_fifo); slave_export = new ("slave_export", this, m_request_fifo, m_response_fifo); create_aliased_exports(); set_report_id_action_hier(s_connection_error_id, UVM_NO_ACTION); endfunction virtual function void connect_phase(uvm_phase phase); put_request_export.connect (m_request_fifo.put_export); get_peek_request_export.connect (m_request_fifo.get_peek_export); m_request_fifo.put_ap.connect (request_ap); put_response_export.connect (m_response_fifo.put_export); get_peek_response_export.connect (m_response_fifo.get_peek_export); m_response_fifo.put_ap.connect (response_ap); endfunction function void create_aliased_exports(); blocking_put_request_export = put_request_export; nonblocking_put_request_export = put_request_export; get_request_export = get_peek_request_export; blocking_get_request_export = get_peek_request_export; nonblocking_get_request_export = get_peek_request_export; peek_request_export = get_peek_request_export; blocking_peek_request_export = get_peek_request_export; nonblocking_peek_request_export = get_peek_request_export; blocking_get_peek_request_export = get_peek_request_export; nonblocking_get_peek_request_export = get_peek_request_export; blocking_put_response_export = put_response_export; nonblocking_put_response_export = put_response_export; get_response_export = get_peek_response_export; blocking_get_response_export = get_peek_response_export; nonblocking_get_response_export = get_peek_response_export; peek_response_export = get_peek_response_export; blocking_peek_response_export = get_peek_response_export; nonblocking_peek_response_export = get_peek_response_export; blocking_get_peek_response_export = get_peek_response_export; nonblocking_get_peek_response_export = get_peek_response_export; blocking_master_export = master_export; nonblocking_master_export = master_export; blocking_slave_export = slave_export; nonblocking_slave_export = slave_export; endfunction endclass class uvm_tlm_transport_channel #(type REQ=int, type RSP=REQ) extends uvm_tlm_req_rsp_channel #(REQ, RSP); typedef uvm_component_registry #(uvm_tlm_transport_channel#(REQ,RSP)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_tlm_transport_channel #(REQ,RSP)"; endfunction : type_name virtual function string get_type_name(); return "uvm_tlm_transport_channel #(REQ,RSP)"; endfunction : get_type_name typedef uvm_tlm_transport_channel #(REQ, RSP) this_type; uvm_transport_imp #(REQ, RSP, this_type) transport_export; function new (string name, uvm_component parent=null); super.new(name, parent, 1, 1); transport_export = new("transport_export", this); endfunction task transport (REQ request, output RSP response ); this.m_request_fifo.put( request ); this.m_response_fifo.get( response ); endtask function bit nb_transport (REQ req, output RSP rsp ); if(this.m_request_fifo.try_put(req)) return this.m_response_fifo.try_get(rsp); else return 0; endfunction endclass class uvm_seq_item_pull_port #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_sqr_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=0, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8)); endfunction virtual function string get_type_name(); return "uvm_seq_item_pull_port"; endfunction function void disable_auto_item_recording(); this.m_if.disable_auto_item_recording(); endfunction function bit is_auto_item_recording_enabled(); return this.m_if.is_auto_item_recording_enabled(); endfunction task get_next_item(output REQ t); this.m_if.get_next_item(t); endtask task try_next_item(output REQ t); this.m_if.try_next_item(t); endtask function void item_done(input RSP t = null); this.m_if.item_done(t); endfunction task wait_for_sequences(); this.m_if.wait_for_sequences(); endtask function bit has_do_available(); return this.m_if.has_do_available(); endfunction function void put_response(input RSP t); this.m_if.put_response(t); endfunction task get(output REQ t); this.m_if.get(t); endtask task peek(output REQ t); this.m_if.peek(t); endtask task put(input RSP t); this.m_if.put(t); endtask bit print_enabled; endclass class uvm_seq_item_pull_export #(type REQ=int, type RSP=REQ) extends uvm_port_base #(uvm_sqr_if_base #(REQ, RSP)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8)); endfunction virtual function string get_type_name(); return "uvm_seq_item_pull_export"; endfunction function void disable_auto_item_recording(); this.m_if.disable_auto_item_recording(); endfunction function bit is_auto_item_recording_enabled(); return this.m_if.is_auto_item_recording_enabled(); endfunction task get_next_item(output REQ t); this.m_if.get_next_item(t); endtask task try_next_item(output REQ t); this.m_if.try_next_item(t); endtask function void item_done(input RSP t = null); this.m_if.item_done(t); endfunction task wait_for_sequences(); this.m_if.wait_for_sequences(); endtask function bit has_do_available(); return this.m_if.has_do_available(); endfunction function void put_response(input RSP t); this.m_if.put_response(t); endfunction task get(output REQ t); this.m_if.get(t); endtask task peek(output REQ t); this.m_if.peek(t); endtask task put(input RSP t); this.m_if.put(t); endtask endclass class uvm_seq_item_pull_imp #(type REQ=int, type RSP=REQ, type IMP=int) extends uvm_port_base #(uvm_sqr_if_base #(REQ, RSP)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8)); endfunction virtual function string get_type_name(); return "uvm_seq_item_pull_imp"; endfunction function void disable_auto_item_recording(); m_imp.disable_auto_item_recording(); endfunction function bit is_auto_item_recording_enabled(); return m_imp.is_auto_item_recording_enabled(); endfunction task get_next_item(output REQ t); m_imp.get_next_item(t); endtask task try_next_item(output REQ t); m_imp.try_next_item(t); endtask function void item_done(input RSP t = null); m_imp.item_done(t); endfunction task wait_for_sequences(); m_imp.wait_for_sequences(); endtask function bit has_do_available(); return m_imp.has_do_available(); endfunction function void put_response(input RSP t); m_imp.put_response(t); endfunction task get(output REQ t); m_imp.get(t); endtask task peek(output REQ t); m_imp.peek(t); endtask task put(input RSP t); m_imp.put(t); endtask endclass class uvm_class_pair #(type T1=int, T2=T1) extends uvm_object; typedef uvm_class_pair #(T1, T2 ) this_type; typedef uvm_object_registry #(this_type) type_id; static function this_type type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); this_type tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_class_pair #(T1,T2)"; endfunction : type_name virtual function string get_type_name(); return "uvm_class_pair #(T1,T2)"; endfunction : get_type_name T1 first; T2 second; function new (string name="", T1 f=null, T2 s=null); super.new(name); if (f == null) first = new; else first = f; if (s == null) second = new; else second = s; endfunction virtual function string convert2string; string s; $sformat(s, "pair : %s, %s", first.convert2string(), second.convert2string()); return s; endfunction virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer); this_type rhs_; if(!$cast(rhs_,rhs)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"WRONG_TYPE")) uvm_report_error ("WRONG_TYPE", {"do_compare: rhs argument is not of type '",get_type_name(),"'"}, UVM_NONE, "t/uvm/src/comps/uvm_pair.svh", 88, "", 1); end return 0; end return first.compare(rhs_.first) && second.compare(rhs_.second); endfunction virtual function void do_copy (uvm_object rhs); this_type rhs_; if(!$cast(rhs_,rhs)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"WRONG_TYPE")) uvm_report_fatal ("WRONG_TYPE", {"do_copy: rhs argument is not of type '",get_type_name(),"'"}, UVM_NONE, "t/uvm/src/comps/uvm_pair.svh", 97, "", 1); end first.copy(rhs_.first); second.copy(rhs_.second); endfunction endclass class uvm_built_in_pair #(type T1=int, T2=T1) extends uvm_object; typedef uvm_built_in_pair #(T1,T2) this_type; typedef uvm_object_registry #(this_type) type_id; static function this_type type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); this_type tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_built_in_pair #(T1,T2)"; endfunction : type_name virtual function string get_type_name(); return "uvm_built_in_pair #(T1,T2)"; endfunction : get_type_name T1 first; T2 second; function new (string name=""); super.new(name); endfunction virtual function string convert2string; return $sformatf("built-in pair : %p, %p", first, second); endfunction virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer); this_type rhs_; if(!$cast(rhs_,rhs)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"WRONG_TYPE")) uvm_report_error ("WRONG_TYPE", {"do_compare: rhs argument is not of type '",get_type_name(),"'"}, UVM_NONE, "t/uvm/src/comps/uvm_pair.svh", 146, "", 1); end return 0; end return first == rhs_.first && second == rhs_.second; endfunction function void do_copy (uvm_object rhs); this_type rhs_; if(!$cast(rhs_,rhs)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"WRONG_TYPE")) uvm_report_fatal ("WRONG_TYPE", {"do_copy: rhs argument is not of type '",get_type_name(),"'"}, UVM_NONE, "t/uvm/src/comps/uvm_pair.svh", 155, "", 1); end first = rhs_.first; second = rhs_.second; endfunction endclass class uvm_built_in_comp #(type T=int); static function bit comp(T a, T b); return a == b; endfunction endclass class uvm_built_in_converter #(type T=int); static function string convert2string(input T t); return $sformatf("%p" , t ); endfunction endclass class uvm_built_in_clone #(type T=int); static function T clone(input T from); return from; endfunction endclass class uvm_class_comp #(type T=int); static function bit comp(input T a, input T b); return a.compare(b); endfunction endclass class uvm_class_converter #(type T=int); static function string convert2string(input T t); return t.convert2string(); endfunction endclass class uvm_class_clone #(type T=int); static function uvm_object clone(input T from); return from.clone(); endfunction endclass class uvm_in_order_comparator #( type T = int , type comp_type = uvm_built_in_comp #( T ) , type convert = uvm_built_in_converter #( T ) , type pair_type = uvm_built_in_pair #( T ) ) extends uvm_component; typedef uvm_in_order_comparator #(T,comp_type,convert,pair_type) this_type; typedef uvm_component_registry #(this_type) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_in_order_comparator #(T,comp_type,convert,pair_type)"; endfunction : type_name virtual function string get_type_name(); return "uvm_in_order_comparator #(T,comp_type,convert,pair_type)"; endfunction : get_type_name uvm_analysis_export #(T) before_export; uvm_analysis_export #(T) after_export; uvm_analysis_port #(pair_type) pair_ap; local uvm_tlm_analysis_fifo #(T) m_before_fifo; local uvm_tlm_analysis_fifo #(T) m_after_fifo; int m_matches, m_mismatches; function new(string name, uvm_component parent); super.new(name, parent); before_export = new("before_export", this); after_export = new("after_export", this); pair_ap = new("pair_ap", this); m_before_fifo = new("before", this); m_after_fifo = new("after", this); m_matches = 0; m_mismatches = 0; endfunction virtual function void connect_phase(uvm_phase phase); before_export.connect(m_before_fifo.analysis_export); after_export.connect(m_after_fifo.analysis_export); endfunction virtual task run_phase(uvm_phase phase); pair_type pair; T b; T a; string s; super.run_phase(phase); forever begin m_before_fifo.get(b); m_after_fifo.get(a); if(!comp_type::comp(b, a)) begin $sformat(s, "%s differs from %s", convert::convert2string(a), convert::convert2string(b)); uvm_report_warning("Comparator Mismatch", s); m_mismatches++; end else begin s = convert::convert2string(b); uvm_report_info("Comparator Match", s); m_matches++; end pair = new("after/before"); pair.first = a; pair.second = b; pair_ap.write(pair); end endtask virtual function void flush(); m_matches = 0; m_mismatches = 0; endfunction endclass class uvm_in_order_built_in_comparator #(type T=int) extends uvm_in_order_comparator #(T); typedef uvm_in_order_built_in_comparator #(T) this_type; typedef uvm_component_registry #(this_type) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_in_order_built_in_comparator #(T)"; endfunction : type_name virtual function string get_type_name(); return "uvm_in_order_built_in_comparator #(T)"; endfunction : get_type_name function new(string name, uvm_component parent); super.new(name, parent); endfunction endclass class uvm_in_order_class_comparator #( type T = int ) extends uvm_in_order_comparator #( T , uvm_class_comp #( T ) , uvm_class_converter #( T ) , uvm_class_pair #( T, T ) ); typedef uvm_in_order_class_comparator #(T) this_type; typedef uvm_component_registry #(this_type) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_in_order_class_comparator #(T)"; endfunction : type_name virtual function string get_type_name(); return "uvm_in_order_class_comparator #(T)"; endfunction : get_type_name function new( string name , uvm_component parent); super.new( name, parent ); endfunction endclass class uvm_algorithmic_comparator #( type BEFORE=int, type AFTER=int, type TRANSFORMER=int) extends uvm_component; typedef uvm_algorithmic_comparator #( BEFORE , AFTER , TRANSFORMER ) this_type; typedef uvm_component_registry #(this_type) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_algorithmic_comparator #(BEFORE,AFTER,TRANSFORMER)"; endfunction : type_name virtual function string get_type_name(); return "uvm_algorithmic_comparator #(BEFORE,AFTER,TRANSFORMER)"; endfunction : get_type_name uvm_analysis_imp #(BEFORE, this_type) before_export; uvm_analysis_export #(AFTER) after_export; local uvm_in_order_class_comparator #(AFTER) comp; local TRANSFORMER m_transformer; function new(string name, uvm_component parent=null, TRANSFORMER transformer=null); super.new( name , parent ); m_transformer = transformer; comp = new("comp", this ); before_export = new("before_analysis_export" , this ); after_export = new("after_analysis_export" , this ); endfunction virtual function void connect_phase(uvm_phase phase); after_export.connect( comp.after_export ); endfunction function void write( input BEFORE b ); comp.before_export.write( m_transformer.transform( b ) ); endfunction endclass virtual class uvm_subscriber #(type T=int) extends uvm_component; typedef uvm_subscriber #(T) this_type; uvm_analysis_imp #(T, this_type) analysis_export; function new (string name, uvm_component parent); super.new(name, parent); analysis_export = new("analysis_imp", this); endfunction pure virtual function void write(T t); endclass virtual class uvm_monitor extends uvm_component; typedef uvm_abstract_component_registry #(uvm_monitor,"uvm_monitor") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_monitor"; endfunction : type_name virtual function string get_type_name(); return "uvm_monitor"; endfunction : get_type_name function new (string name, uvm_component parent); super.new(name, parent); endfunction endclass typedef class uvm_sequence_item; class uvm_driver #(type REQ=uvm_sequence_item, type RSP=REQ) extends uvm_component; typedef uvm_component_registry #(uvm_driver#(REQ,RSP)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_driver #(REQ,RSP)"; endfunction : type_name virtual function string get_type_name(); return "uvm_driver #(REQ,RSP)"; endfunction : get_type_name uvm_seq_item_pull_port #(REQ, RSP) seq_item_port; uvm_seq_item_pull_port #(REQ, RSP) seq_item_prod_if; uvm_analysis_port #(RSP) rsp_port; REQ req; RSP rsp; function new (string name, uvm_component parent); super.new(name, parent); seq_item_port = new("seq_item_port", this); rsp_port = new("rsp_port", this); seq_item_prod_if = seq_item_port; endfunction virtual function void end_of_elaboration_phase(uvm_phase phase); if(seq_item_port.size<1) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"DRVCONNECT")) uvm_report_warning ("DRVCONNECT", "the driver is not connected to a sequencer via the standard mechanisms enabled by connect()", UVM_NONE, "t/uvm/src/comps/uvm_driver.svh", 90, "", 1); end endfunction endclass class uvm_push_driver #(type REQ=uvm_sequence_item, type RSP=REQ) extends uvm_component; typedef uvm_component_registry #(uvm_push_driver#(REQ,RSP)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_push_driver #(REQ,RSP)"; endfunction : type_name virtual function string get_type_name(); return "uvm_push_driver #(REQ,RSP)"; endfunction : get_type_name uvm_blocking_put_imp #(REQ, uvm_push_driver #(REQ,RSP)) req_export; uvm_analysis_port #(RSP) rsp_port; REQ req; RSP rsp; function new (string name, uvm_component parent); super.new(name, parent); req_export = new("req_export", this); rsp_port = new("rsp_port", this); endfunction function void check_port_connections(); if (req_export.size() != 1) uvm_report_fatal("Connection Error", $sformatf("Must connect to seq_item_port(%0d)", req_export.size()), UVM_NONE); endfunction virtual function void end_of_elaboration_phase(uvm_phase phase); super.end_of_elaboration_phase(phase); check_port_connections(); endfunction virtual task put(REQ item); uvm_report_fatal("UVM_PUSH_DRIVER", "Put task for push driver is not implemented", UVM_NONE); endtask endclass virtual class uvm_scoreboard extends uvm_component; typedef uvm_abstract_component_registry #(uvm_scoreboard,"uvm_scoreboard") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_scoreboard"; endfunction : type_name virtual function string get_type_name(); return "uvm_scoreboard"; endfunction : get_type_name function new (string name, uvm_component parent); super.new(name, parent); endfunction endclass virtual class uvm_agent extends uvm_component; uvm_active_passive_enum is_active = UVM_ACTIVE; typedef uvm_abstract_component_registry #(uvm_agent,"uvm_agent") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_agent"; endfunction : type_name virtual function string get_type_name(); return "uvm_agent"; endfunction : get_type_name function new (string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); int active; uvm_resource_pool rp; uvm_resource_types::rsrc_q_t rq; bit found; super.build_phase(phase); rp = uvm_resource_pool::get(); rq = rp.lookup_name(get_full_name(), "is_active", null, 0); uvm_resource_pool::sort_by_precedence(rq); for (int i = 0; i < rq.size() && !found; i++) begin uvm_resource_base rsrc = rq.get(i); begin begin uvm_resource#(uvm_active_passive_enum) __tmp_rsrc__; found = $cast(__tmp_rsrc__, rsrc); if (found) begin is_active = __tmp_rsrc__.read(this); end end if (!found) begin uvm_active_passive_enum __tmp_val__; string __tmp_string_val__; bit __tmp_success_val__; begin uvm_resource#(string) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_string_val__ = __tmp_rsrc__.read(this); end end if (__tmp_success_val__ && uvm_enum_wrapper#(uvm_active_passive_enum)::from_name(__tmp_string_val__, __tmp_val__)) begin is_active = __tmp_val__; found = __tmp_success_val__; end end if (!found) begin typedef bit [$bits(uvm_active_passive_enum)-1:0] __tmp_int_t__; __tmp_int_t__ __tmp_int_val__; bit __tmp_success_val__; begin begin uvm_resource#(__tmp_int_t__) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_int_val__ = __tmp_rsrc__.read(this); end end if (!__tmp_success_val__) begin begin uvm_resource#(uvm_integral_t) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_int_val__ = __tmp_rsrc__.read(this); end end if (!__tmp_success_val__) begin uvm_resource#(uvm_bitstream_t) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_int_val__ = __tmp_rsrc__.read(this); end end if (!__tmp_success_val__) begin uvm_resource#(int) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_int_val__ = __tmp_rsrc__.read(this); end end if (!__tmp_success_val__) begin uvm_resource#(int unsigned) __tmp_rsrc__; __tmp_success_val__ = $cast(__tmp_rsrc__, rsrc); if (__tmp_success_val__) begin __tmp_int_val__ = __tmp_rsrc__.read(this); end end end end if (__tmp_success_val__) begin is_active = uvm_active_passive_enum'(__tmp_int_val__); found = __tmp_success_val__; end end end end endfunction virtual function uvm_active_passive_enum get_is_active(); return is_active; endfunction endclass virtual class uvm_env extends uvm_component; typedef uvm_abstract_component_registry #(uvm_env,"uvm_env") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_env"; endfunction : type_name virtual function string get_type_name(); return "uvm_env"; endfunction : get_type_name function new (string name="env", uvm_component parent=null); super.new(name,parent); endfunction endclass virtual class uvm_test extends uvm_component; typedef uvm_abstract_component_registry #(uvm_test,"uvm_test") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_test"; endfunction : type_name virtual function string get_type_name(); return "uvm_test"; endfunction : get_type_name function new (string name, uvm_component parent); super.new(name,parent); endfunction endclass typedef class uvm_sequence_base; typedef class uvm_sequencer_base; class uvm_sequence_item extends uvm_transaction; local int m_sequence_id = -1; protected bit m_use_sequence_info; protected int m_depth = -1; protected uvm_sequencer_base m_sequencer; protected uvm_sequence_base m_parent_sequence; static bit issued1,issued2; bit print_sequence_info; function new (string name = "uvm_sequence_item"); super.new(name); endfunction function string get_type_name(); return "uvm_sequence_item"; endfunction typedef uvm_object_registry#(uvm_sequence_item,"uvm_sequence_item") type_id; static function uvm_sequence_item type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function void set_sequence_id(int id); m_sequence_id = id; endfunction function int get_sequence_id(); return (m_sequence_id); endfunction function void set_item_context(uvm_sequence_base parent_seq, uvm_sequencer_base sequencer = null); set_use_sequence_info(1); if (parent_seq != null) set_parent_sequence(parent_seq); if (sequencer == null && m_parent_sequence != null) sequencer = m_parent_sequence.get_sequencer(); set_sequencer(sequencer); if (m_parent_sequence != null) set_depth(m_parent_sequence.get_depth() + 1); reseed(); endfunction function void set_use_sequence_info(bit value); m_use_sequence_info = value; endfunction function bit get_use_sequence_info(); return (m_use_sequence_info); endfunction function void set_id_info(uvm_sequence_item item); if (item == null) begin uvm_report_fatal(get_full_name(), "set_id_info called with null parameter", UVM_NONE); end this.set_transaction_id(item.get_transaction_id()); this.set_sequence_id(item.get_sequence_id()); endfunction virtual function void set_sequencer(uvm_sequencer_base sequencer); m_sequencer = sequencer; m_set_p_sequencer(); endfunction function uvm_sequencer_base get_sequencer(); return m_sequencer; endfunction function void set_parent_sequence(uvm_sequence_base parent); m_parent_sequence = parent; endfunction function uvm_sequence_base get_parent_sequence(); return (m_parent_sequence); endfunction function void set_depth(int value); m_depth = value; endfunction function int get_depth(); if (m_depth != -1) begin return (m_depth); end if (m_parent_sequence == null) begin m_depth = 1; end else begin m_depth = m_parent_sequence.get_depth() + 1; end return (m_depth); endfunction virtual function bit is_item(); return(1); endfunction function string get_full_name(); if(m_parent_sequence != null) get_full_name = {m_parent_sequence.get_full_name(), "."}; else if(m_sequencer!=null) get_full_name = {m_sequencer.get_full_name(), "."}; if(get_name() != "") get_full_name = {get_full_name, get_name()}; else begin get_full_name = {get_full_name, "_item"}; end endfunction function string get_root_sequence_name(); uvm_sequence_base root_seq; root_seq = get_root_sequence(); if (root_seq == null) return ""; else return root_seq.get_name(); endfunction virtual function void m_set_p_sequencer(); return; endfunction function uvm_sequence_base get_root_sequence(); uvm_sequence_item root_seq_base; uvm_sequence_base root_seq; root_seq_base = this; while(1) begin if(root_seq_base.get_parent_sequence()!=null) begin root_seq_base = root_seq_base.get_parent_sequence(); $cast(root_seq, root_seq_base); end else return root_seq; end endfunction function string get_sequence_path(); uvm_sequence_item this_item; string seq_path; this_item = this; seq_path = this.get_name(); while(1) begin if(this_item.get_parent_sequence()!=null) begin this_item = this_item.get_parent_sequence(); seq_path = {this_item.get_name(), ".", seq_path}; end else return seq_path; end endfunction virtual function uvm_report_object uvm_get_report_object(); if(m_sequencer == null) begin uvm_coreservice_t cs = uvm_coreservice_t::get(); return cs.get_root(); end else return m_sequencer; endfunction function int uvm_report_enabled(int verbosity, uvm_severity severity=UVM_INFO, string id=""); uvm_report_object l_report_object = uvm_get_report_object(); if (l_report_object.get_report_verbosity_level(severity, id) < verbosity) return 0; return 1; endfunction virtual function void uvm_report( uvm_severity severity, string id, string message, int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW : (severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); uvm_report_message l_report_message; if (report_enabled_checked == 0) begin if (!uvm_report_enabled(verbosity, severity, id)) return; end l_report_message = uvm_report_message::new_report_message(); l_report_message.set_report_message(severity, id, message, verbosity, filename, line, context_name); uvm_process_report_message(l_report_message); endfunction virtual function void uvm_report_info( string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); this.uvm_report(UVM_INFO, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_warning( string id, string message, int verbosity = UVM_MEDIUM, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); this.uvm_report(UVM_WARNING, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_error( string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); this.uvm_report(UVM_ERROR, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_report_fatal( string id, string message, int verbosity = UVM_NONE, string filename = "", int line = 0, string context_name = "", bit report_enabled_checked = 0); this.uvm_report(UVM_FATAL, id, message, verbosity, filename, line, context_name, report_enabled_checked); endfunction virtual function void uvm_process_report_message (uvm_report_message report_message); uvm_report_object l_report_object = uvm_get_report_object(); report_message.set_report_object(l_report_object); if (report_message.get_context() == "") report_message.set_context(get_sequence_path()); l_report_object.m_rh.process_report_message(report_message); endfunction function void do_print (uvm_printer printer); string temp_str0, temp_str1; int depth = get_depth(); super.do_print(printer); if(print_sequence_info || m_use_sequence_info) begin printer.print_field_int("depth", depth, $bits(depth), UVM_DEC, ".", "int"); if(m_parent_sequence != null) begin temp_str0 = m_parent_sequence.get_name(); temp_str1 = m_parent_sequence.get_full_name(); end printer.print_string("parent sequence (name)", temp_str0); printer.print_string("parent sequence (full name)", temp_str1); temp_str1 = ""; if(m_sequencer != null) begin temp_str1 = m_sequencer.get_full_name(); end printer.print_string("sequencer", temp_str1); end endfunction endclass typedef uvm_config_db#(uvm_sequence_base) uvm_config_seq; typedef class uvm_sequence_request; class uvm_sequence_process_wrapper; process pid; uvm_sequence_base seq; endclass : uvm_sequence_process_wrapper virtual class uvm_sequencer_base extends uvm_component; typedef enum {SEQ_TYPE_REQ, SEQ_TYPE_LOCK} seq_req_t; protected uvm_sequence_request arb_sequence_q[$]; protected bit arb_completed[int]; protected uvm_sequence_base lock_list[$]; protected uvm_sequence_base reg_sequences[int]; protected int m_sequencer_id; protected int m_lock_arb_size; protected int m_arb_size; protected int m_wait_for_item_sequence_id, m_wait_for_item_transaction_id; protected int m_wait_relevant_count = 0 ; protected int m_max_zero_time_wait_relevant_count = 10; protected time m_last_wait_relevant_time = 0 ; local uvm_sequencer_arb_mode m_arbitration = UVM_SEQ_ARB_FIFO; local static int g_request_id; local static int g_sequence_id = 1; local static int g_sequencer_id = 1; extern function new (string name, uvm_component parent); extern function bit is_child (uvm_sequence_base parent, uvm_sequence_base child); extern virtual function int user_priority_arbitration(int avail_sequences[$]); extern virtual task execute_item(uvm_sequence_item item); protected uvm_sequence_process_wrapper m_default_sequences[uvm_phase]; extern virtual function void start_phase_sequence(uvm_phase phase); extern virtual function void stop_phase_sequence(uvm_phase phase); extern virtual task wait_for_grant(uvm_sequence_base sequence_ptr, int item_priority = -1, bit lock_request = 0); extern virtual task wait_for_item_done(uvm_sequence_base sequence_ptr, int transaction_id); extern function bit is_blocked(uvm_sequence_base sequence_ptr); extern function bit has_lock(uvm_sequence_base sequence_ptr); extern virtual task lock(uvm_sequence_base sequence_ptr); extern virtual task grab(uvm_sequence_base sequence_ptr); extern virtual function void unlock(uvm_sequence_base sequence_ptr); extern virtual function void ungrab(uvm_sequence_base sequence_ptr); extern virtual function void stop_sequences(); extern virtual function bit is_grabbed(); extern virtual function uvm_sequence_base current_grabber(); extern virtual function bit has_do_available(); extern function void set_arbitration(UVM_SEQ_ARB_TYPE val); extern function UVM_SEQ_ARB_TYPE get_arbitration(); extern virtual task wait_for_sequences(); extern virtual function void send_request(uvm_sequence_base sequence_ptr, uvm_sequence_item t, bit rerandomize = 0); extern virtual function void set_max_zero_time_wait_relevant_count(int new_val) ; extern virtual function uvm_sequence_base get_arbitration_sequence( int index ); extern protected function void grant_queued_locks(); extern protected task m_select_sequence(); extern protected function int m_choose_next_request(); extern task m_wait_for_arbitration_completed(int request_id); extern function void m_set_arbitration_completed(int request_id); extern local task m_lock_req(uvm_sequence_base sequence_ptr, bit lock); extern function void m_unlock_req(uvm_sequence_base sequence_ptr); extern local function void remove_sequence_from_queues(uvm_sequence_base sequence_ptr); extern function void m_sequence_exiting(uvm_sequence_base sequence_ptr); extern function void kill_sequence(uvm_sequence_base sequence_ptr); extern virtual function void analysis_write(uvm_sequence_item t); extern function void do_print (uvm_printer printer); extern virtual function int m_register_sequence(uvm_sequence_base sequence_ptr); extern protected virtual function void m_unregister_sequence(int sequence_id); extern protected function uvm_sequence_base m_find_sequence(int sequence_id); extern protected function void m_update_lists(); extern function string convert2string(); extern protected virtual function int m_find_number_driver_connections(); extern protected task m_wait_arb_not_equal(); extern protected task m_wait_for_available_sequence(); extern protected function int m_get_seq_item_priority(uvm_sequence_request seq_q_entry); int m_is_relevant_completed; local bit m_auto_item_recording = 1; virtual function void disable_auto_item_recording(); m_auto_item_recording = 0; endfunction virtual function bit is_auto_item_recording_enabled(); return m_auto_item_recording; endfunction static uvm_sequencer_base all_sequencer_insts[int unsigned]; endclass function uvm_sequencer_base::new (string name, uvm_component parent); super.new(name, parent); m_sequencer_id = g_sequencer_id++; m_lock_arb_size = -1; all_sequencer_insts[m_sequencer_id]=this; endfunction function void uvm_sequencer_base::do_print (uvm_printer printer); super.do_print(printer); printer.print_array_header("arbitration_queue", arb_sequence_q.size()); foreach (arb_sequence_q[i]) printer.print_string($sformatf("[%0d]", i), $sformatf("%s@seqid%0d",arb_sequence_q[i].request.name(),arb_sequence_q[i].sequence_id), "["); printer.print_array_footer(arb_sequence_q.size()); printer.print_array_header("lock_queue", lock_list.size()); foreach(lock_list[i]) printer.print_string($sformatf("[%0d]", i), $sformatf("%s@seqid%0d",lock_list[i].get_full_name(),lock_list[i].get_sequence_id()), "["); printer.print_array_footer(lock_list.size()); endfunction function void uvm_sequencer_base::m_update_lists(); m_lock_arb_size++; endfunction function string uvm_sequencer_base::convert2string(); string s; $sformat(s, " -- arb i/id/type: "); foreach (arb_sequence_q[i]) begin $sformat(s, "%s %0d/%0d/%s ", s, i, arb_sequence_q[i].sequence_id, arb_sequence_q[i].request.name()); end $sformat(s, "%s\n -- lock_list i/id: ", s); foreach (lock_list[i]) begin $sformat(s, "%s %0d/%0d",s, i, lock_list[i].get_sequence_id()); end return(s); endfunction function int uvm_sequencer_base::m_find_number_driver_connections(); return 0; endfunction function int uvm_sequencer_base::m_register_sequence(uvm_sequence_base sequence_ptr); if (sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1) > 0) return sequence_ptr.get_sequence_id(); sequence_ptr.m_set_sqr_sequence_id(m_sequencer_id, g_sequence_id++); reg_sequences[sequence_ptr.get_sequence_id()] = sequence_ptr; return sequence_ptr.get_sequence_id(); endfunction function uvm_sequence_base uvm_sequencer_base::m_find_sequence(int sequence_id); uvm_sequence_base seq_ptr; int i; if (sequence_id == -1) begin if (reg_sequences.first(i)) begin return(reg_sequences[i]); end return(null); end if (!reg_sequences.exists(sequence_id)) return null; return reg_sequences[sequence_id]; endfunction function void uvm_sequencer_base::m_unregister_sequence(int sequence_id); if (!reg_sequences.exists(sequence_id)) return; reg_sequences.delete(sequence_id); endfunction function int uvm_sequencer_base::user_priority_arbitration(int avail_sequences[$]); return avail_sequences[0]; endfunction function void uvm_sequencer_base::grant_queued_locks(); begin uvm_sequence_request zombies[$]; zombies = arb_sequence_q.find(item) with (item.request==SEQ_TYPE_LOCK && item.process_id.status inside {process::KILLED,process::FINISHED}); foreach(zombies[idx]) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLCKZMB")) uvm_report_error ("SEQLCKZMB", $sformatf("The task responsible for requesting a lock on sequencer '%s' for sequence '%s' has been killed, to avoid a deadlock the sequence will be removed from the arbitration queues", this.get_full_name(), zombies[idx].sequence_ptr.get_full_name()), UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 557, "", 1); end remove_sequence_from_queues(zombies[idx].sequence_ptr); end end begin int lock_req_indices[$]; lock_req_indices = arb_sequence_q.find_first_index(item) with (item.request==SEQ_TYPE_LOCK && is_blocked(item.sequence_ptr) == 0); if(lock_req_indices.size()) begin uvm_sequence_request lock_req = arb_sequence_q[lock_req_indices[0]]; lock_list.push_back(lock_req.sequence_ptr); m_set_arbitration_completed(lock_req.request_id); arb_sequence_q.delete(lock_req_indices[0]); m_update_lists(); end end endfunction task uvm_sequencer_base::m_select_sequence(); int selected_sequence; do begin wait_for_sequences(); selected_sequence = m_choose_next_request(); if (selected_sequence == -1) begin m_wait_for_available_sequence(); end end while (selected_sequence == -1); if (selected_sequence >= 0) begin m_set_arbitration_completed(arb_sequence_q[selected_sequence].request_id); arb_sequence_q.delete(selected_sequence); m_update_lists(); end endtask function int uvm_sequencer_base::m_choose_next_request(); int i, temp; int avail_sequence_count; int sum_priority_val; int avail_sequences[$]; int highest_sequences[$]; int highest_pri; string s; avail_sequence_count = 0; grant_queued_locks(); i = 0; while (i < arb_sequence_q.size()) begin if ((arb_sequence_q[i].process_id.status == process::KILLED) || (arb_sequence_q[i].process_id.status == process::FINISHED)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQREQZMB")) uvm_report_error ("SEQREQZMB", $sformatf("The task responsible for requesting a wait_for_grant on sequencer '%s' for sequence '%s' has been killed, to avoid a deadlock the sequence will be removed from the arbitration queues", this.get_full_name(), arb_sequence_q[i].sequence_ptr.get_full_name()), UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 625, "", 1); end remove_sequence_from_queues(arb_sequence_q[i].sequence_ptr); continue; end if (i < arb_sequence_q.size()) if (arb_sequence_q[i].request == SEQ_TYPE_REQ) if (is_blocked(arb_sequence_q[i].sequence_ptr) == 0) if (arb_sequence_q[i].sequence_ptr.is_relevant() == 1) begin if (m_arbitration == UVM_SEQ_ARB_FIFO) begin return i; end else avail_sequences.push_back(i); end i++; end if (m_arbitration == UVM_SEQ_ARB_FIFO) begin return -1; end if (avail_sequences.size() < 1) begin return -1; end if (avail_sequences.size() == 1) begin return avail_sequences[0]; end if (lock_list.size() > 0) begin for (i = 0; i < avail_sequences.size(); i++) begin if (is_blocked(arb_sequence_q[avail_sequences[i]].sequence_ptr) != 0) begin avail_sequences.delete(i); i--; end end if (avail_sequences.size() < 1) return -1; if (avail_sequences.size() == 1) return avail_sequences[0]; end if (m_arbitration == UVM_SEQ_ARB_WEIGHTED) begin sum_priority_val = 0; for (i = 0; i < avail_sequences.size(); i++) begin sum_priority_val += m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end temp = $urandom_range(sum_priority_val-1, 0); sum_priority_val = 0; for (i = 0; i < avail_sequences.size(); i++) begin if ((m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) + sum_priority_val) > temp) begin return avail_sequences[i]; end sum_priority_val += m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end uvm_report_fatal("Sequencer", "UVM Internal error in weighted arbitration code", UVM_NONE); end if (m_arbitration == UVM_SEQ_ARB_RANDOM) begin i = $urandom_range(avail_sequences.size()-1, 0); return avail_sequences[i]; end if ((m_arbitration == UVM_SEQ_ARB_STRICT_FIFO) || m_arbitration == UVM_SEQ_ARB_STRICT_RANDOM) begin highest_pri = 0; for (i = 0; i < avail_sequences.size(); i++) begin if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) > highest_pri) begin highest_sequences.delete(); highest_sequences.push_back(avail_sequences[i]); highest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end else if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) == highest_pri) begin highest_sequences.push_back(avail_sequences[i]); end end if (m_arbitration == UVM_SEQ_ARB_STRICT_FIFO) begin return(highest_sequences[0]); end i = $urandom_range(highest_sequences.size()-1, 0); return highest_sequences[i]; end if (m_arbitration == UVM_SEQ_ARB_USER) begin i = user_priority_arbitration( avail_sequences); highest_sequences = avail_sequences.find with (item == i); if (highest_sequences.size() == 0) begin uvm_report_fatal("Sequencer", $sformatf("Error in User arbitration, sequence %0d not available\n%s", i, convert2string()), UVM_NONE); end return(i); end uvm_report_fatal("Sequencer", "Internal error: Failed to choose sequence", UVM_NONE); endfunction task uvm_sequencer_base::m_wait_arb_not_equal(); wait (m_arb_size != m_lock_arb_size); endtask task uvm_sequencer_base::m_wait_for_available_sequence(); int i; int is_relevant_entries[$]; m_arb_size = m_lock_arb_size; for (i = 0; i < arb_sequence_q.size(); i++) begin if (arb_sequence_q[i].request == SEQ_TYPE_REQ) begin if (is_blocked(arb_sequence_q[i].sequence_ptr) == 0) begin if (arb_sequence_q[i].sequence_ptr.is_relevant() == 0) begin is_relevant_entries.push_back(i); end end end end if (is_relevant_entries.size() == 0) begin m_wait_arb_not_equal(); return; end fork begin fork begin fork begin m_is_relevant_completed = 0; for(i = 0; i < is_relevant_entries.size(); i++) begin fork automatic int k = i; begin arb_sequence_q[is_relevant_entries[k]].sequence_ptr.wait_for_relevant(); if ($realtime != m_last_wait_relevant_time) begin m_last_wait_relevant_time = $realtime ; m_wait_relevant_count = 0 ; end else begin m_wait_relevant_count++ ; if (m_wait_relevant_count > m_max_zero_time_wait_relevant_count) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"SEQRELEVANTLOOP")) uvm_report_fatal ("SEQRELEVANTLOOP", $sformatf("Zero time loop detected, passed wait_for_relevant %0d times without time advancing",m_wait_relevant_count), UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 798, "", 1); end end end m_is_relevant_completed = 1; end join_none end wait (m_is_relevant_completed > 0); end begin m_wait_arb_not_equal(); end join_any end join_any disable fork; end join endtask function int uvm_sequencer_base::m_get_seq_item_priority(uvm_sequence_request seq_q_entry); if (seq_q_entry.item_priority != -1) begin if (seq_q_entry.item_priority <= 0) begin uvm_report_fatal("SEQITEMPRI", $sformatf("Sequence item from %s has illegal priority: %0d", seq_q_entry.sequence_ptr.get_full_name(), seq_q_entry.item_priority), UVM_NONE); end return seq_q_entry.item_priority; end if (seq_q_entry.sequence_ptr.get_priority() < 0) begin uvm_report_fatal("SEQDEFPRI", $sformatf("Sequence %s has illegal priority: %0d", seq_q_entry.sequence_ptr.get_full_name(), seq_q_entry.sequence_ptr.get_priority()), UVM_NONE); end return seq_q_entry.sequence_ptr.get_priority(); endfunction task uvm_sequencer_base::m_wait_for_arbitration_completed(int request_id); int lock_arb_size; forever begin lock_arb_size = m_lock_arb_size; if (arb_completed.exists(request_id)) begin arb_completed.delete(request_id); return; end wait (lock_arb_size != m_lock_arb_size); end endtask function void uvm_sequencer_base::m_set_arbitration_completed(int request_id); arb_completed[request_id] = 1; endfunction function bit uvm_sequencer_base::is_child (uvm_sequence_base parent, uvm_sequence_base child); uvm_sequence_base child_parent; if (child == null) begin uvm_report_fatal("uvm_sequencer", "is_child passed null child", UVM_NONE); end if (parent == null) begin uvm_report_fatal("uvm_sequencer", "is_child passed null parent", UVM_NONE); end child_parent = child.get_parent_sequence(); while (child_parent != null) begin if (child_parent.get_inst_id() == parent.get_inst_id()) begin return 1; end child_parent = child_parent.get_parent_sequence(); end return 0; endfunction class m_uvm_sqr_seq_base extends uvm_sequence_base; function new(string name="unnamed-m_uvm_sqr_seq_base"); super.new(name); endfunction : new endclass : m_uvm_sqr_seq_base task uvm_sequencer_base::execute_item(uvm_sequence_item item); m_uvm_sqr_seq_base seq; seq = new("execute_item_seq"); item.set_sequencer(this); item.set_parent_sequence(seq); seq.set_sequencer(this); seq.start_item(item); seq.finish_item(item); endtask task uvm_sequencer_base::wait_for_grant(uvm_sequence_base sequence_ptr, int item_priority = -1, bit lock_request = 0); uvm_sequence_request req_s; int my_seq_id; if (sequence_ptr == null) uvm_report_fatal("uvm_sequencer", "wait_for_grant passed null sequence_ptr", UVM_NONE); my_seq_id = m_register_sequence(sequence_ptr); if (lock_request == 1) begin req_s = new(); req_s.grant = 0; req_s.sequence_id = my_seq_id; req_s.request = SEQ_TYPE_LOCK; req_s.sequence_ptr = sequence_ptr; req_s.request_id = g_request_id++; req_s.process_id = process::self(); arb_sequence_q.push_back(req_s); end req_s = new(); req_s.grant = 0; req_s.request = SEQ_TYPE_REQ; req_s.sequence_id = my_seq_id; req_s.item_priority = item_priority; req_s.sequence_ptr = sequence_ptr; req_s.request_id = g_request_id++; req_s.process_id = process::self(); arb_sequence_q.push_back(req_s); m_update_lists(); m_wait_for_arbitration_completed(req_s.request_id); req_s.sequence_ptr.m_wait_for_grant_semaphore++; endtask task uvm_sequencer_base::wait_for_item_done(uvm_sequence_base sequence_ptr, int transaction_id); int sequence_id; sequence_id = sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1); m_wait_for_item_sequence_id = -1; m_wait_for_item_transaction_id = -1; if (transaction_id == -1) wait (m_wait_for_item_sequence_id == sequence_id); else wait ((m_wait_for_item_sequence_id == sequence_id && m_wait_for_item_transaction_id == transaction_id)); endtask function bit uvm_sequencer_base::is_blocked(uvm_sequence_base sequence_ptr); if (sequence_ptr == null) uvm_report_fatal("uvm_sequence_controller", "is_blocked passed null sequence_ptr", UVM_NONE); foreach (lock_list[i]) begin if ((lock_list[i].get_inst_id() != sequence_ptr.get_inst_id()) && (is_child(lock_list[i], sequence_ptr) == 0)) begin return 1; end end return 0; endfunction function bit uvm_sequencer_base::has_lock(uvm_sequence_base sequence_ptr); int my_seq_id; if (sequence_ptr == null) uvm_report_fatal("uvm_sequence_controller", "has_lock passed null sequence_ptr", UVM_NONE); my_seq_id = m_register_sequence(sequence_ptr); foreach (lock_list[i]) begin if (lock_list[i].get_inst_id() == sequence_ptr.get_inst_id()) begin return 1; end end return 0; endfunction task uvm_sequencer_base::m_lock_req(uvm_sequence_base sequence_ptr, bit lock); int my_seq_id; uvm_sequence_request new_req; if (sequence_ptr == null) uvm_report_fatal("uvm_sequence_controller", "lock_req passed null sequence_ptr", UVM_NONE); my_seq_id = m_register_sequence(sequence_ptr); new_req = new(); new_req.grant = 0; new_req.sequence_id = sequence_ptr.get_sequence_id(); new_req.request = SEQ_TYPE_LOCK; new_req.sequence_ptr = sequence_ptr; new_req.request_id = g_request_id++; new_req.process_id = process::self(); if (lock == 1) begin arb_sequence_q.push_back(new_req); end else begin arb_sequence_q.push_front(new_req); m_update_lists(); end grant_queued_locks(); m_wait_for_arbitration_completed(new_req.request_id); endtask function void uvm_sequencer_base::m_unlock_req(uvm_sequence_base sequence_ptr); if (sequence_ptr == null) begin uvm_report_fatal("uvm_sequencer", "m_unlock_req passed null sequence_ptr", UVM_NONE); end begin int q[$]; int seqid=sequence_ptr.get_inst_id(); q=lock_list.find_first_index(item) with (item.get_inst_id() == seqid); if(q.size()==1) begin lock_list.delete(q[0]); grant_queued_locks(); m_update_lists(); end else uvm_report_warning("SQRUNL", {"Sequence '", sequence_ptr.get_full_name(), "' called ungrab / unlock, but didn't have lock"}, UVM_NONE); end endfunction task uvm_sequencer_base::lock(uvm_sequence_base sequence_ptr); m_lock_req(sequence_ptr, 1); endtask task uvm_sequencer_base::grab(uvm_sequence_base sequence_ptr); m_lock_req(sequence_ptr, 0); endtask function void uvm_sequencer_base::unlock(uvm_sequence_base sequence_ptr); m_unlock_req(sequence_ptr); endfunction function void uvm_sequencer_base::ungrab(uvm_sequence_base sequence_ptr); m_unlock_req(sequence_ptr); endfunction function void uvm_sequencer_base::remove_sequence_from_queues( uvm_sequence_base sequence_ptr); int i; int seq_id; seq_id = sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 0); i = 0; do begin if (arb_sequence_q.size() > i) begin if ((arb_sequence_q[i].sequence_id == seq_id) || (is_child(sequence_ptr, arb_sequence_q[i].sequence_ptr))) begin if (sequence_ptr.get_sequence_state() == UVM_FINISHED) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQFINERR")) uvm_report_error ("SEQFINERR", $sformatf("Parent sequence '%s' should not finish before all items from itself and items from descendent sequences are processed. The item request from the sequence '%s' is being removed.", sequence_ptr.get_full_name(), arb_sequence_q[i].sequence_ptr.get_full_name()), UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 1153, "", 1); end arb_sequence_q.delete(i); m_update_lists(); end else begin i++; end end end while (i < arb_sequence_q.size()); i = 0; do begin if (lock_list.size() > i) begin if ((lock_list[i].get_inst_id() == sequence_ptr.get_inst_id()) || (is_child(sequence_ptr, lock_list[i]))) begin if (sequence_ptr.get_sequence_state() == UVM_FINISHED) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQFINERR")) uvm_report_error ("SEQFINERR", $sformatf("Parent sequence '%s' should not finish before locks from itself and descedent sequences are removed. The lock held by the child sequence '%s' is being removed.",sequence_ptr.get_full_name(), lock_list[i].get_full_name()), UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 1172, "", 1); end lock_list.delete(i); m_update_lists(); end else begin i++; end end end while (i < lock_list.size()); m_unregister_sequence(sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1)); endfunction function void uvm_sequencer_base::stop_sequences(); uvm_sequence_base seq_ptr; seq_ptr = m_find_sequence(-1); while (seq_ptr != null) begin kill_sequence(seq_ptr); seq_ptr = m_find_sequence(-1); end endfunction function void uvm_sequencer_base::m_sequence_exiting(uvm_sequence_base sequence_ptr); remove_sequence_from_queues(sequence_ptr); endfunction function void uvm_sequencer_base::kill_sequence(uvm_sequence_base sequence_ptr); remove_sequence_from_queues(sequence_ptr); sequence_ptr.m_kill(); endfunction function bit uvm_sequencer_base::is_grabbed(); return (lock_list.size() != 0); endfunction function uvm_sequence_base uvm_sequencer_base::current_grabber(); if (lock_list.size() == 0) begin return null; end return lock_list[lock_list.size()-1]; endfunction function bit uvm_sequencer_base::has_do_available(); foreach (arb_sequence_q[i]) begin if ((arb_sequence_q[i].sequence_ptr.is_relevant() == 1) && (is_blocked(arb_sequence_q[i].sequence_ptr) == 0)) begin return 1; end end return 0; endfunction function void uvm_sequencer_base::set_arbitration(UVM_SEQ_ARB_TYPE val); m_arbitration = val; endfunction function UVM_SEQ_ARB_TYPE uvm_sequencer_base::get_arbitration(); return m_arbitration; endfunction function uvm_sequence_base uvm_sequencer_base::get_arbitration_sequence( int index); return arb_sequence_q[index].sequence_ptr; endfunction function void uvm_sequencer_base::analysis_write(uvm_sequence_item t); return; endfunction task uvm_sequencer_base::wait_for_sequences(); uvm_wait_for_nba_region(); endtask function void uvm_sequencer_base::send_request(uvm_sequence_base sequence_ptr, uvm_sequence_item t, bit rerandomize = 0); return; endfunction function void uvm_sequencer_base::set_max_zero_time_wait_relevant_count(int new_val) ; m_max_zero_time_wait_relevant_count = new_val ; endfunction function void uvm_sequencer_base::start_phase_sequence(uvm_phase phase); uvm_resource_pool rp = uvm_resource_pool::get(); uvm_resource_types::rsrc_q_t rq; uvm_sequence_base seq; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory f = cs.get_factory(); rq = rp.lookup_name({get_full_name(), ".", phase.get_name(), "_phase"}, "default_sequence", null, 0); uvm_resource_pool::sort_by_precedence(rq); for (int i = 0; seq == null && i < rq.size(); i++) begin uvm_resource_base rsrc = rq.get(i); uvm_resource#(uvm_sequence_base) sbr; uvm_resource#(uvm_object_wrapper) owr; if ($cast(sbr, rsrc) && sbr != null) begin seq = sbr.read(this); if (seq == null) begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"UVM/SQR/PH/DEF/SB/NULL")) uvm_report_info ("UVM/SQR/PH/DEF/SB/NULL", {"Default phase sequence for phase '", phase.get_name(),"' explicitly disabled"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1341, "", 1); end return; end end else if ($cast(owr, rsrc) && owr != null) begin uvm_object_wrapper wrapper; wrapper = owr.read(this); if (wrapper == null) begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"UVM/SQR/PH/DEF/OW/NULL")) uvm_report_info ("UVM/SQR/PH/DEF/OW/NULL", {"Default phase sequence for phase '", phase.get_name(),"' explicitly disabled"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1353, "", 1); end return; end if (!$cast(seq, f.create_object_by_type(wrapper, get_full_name(), wrapper.get_type_name())) || seq == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"PHASESEQ")) uvm_report_warning ("PHASESEQ", {"Default sequence for phase '", phase.get_name(),"' %s is not a sequence type"}, UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 1361, "", 1); end return; end end end if (seq == null) begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"PHASESEQ")) uvm_report_info ("PHASESEQ", {"No default phase sequence for phase '", phase.get_name(),"'"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1369, "", 1); end return; end begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"PHASESEQ")) uvm_report_info ("PHASESEQ", {"Starting default sequence '", seq.get_type_name(),"' for phase '", phase.get_name(),"'"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1374, "", 1); end seq.print_sequence_info = 1; seq.set_sequencer(this); seq.reseed(); seq.set_starting_phase(phase); if (seq.get_randomize_enabled() && !seq.randomize()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"STRDEFSEQ")) uvm_report_warning ("STRDEFSEQ", {"Randomization failed for default sequence '", seq.get_type_name(),"' for phase '", phase.get_name(),"'"}, UVM_NONE, "t/uvm/src/seq/uvm_sequencer_base.svh", 1383, "", 1); end return; end fork begin uvm_sequence_process_wrapper w = new(); w.pid = process::self(); w.seq = seq; w.pid.srandom(uvm_create_random_seed(seq.get_type_name(), this.get_full_name())); m_default_sequences[phase] = w; seq.start(this); m_default_sequences.delete(phase); end join_none endfunction function void uvm_sequencer_base::stop_phase_sequence(uvm_phase phase); if (m_default_sequences.exists(phase)) begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"PHASESEQ")) uvm_report_info ("PHASESEQ", {"Killing default sequence '", m_default_sequences[phase].seq.get_type_name(), "' for phase '", phase.get_name(), "'"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1409, "", 1); end m_default_sequences[phase].seq.kill(); end else begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"PHASESEQ")) uvm_report_info ("PHASESEQ", {"No default sequence to kill for phase '", phase.get_name(), "'"}, UVM_FULL, "t/uvm/src/seq/uvm_sequencer_base.svh", 1415, "", 1); end end endfunction : stop_phase_sequence class uvm_sequence_request; bit grant; int sequence_id; int request_id; int item_priority; process process_id; uvm_sequencer_base::seq_req_t request; uvm_sequence_base sequence_ptr; endclass class uvm_sequencer_analysis_fifo #(type RSP = uvm_sequence_item) extends uvm_tlm_fifo #(RSP); uvm_analysis_imp #(RSP, uvm_sequencer_analysis_fifo #(RSP)) analysis_export; uvm_sequencer_base sequencer_ptr; function new (string name, uvm_component parent = null); super.new(name, parent, 0); analysis_export = new ("analysis_export", this); endfunction function void write(input RSP t); if (sequencer_ptr == null) uvm_report_fatal ("SEQRNULL", "The sequencer pointer is null when attempting a write", UVM_NONE); sequencer_ptr.analysis_write(t); endfunction endclass virtual class uvm_sequencer_param_base #(type REQ = uvm_sequence_item, type RSP = REQ) extends uvm_sequencer_base; typedef uvm_sequencer_param_base #( REQ , RSP) this_type; typedef REQ req_type; typedef RSP rsp_type; REQ m_last_req_buffer[$]; RSP m_last_rsp_buffer[$]; protected int m_num_last_reqs = 1; protected int num_last_items = m_num_last_reqs; protected int m_num_last_rsps = 1; protected int m_num_reqs_sent; protected int m_num_rsps_received; uvm_sequencer_analysis_fifo #(RSP) sqr_rsp_analysis_fifo; extern function new (string name, uvm_component parent); extern virtual function void send_request(uvm_sequence_base sequence_ptr, uvm_sequence_item t, bit rerandomize = 0); function REQ get_current_item(); REQ t; if (m_req_fifo.try_peek(t) == 0) return null; return t; endfunction extern function int get_num_reqs_sent(); extern function void set_num_last_reqs(int unsigned max); extern function int unsigned get_num_last_reqs(); function REQ last_req(int unsigned n = 0); if(n > m_num_last_reqs) begin uvm_report_warning("HSTOB", $sformatf("Invalid last access (%0d), the max history is %0d", n, m_num_last_reqs)); return null; end if(n == m_last_req_buffer.size()) return null; return m_last_req_buffer[n]; endfunction uvm_analysis_export #(RSP) rsp_export; extern function int get_num_rsps_received(); extern function void set_num_last_rsps(int unsigned max); extern function int unsigned get_num_last_rsps(); function RSP last_rsp(int unsigned n = 0); if(n > m_num_last_rsps) begin uvm_report_warning("HSTOB", $sformatf("Invalid last access (%0d), the max history is %0d", n, m_num_last_rsps)); return null; end if(n == m_last_rsp_buffer.size()) return null; return m_last_rsp_buffer[n]; endfunction extern function void m_last_rsp_push_front(RSP item); extern function void put_response (RSP t); extern virtual function void build_phase(uvm_phase phase); extern virtual function void connect_phase(uvm_phase phase); extern virtual function void do_print (uvm_printer printer); extern virtual function void analysis_write(uvm_sequence_item t); extern function void m_last_req_push_front(REQ item); uvm_tlm_fifo #(REQ) m_req_fifo; endclass function uvm_sequencer_param_base::new (string name, uvm_component parent); super.new(name, parent); rsp_export = new("rsp_export", this); sqr_rsp_analysis_fifo = new("sqr_rsp_analysis_fifo", this); sqr_rsp_analysis_fifo.print_enabled = 0; m_req_fifo = new("req_fifo", this); m_req_fifo.print_enabled = 0; endfunction function void uvm_sequencer_param_base::do_print (uvm_printer printer); super.do_print(printer); printer.print_field_int("num_last_reqs", m_num_last_reqs, $bits(m_num_last_reqs), UVM_DEC); printer.print_field_int("num_last_rsps", m_num_last_rsps, $bits(m_num_last_rsps), UVM_DEC); endfunction function void uvm_sequencer_param_base::connect_phase(uvm_phase phase); super.connect_phase(phase); rsp_export.connect(sqr_rsp_analysis_fifo.analysis_export); endfunction function void uvm_sequencer_param_base::build_phase(uvm_phase phase); super.build_phase(phase); sqr_rsp_analysis_fifo.sequencer_ptr = this; endfunction function void uvm_sequencer_param_base::send_request(uvm_sequence_base sequence_ptr, uvm_sequence_item t, bit rerandomize = 0); REQ param_t; if (sequence_ptr == null) begin uvm_report_fatal("SNDREQ", "Send request sequence_ptr is null", UVM_NONE); end if (sequence_ptr.m_wait_for_grant_semaphore < 1) begin uvm_report_fatal("SNDREQ", "Send request called without wait_for_grant", UVM_NONE); end sequence_ptr.m_wait_for_grant_semaphore--; if ($cast(param_t, t)) begin if (rerandomize == 1) begin if (!param_t.randomize()) begin uvm_report_warning("SQRSNDREQ", "Failed to rerandomize sequence item in send_request"); end end if (param_t.get_transaction_id() == -1) begin param_t.set_transaction_id(sequence_ptr.m_next_transaction_id++); end m_last_req_push_front(param_t); end else begin uvm_report_fatal("SQRSNDREQCAST",$sformatf("send_request failed to cast sequence item"), UVM_NONE); end param_t.set_sequence_id(sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1)); t.set_sequencer(this); if (m_req_fifo.try_put(param_t) != 1) begin uvm_report_fatal("SQRSNDREQGNI", "Concurrent calls to get_next_item() not supported. Consider using a semaphore to ensure that concurrent processes take turns in the driver", UVM_NONE); end m_num_reqs_sent++; grant_queued_locks(); endfunction function void uvm_sequencer_param_base::put_response (RSP t); uvm_sequence_base sequence_ptr; if (t == null) begin uvm_report_fatal("SQRPUT", "Driver put a null response", UVM_NONE); end m_last_rsp_push_front(t); m_num_rsps_received++; if (t.get_sequence_id() == -1) begin uvm_report_fatal("SQRPUT", "Driver put a response with null sequence_id", UVM_NONE); return; end sequence_ptr = m_find_sequence(t.get_sequence_id()); if (sequence_ptr != null) begin if (sequence_ptr.get_use_response_handler() == 1) begin sequence_ptr.response_handler(t); return; end sequence_ptr.put_response(t); end else begin uvm_report_warning("Sequencer", $sformatf("Dropping response for sequence %0d, sequence not found. Probable cause: sequence exited or has been killed", t.get_sequence_id())); end endfunction function void uvm_sequencer_param_base::analysis_write(uvm_sequence_item t); RSP response; if (!$cast(response, t)) begin uvm_report_fatal("ANALWRT", "Failure to cast analysis port write item", UVM_NONE); end put_response(response); endfunction function int uvm_sequencer_param_base::get_num_reqs_sent(); return m_num_reqs_sent; endfunction function int uvm_sequencer_param_base::get_num_rsps_received(); return m_num_rsps_received; endfunction function void uvm_sequencer_param_base::set_num_last_reqs(int unsigned max); if(max > 1024) begin uvm_report_warning("HSTOB", $sformatf("Invalid last size; 1024 is the maximum and will be used")); max = 1024; end while((m_last_req_buffer.size() != 0) && (m_last_req_buffer.size() > max)) void'(m_last_req_buffer.pop_back()); m_num_last_reqs = max; num_last_items = max; endfunction function int unsigned uvm_sequencer_param_base::get_num_last_reqs(); return m_num_last_reqs; endfunction function void uvm_sequencer_param_base::m_last_req_push_front(REQ item); if(!m_num_last_reqs) return; if(m_last_req_buffer.size() == m_num_last_reqs) void'(m_last_req_buffer.pop_back()); this.m_last_req_buffer.push_front(item); endfunction function void uvm_sequencer_param_base::set_num_last_rsps(int unsigned max); if(max > 1024) begin uvm_report_warning("HSTOB", $sformatf("Invalid last size; 1024 is the maximum and will be used")); max = 1024; end while((m_last_rsp_buffer.size() != 0) && (m_last_rsp_buffer.size() > max)) begin void'(m_last_rsp_buffer.pop_back()); end m_num_last_rsps = max; endfunction function int unsigned uvm_sequencer_param_base::get_num_last_rsps(); return m_num_last_rsps; endfunction function void uvm_sequencer_param_base::m_last_rsp_push_front(RSP item); if(!m_num_last_rsps) return; if(m_last_rsp_buffer.size() == m_num_last_rsps) void'(m_last_rsp_buffer.pop_back()); this.m_last_rsp_buffer.push_front(item); endfunction class uvm_sequencer #(type REQ=uvm_sequence_item, RSP=REQ) extends uvm_sequencer_param_base #(REQ, RSP); typedef uvm_sequencer #( REQ , RSP) this_type; bit sequence_item_requested; bit get_next_item_called; typedef uvm_component_registry #(this_type) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction extern function new (string name, uvm_component parent=null); extern virtual function void stop_sequences(); extern virtual function string get_type_name(); uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export; extern virtual task get_next_item (output REQ t); extern virtual task try_next_item (output REQ t); extern virtual function void item_done (RSP item = null); extern virtual task put (RSP t); extern task get (output REQ t); extern task peek (output REQ t); extern function void item_done_trigger(RSP item = null); function RSP item_done_get_trigger_data(); return last_rsp(0); endfunction extern protected virtual function int m_find_number_driver_connections(); endclass typedef uvm_sequencer #(uvm_sequence_item) uvm_virtual_sequencer; function uvm_sequencer::new (string name, uvm_component parent=null); super.new(name, parent); //TODO issue #4497 - Fix uvm_sequencer wrong reference type //TODO %Error: t/t_uvm_pkg_todo.vh:19869:21: Function Argument expects a CLASSREFDTYPE 'uvm_sequencer__Tz97_TBz97', got CLASSREFDTYPE 'uvm_sequencer__Tz97' //TODO seq_item_export = new ("seq_item_export", this); endfunction function void uvm_sequencer::stop_sequences(); REQ t; super.stop_sequences(); sequence_item_requested = 0; get_next_item_called = 0; if (m_req_fifo.used()) begin uvm_report_info(get_full_name(), "Sequences stopped. Removing request from sequencer fifo"); m_req_fifo.flush(); end endfunction function string uvm_sequencer::get_type_name(); return "uvm_sequencer"; endfunction function int uvm_sequencer::m_find_number_driver_connections(); uvm_port_base #(uvm_sqr_if_base #(REQ, RSP)) provided_to_port_list[string]; seq_item_export.get_provided_to(provided_to_port_list); return provided_to_port_list.num(); endfunction task uvm_sequencer::get_next_item(output REQ t); REQ req_item; if (get_next_item_called == 1) uvm_report_error(get_full_name(), "Get_next_item called twice without item_done or get in between", UVM_NONE); if (!sequence_item_requested) m_select_sequence(); sequence_item_requested = 1; get_next_item_called = 1; m_req_fifo.peek(t); endtask task uvm_sequencer::try_next_item(output REQ t); int selected_sequence; time arb_time; uvm_sequence_base seq; if (get_next_item_called == 1) begin uvm_report_error(get_full_name(), "get_next_item/try_next_item called twice without item_done or get in between", UVM_NONE); return; end wait_for_sequences(); selected_sequence = m_choose_next_request(); if (selected_sequence == -1) begin t = null; return; end m_set_arbitration_completed(arb_sequence_q[selected_sequence].request_id); seq = arb_sequence_q[selected_sequence].sequence_ptr; arb_sequence_q.delete(selected_sequence); m_update_lists(); sequence_item_requested = 1; get_next_item_called = 1; wait_for_sequences(); if (!m_req_fifo.try_peek(t)) uvm_report_error("TRY_NEXT_BLOCKED", {"try_next_item: the selected sequence '", seq.get_full_name(), "' did not produce an item within an NBA delay. ", "Sequences should not consume time between calls to start_item and finish_item. ", "Returning null item."}, UVM_NONE); endtask function void uvm_sequencer::item_done(RSP item = null); REQ t; sequence_item_requested = 0; get_next_item_called = 0; if (m_req_fifo.try_get(t) == 0) begin uvm_report_fatal("SQRBADITMDN", {"Item_done() called with no outstanding requests.", " Each call to item_done() must be paired with a previous call to get_next_item()."}); end else begin m_wait_for_item_sequence_id = t.get_sequence_id(); m_wait_for_item_transaction_id = t.get_transaction_id(); end if (item != null) begin seq_item_export.put_response(item); end grant_queued_locks(); endfunction task uvm_sequencer::put (RSP t); put_response(t); endtask task uvm_sequencer::get(output REQ t); if (sequence_item_requested == 0) begin m_select_sequence(); end sequence_item_requested = 1; m_req_fifo.peek(t); item_done(); endtask task uvm_sequencer::peek(output REQ t); if (sequence_item_requested == 0) begin m_select_sequence(); end sequence_item_requested = 1; m_req_fifo.peek(t); endtask function void uvm_sequencer::item_done_trigger(RSP item = null); item_done(item); endfunction class uvm_push_sequencer #(type REQ=uvm_sequence_item, RSP=REQ) extends uvm_sequencer_param_base #(REQ, RSP); typedef uvm_push_sequencer #( REQ , RSP) this_type; uvm_blocking_put_port #(REQ) req_port; function new (string name, uvm_component parent=null); super.new(name, parent); req_port = new ("req_port", this); endfunction task run_phase(uvm_phase phase); REQ t; int selected_sequence; fork super.run_phase(phase); forever begin m_select_sequence(); m_req_fifo.get(t); req_port.put(t); m_wait_for_item_sequence_id = t.get_sequence_id(); m_wait_for_item_transaction_id = t.get_transaction_id(); end join endtask protected virtual function int m_find_number_driver_connections(); return req_port.size(); endfunction endclass virtual class uvm_sequence_base extends uvm_sequence_item; typedef uvm_abstract_object_registry#(uvm_sequence_base,"uvm_sequence_base") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_sequence_base"; endfunction : type_name virtual function string get_type_name(); return "uvm_sequence_base"; endfunction : get_type_name protected uvm_sequence_state m_sequence_state; int m_next_transaction_id = 1; local int m_priority = -1; uvm_recorder m_tr_recorder; int m_wait_for_grant_semaphore; protected int m_sqr_seq_ids[int]; protected bit children_array[uvm_sequence_base]; protected uvm_sequence_item response_queue[$]; protected int response_queue_depth = 8; protected bit response_queue_error_report_enabled; local bit do_not_randomize; protected process m_sequence_process; local bit m_use_response_handler; local bit is_rel_default; local bit wait_rel_default; function new (string name = "uvm_sequence"); super.new(name); m_sequence_state = UVM_CREATED; m_wait_for_grant_semaphore = 0; m_init_phase_daps(1); endfunction virtual function bit get_randomize_enabled(); return (do_not_randomize == 0); endfunction : get_randomize_enabled virtual function void set_randomize_enabled(bit enable); do_not_randomize = !enable; endfunction : set_randomize_enabled virtual function bit is_item(); return 0; endfunction function uvm_sequence_state_enum get_sequence_state(); return m_sequence_state; endfunction task wait_for_sequence_state(int unsigned state_mask); wait (m_sequence_state & state_mask); endtask function int get_tr_handle(); if (m_tr_recorder != null) return m_tr_recorder.get_handle(); else return 0; endfunction virtual task start (uvm_sequencer_base sequencer, uvm_sequence_base parent_sequence = null, int this_priority = -1, bit call_pre_post = 1); bit old_automatic_phase_objection; set_item_context(parent_sequence, sequencer); if (!(m_sequence_state inside {UVM_CREATED,UVM_STOPPED,UVM_FINISHED})) begin uvm_report_fatal("SEQ_NOT_DONE", {"Sequence ", get_full_name(), " already started"},UVM_NONE); end if (m_parent_sequence != null) begin m_parent_sequence.children_array[this] = 1; end if (this_priority < -1) begin uvm_report_fatal("SEQPRI", $sformatf("Sequence %s start has illegal priority: %0d", get_full_name(), this_priority), UVM_NONE); end if (this_priority < 0) begin if (parent_sequence == null) this_priority = 100; else this_priority = parent_sequence.get_priority(); end clear_response_queue(); m_priority = this_priority; if (m_sequencer != null) begin int handle; if (m_parent_sequence == null) begin handle = m_sequencer.begin_tr(this, get_name()); m_tr_recorder = uvm_recorder::get_recorder_from_handle(handle); end else begin handle = m_sequencer.begin_tr(.tr(this), .stream_name(get_root_sequence_name()), .parent_handle((m_parent_sequence.m_tr_recorder == null) ? 0 : m_parent_sequence.m_tr_recorder.get_handle())); m_tr_recorder = uvm_recorder::get_recorder_from_handle(handle); end end set_sequence_id(-1); if (m_sequencer != null) begin void'(m_sequencer.m_register_sequence(this)); end m_sequence_state = UVM_PRE_START; fork begin m_sequence_process = process::self(); #0; if (get_automatic_phase_objection()) begin m_safe_raise_starting_phase("automatic phase objection"); end pre_start(); if (call_pre_post == 1) begin m_sequence_state = UVM_PRE_BODY; #0; pre_body(); end if (parent_sequence != null) begin parent_sequence.pre_do(0); parent_sequence.mid_do(this); end m_sequence_state = UVM_BODY; #0; body(); m_sequence_state = UVM_ENDED; #0; if (parent_sequence != null) begin parent_sequence.post_do(this); end if (call_pre_post == 1) begin m_sequence_state = UVM_POST_BODY; #0; post_body(); end m_sequence_state = UVM_POST_START; #0; post_start(); if (get_automatic_phase_objection()) begin m_safe_drop_starting_phase("automatic phase objection"); end m_sequence_state = UVM_FINISHED; #0; end join if (m_sequencer != null) begin m_sequencer.end_tr(this); end if (m_sequence_state != UVM_STOPPED) begin clean_exit_sequence(); end #0; if ((m_parent_sequence != null) && (m_parent_sequence.children_array.exists(this))) begin m_parent_sequence.children_array.delete(this); end old_automatic_phase_objection = get_automatic_phase_objection(); m_init_phase_daps(1); set_automatic_phase_objection(old_automatic_phase_objection); endtask function void clean_exit_sequence(); if (m_sequencer != null) m_sequencer.m_sequence_exiting(this); else foreach(m_sqr_seq_ids[seqrID]) begin uvm_sequencer_base s = uvm_sequencer_base::all_sequencer_insts[seqrID]; s.m_sequence_exiting(this); end m_sqr_seq_ids.delete(); endfunction virtual task pre_start(); return; endtask virtual task pre_body(); return; endtask virtual task pre_do(bit is_item); return; endtask virtual function void mid_do(uvm_sequence_item this_item); return; endfunction virtual task body(); uvm_report_warning("uvm_sequence_base", "Body definition undefined"); return; endtask virtual function void post_do(uvm_sequence_item this_item); return; endfunction virtual task post_body(); return; endtask virtual task post_start(); return; endtask local uvm_get_to_lock_dap#(bit) m_automatic_phase_objection_dap; local uvm_get_to_lock_dap#(uvm_phase) m_starting_phase_dap; function void m_init_phase_daps(bit create); string apo_name = $sformatf("%s.automatic_phase_objection", get_full_name()); string sp_name = $sformatf("%s.starting_phase", get_full_name()); if (create) begin m_automatic_phase_objection_dap = uvm_get_to_lock_dap#(bit)::type_id_create(apo_name, get_sequencer()); m_starting_phase_dap = uvm_get_to_lock_dap#(uvm_phase)::type_id_create(sp_name, get_sequencer()); end else begin m_automatic_phase_objection_dap.set_name(apo_name); m_starting_phase_dap.set_name(sp_name); end endfunction : m_init_phase_daps function uvm_phase get_starting_phase(); return m_starting_phase_dap.get(); endfunction : get_starting_phase function void set_starting_phase(uvm_phase phase); m_starting_phase_dap.set(phase); endfunction : set_starting_phase function void set_automatic_phase_objection(bit value); m_automatic_phase_objection_dap.set(value); endfunction : set_automatic_phase_objection function bit get_automatic_phase_objection(); return m_automatic_phase_objection_dap.get(); endfunction : get_automatic_phase_objection function void m_safe_raise_starting_phase(string description = "", int count = 1); uvm_phase starting_phase = get_starting_phase(); if (starting_phase != null) starting_phase.raise_objection(this, description, count); endfunction : m_safe_raise_starting_phase function void m_safe_drop_starting_phase(string description = "", int count = 1); uvm_phase starting_phase = get_starting_phase(); if (starting_phase != null) starting_phase.drop_objection(this, description, count); endfunction : m_safe_drop_starting_phase function void set_priority (int value); m_priority = value; endfunction function int get_priority(); return m_priority; endfunction virtual function bit is_relevant(); is_rel_default = 1; return 1; endfunction virtual task wait_for_relevant(); event e; wait_rel_default = 1; if (is_rel_default != wait_rel_default) uvm_report_fatal("RELMSM", "is_relevant() was implemented without defining wait_for_relevant()", UVM_NONE); //TODO issue #4495 - unsupported local event - may want to model the larger context where is used - might be case where edit upstream? //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:20247:5: Unsupported: waiting on local event variables //TODO @e; endtask task lock(uvm_sequencer_base sequencer = null); if (sequencer == null) sequencer = m_sequencer; if (sequencer == null) uvm_report_fatal("LOCKSEQR", "Null m_sequencer reference", UVM_NONE); sequencer.lock(this); endtask task grab(uvm_sequencer_base sequencer = null); if (sequencer == null) begin if (m_sequencer == null) begin uvm_report_fatal("GRAB", "Null m_sequencer reference", UVM_NONE); end m_sequencer.grab(this); end else begin sequencer.grab(this); end endtask function void unlock(uvm_sequencer_base sequencer = null); if (sequencer == null) begin if (m_sequencer == null) begin uvm_report_fatal("UNLOCK", "Null m_sequencer reference", UVM_NONE); end m_sequencer.unlock(this); end else begin sequencer.unlock(this); end endfunction function void ungrab(uvm_sequencer_base sequencer = null); unlock(sequencer); endfunction function bit is_blocked(); return m_sequencer.is_blocked(this); endfunction function bit has_lock(); return m_sequencer.has_lock(this); endfunction function void kill(); if (m_sequence_process != null) begin if (m_sequencer == null) begin m_kill(); if (get_automatic_phase_objection()) begin m_safe_drop_starting_phase("automatic phase objection"); end return; end m_sequencer.kill_sequence(this); if (get_automatic_phase_objection()) begin m_safe_drop_starting_phase("automatic phase objection"); end return; end endfunction virtual function void do_kill(); return; endfunction function void m_kill(); do_kill(); foreach(children_array[i]) begin i.kill(); end if (m_sequence_process != null) begin m_sequence_process.kill; m_sequence_process = null; end m_sequence_state = UVM_STOPPED; if ((m_parent_sequence != null) && (m_parent_sequence.children_array.exists(this))) m_parent_sequence.children_array.delete(this); clean_exit_sequence(); endfunction protected function uvm_sequence_item create_item(uvm_object_wrapper type_var, uvm_sequencer_base l_sequencer, string name); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); $cast(create_item, factory.create_object_by_type( type_var, this.get_full_name(), name )); create_item.set_item_context(this, l_sequencer); endfunction virtual task start_item (uvm_sequence_item item, int set_priority = -1, uvm_sequencer_base sequencer=null); if(item == null) begin uvm_report_fatal("NULLITM", {"attempting to start a null item from sequence '", get_full_name(), "'"}, UVM_NONE); return; end if ( ! item.is_item() ) begin uvm_report_fatal("SEQNOTITM", {"attempting to start a sequence using start_item() from sequence '", get_full_name(), "'. Use seq.start() instead."}, UVM_NONE); return; end if (sequencer == null) sequencer = item.get_sequencer(); if(sequencer == null) sequencer = get_sequencer(); if(sequencer == null) begin uvm_report_fatal("SEQ",{"neither the item's sequencer nor dedicated sequencer has been supplied to start item in ",get_full_name()},UVM_NONE); return; end item.set_item_context(this, sequencer); if (set_priority < 0) set_priority = get_priority(); sequencer.wait_for_grant(this, set_priority); if (sequencer.is_auto_item_recording_enabled()) begin void'(sequencer.begin_tr(.tr(item), .stream_name(item.get_root_sequence_name()), .label("Transactions"), .parent_handle((m_tr_recorder == null) ? 0 : m_tr_recorder.get_handle()))); end pre_do(1); endtask virtual task finish_item (uvm_sequence_item item, int set_priority = -1); uvm_sequencer_base sequencer; sequencer = item.get_sequencer(); if (sequencer == null) begin uvm_report_fatal("STRITM", "sequence_item has null sequencer", UVM_NONE); end mid_do(item); sequencer.send_request(this, item); sequencer.wait_for_item_done(this, -1); if (sequencer.is_auto_item_recording_enabled()) begin sequencer.end_tr(item); end post_do(item); endtask virtual task wait_for_grant(int item_priority = -1, bit lock_request = 0); if (m_sequencer == null) begin uvm_report_fatal("WAITGRANT", "Null m_sequencer reference", UVM_NONE); end m_sequencer.wait_for_grant(this, item_priority, lock_request); endtask virtual function void send_request(uvm_sequence_item request, bit rerandomize = 0); if (m_sequencer == null) begin uvm_report_fatal("SENDREQ", "Null m_sequencer reference", UVM_NONE); end m_sequencer.send_request(this, request, rerandomize); endfunction virtual task wait_for_item_done(int transaction_id = -1); if (m_sequencer == null) begin uvm_report_fatal("WAITITEMDONE", "Null m_sequencer reference", UVM_NONE); end m_sequencer.wait_for_item_done(this, transaction_id); endtask function void use_response_handler(bit enable); m_use_response_handler = enable; endfunction function bit get_use_response_handler(); return m_use_response_handler; endfunction virtual function void response_handler(uvm_sequence_item response); return; endfunction function void set_response_queue_error_report_enabled(bit value); response_queue_error_report_enabled = value; endfunction : set_response_queue_error_report_enabled function bit get_response_queue_error_report_enabled(); return response_queue_error_report_enabled; endfunction : get_response_queue_error_report_enabled function void set_response_queue_depth(int value); response_queue_depth = value; endfunction function int get_response_queue_depth(); return response_queue_depth; endfunction virtual function void clear_response_queue(); response_queue.delete(); endfunction virtual function void put_base_response(input uvm_sequence_item response); if ((response_queue_depth == -1) || (response_queue.size() < response_queue_depth)) begin response_queue.push_back(response); return; end if (response_queue_error_report_enabled) begin uvm_report_error(get_full_name(), "Response queue overflow, response was dropped", UVM_NONE); end endfunction virtual function void put_response (uvm_sequence_item response_item); put_base_response(response_item); endfunction virtual task get_base_response(output uvm_sequence_item response, input int transaction_id = -1); int queue_size, i; if (response_queue.size() == 0) wait (response_queue.size() != 0); if (transaction_id == -1) begin response = response_queue.pop_front(); return; end forever begin queue_size = response_queue.size(); for (i = 0; i < queue_size; i++) begin if (response_queue[i].get_transaction_id() == transaction_id) begin $cast(response,response_queue[i]); response_queue.delete(i); return; end end wait (response_queue.size() != queue_size); end endtask function int m_get_sqr_sequence_id(int sequencer_id, bit update_sequence_id); if (m_sqr_seq_ids.exists(sequencer_id)) begin if (update_sequence_id == 1) begin set_sequence_id(m_sqr_seq_ids[sequencer_id]); end return m_sqr_seq_ids[sequencer_id]; end if (update_sequence_id == 1) set_sequence_id(-1); return -1; endfunction function void m_set_sqr_sequence_id(int sequencer_id, int sequence_id); m_sqr_seq_ids[sequencer_id] = sequence_id; set_sequence_id(sequence_id); endfunction endclass virtual class uvm_sequence #(type REQ = uvm_sequence_item, type RSP = REQ) extends uvm_sequence_base; typedef uvm_sequencer_param_base #(REQ, RSP) sequencer_t; sequencer_t param_sequencer; REQ req; RSP rsp; function new (string name = "uvm_sequence"); super.new(name); endfunction function void send_request(uvm_sequence_item request, bit rerandomize = 0); REQ m_request; if (m_sequencer == null) begin uvm_report_fatal("SSENDREQ", "Null m_sequencer reference", UVM_NONE); end if (!$cast(m_request, request)) begin uvm_report_fatal("SSENDREQ", "Failure to cast uvm_sequence_item to request", UVM_NONE); end m_sequencer.send_request(this, m_request, rerandomize); endfunction function REQ get_current_item(); if (!$cast(param_sequencer, m_sequencer)) uvm_report_fatal("SGTCURR", "Failure to cast m_sequencer to the parameterized sequencer", UVM_NONE); return (param_sequencer.get_current_item()); endfunction virtual task get_response(output RSP response, input int transaction_id = -1); uvm_sequence_item rsp; get_base_response( rsp, transaction_id); $cast(response,rsp); endtask virtual function void put_response(uvm_sequence_item response_item); RSP response; if (!$cast(response, response_item)) begin uvm_report_fatal("PUTRSP", "Failure to cast response in put_response", UVM_NONE); end put_base_response(response_item); endfunction function void do_print (uvm_printer printer); super.do_print(printer); printer.print_object("req", req); printer.print_object("rsp", rsp); endfunction endclass typedef class uvm_sequence_library_cfg; class uvm_sequence_library #(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequence #(REQ,RSP); typedef uvm_object_registry #(uvm_sequence_library#(REQ,RSP)) type_id; static function uvm_sequence_library#(REQ,RSP) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_sequence_library#(REQ,RSP) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_sequence_library #(REQ,RSP)"; endfunction : type_name virtual function string get_type_name(); return "uvm_sequence_library #(REQ,RSP)"; endfunction : get_type_name extern function new(string name=""); uvm_sequence_lib_mode selection_mode; int unsigned min_random_count=10; int unsigned max_random_count=10; protected int unsigned sequences_executed; rand int unsigned sequence_count = 10; rand int unsigned select_rand; randc bit [15:0] select_randc; protected int seqs_distrib[string] = '{default:0}; protected uvm_object_wrapper sequences[$]; constraint valid_rand_selection { select_rand inside {[0:sequences.size()-1]}; } constraint valid_randc_selection { select_randc inside {[0:sequences.size()-1]}; } constraint valid_sequence_count { sequence_count inside {[min_random_count:max_random_count]}; } extern virtual function int unsigned select_sequence(int unsigned max); extern static function void add_typewide_sequence(uvm_object_wrapper seq_type); extern static function void add_typewide_sequences(uvm_object_wrapper seq_types[$]); extern function void add_sequence(uvm_object_wrapper seq_type); extern virtual function void add_sequences(uvm_object_wrapper seq_types[$]); extern virtual function void remove_sequence(uvm_object_wrapper seq_type); extern virtual function void get_sequences(ref uvm_object_wrapper seq_types[$]); extern virtual function uvm_object_wrapper get_sequence(int unsigned idx); extern function void init_sequence_library(); typedef uvm_sequence_library #(REQ,RSP) this_type; static protected uvm_object_wrapper m_typewide_sequences[$]; bit m_abort; extern static function bit m_static_check(uvm_object_wrapper seq_type); extern static function bit m_check(uvm_object_wrapper seq_type, this_type lib); extern function bit m_dyn_check(uvm_object_wrapper seq_type); extern function void m_get_config(); extern static function bit m_add_typewide_sequence(uvm_object_wrapper seq_type); extern virtual task execute(uvm_object_wrapper wrap); extern virtual task body(); extern virtual function void do_print(uvm_printer printer); extern function void pre_randomize(); endclass class uvm_sequence_library_cfg extends uvm_object; typedef uvm_object_registry#(uvm_sequence_library_cfg,"uvm_sequence_library_cfg") type_id; static function uvm_sequence_library_cfg type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_sequence_library_cfg tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_sequence_library_cfg"; endfunction : type_name virtual function string get_type_name(); return "uvm_sequence_library_cfg"; endfunction : get_type_name uvm_sequence_lib_mode selection_mode; int unsigned min_random_count; int unsigned max_random_count; function new(string name="", uvm_sequence_lib_mode mode=UVM_SEQ_LIB_RAND, int unsigned min=1, int unsigned max=10); super.new(name); selection_mode = mode; min_random_count = min; max_random_count = max; endfunction endclass function uvm_sequence_library::new(string name=""); super.new(name); init_sequence_library(); valid_rand_selection.constraint_mode(0); valid_randc_selection.constraint_mode(0); endfunction function bit uvm_sequence_library::m_add_typewide_sequence(uvm_object_wrapper seq_type); this_type::add_typewide_sequence(seq_type); return 1; endfunction function void uvm_sequence_library::add_typewide_sequence(uvm_object_wrapper seq_type); if (m_static_check(seq_type)) m_typewide_sequences.push_back(seq_type); endfunction function void uvm_sequence_library::add_typewide_sequences(uvm_object_wrapper seq_types[$]); foreach (seq_types[i]) add_typewide_sequence(seq_types[i]); endfunction function void uvm_sequence_library::add_sequence(uvm_object_wrapper seq_type); if (m_dyn_check(seq_type)) sequences.push_back(seq_type); endfunction function void uvm_sequence_library::add_sequences(uvm_object_wrapper seq_types[$]); foreach (seq_types[i]) add_sequence(seq_types[i]); endfunction function void uvm_sequence_library::remove_sequence(uvm_object_wrapper seq_type); foreach (sequences[i]) if (sequences[i] == seq_type) begin sequences.delete(i); return; end endfunction function void uvm_sequence_library::get_sequences(ref uvm_object_wrapper seq_types[$]); foreach (sequences[i]) seq_types.push_back(sequences[i]); endfunction function uvm_object_wrapper uvm_sequence_library::get_sequence(int unsigned idx); if(idx < sequences.size()) return sequences[idx]; else begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQ_LIB/GET_SEQ")) uvm_report_error ("SEQ_LIB/GET_SEQ", $sformatf("idx %0d > number of sequences in library", idx), UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 453, "", 1); end return null; end endfunction function int unsigned uvm_sequence_library::select_sequence(int unsigned max); static int unsigned counter; select_sequence = counter; counter++; if (counter >= max) counter = 0; endfunction function void uvm_sequence_library::init_sequence_library(); foreach (this_type::m_typewide_sequences[i]) sequences.push_back(this_type::m_typewide_sequences[i]); endfunction function bit uvm_sequence_library::m_static_check(uvm_object_wrapper seq_type); if (!m_check(seq_type,null)) return 0; foreach (m_typewide_sequences[i]) if (m_typewide_sequences[i] == seq_type) return 0; return 1; endfunction function bit uvm_sequence_library::m_dyn_check(uvm_object_wrapper seq_type); if (!m_check(seq_type,this)) return 0; foreach (sequences[i]) if (sequences[i] == seq_type) return 0; return 1; endfunction function bit uvm_sequence_library::m_check(uvm_object_wrapper seq_type, this_type lib); uvm_object obj; uvm_sequence_base seq; uvm_root top; uvm_coreservice_t cs; string name; string typ; obj = seq_type.create_object(); name = (lib == null) ? type_name() : lib.get_full_name(); typ = (lib == null) ? type_name() : lib.get_type_name(); cs = uvm_coreservice_t::get(); top = cs.get_root(); if (!$cast(seq, obj)) begin begin if (top.uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/BAD_SEQ_TYPE")) top.uvm_report_error ("SEQLIB/BAD_SEQ_TYPE", {"Object '",obj.get_type_name(), "' is not a sequence. Cannot add to sequence library '",name, "'"}, UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 538, "", 1); end return 0; end return 1; endfunction function void uvm_sequence_library::pre_randomize(); m_get_config(); endfunction function void uvm_sequence_library::m_get_config(); uvm_sequence_library_cfg cfg; string phase_name; uvm_phase starting_phase = get_starting_phase(); if (starting_phase != null) begin phase_name = {starting_phase.get_name(),"_phase"}; end if (uvm_config_db #(uvm_sequence_library_cfg)::get(m_sequencer, phase_name, "default_sequence.config", cfg) ) begin selection_mode = cfg.selection_mode; min_random_count = cfg.min_random_count; max_random_count = cfg.max_random_count; end else begin void'(uvm_config_db #(int unsigned)::get(m_sequencer, phase_name, "default_sequence.min_random_count", min_random_count) ); void'(uvm_config_db #(int unsigned)::get(m_sequencer, phase_name, "default_sequence.max_random_count", max_random_count) ); void'(uvm_config_db #(uvm_sequence_lib_mode)::get(m_sequencer, phase_name, "default_sequence.selection_mode", selection_mode) ); end if (max_random_count == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"SEQLIB/MAX_ZERO")) uvm_report_warning ("SEQLIB/MAX_ZERO", $sformatf("max_random_count (%0d) zero. Nothing will be done.", max_random_count), UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 593, "", 1); end if (min_random_count > max_random_count) min_random_count = max_random_count; end else if (min_random_count > max_random_count) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/MIN_GT_MAX")) uvm_report_error ("SEQLIB/MIN_GT_MAX", $sformatf("min_random_count (%0d) greater than max_random_count (%0d). Setting min to max.", min_random_count,max_random_count), UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 600, "", 1); end min_random_count = max_random_count; end else begin if (selection_mode == UVM_SEQ_LIB_ITEM) begin uvm_sequencer #(REQ,RSP) seqr; uvm_object_wrapper lhs = REQ::get_type(); uvm_object_wrapper rhs = uvm_sequence_item::get_type(); if (lhs == rhs) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/BASE_ITEM")) uvm_report_error ("SEQLIB/BASE_ITEM", {"selection_mode cannot be UVM_SEQ_LIB_ITEM when ", "the REQ type is the base uvm_sequence_item. Using UVM_SEQ_LIB_RAND mode"}, UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 610, "", 1); end selection_mode = UVM_SEQ_LIB_RAND; end if (m_sequencer == null || !$cast(seqr,m_sequencer)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/VIRT_SEQ")) uvm_report_error ("SEQLIB/VIRT_SEQ", {"selection_mode cannot be UVM_SEQ_LIB_ITEM when ", "running as a virtual sequence. Using UVM_SEQ_LIB_RAND mode"}, UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 615, "", 1); end selection_mode = UVM_SEQ_LIB_RAND; end end end endfunction task uvm_sequence_library::body(); uvm_object_wrapper wrap; uvm_phase starting_phase = get_starting_phase(); if (m_sequencer == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"SEQLIB/VIRT_SEQ")) uvm_report_fatal ("SEQLIB/VIRT_SEQ", {"Sequence library 'm_sequencer' handle is null ", " no current support for running as a virtual sequence."}, UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 634, "", 1); end return; end if (sequences.size() == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/NOSEQS")) uvm_report_error ("SEQLIB/NOSEQS", "Sequence library does not contain any sequences. Did you forget to call init_sequence_library() in the constructor?", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 639, "", 1); end return; end if (!get_randomize_enabled()) m_get_config(); m_safe_raise_starting_phase({"starting sequence library ",get_full_name()," (", get_type_name(),")"}); begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"SEQLIB/START")) uvm_report_info ("SEQLIB/START", $sformatf("Starting sequence library %s in %s phase: %0d iterations in mode %s", get_type_name(), (starting_phase != null ? starting_phase.get_name() : "unknown"), sequence_count, selection_mode.name()), UVM_LOW, "t/uvm/src/seq/uvm_sequence_library.svh", 652, "", 1); end begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"SEQLIB/SPRINT")) uvm_report_info ("SEQLIB/SPRINT", {"\n",sprint(uvm_table_printer::get_default())}, UVM_FULL, "t/uvm/src/seq/uvm_sequence_library.svh", 654, "", 1); end case (selection_mode) UVM_SEQ_LIB_RAND: begin valid_rand_selection.constraint_mode(1); valid_sequence_count.constraint_mode(0); for (int i=1; i<=sequence_count; i++) begin if (!randomize(select_rand)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/RAND_FAIL")) uvm_report_error ("SEQLIB/RAND_FAIL", "Random sequence selection failed", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 663, "", 1); end break; end else begin wrap = sequences[select_rand]; end execute(wrap); end valid_rand_selection.constraint_mode(0); valid_sequence_count.constraint_mode(1); end UVM_SEQ_LIB_RANDC: begin uvm_object_wrapper q[$]; valid_randc_selection.constraint_mode(1); valid_sequence_count.constraint_mode(0); for (int i=1; i<=sequence_count; i++) begin if (!randomize(select_randc)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/RANDC_FAIL")) uvm_report_error ("SEQLIB/RANDC_FAIL", "Random sequence selection failed", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 681, "", 1); end break; end else begin wrap = sequences[select_randc]; end q.push_back(wrap); end valid_randc_selection.constraint_mode(0); valid_sequence_count.constraint_mode(1); foreach(q[i]) execute(q[i]); valid_randc_selection.constraint_mode(0); valid_sequence_count.constraint_mode(1); end UVM_SEQ_LIB_ITEM: begin for (int i=1; i<=sequence_count; i++) begin wrap = REQ::get_type(); execute(wrap); end end UVM_SEQ_LIB_USER: begin for (int i=1; i<=sequence_count; i++) begin int user_selection; user_selection = select_sequence(sequences.size()-1); if (user_selection >= sequences.size()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/USER_FAIL")) uvm_report_error ("SEQLIB/USER_FAIL", "User sequence selection out of range", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 709, "", 1); end wrap = REQ::get_type(); end else begin wrap = sequences[user_selection]; end execute(wrap); end end default: begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"SEQLIB/RAND_MODE")) uvm_report_fatal ("SEQLIB/RAND_MODE", $sformatf("Unknown random sequence selection mode: %0d",selection_mode), UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 721, "", 1); end end endcase begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"SEQLIB/END")) uvm_report_info ("SEQLIB/END", {"Ending sequence library in phase ", (starting_phase != null ? starting_phase.get_name() : "unknown")}, UVM_LOW, "t/uvm/src/seq/uvm_sequence_library.svh", 726, "", 1); end begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"SEQLIB/DSTRB")) uvm_report_info ("SEQLIB/DSTRB", $sformatf("%p",seqs_distrib), UVM_HIGH, "t/uvm/src/seq/uvm_sequence_library.svh", 728, "", 1); end m_safe_drop_starting_phase({"starting sequence library ",get_full_name()," (", get_type_name(),")"}); endtask task uvm_sequence_library::execute(uvm_object_wrapper wrap); uvm_object obj; uvm_sequence_item seq_or_item; uvm_sequence_base seq_base; REQ req_item; uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); obj = factory.create_object_by_type(wrap,get_full_name(), $sformatf("%s:%0d",wrap.get_type_name(),sequences_executed+1)); if (!$cast(seq_base, obj)) begin if (!$cast(req_item, obj)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"SEQLIB/WRONG_ITEM_TYPE")) uvm_report_error ("SEQLIB/WRONG_ITEM_TYPE", {"The item created by '", get_full_name(), "' when in 'UVM_SEQ_LIB_ITEM' mode doesn't match the REQ type which was passed in to the uvm_sequence_library#(REQ[,RSP]), this can happen if the REQ type which was passed in was a pure-virtual type. Either configure the factory overrides to properly generate items for this sequence library, or do not execute this sequence library in UVM_SEQ_LIB_ITEM mode."}, UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 756, "", 1); end return; end end void'($cast(seq_or_item,obj)); begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"SEQLIB/EXEC")) uvm_report_info ("SEQLIB/EXEC", {"Executing ",(seq_or_item.is_item() ? "item " : "sequence "),seq_or_item.get_name(), " (",seq_or_item.get_type_name(),")"}, UVM_FULL, "t/uvm/src/seq/uvm_sequence_library.svh", 764, "", 1); end seq_or_item.print_sequence_info = 1; begin uvm_sequence_base __seq; if ( seq_or_item.is_item() ) begin start_item(seq_or_item, -1); if ( ! seq_or_item.randomize() with {} ) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RNDFLD")) uvm_report_warning ("RNDFLD", "Randomization failed in uvm_rand_send action", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 766, "", 1); end end finish_item(seq_or_item, -1); end else if ( $cast( __seq, seq_or_item ) ) begin __seq.set_item_context(this,seq_or_item.get_sequencer()); if ( __seq.get_randomize_enabled() ) begin if ( ! seq_or_item.randomize() with {} ) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RNDFLD")) uvm_report_warning ("RNDFLD", "Randomization failed in uvm_rand_send action", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 766, "", 1); end end end __seq.start(__seq.get_sequencer(), this, -1, 0); end else begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"NOT_SEQ_OR_ITEM")) uvm_report_warning ("NOT_SEQ_OR_ITEM", "Object passed uvm_rand_send appears to be neither a sequence or item.", UVM_NONE, "t/uvm/src/seq/uvm_sequence_library.svh", 766, "", 1); end end end seqs_distrib[seq_or_item.get_type_name()] = seqs_distrib[seq_or_item.get_type_name()]+1; sequences_executed++; endtask function void uvm_sequence_library::do_print(uvm_printer printer); printer.print_field_int("min_random_count",min_random_count,32,UVM_DEC,,"int unsigned"); printer.print_field_int("max_random_count",max_random_count,32,UVM_DEC,,"int unsigned"); printer.print_generic("selection_mode","uvm_sequence_lib_mode",32,selection_mode.name()); printer.print_field_int("sequence_count",sequence_count,32,UVM_DEC,,"int unsigned"); printer.print_array_header("typewide_sequences",m_typewide_sequences.size(),"queue_object_types"); foreach (m_typewide_sequences[i]) printer.print_generic($sformatf("[%0d]",i),"uvm_object_wrapper","-",m_typewide_sequences[i].get_type_name()); printer.print_array_footer(); printer.print_array_header("sequences",sequences.size(),"queue_object_types"); foreach (sequences[i]) printer.print_generic($sformatf("[%0d]",i),"uvm_object_wrapper","-",sequences[i].get_type_name()); printer.print_array_footer(); printer.print_array_header("seqs_distrib",seqs_distrib.num(),"as_int_string"); foreach (seqs_distrib[typ]) begin printer.print_field_int({"[",typ,"]"},seqs_distrib[typ],32,,UVM_DEC,"int unsigned"); end printer.print_array_footer(); endfunction typedef uvm_sequence #(uvm_sequence_item, uvm_sequence_item) uvm_default_sequence_type; typedef uvm_sequencer #(uvm_sequence_item, uvm_sequence_item) uvm_default_sequencer_type; typedef uvm_driver #(uvm_sequence_item, uvm_sequence_item) uvm_default_driver_type; typedef uvm_sequencer_param_base #(uvm_sequence_item, uvm_sequence_item) uvm_default_sequencer_param_type; class uvm_time; static local real m_resolution = 1.0e-12; local real m_res; local time m_time; local string m_name; static function void set_time_resolution(real res); m_resolution = res; endfunction function new(string name = "uvm_tlm_time", real res = 0); m_name = name; m_res = (res == 0) ? m_resolution : res; reset(); endfunction function string get_name(); return m_name; endfunction function void reset(); m_time = 0; endfunction local function real to_m_res(real t, time scaled, real secs); return t/real'(scaled) * (secs/m_res); endfunction function real get_realtime(time scaled, real secs = 1.0e-9); return m_time*real'(scaled) * m_res/secs; endfunction function void incr(real t, time scaled, real secs = 1.0e-9); if (t < 0.0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/TIMENEG")) uvm_report_error ("UVM/TLM/TIMENEG", {"Cannot increment uvm_tlm_time variable ", m_name, " by a negative value"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm_time.svh", 134, "", 1); end return; end if (scaled == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"UVM/TLM/BADSCALE")) uvm_report_fatal ("UVM/TLM/BADSCALE", "uvm_tlm_time::incr() called with a scaled time literal that is smaller than the current timescale", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm_time.svh", 139, "", 1); end end m_time += to_m_res(t, scaled, secs); endfunction function void decr(real t, time scaled, real secs); if (t < 0.0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/TIMENEG")) uvm_report_error ("UVM/TLM/TIMENEG", {"Cannot decrement uvm_tlm_time variable ", m_name, " by a negative value"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm_time.svh", 161, "", 1); end return; end if (scaled == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"UVM/TLM/BADSCALE")) uvm_report_fatal ("UVM/TLM/BADSCALE", "uvm_tlm_time::decr() called with a scaled time literal that is smaller than the current timescale", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm_time.svh", 166, "", 1); end end m_time -= to_m_res(t, scaled, secs); if (m_time < 0.0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/TOODECR")) uvm_report_error ("UVM/TLM/TOODECR", {"Cannot decrement uvm_tlm_time variable ", m_name, " to a negative value"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm_time.svh", 172, "", 1); end reset(); end endfunction function real get_abstime(real secs); return m_time*m_res/secs; endfunction function void set_abstime(real t, real secs); m_time = t*secs/m_res; endfunction endclass typedef uvm_time uvm_tlm_time; typedef enum { UVM_TLM_READ_COMMAND, UVM_TLM_WRITE_COMMAND, UVM_TLM_IGNORE_COMMAND } uvm_tlm_command_e; typedef enum { UVM_TLM_OK_RESPONSE = 1, UVM_TLM_INCOMPLETE_RESPONSE = 0, UVM_TLM_GENERIC_ERROR_RESPONSE = -1, UVM_TLM_ADDRESS_ERROR_RESPONSE = -2, UVM_TLM_COMMAND_ERROR_RESPONSE = -3, UVM_TLM_BURST_ERROR_RESPONSE = -4, UVM_TLM_BYTE_ENABLE_ERROR_RESPONSE = -5 } uvm_tlm_response_status_e; typedef class uvm_tlm_extension_base; class uvm_tlm_generic_payload extends uvm_sequence_item; rand bit [63:0] m_address; rand uvm_tlm_command_e m_command; //TODO issue-4625 - Rand fields of dynamic array types //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'byte[]' /*TODO rand*/ byte unsigned m_data[]; rand int unsigned m_length; rand uvm_tlm_response_status_e m_response_status; bit m_dmi; //TODO issue-4625 - Rand fields of dynamic array types //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'byte[]' /*TODO rand*/ byte unsigned m_byte_enable[]; rand int unsigned m_byte_enable_length; rand int unsigned m_streaming_width; protected uvm_tlm_extension_base m_extensions [uvm_tlm_extension_base]; //TODO issue-4625 - Rand fields of dynamic array types //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'CLASSREFDTYPE 'uvm_tlm_extension_base'[]' local /*rand*/ uvm_tlm_extension_base m_rand_exts[]; typedef uvm_object_registry#(uvm_tlm_generic_payload,"uvm_tlm_generic_payload") type_id; static function uvm_tlm_generic_payload type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_tlm_generic_payload tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_tlm_generic_payload"; endfunction : type_name virtual function string get_type_name(); return "uvm_tlm_generic_payload"; endfunction : get_type_name function new(string name=""); super.new(name); m_address = 0; m_command = UVM_TLM_IGNORE_COMMAND; m_length = 0; m_response_status = UVM_TLM_INCOMPLETE_RESPONSE; m_dmi = 0; m_byte_enable_length = 0; m_streaming_width = 0; endfunction function void do_print(uvm_printer printer); byte unsigned be; super.do_print(printer); printer.print_field_int ("address", m_address, 64, UVM_HEX); printer.print_generic ("command", "uvm_tlm_command_e", 32, m_command.name()); printer.print_generic ("response_status", "uvm_tlm_response_status_e", 32, m_response_status.name()); printer.print_field_int ("streaming_width", m_streaming_width, 32, UVM_HEX); printer.print_array_header("data", m_length, "darray(byte)"); for (int i=0; i < m_length && i < m_data.size(); i++) begin if (m_byte_enable_length) begin be = m_byte_enable[i % m_byte_enable_length]; printer.print_generic ($sformatf("[%0d]",i), "byte", 8, $sformatf("'h%h%s",m_data[i],((be=='hFF) ? "" : " x"))); end else printer.print_generic ($sformatf("[%0d]",i), "byte", 8, $sformatf("'h%h",m_data[i])); end printer.print_array_footer(); begin string name; printer.print_array_header("extensions", m_extensions.num(), "aa(obj,obj)"); foreach (m_extensions[ext_]) begin uvm_tlm_extension_base ext = m_extensions[ext_]; name = {"[",ext.get_name(),"]"}; printer.print_object(name, ext, "["); end printer.print_array_footer(); end endfunction function void do_copy(uvm_object rhs); uvm_tlm_generic_payload gp; super.do_copy(rhs); $cast(gp, rhs); m_address = gp.m_address; m_command = gp.m_command; m_data = gp.m_data; m_dmi = gp.m_dmi; m_length = gp.m_length; m_response_status = gp.m_response_status; m_byte_enable = gp.m_byte_enable; m_streaming_width = gp.m_streaming_width; m_byte_enable_length = gp.m_byte_enable_length; m_extensions.delete(); foreach (gp.m_extensions[ext]) $cast(m_extensions[ext], gp.m_extensions[ext].clone()); endfunction function bit do_compare(uvm_object rhs, uvm_comparer comparer); uvm_tlm_generic_payload gp; do_compare = super.do_compare(rhs, comparer); $cast(gp, rhs); if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_address) != (gp.m_address)) ) begin string name = ("" == "") ? "m_address" : ""; void'(comparer.compare_field_int(name , m_address, gp.m_address, $bits(m_address), UVM_HEX)); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_command) != (gp.m_command)) ) begin string name = ("" == "") ? "m_command" : ""; void'( comparer.compare_string(name, $sformatf("%s'(%s)", "uvm_tlm_command_e", m_command.name()), $sformatf("%s'(%s)", "uvm_tlm_command_e", gp.m_command.name())) ); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_length) != (gp.m_length)) ) begin string name = ("" == "") ? "m_length" : ""; void'(comparer.compare_field_int(name , m_length, gp.m_length, $bits(m_length), UVM_UNSIGNED)); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_dmi) != (gp.m_dmi)) ) begin string name = ("" == "") ? "m_dmi" : ""; void'(comparer.compare_field_int(name , m_dmi, gp.m_dmi, $bits(m_dmi), UVM_BIN)); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_byte_enable_length) != (gp.m_byte_enable_length)) ) begin string name = ("" == "") ? "m_byte_enable_length" : ""; void'(comparer.compare_field_int(name , m_byte_enable_length, gp.m_byte_enable_length, $bits(m_byte_enable_length), UVM_UNSIGNED)); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_response_status) != (gp.m_response_status)) ) begin string name = ("" == "") ? "m_response_status" : ""; void'( comparer.compare_string(name, $sformatf("%s'(%s)", "uvm_tlm_response_status_e", m_response_status.name()), $sformatf("%s'(%s)", "uvm_tlm_response_status_e", gp.m_response_status.name())) ); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_streaming_width) != (gp.m_streaming_width)) ) begin string name = ("" == "") ? "m_streaming_width" : ""; void'(comparer.compare_field_int(name , m_streaming_width, gp.m_streaming_width, $bits(m_streaming_width), UVM_UNSIGNED)); end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && m_byte_enable_length == gp.m_byte_enable_length ) begin for (int i=0; i < m_byte_enable_length && i < m_byte_enable.size(); i++) begin if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_byte_enable[i]) != (gp.m_byte_enable[i])) ) begin string name = ($sformatf("m_byte_enable[%0d]", i) == "") ? "m_byte_enable[i]" : $sformatf("m_byte_enable[%0d]", i); void'(comparer.compare_field_int(name , m_byte_enable[i], gp.m_byte_enable[i], $bits(m_byte_enable[i]), UVM_HEX)); end end end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && m_length == gp.m_length ) begin byte unsigned be; for (int i=0; i < m_length && i < m_data.size(); i++) begin if (m_byte_enable_length) begin be = m_byte_enable[i % m_byte_enable_length]; end else begin be = 8'hFF; end if ( (!comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold())) && ((m_data[i] & be) != (gp.m_data[i] & be)) ) begin string name = ($sformatf("m_data[%0d] & %0x", i, be) == "") ? "m_data[i] & be" : $sformatf("m_data[%0d] & %0x", i, be); void'(comparer.compare_field_int(name , m_data[i] & be, gp.m_data[i] & be, $bits(m_data[i] & be), UVM_HEX)); end end end if ( !comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold()) ) foreach (m_extensions[ext_]) begin uvm_tlm_extension_base ext = ext_; uvm_tlm_extension_base rhs_ext = gp.m_extensions.exists(ext) ? gp.m_extensions[ext] : null; void'(comparer.compare_object(ext.get_name(), m_extensions[ext], rhs_ext)); if ( !comparer.get_threshold() || (comparer.get_result() < comparer.get_threshold()) ) break; end if (comparer.get_result()) begin string msg = $sformatf("GP miscompare between '%s' and '%s':\nlhs = %s\nrhs = %s", get_full_name(), gp.get_full_name(), this.convert2string(), gp.convert2string()); comparer.print_msg(msg); end return (comparer.get_result() == 0); endfunction function void do_pack(uvm_packer packer); super.do_pack(packer); if (m_length > m_data.size()) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PACK_DATA_ARR")) uvm_report_fatal ("PACK_DATA_ARR", $sformatf("Data array m_length property (%0d) greater than m_data.size (%0d)", m_length,m_data.size()), UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_generic_payload.svh", 562, "", 1); end if (m_byte_enable_length > m_byte_enable.size()) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"PACK_DATA_ARR")) uvm_report_fatal ("PACK_DATA_ARR", $sformatf("Data array m_byte_enable_length property (%0d) greater than m_byte_enable.size (%0d)", m_byte_enable_length,m_byte_enable.size()), UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_generic_payload.svh", 566, "", 1); end begin bit __array[]; { << bit { __array}} = m_address; __array = new [64] (__array); packer.pack_bits(__array, 64); end begin bit __array[]; { << bit { __array}} = m_command; __array = new [32] (__array); packer.pack_bits(__array, 32); end begin bit __array[]; { << bit { __array}} = m_length; __array = new [32] (__array); packer.pack_bits(__array, 32); end begin bit __array[]; { << bit { __array}} = m_dmi; __array = new [1] (__array); packer.pack_bits(__array, 1); end for (int i=0; i 64) recorder.record_field("address", m_address, $bits(m_address), UVM_NORADIX); else recorder.record_field_int("address", m_address, $bits(m_address), UVM_NORADIX); end if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic("command", $sformatf("%p", m_command.name())); else recorder.record_string("command",m_command.name()); end if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic("data_length", $sformatf("%p", m_length)); else if ($bits(m_length) > 64) recorder.record_field("data_length", m_length, $bits(m_length), UVM_NORADIX); else recorder.record_field_int("data_length", m_length, $bits(m_length), UVM_NORADIX); end if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic("byte_enable_length", $sformatf("%p", m_byte_enable_length)); else if ($bits(m_byte_enable_length) > 64) recorder.record_field("byte_enable_length", m_byte_enable_length, $bits(m_byte_enable_length), UVM_NORADIX); else recorder.record_field_int("byte_enable_length", m_byte_enable_length, $bits(m_byte_enable_length), UVM_NORADIX); end if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic("response_status", $sformatf("%p", m_response_status.name())); else recorder.record_string("response_status",m_response_status.name()); end if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic("streaming_width", $sformatf("%p", m_streaming_width)); else if ($bits(m_streaming_width) > 64) recorder.record_field("streaming_width", m_streaming_width, $bits(m_streaming_width), UVM_NORADIX); else recorder.record_field_int("streaming_width", m_streaming_width, $bits(m_streaming_width), UVM_NORADIX); end for (int i=0; i < m_length; i++) if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic($sformatf("\\data[%0d] ", i), $sformatf("%p", m_data[i])); else if ($bits(m_data[i]) > 64) recorder.record_field($sformatf("\\data[%0d] ", i), m_data[i], $bits(m_data[i]), UVM_NORADIX); else recorder.record_field_int($sformatf("\\data[%0d] ", i), m_data[i], $bits(m_data[i]), UVM_NORADIX); end for (int i=0; i < m_byte_enable_length; i++) if (recorder != null && recorder.is_open()) begin if (recorder.use_record_attribute()) recorder.record_generic($sformatf("\\byte_en[%0d] ", i), $sformatf("%p", m_byte_enable[i])); else if ($bits(m_byte_enable[i]) > 64) recorder.record_field($sformatf("\\byte_en[%0d] ", i), m_byte_enable[i], $bits(m_byte_enable[i]), UVM_NORADIX); else recorder.record_field_int($sformatf("\\byte_en[%0d] ", i), m_byte_enable[i], $bits(m_byte_enable[i]), UVM_NORADIX); end foreach (m_extensions[ext]) recorder.record_object(ext.get_name(),m_extensions[ext]); endfunction function string convert2string(); string msg; string s; $sformat(msg, "%s %s [0x%16x] =", super.convert2string(), m_command.name(), m_address); for(int unsigned i = 0; i < m_length; i++) begin if (!m_byte_enable_length || (m_byte_enable[i % m_byte_enable_length] == 'hFF)) $sformat(s, " %02x", m_data[i]); else $sformat(s, " --"); msg = { msg , s }; end msg = { msg, " (status=", get_response_string(), ")" }; return msg; endfunction virtual function uvm_tlm_command_e get_command(); return m_command; endfunction virtual function void set_command(uvm_tlm_command_e command); m_command = command; endfunction virtual function bit is_read(); return (m_command == UVM_TLM_READ_COMMAND); endfunction virtual function void set_read(); set_command(UVM_TLM_READ_COMMAND); endfunction virtual function bit is_write(); return (m_command == UVM_TLM_WRITE_COMMAND); endfunction virtual function void set_write(); set_command(UVM_TLM_WRITE_COMMAND); endfunction virtual function void set_address(bit [63:0] addr); m_address = addr; endfunction virtual function bit [63:0] get_address(); return m_address; endfunction virtual function void get_data (output byte unsigned p []); p = m_data; endfunction virtual function void set_data(ref byte unsigned p []); m_data = p; endfunction virtual function int unsigned get_data_length(); return m_length; endfunction virtual function void set_data_length(int unsigned length); m_length = length; endfunction virtual function int unsigned get_streaming_width(); return m_streaming_width; endfunction virtual function void set_streaming_width(int unsigned width); m_streaming_width = width; endfunction virtual function void get_byte_enable(output byte unsigned p[]); p = m_byte_enable; endfunction virtual function void set_byte_enable(ref byte unsigned p[]); m_byte_enable = p; endfunction virtual function int unsigned get_byte_enable_length(); return m_byte_enable_length; endfunction virtual function void set_byte_enable_length(int unsigned length); m_byte_enable_length = length; endfunction virtual function void set_dmi_allowed(bit dmi); m_dmi = dmi; endfunction virtual function bit is_dmi_allowed(); return m_dmi; endfunction virtual function uvm_tlm_response_status_e get_response_status(); return m_response_status; endfunction virtual function void set_response_status(uvm_tlm_response_status_e status); m_response_status = status; endfunction virtual function bit is_response_ok(); return (int'(m_response_status) > 0); endfunction virtual function bit is_response_error(); return !is_response_ok(); endfunction virtual function string get_response_string(); case(m_response_status) UVM_TLM_OK_RESPONSE : return "OK"; UVM_TLM_INCOMPLETE_RESPONSE : return "INCOMPLETE"; UVM_TLM_GENERIC_ERROR_RESPONSE : return "GENERIC_ERROR"; UVM_TLM_ADDRESS_ERROR_RESPONSE : return "ADDRESS_ERROR"; UVM_TLM_COMMAND_ERROR_RESPONSE : return "COMMAND_ERROR"; UVM_TLM_BURST_ERROR_RESPONSE : return "BURST_ERROR"; UVM_TLM_BYTE_ENABLE_ERROR_RESPONSE : return "BYTE_ENABLE_ERROR"; endcase return "UNKNOWN_RESPONSE"; endfunction function uvm_tlm_extension_base set_extension(uvm_tlm_extension_base ext); uvm_tlm_extension_base ext_handle = ext.get_type_handle(); if(!m_extensions.exists(ext_handle)) set_extension = null; else set_extension = m_extensions[ext_handle]; m_extensions[ext_handle] = ext; endfunction function int get_num_extensions(); return m_extensions.num(); endfunction: get_num_extensions function uvm_tlm_extension_base get_extension(uvm_tlm_extension_base ext_handle); if(!m_extensions.exists(ext_handle)) return null; return m_extensions[ext_handle]; endfunction function void clear_extension(uvm_tlm_extension_base ext_handle); if(m_extensions.exists(ext_handle)) m_extensions.delete(ext_handle); else begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"GP_EXT")) uvm_report_info ("GP_EXT", $sformatf("Unable to find extension to clear"), UVM_MEDIUM, "t/uvm/src/tlm2/uvm_tlm2_generic_payload.svh", 965, "", 1); end endfunction function void clear_extensions(); m_extensions.delete(); endfunction function void pre_randomize(); int i; m_rand_exts = new [m_extensions.num()]; foreach (m_extensions[ext_]) begin uvm_tlm_extension_base ext = ext_; m_rand_exts[i++] = m_extensions[ext]; end endfunction function void post_randomize(); m_rand_exts.delete(); endfunction endclass typedef uvm_tlm_generic_payload uvm_tlm_gp; virtual class uvm_tlm_extension_base extends uvm_object; function new(string name = ""); super.new(name); endfunction pure virtual function uvm_tlm_extension_base get_type_handle(); pure virtual function string get_type_handle_name(); virtual function void do_copy(uvm_object rhs); super.do_copy(rhs); endfunction virtual function uvm_object create (string name=""); return null; endfunction endclass class uvm_tlm_extension #(type T=int) extends uvm_tlm_extension_base; typedef uvm_tlm_extension#(T) this_type; local static this_type m_my_tlm_ext_type = ID(); function new(string name=""); super.new(name); endfunction static function this_type ID(); if (m_my_tlm_ext_type == null) m_my_tlm_ext_type = new(); return m_my_tlm_ext_type; endfunction virtual function uvm_tlm_extension_base get_type_handle(); return ID(); endfunction virtual function string get_type_handle_name(); return $typename(T); endfunction virtual function uvm_object create (string name=""); return null; endfunction endclass typedef class uvm_time; typedef enum { UNINITIALIZED_PHASE, BEGIN_REQ, END_REQ, BEGIN_RESP, END_RESP } uvm_tlm_phase_e; typedef enum { UVM_TLM_ACCEPTED, UVM_TLM_UPDATED, UVM_TLM_COMPLETED } uvm_tlm_sync_e; class uvm_tlm_if #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e); virtual function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"nb_transport_fw")) uvm_report_error ("nb_transport_fw", "UVM TLM 2 interface function not implemented", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ifs.svh", 115, "", 1); end return UVM_TLM_ACCEPTED; endfunction virtual function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"nb_transport_bw")) uvm_report_error ("nb_transport_bw", "UVM TLM 2 interface function not implemented", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ifs.svh", 158, "", 1); end return UVM_TLM_ACCEPTED; endfunction virtual task b_transport(T t, uvm_tlm_time delay); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"b_transport")) uvm_report_error ("b_transport", "TLM-2 interface task not implemented", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ifs.svh", 182, "", 1); end endtask endclass class uvm_tlm_b_transport_imp #(type T=uvm_tlm_generic_payload, type IMP=int) extends uvm_port_base #(uvm_tlm_if #(T)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_transport_imp"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_imps.svh", 173, "", 1); end return; end m_imp.b_transport(t, delay); endtask endclass class uvm_tlm_nb_transport_fw_imp #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e, type IMP=int) extends uvm_port_base #(uvm_tlm_if #(T,P)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_fw_imp"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_imps.svh", 190, "", 1); end return UVM_TLM_COMPLETED; end return m_imp.nb_transport_fw(t, p, delay); endfunction endclass class uvm_tlm_nb_transport_bw_imp #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e, type IMP=int) extends uvm_port_base #(uvm_tlm_if #(T,P)); local IMP m_imp; function new (string name, IMP imp); super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); m_imp = imp; m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_bw_imp"; endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_imps.svh", 207, "", 1); end return UVM_TLM_COMPLETED; end return m_imp.nb_transport_bw(t, p, delay); endfunction endclass class uvm_tlm_b_transport_port #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_transport_port"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ports.svh", 41, "", 1); end return; end this.m_if.b_transport(t, delay); endtask endclass class uvm_tlm_nb_transport_fw_port #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_fw_port"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ports.svh", 59, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_fw(t, p, delay); endfunction endclass class uvm_tlm_nb_transport_bw_port #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_bw_port"; endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_ports.svh", 78, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_bw(t, p, delay); endfunction endclass class uvm_tlm_b_transport_export #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_transport_export"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_exports.svh", 39, "", 1); end return; end this.m_if.b_transport(t, delay); endtask endclass class uvm_tlm_nb_transport_fw_export #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_fw_export"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_exports.svh", 53, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_fw(t, p, delay); endfunction endclass class uvm_tlm_nb_transport_bw_export #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<1); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_transport_bw_export"; endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_exports.svh", 68, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_bw(t, p, delay); endfunction endclass virtual class uvm_tlm_b_target_socket_base #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent); super.new (name, parent, UVM_IMPLEMENTATION, 1, 1); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_target_socket"; endfunction endclass virtual class uvm_tlm_b_initiator_socket_base #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_initiator_socket"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 77, "", 1); end return; end this.m_if.b_transport(t, delay); endtask endclass virtual class uvm_tlm_nb_target_socket_base #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); uvm_tlm_nb_transport_bw_port #(T,P) bw_port; function new (string name, uvm_component parent); super.new (name, parent, UVM_IMPLEMENTATION, 1, 1); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_target_socket"; endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 102, "", 1); end return UVM_TLM_COMPLETED; end return bw_port.nb_transport_bw(t, p, delay); endfunction endclass virtual class uvm_tlm_nb_initiator_socket_base #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); function new (string name, uvm_component parent); super.new (name, parent, UVM_PORT, 1, 1); m_if_mask = (1<<0); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_initiator_socket"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 125, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_fw(t, p, delay); endfunction endclass virtual class uvm_tlm_nb_passthrough_initiator_socket_base #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); uvm_tlm_nb_transport_bw_export #(T,P) bw_export; function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<0); bw_export = new("bw_export", get_comp()); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_passthrough_initiator_socket"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 155, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_fw(t, p, delay); endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 156, "", 1); end return UVM_TLM_COMPLETED; end return bw_export.nb_transport_bw(t, p, delay); endfunction endclass virtual class uvm_tlm_nb_passthrough_target_socket_base #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_port_base #(uvm_tlm_if #(T,P)); uvm_tlm_nb_transport_bw_port #(T,P) bw_port; function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<0); bw_port = new("bw_port", get_comp()); endfunction virtual function string get_type_name(); return "uvm_tlm_nb_passthrough_target_socket"; endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 183, "", 1); end return UVM_TLM_COMPLETED; end return this.m_if.nb_transport_fw(t, p, delay); endfunction function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_bw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 184, "", 1); end return UVM_TLM_COMPLETED; end return bw_port.nb_transport_bw(t, p, delay); endfunction endclass virtual class uvm_tlm_b_passthrough_initiator_socket_base #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_PORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_passthrough_initiator_socket"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 200, "", 1); end return; end this.m_if.b_transport(t, delay); endtask endclass virtual class uvm_tlm_b_passthrough_target_socket_base #(type T=uvm_tlm_generic_payload) extends uvm_port_base #(uvm_tlm_if #(T)); function new (string name, uvm_component parent, int min_size=1, int max_size=1); super.new (name, parent, UVM_EXPORT, min_size, max_size); m_if_mask = (1<<2); endfunction virtual function string get_type_name(); return "uvm_tlm_b_passthrough_target_socket"; endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets_base.svh", 217, "", 1); end return; end this.m_if.b_transport(t, delay); endtask endclass class uvm_tlm_b_initiator_socket #(type T=uvm_tlm_generic_payload) extends uvm_tlm_b_initiator_socket_base #(T); function new(string name, uvm_component parent); super.new(name, parent); endfunction function void connect(this_type provider); uvm_tlm_b_passthrough_initiator_socket_base #(T) initiator_pt_socket; uvm_tlm_b_passthrough_target_socket_base #(T) target_pt_socket; uvm_tlm_b_target_socket_base #(T) target_socket; uvm_component c; super.connect(provider); if($cast(initiator_pt_socket, provider) || $cast(target_pt_socket, provider) || $cast(target_socket, provider)) return; c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 87, "", 1); end endfunction endclass class uvm_tlm_b_target_socket #(type IMP=int, type T=uvm_tlm_generic_payload) extends uvm_tlm_b_target_socket_base #(T); local IMP m_imp; function new (string name, uvm_component parent, IMP imp = null); super.new (name, parent); if (imp == null) $cast(m_imp, parent); else m_imp = imp; if (m_imp == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM2/NOIMP")) uvm_report_error ("UVM/TLM2/NOIMP", {"b_target socket ", name, " has no implementation"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 121, "", 1); end endfunction function void connect(this_type provider); uvm_component c; super.connect(provider); c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "You cannot call connect() on a target termination socket", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 134, "", 1); end endfunction task b_transport(T t, uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".b_transport() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 137, "", 1); end return; end m_imp.b_transport(t, delay); endtask endclass class uvm_tlm_nb_initiator_socket #(type IMP=int, type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_tlm_nb_initiator_socket_base #(T,P); uvm_tlm_nb_transport_bw_imp #(T,P,IMP) bw_imp; function new(string name, uvm_component parent, IMP imp = null); super.new (name, parent); if (imp == null) $cast(imp, parent); if (imp == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM2/NOIMP")) uvm_report_error ("UVM/TLM2/NOIMP", {"nb_initiator socket ", name, " has no implementation"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 168, "", 1); end bw_imp = new("bw_imp", imp); endfunction function void connect(this_type provider); uvm_tlm_nb_passthrough_initiator_socket_base #(T,P) initiator_pt_socket; uvm_tlm_nb_passthrough_target_socket_base #(T,P) target_pt_socket; uvm_tlm_nb_target_socket_base #(T,P) target_socket; uvm_component c; super.connect(provider); if($cast(initiator_pt_socket, provider)) begin initiator_pt_socket.bw_export.connect(bw_imp); return; end if($cast(target_pt_socket, provider)) begin target_pt_socket.bw_port.connect(bw_imp); return; end if($cast(target_socket, provider)) begin target_socket.bw_port.connect(bw_imp); return; end c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 200, "", 1); end endfunction endclass class uvm_tlm_nb_target_socket #(type IMP=int, type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_tlm_nb_target_socket_base #(T,P); local IMP m_imp; function new (string name, uvm_component parent, IMP imp = null); super.new (name, parent); if (imp == null) $cast(m_imp, parent); else m_imp = imp; bw_port = new("bw_port", get_comp()); if (m_imp == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM2/NOIMP")) uvm_report_error ("UVM/TLM2/NOIMP", {"nb_target socket ", name, " has no implementation"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 236, "", 1); end endfunction function void connect(this_type provider); uvm_component c; super.connect(provider); c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "You cannot call connect() on a target termination socket", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 249, "", 1); end endfunction function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay); if (delay == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/TLM/NULLDELAY")) uvm_report_error ("UVM/TLM/NULLDELAY", {get_full_name(), ".nb_transport_fw() called with 'null' delay"}, UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 252, "", 1); end return UVM_TLM_COMPLETED; end return m_imp.nb_transport_fw(t, p, delay); endfunction endclass class uvm_tlm_b_passthrough_initiator_socket #(type T=uvm_tlm_generic_payload) extends uvm_tlm_b_passthrough_initiator_socket_base #(T); function new(string name, uvm_component parent); super.new(name, parent); endfunction function void connect(this_type provider); uvm_tlm_b_passthrough_initiator_socket_base #(T) initiator_pt_socket; uvm_tlm_b_passthrough_target_socket_base #(T) target_pt_socket; uvm_tlm_b_target_socket_base #(T) target_socket; uvm_component c; super.connect(provider); if($cast(initiator_pt_socket, provider) || $cast(target_pt_socket, provider) || $cast(target_socket, provider)) return; c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 290, "", 1); end endfunction endclass class uvm_tlm_b_passthrough_target_socket #(type T=uvm_tlm_generic_payload) extends uvm_tlm_b_passthrough_target_socket_base #(T); function new(string name, uvm_component parent); super.new(name, parent); endfunction function void connect(this_type provider); uvm_tlm_b_passthrough_target_socket_base #(T) target_pt_socket; uvm_tlm_b_target_socket_base #(T) target_socket; uvm_component c; super.connect(provider); if($cast(target_pt_socket, provider) || $cast(target_socket, provider)) return; c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 323, "", 1); end endfunction endclass class uvm_tlm_nb_passthrough_initiator_socket #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_tlm_nb_passthrough_initiator_socket_base #(T,P); function new(string name, uvm_component parent); super.new(name, parent); endfunction function void connect(this_type provider); uvm_tlm_nb_passthrough_initiator_socket_base #(T,P) initiator_pt_socket; uvm_tlm_nb_passthrough_target_socket_base #(T,P) target_pt_socket; uvm_tlm_nb_target_socket_base #(T,P) target_socket; uvm_component c; super.connect(provider); if($cast(initiator_pt_socket, provider)) begin bw_export.connect(initiator_pt_socket.bw_export); return; end if($cast(target_pt_socket, provider)) begin target_pt_socket.bw_port.connect(bw_export); return; end if($cast(target_socket, provider)) begin target_socket.bw_port.connect(bw_export); return; end c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 375, "", 1); end endfunction endclass class uvm_tlm_nb_passthrough_target_socket #(type T=uvm_tlm_generic_payload, type P=uvm_tlm_phase_e) extends uvm_tlm_nb_passthrough_target_socket_base #(T,P); function new(string name, uvm_component parent); super.new(name, parent); endfunction function void connect(this_type provider); uvm_tlm_nb_passthrough_target_socket_base #(T,P) target_pt_socket; uvm_tlm_nb_target_socket_base #(T,P) target_socket; uvm_component c; super.connect(provider); if($cast(target_pt_socket, provider)) begin target_pt_socket.bw_port.connect(bw_port); return; end if($cast(target_socket, provider)) begin target_socket.bw_port.connect(bw_port); return; end c = get_comp(); begin if (c.uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) c.uvm_report_error (get_type_name(), "type mismatch in connect -- connection cannot be completed", UVM_NONE, "t/uvm/src/tlm2/uvm_tlm2_sockets.svh", 419, "", 1); end endfunction endclass typedef class uvm_reg_field; typedef class uvm_vreg_field; typedef class uvm_reg; typedef class uvm_reg_file; typedef class uvm_vreg; typedef class uvm_reg_block; typedef class uvm_mem; typedef class uvm_reg_item; typedef class uvm_reg_map; typedef class uvm_reg_map_info; typedef class uvm_reg_sequence; typedef class uvm_reg_adapter; typedef class uvm_reg_indirect_data; typedef bit unsigned [64-1:0] uvm_reg_data_t ; typedef logic unsigned [64-1:0] uvm_reg_data_logic_t ; typedef bit unsigned [64-1:0] uvm_reg_addr_t ; typedef logic unsigned [64-1:0] uvm_reg_addr_logic_t ; typedef bit unsigned [((64-1)/8+1)-1:0] uvm_reg_byte_en_t ; typedef bit [32-1:0] uvm_reg_cvr_t ; typedef struct { string path; int offset; int size; } uvm_hdl_path_slice; typedef uvm_resource_db#(uvm_reg_cvr_t) uvm_reg_cvr_rsrc_db; typedef enum { UVM_IS_OK, UVM_NOT_OK, UVM_HAS_X } uvm_status_e; typedef enum { UVM_FRONTDOOR, UVM_BACKDOOR, UVM_PREDICT, UVM_DEFAULT_DOOR } uvm_door_e; typedef enum { UVM_NO_CHECK, UVM_CHECK } uvm_check_e; typedef enum { UVM_NO_ENDIAN, UVM_LITTLE_ENDIAN, UVM_BIG_ENDIAN, UVM_LITTLE_FIFO, UVM_BIG_FIFO } uvm_endianness_e; typedef enum { UVM_REG, UVM_FIELD, UVM_MEM } uvm_elem_kind_e; typedef enum { UVM_READ, UVM_WRITE, UVM_BURST_READ, UVM_BURST_WRITE } uvm_access_e; typedef enum { UVM_NO_HIER, UVM_HIER } uvm_hier_e; typedef enum { UVM_PREDICT_DIRECT, UVM_PREDICT_READ, UVM_PREDICT_WRITE } uvm_predict_e; typedef enum uvm_reg_cvr_t { UVM_NO_COVERAGE = 'h0000, UVM_CVR_REG_BITS = 'h0001, UVM_CVR_ADDR_MAP = 'h0002, UVM_CVR_FIELD_VALS = 'h0004, UVM_CVR_ALL = -1 } uvm_coverage_model_e; typedef enum bit [63:0] { UVM_DO_REG_HW_RESET = 64'h0000_0000_0000_0001, UVM_DO_REG_BIT_BASH = 64'h0000_0000_0000_0002, UVM_DO_REG_ACCESS = 64'h0000_0000_0000_0004, UVM_DO_MEM_ACCESS = 64'h0000_0000_0000_0008, UVM_DO_SHARED_ACCESS = 64'h0000_0000_0000_0010, UVM_DO_MEM_WALK = 64'h0000_0000_0000_0020, UVM_DO_ALL_REG_MEM_TESTS = 64'hffff_ffff_ffff_ffff } uvm_reg_mem_tests_e; class uvm_hdl_path_concat; uvm_hdl_path_slice slices[]; function void set(uvm_hdl_path_slice t[]); slices = t; endfunction function void add_slice(uvm_hdl_path_slice slice); slices = new [slices.size()+1] (slices); slices[slices.size()-1] = slice; endfunction function void add_path(string path, int unsigned offset = -1, int unsigned size = -1); uvm_hdl_path_slice t; t.offset = offset; t.path = path; t.size = size; add_slice(t); endfunction endclass function automatic string uvm_hdl_concat2string(uvm_hdl_path_concat concat); string image = "{"; if (concat.slices.size() == 1 && concat.slices[0].offset == -1 && concat.slices[0].size == -1) return concat.slices[0].path; foreach (concat.slices[i]) begin uvm_hdl_path_slice slice=concat.slices[i]; image = { image, (i == 0) ? "" : ", ", slice.path }; if (slice.offset >= 0) image = { image, "@", $sformatf("[%0d +: %0d]", slice.offset, slice.size) }; end image = { image, "}" }; return image; endfunction typedef struct packed { uvm_reg_addr_t min; uvm_reg_addr_t max; int unsigned stride; } uvm_reg_map_addr_range; class uvm_reg_item extends uvm_sequence_item; typedef uvm_object_registry#(uvm_reg_item,"uvm_reg_item") type_id; static function uvm_reg_item type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_item tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_item"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_item"; endfunction : get_type_name uvm_elem_kind_e element_kind; uvm_object element; rand uvm_access_e kind; //TODO issue-4625 - Rand fields of dynamic array types //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'bit[]' /*rand*/ uvm_reg_data_t value[]; constraint max_values { value.size() > 0 && value.size() < 1000; } rand uvm_reg_addr_t offset; uvm_status_e status; uvm_reg_map local_map; uvm_reg_map map; uvm_door_e path; rand uvm_sequence_base parent; int prior = -1; rand uvm_object extension; string bd_kind; string fname; int lineno; function new(string name=""); super.new(name); value = new[1]; endfunction virtual function string convert2string(); string s,value_s; s = {"kind=",kind.name(), " ele_kind=",element_kind.name(), " ele_name=",element==null?"null":element.get_full_name() }; if (value.size() > 1 && uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin value_s = "'{"; foreach (value[i]) value_s = {value_s,$sformatf("%0h,",value[i])}; value_s[value_s.len()-1]="}"; end else value_s = $sformatf("%0h",value[0]); s = {s, " value=",value_s}; if (element_kind == UVM_MEM) s = {s, $sformatf(" offset=%0h",offset)}; s = {s," map=",(map==null?"null":map.get_full_name())," path=",path.name()}; s = {s," status=",status.name()}; return s; endfunction virtual function void do_copy(uvm_object rhs); uvm_reg_item rhs_; if (rhs == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/NULL")) uvm_report_fatal ("REG/NULL", "do_copy: rhs argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_item.svh", 215, "", 1); end if (!$cast(rhs_,rhs)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"WRONG_TYPE")) uvm_report_error ("WRONG_TYPE", "Provided rhs is not of type uvm_reg_item", UVM_NONE, "t/uvm/src/reg/uvm_reg_item.svh", 218, "", 1); end return; end super.do_copy(rhs); element_kind = rhs_.element_kind; element = rhs_.element; kind = rhs_.kind; value = rhs_.value; offset = rhs_.offset; status = rhs_.status; local_map = rhs_.local_map; map = rhs_.map; path = rhs_.path; extension = rhs_.extension; bd_kind = rhs_.bd_kind; parent = rhs_.parent; prior = rhs_.prior; fname = rhs_.fname; lineno = rhs_.lineno; endfunction endclass typedef struct { uvm_access_e kind; uvm_reg_addr_t addr; uvm_reg_data_t data; int n_bits; uvm_reg_byte_en_t byte_en; uvm_status_e status; } uvm_reg_bus_op; virtual class uvm_reg_adapter extends uvm_object; typedef uvm_abstract_object_registry#(uvm_reg_adapter,"uvm_reg_adapter") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_reg_adapter"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_adapter"; endfunction : get_type_name function new(string name=""); super.new(name); endfunction bit supports_byte_enable; bit provides_responses; uvm_sequence_base parent_sequence; pure virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); pure virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw); local uvm_reg_item m_item; virtual function uvm_reg_item get_item(); return m_item; endfunction virtual function void m_set_item(uvm_reg_item item); m_item = item; endfunction endclass class uvm_reg_tlm_adapter extends uvm_reg_adapter; typedef uvm_object_registry#(uvm_reg_tlm_adapter,"uvm_reg_tlm_adapter") type_id; static function uvm_reg_tlm_adapter type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_tlm_adapter tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_tlm_adapter"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_tlm_adapter"; endfunction : get_type_name function new(string name = "uvm_reg_tlm_adapter"); super.new(name); endfunction virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); uvm_tlm_gp gp = uvm_tlm_gp::type_id_create("tlm_gp",, this.get_full_name()); int nbytes = (rw.n_bits-1)/8+1; uvm_reg_addr_t addr=rw.addr; if (rw.kind == UVM_WRITE) gp.set_command(UVM_TLM_WRITE_COMMAND); else gp.set_command(UVM_TLM_READ_COMMAND); gp.set_address(addr); gp.m_byte_enable = new [nbytes]; gp.m_byte_enable_length = nbytes; gp.set_streaming_width (nbytes); gp.m_data = new [gp.get_streaming_width()]; gp.m_length = nbytes; for (int i = 0; i < nbytes; i++) begin gp.m_data[i] = rw.data[i*8+:8]; gp.m_byte_enable[i] = (i > nbytes) ? 8'h00 : (rw.byte_en[i] ? 8'hFF : 8'h00); end return gp; endfunction virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw); uvm_tlm_gp gp; int nbytes; if (bus_item == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/NULL_ITEM")) uvm_report_fatal ("REG/NULL_ITEM", "bus2reg: bus_item argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_adapter.svh", 232, "", 1); end if (!$cast(gp,bus_item)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"WRONG_TYPE")) uvm_report_error ("WRONG_TYPE", "Provided bus_item is not of type uvm_tlm_gp", UVM_NONE, "t/uvm/src/reg/uvm_reg_adapter.svh", 235, "", 1); end return; end if (gp.get_command() == UVM_TLM_WRITE_COMMAND) rw.kind = UVM_WRITE; else rw.kind = UVM_READ; rw.addr = gp.get_address(); rw.byte_en = 0; foreach (gp.m_byte_enable[i]) rw.byte_en[i] = gp.m_byte_enable[i]; rw.data = 0; foreach (gp.m_data[i]) rw.data[i*8+:8] = gp.m_data[i]; rw.status = (gp.is_response_ok()) ? UVM_IS_OK : UVM_NOT_OK; endfunction endclass class uvm_predict_s; bit addr[uvm_reg_addr_t]; uvm_reg_item reg_item; endclass class uvm_reg_predictor #(type BUSTYPE=int) extends uvm_component; typedef uvm_component_registry #(uvm_reg_predictor#(BUSTYPE)) type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction uvm_analysis_imp #(BUSTYPE, uvm_reg_predictor #(BUSTYPE)) bus_in; uvm_analysis_port #(uvm_reg_item) reg_ap; uvm_reg_map map; uvm_reg_adapter adapter; function new (string name, uvm_component parent); super.new(name, parent); bus_in = new("bus_in", this); reg_ap = new("reg_ap", this); endfunction static function string type_name(); static string m_type_name; if (m_type_name == "") begin BUSTYPE t; t = BUSTYPE::type_id_create("t"); m_type_name = {"uvm_reg_predictor #(", t.get_type_name(), ")"}; end return m_type_name; endfunction virtual function string get_type_name(); return type_name(); endfunction : get_type_name virtual function void pre_predict(uvm_reg_item rw); endfunction local uvm_predict_s m_pending[uvm_reg]; virtual function void write(BUSTYPE tr); uvm_reg rg; uvm_reg_bus_op rw; if (adapter == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/WRITE/NULL")) uvm_report_fatal ("REG/WRITE/NULL", "write: adapter handle is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_predictor.svh", 168, "", 1); end rw.byte_en = -1; adapter.bus2reg(tr,rw); rg = map.get_reg_by_offset(rw.addr, (rw.kind == UVM_READ)); if (rg != null) begin bit found; uvm_reg_item reg_item; uvm_reg_map local_map; uvm_reg_map_info map_info; uvm_predict_s predict_info; uvm_reg_indirect_data ireg; uvm_reg ir; if (!m_pending.exists(rg)) begin uvm_reg_item item = new; predict_info =new; item.element_kind = UVM_REG; item.element = rg; item.path = UVM_PREDICT; item.map = map; item.kind = rw.kind; predict_info.reg_item = item; m_pending[rg] = predict_info; end predict_info = m_pending[rg]; reg_item = predict_info.reg_item; if (predict_info.addr.exists(rw.addr)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG_PREDICT_COLLISION")) uvm_report_error ("REG_PREDICT_COLLISION", {"Collision detected for register '", rg.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_predictor.svh", 202, "", 1); end m_pending.delete(rg); end local_map = rg.get_local_map(map); map_info = local_map.get_reg_map_info(rg); ir=($cast(ireg, rg))?ireg.get_indirect_reg():rg; foreach (map_info.addr[i]) begin if (rw.addr == map_info.addr[i]) begin found = 1; reg_item.value[0] |= rw.data << (i * map.get_n_bytes()*8); predict_info.addr[rw.addr] = 1; if (predict_info.addr.num() == map_info.addr.size()) begin uvm_predict_e predict_kind = (reg_item.kind == UVM_WRITE) ? UVM_PREDICT_WRITE : UVM_PREDICT_READ; if (reg_item.kind == UVM_READ && local_map.get_check_on_read() && reg_item.status != UVM_NOT_OK) begin void'(rg.do_check(ir.get_mirrored_value(), reg_item.value[0], local_map)); end pre_predict(reg_item); ir.XsampleX(reg_item.value[0], rw.byte_en, reg_item.kind == UVM_READ, local_map); begin uvm_reg_block blk = rg.get_parent(); blk.XsampleX(map_info.offset, reg_item.kind == UVM_READ, local_map); end rg.do_predict(reg_item, predict_kind, rw.byte_en); if(reg_item.kind == UVM_WRITE) begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"REG_PREDICT")) uvm_report_info ("REG_PREDICT", {"Observed WRITE transaction to register ", ir.get_full_name(), ": value='h", $sformatf("%0h",reg_item.value[0]), " : updated value = 'h", $sformatf("%0h",ir.get())}, UVM_HIGH, "t/uvm/src/reg/uvm_reg_predictor.svh", 243, "", 1); end else begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"REG_PREDICT")) uvm_report_info ("REG_PREDICT", {"Observed READ transaction to register ", ir.get_full_name(), ": value='h", $sformatf("%0h",reg_item.value[0])}, UVM_HIGH, "t/uvm/src/reg/uvm_reg_predictor.svh", 247, "", 1); end reg_ap.write(reg_item); m_pending.delete(rg); end break; end end if (!found) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG_PREDICT_INTERNAL")) uvm_report_error ("REG_PREDICT_INTERNAL", {"Unexpected failed address lookup for register '", rg.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_predictor.svh", 256, "", 1); end end else begin begin if (uvm_report_enabled(UVM_FULL,UVM_INFO,"REG_PREDICT_NOT_FOR_ME")) uvm_report_info ("REG_PREDICT_NOT_FOR_ME", {"Observed transaction does not target a register: ", $sformatf("%p",tr)}, UVM_FULL, "t/uvm/src/reg/uvm_reg_predictor.svh", 261, "", 1); end end endfunction virtual function void check_phase(uvm_phase phase); string q[$]; super.check_phase(phase); foreach (m_pending[l]) begin uvm_reg rg=l; q.push_back($sformatf("\n%s",rg.get_full_name())); end if (m_pending.num() > 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"PENDING REG ITEMS")) uvm_report_error ("PENDING REG ITEMS", $sformatf("There are %0d incomplete register transactions still pending completion:%s",m_pending.num(),uvm_pkg::m_uvm_string_queue_join(q)), UVM_NONE, "t/uvm/src/reg/uvm_reg_predictor.svh", 282, "", 1); end end endfunction endclass class uvm_reg_sequence #(type BASE=uvm_sequence #(uvm_reg_item)) extends BASE; typedef uvm_object_registry #(uvm_reg_sequence #(BASE)) type_id; static function uvm_reg_sequence #(BASE) type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_sequence #(BASE) tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction uvm_reg_block model; uvm_reg_adapter adapter; uvm_sequencer #(uvm_reg_item) reg_seqr; function new (string name="uvm_reg_sequence_inst"); super.new(name); endfunction virtual task body(); if (m_sequencer == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"NO_SEQR")) uvm_report_fatal ("NO_SEQR", {"Sequence executing as translation sequence, ", "but is not associated with a sequencer (m_sequencer == null)"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 127, "", 1); end end if (reg_seqr == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"REG_XLATE_NO_SEQR")) uvm_report_warning ("REG_XLATE_NO_SEQR", {"Executing RegModel translation sequence on sequencer ", m_sequencer.get_full_name(),"' does not have an upstream sequencer defined. ", "Execution of register items available only via direct calls to 'do_reg_item'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 133, "", 1); end wait(0); end begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"REG_XLATE_SEQ_START")) uvm_report_info ("REG_XLATE_SEQ_START", {"Starting RegModel translation sequence on sequencer ", m_sequencer.get_full_name(),"'"}, UVM_LOW, "t/uvm/src/reg/uvm_reg_sequence.svh", 138, "", 1); end forever begin uvm_reg_item reg_item; reg_seqr.peek(reg_item); do_reg_item(reg_item); reg_seqr.get(reg_item); #0; end endtask typedef enum { LOCAL, UPSTREAM } seq_parent_e; seq_parent_e parent_select = LOCAL; uvm_sequence_base upstream_parent; virtual task do_reg_item(uvm_reg_item rw); string rws=rw.convert2string(); if (m_sequencer == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/DO_ITEM/NULL")) uvm_report_fatal ("REG/DO_ITEM/NULL", "do_reg_item: m_sequencer is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 161, "", 1); end if (adapter == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/DO_ITEM/NULL")) uvm_report_fatal ("REG/DO_ITEM/NULL", "do_reg_item: adapter handle is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 163, "", 1); end begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"DO_RW_ACCESS")) uvm_report_info ("DO_RW_ACCESS", {"Doing transaction: ",rws}, UVM_HIGH, "t/uvm/src/reg/uvm_reg_sequence.svh", 165, "", 1); end if (parent_select == LOCAL) begin upstream_parent = rw.parent; rw.parent = this; end if (rw.kind == UVM_WRITE) rw.local_map.do_bus_write(rw, m_sequencer, adapter); else rw.local_map.do_bus_read(rw, m_sequencer, adapter); if (parent_select == LOCAL) rw.parent = upstream_parent; endtask virtual task write_reg(input uvm_reg rg, output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 211, "", 1); end else rg.write(status,value,path,map,this,prior,extension,fname,lineno); endtask virtual task read_reg(input uvm_reg rg, output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 229, "", 1); end else rg.read(status,value,path,map,this,prior,extension,fname,lineno); endtask virtual task poke_reg(input uvm_reg rg, output uvm_status_e status, input uvm_reg_data_t value, input string kind = "", input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 246, "", 1); end else rg.poke(status,value,kind,this,extension,fname,lineno); endtask virtual task peek_reg(input uvm_reg rg, output uvm_status_e status, output uvm_reg_data_t value, input string kind = "", input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 263, "", 1); end else rg.peek(status,value,kind,this,extension,fname,lineno); endtask virtual task update_reg(input uvm_reg rg, output uvm_status_e status, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 281, "", 1); end else rg.update(status,path,map,this,prior,extension,fname,lineno); endtask virtual task mirror_reg(input uvm_reg rg, output uvm_status_e status, input uvm_check_e check = UVM_NO_CHECK, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (rg == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_REG")) uvm_report_error ("NO_REG", "Register argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 300, "", 1); end else rg.mirror(status,check,path,map,this,prior,extension,fname,lineno); endtask virtual task write_mem(input uvm_mem mem, output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (mem == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_MEM")) uvm_report_error ("NO_MEM", "Memory argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 320, "", 1); end else mem.write(status,offset,value,path,map,this,prior,extension,fname,lineno); endtask virtual task read_mem(input uvm_mem mem, output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (mem == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_MEM")) uvm_report_error ("NO_MEM", "Memory argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 339, "", 1); end else mem.read(status,offset,value,path,map,this,prior,extension,fname,lineno); endtask virtual task poke_mem(input uvm_mem mem, output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input string kind = "", input uvm_object extension = null, input string fname = "", input int lineno = 0); if (mem == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_MEM")) uvm_report_error ("NO_MEM", "Memory argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 357, "", 1); end else mem.poke(status,offset,value,kind,this,extension,fname,lineno); endtask virtual task peek_mem(input uvm_mem mem, output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input string kind = "", input uvm_object extension = null, input string fname = "", input int lineno = 0); if (mem == null) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"NO_MEM")) uvm_report_error ("NO_MEM", "Memory argument is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_sequence.svh", 375, "", 1); end else mem.peek(status,offset,value,kind,this,extension,fname,lineno); endtask virtual function void put_response(uvm_sequence_item response_item); put_base_response(response_item); endfunction endclass virtual class uvm_reg_frontdoor extends uvm_reg_sequence #(uvm_sequence #(uvm_sequence_item)); typedef uvm_abstract_object_registry#(uvm_reg_frontdoor,"uvm_reg_frontdoor") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_reg_frontdoor"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_frontdoor"; endfunction : get_type_name uvm_reg_item rw_info; uvm_sequencer_base sequencer; function new(string name=""); super.new(name); endfunction string fname; int lineno; endclass: uvm_reg_frontdoor typedef class uvm_reg; typedef class uvm_mem; typedef class uvm_reg_backdoor; class uvm_reg_cbs extends uvm_callback; typedef uvm_object_registry#(uvm_reg_cbs,"uvm_reg_cbs") type_id; static function uvm_reg_cbs type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_cbs tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_cbs"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_cbs"; endfunction : get_type_name function new(string name = "uvm_reg_cbs"); super.new(name); endfunction virtual task pre_write(uvm_reg_item rw); endtask virtual task post_write(uvm_reg_item rw); endtask virtual task pre_read(uvm_reg_item rw); endtask virtual task post_read(uvm_reg_item rw); endtask virtual function void post_predict(input uvm_reg_field fld, input uvm_reg_data_t previous, inout uvm_reg_data_t value, input uvm_predict_e kind, input uvm_door_e path, input uvm_reg_map map); endfunction virtual function void encode(ref uvm_reg_data_t data[]); endfunction virtual function void decode(ref uvm_reg_data_t data[]); endfunction endclass typedef uvm_callbacks#(uvm_reg, uvm_reg_cbs) uvm_reg_cb ; typedef uvm_callback_iter#(uvm_reg, uvm_reg_cbs) uvm_reg_cb_iter ; typedef uvm_callbacks#(uvm_reg_backdoor, uvm_reg_cbs) uvm_reg_bd_cb ; typedef uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) uvm_reg_bd_cb_iter ; typedef uvm_callbacks#(uvm_mem, uvm_reg_cbs) uvm_mem_cb ; typedef uvm_callback_iter#(uvm_mem, uvm_reg_cbs) uvm_mem_cb_iter ; typedef uvm_callbacks#(uvm_reg_field, uvm_reg_cbs) uvm_reg_field_cb ; typedef uvm_callback_iter#(uvm_reg_field, uvm_reg_cbs) uvm_reg_field_cb_iter ; class uvm_reg_read_only_cbs extends uvm_reg_cbs; function new(string name = "uvm_reg_read_only_cbs"); super.new(name); endfunction typedef uvm_object_registry#(uvm_reg_read_only_cbs,"uvm_reg_read_only_cbs") type_id; static function uvm_reg_read_only_cbs type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_read_only_cbs tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_read_only_cbs"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_read_only_cbs"; endfunction : get_type_name virtual task pre_write(uvm_reg_item rw); string name = rw.element.get_full_name(); if (rw.status != UVM_IS_OK) return; if (rw.element_kind == UVM_FIELD) begin uvm_reg_field fld; uvm_reg rg; $cast(fld, rw.element); rg = fld.get_parent(); name = rg.get_full_name(); end begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/READONLY")) uvm_report_error ("UVM/REG/READONLY", {name, " is read-only. Cannot call write() method."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_cbs.svh", 232, "", 1); end rw.status = UVM_NOT_OK; endtask local static uvm_reg_read_only_cbs m_me; local static function uvm_reg_read_only_cbs get(); if (m_me == null) m_me = new; return m_me; endfunction static function void add(uvm_reg rg); uvm_reg_field flds[$]; uvm_reg_cb::add(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::add(flds[i], get()); end endfunction static function void remove(uvm_reg rg); uvm_reg_cb_iter cbs = new(rg); uvm_reg_field flds[$]; void'(cbs.first()); while (cbs.get_cb() != get()) begin if (cbs.get_cb() == null) return; void'(cbs.next()); end uvm_reg_cb::delete(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::delete(flds[i], get()); end endfunction endclass class uvm_reg_write_only_cbs extends uvm_reg_cbs; function new(string name = "uvm_reg_write_only_cbs"); super.new(name); endfunction typedef uvm_object_registry#(uvm_reg_write_only_cbs,"uvm_reg_write_only_cbs") type_id; static function uvm_reg_write_only_cbs type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_write_only_cbs tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_write_only_cbs"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_write_only_cbs"; endfunction : get_type_name virtual task pre_read(uvm_reg_item rw); string name = rw.element.get_full_name(); if (rw.status != UVM_IS_OK) return; if (rw.element_kind == UVM_FIELD) begin uvm_reg_field fld; uvm_reg rg; $cast(fld, rw.element); rg = fld.get_parent(); name = rg.get_full_name(); end begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/WRTEONLY")) uvm_report_error ("UVM/REG/WRTEONLY", {name, " is write-only. Cannot call read() method."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_cbs.svh", 316, "", 1); end rw.status = UVM_NOT_OK; endtask local static uvm_reg_write_only_cbs m_me; local static function uvm_reg_write_only_cbs get(); if (m_me == null) m_me = new; return m_me; endfunction static function void add(uvm_reg rg); uvm_reg_field flds[$]; uvm_reg_cb::add(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::add(flds[i], get()); end endfunction static function void remove(uvm_reg rg); uvm_reg_cb_iter cbs = new(rg); uvm_reg_field flds[$]; void'(cbs.first()); while (cbs.get_cb() != get()) begin if (cbs.get_cb() == null) return; void'(cbs.next()); end uvm_reg_cb::delete(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::delete(flds[i], get()); end endfunction endclass typedef class uvm_reg_cbs; virtual class uvm_reg_backdoor extends uvm_object; typedef uvm_abstract_object_registry#(uvm_reg_backdoor,"uvm_reg_backdoor") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_reg_backdoor"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_backdoor"; endfunction : get_type_name function new(string name = ""); super.new(name); endfunction: new protected task do_pre_read(uvm_reg_item rw); pre_read(rw); begin uvm_callback_iter#(uvm_reg_backdoor,uvm_reg_cbs) iter = new(this); uvm_reg_cbs cb = iter.first(); while(cb != null) begin cb.pre_read(rw); cb = iter.next(); end end endtask protected task do_post_read(uvm_reg_item rw); uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this); for(uvm_reg_cbs cb = iter.last(); cb != null; cb=iter.prev()) cb.decode(rw.value); begin uvm_callback_iter#(uvm_reg_backdoor,uvm_reg_cbs) iter = new(this); uvm_reg_cbs cb = iter.first(); while(cb != null) begin cb.post_read(rw); cb = iter.next(); end end post_read(rw); endtask protected task do_pre_write(uvm_reg_item rw); uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this); pre_write(rw); begin uvm_callback_iter#(uvm_reg_backdoor,uvm_reg_cbs) iter = new(this); uvm_reg_cbs cb = iter.first(); while(cb != null) begin cb.pre_write(rw); cb = iter.next(); end end for(uvm_reg_cbs cb = iter.first(); cb != null; cb = iter.next()) cb.encode(rw.value); endtask protected task do_post_write(uvm_reg_item rw); begin uvm_callback_iter#(uvm_reg_backdoor,uvm_reg_cbs) iter = new(this); uvm_reg_cbs cb = iter.first(); while(cb != null) begin cb.post_write(rw); cb = iter.next(); end end post_write(rw); endtask extern virtual task write(uvm_reg_item rw); extern virtual task read(uvm_reg_item rw); extern virtual function void read_func(uvm_reg_item rw); extern virtual function bit is_auto_updated(uvm_reg_field field); extern virtual local task wait_for_change(uvm_object element); extern function void start_update_thread(uvm_object element); extern function void kill_update_thread(uvm_object element); extern function bit has_update_threads(); virtual task pre_read(uvm_reg_item rw); endtask virtual task post_read(uvm_reg_item rw); endtask virtual task pre_write(uvm_reg_item rw); endtask virtual task post_write(uvm_reg_item rw); endtask string fname; int lineno; local process m_update_thread[uvm_object]; static local bit m_register_cb_uvm_reg_cbs = uvm_callbacks#(uvm_reg_backdoor,uvm_reg_cbs)::m_register_pair("uvm_reg_backdoor","uvm_reg_cbs"); endclass: uvm_reg_backdoor function bit uvm_reg_backdoor::is_auto_updated(uvm_reg_field field); return 0; endfunction task uvm_reg_backdoor::wait_for_change(uvm_object element); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "uvm_reg_backdoor::wait_for_change() method has not been overloaded", UVM_NONE, "t/uvm/src/reg/uvm_reg_backdoor.svh", 171, "", 1); end endtask function void uvm_reg_backdoor::start_update_thread(uvm_object element); uvm_reg rg; if (this.m_update_thread.exists(element)) begin this.kill_update_thread(element); end if (!$cast(rg,element)) return; fork begin uvm_reg_field fields[$]; this.m_update_thread[element] = process::self(); rg.get_fields(fields); forever begin uvm_status_e status; uvm_reg_data_t val; uvm_reg_item r_item = new("bd_r_item"); r_item.element = rg; r_item.element_kind = UVM_REG; this.read(r_item); val = r_item.value[0]; if (r_item.status != UVM_IS_OK) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Backdoor read of register '%s' failed.", rg.get_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_backdoor.svh", 206, "", 1); end end foreach (fields[i]) begin if (this.is_auto_updated(fields[i])) begin r_item.value[0] = (val >> fields[i].get_lsb_pos()) & ((1 << fields[i].get_n_bits())-1); fields[i].do_predict(r_item); end end this.wait_for_change(element); end end join_none endfunction function void uvm_reg_backdoor::kill_update_thread(uvm_object element); if (this.m_update_thread.exists(element)) begin this.m_update_thread[element].kill(); this.m_update_thread.delete(element); end endfunction function bit uvm_reg_backdoor::has_update_threads(); return this.m_update_thread.num() > 0; endfunction task uvm_reg_backdoor::write(uvm_reg_item rw); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "uvm_reg_backdoor::write() method has not been overloaded", UVM_NONE, "t/uvm/src/reg/uvm_reg_backdoor.svh", 248, "", 1); end endtask task uvm_reg_backdoor::read(uvm_reg_item rw); do_pre_read(rw); read_func(rw); do_post_read(rw); endtask function void uvm_reg_backdoor::read_func(uvm_reg_item rw); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "uvm_reg_backdoor::read_func() method has not been overloaded", UVM_NONE, "t/uvm/src/reg/uvm_reg_backdoor.svh", 264, "", 1); end rw.status = UVM_NOT_OK; endfunction typedef class uvm_reg_cbs; class uvm_reg_field extends uvm_object; rand uvm_reg_data_t value; local uvm_reg_data_t m_mirrored; local uvm_reg_data_t m_desired; local string m_access; local uvm_reg m_parent; local int unsigned m_lsb; local int unsigned m_size; local bit m_volatile; local uvm_reg_data_t m_reset[string]; local bit m_written; local bit m_read_in_progress; local bit m_write_in_progress; local string m_fname; local int m_lineno; local int m_cover_on; local bit m_individually_accessible; local uvm_check_e m_check; local static int m_max_size; local static bit m_policy_names[string]; constraint uvm_reg_field_valid { if (64 > m_size) { value < (64'h1 << m_size); } } typedef uvm_object_registry#(uvm_reg_field,"uvm_reg_field") type_id; static function uvm_reg_field type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_field tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_field"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_field"; endfunction : get_type_name extern function new(string name = "uvm_reg_field"); extern function void configure(uvm_reg parent, int unsigned size, int unsigned lsb_pos, string access, bit volatile, uvm_reg_data_t reset, bit has_reset, bit is_rand, bit individually_accessible); extern virtual function string get_full_name(); extern virtual function uvm_reg get_parent(); extern virtual function uvm_reg get_register(); extern virtual function int unsigned get_lsb_pos(); extern virtual function int unsigned get_n_bits(); extern static function int unsigned get_max_size(); extern virtual function string set_access(string mode); extern static function bit define_access(string name); local static bit m_predefined = m_predefine_policies(); extern local static function bit m_predefine_policies(); extern virtual function string get_access(uvm_reg_map map = null); extern virtual function bit is_known_access(uvm_reg_map map = null); extern virtual function void set_volatility(bit volatile); extern virtual function bit is_volatile(); extern virtual function void set(uvm_reg_data_t value, string fname = "", int lineno = 0); extern virtual function uvm_reg_data_t get(string fname = "", int lineno = 0); extern virtual function uvm_reg_data_t get_mirrored_value(string fname = "", int lineno = 0); extern virtual function void reset(string kind = "HARD"); extern virtual function uvm_reg_data_t get_reset(string kind = "HARD"); extern virtual function bit has_reset(string kind = "HARD", bit delete = 0); extern virtual function void set_reset(uvm_reg_data_t value, string kind = "HARD"); extern virtual function bit needs_update(); extern virtual task write (output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task read (output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task poke (output uvm_status_e status, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task peek (output uvm_status_e status, output uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task mirror(output uvm_status_e status, input uvm_check_e check = UVM_NO_CHECK, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern function void set_compare(uvm_check_e check=UVM_CHECK); extern function uvm_check_e get_compare(); extern function bit is_indv_accessible (uvm_door_e path, uvm_reg_map local_map); extern function bit predict (uvm_reg_data_t value, uvm_reg_byte_en_t be = -1, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_door_e path = UVM_FRONTDOOR, uvm_reg_map map = null, string fname = "", int lineno = 0); extern virtual function uvm_reg_data_t XpredictX (uvm_reg_data_t cur_val, uvm_reg_data_t wr_val, uvm_reg_map map); extern virtual function uvm_reg_data_t XupdateX(); extern function bit Xcheck_accessX (input uvm_reg_item rw, output uvm_reg_map_info map_info); extern virtual task do_write(uvm_reg_item rw); extern virtual task do_read(uvm_reg_item rw); extern virtual function void do_predict (uvm_reg_item rw, uvm_predict_e kind=UVM_PREDICT_DIRECT, uvm_reg_byte_en_t be = -1); extern function void pre_randomize(); extern function void post_randomize(); static local bit m_register_cb_uvm_reg_cbs = uvm_callbacks#(uvm_reg_field,uvm_reg_cbs)::m_register_pair("uvm_reg_field","uvm_reg_cbs"); virtual task pre_write (uvm_reg_item rw); endtask virtual task post_write (uvm_reg_item rw); endtask virtual task pre_read (uvm_reg_item rw); endtask virtual task post_read (uvm_reg_item rw); endtask extern virtual function void do_print (uvm_printer printer); extern virtual function string convert2string; extern virtual function uvm_object clone(); 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); endclass: uvm_reg_field function uvm_reg_field::new(string name = "uvm_reg_field"); super.new(name); endfunction: new function void uvm_reg_field::configure(uvm_reg parent, int unsigned size, int unsigned lsb_pos, string access, bit volatile, uvm_reg_data_t reset, bit has_reset, bit is_rand, bit individually_accessible); m_parent = parent; if (size == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Field \"%s\" cannot have 0 bits", get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 416, "", 1); end size = 1; end m_size = size; m_volatile = volatile; m_access = access.toupper(); m_lsb = lsb_pos; m_cover_on = UVM_NO_COVERAGE; m_written = 0; m_check = volatile ? UVM_NO_CHECK : UVM_CHECK; m_individually_accessible = individually_accessible; if (has_reset) set_reset(reset); m_parent.add_field(this); if (!m_policy_names.exists(m_access)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Access policy '",access, "' for field '",get_full_name(),"' is not defined. Setting to RW"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 436, "", 1); end m_access = "RW"; end if (size > m_max_size) m_max_size = size; case (access) "RO", "RC", "RS", "WC", "WS", "W1C", "W1S", "W1T", "W0C", "W0S", "W0T", "W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS", "WOC", "WOS": is_rand = 0; endcase if (!is_rand) value.rand_mode(0); endfunction: configure function uvm_reg uvm_reg_field::get_parent(); return m_parent; endfunction: get_parent function string uvm_reg_field::get_full_name(); return {m_parent.get_full_name(), ".", get_name()}; endfunction: get_full_name function uvm_reg uvm_reg_field::get_register(); return m_parent; endfunction: get_register function int unsigned uvm_reg_field::get_lsb_pos(); return m_lsb; endfunction: get_lsb_pos function int unsigned uvm_reg_field::get_n_bits(); return m_size; endfunction: get_n_bits function int unsigned uvm_reg_field::get_max_size(); return m_max_size; endfunction: get_max_size function bit uvm_reg_field::is_known_access(uvm_reg_map map = null); string acc = get_access(map); case (acc) "RO", "RW", "RC", "RS", "WC", "WS", "W1C", "W1S", "W1T", "W0C", "W0S", "W0T", "WRC", "WRS", "W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS", "WO", "WOC", "WOS", "W1", "WO1" : return 1; endcase return 0; endfunction function string uvm_reg_field::get_access(uvm_reg_map map = null); string field_access = m_access; if (map == uvm_reg_map::backdoor()) return field_access; case (m_parent.get_rights(map)) "RW": return field_access; "RO": case (field_access) "RW", "RO", "WC", "WS", "W1C", "W1S", "W1T", "W0C", "W0S", "W0T", "W1" : field_access = "RO"; "RC", "WRC", "W1SRC", "W0SRC", "WSRC" : field_access = "RC"; "RS", "WRS", "W1CRS", "W0CRS", "WCRS" : field_access = "RS"; "WO", "WOC", "WOS", "WO1": begin field_access = "NOACCESS"; end endcase "WO": case (field_access) "RW","WRC","WRS" : field_access = "WO"; "W1SRC" : field_access = "W1S"; "W0SRC": field_access = "W0S"; "W1CRS": field_access = "W1C"; "W0CRS": field_access = "W0C"; "WCRS": field_access = "WC"; "W1" : field_access = "W1"; "WO1" : field_access = "WO1"; "WSRC" : field_access = "WS"; "RO","RC","RS": field_access = "NOACCESS"; endcase default: begin field_access = "NOACCESS"; begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Register '",m_parent.get_full_name(), "' containing field '",get_name(),"' is mapped in map '", map.get_full_name(),"' with unknown access right '", m_parent.get_rights(map), "'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 570, "", 1); end end endcase return field_access; endfunction: get_access function string uvm_reg_field::set_access(string mode); set_access = m_access; m_access = mode.toupper(); if (!m_policy_names.exists(m_access)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Access policy '",m_access, "' is not a defined field access policy"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 584, "", 1); end m_access = set_access; end endfunction: set_access function bit uvm_reg_field::define_access(string name); if (!m_predefined) m_predefined = m_predefine_policies(); name = name.toupper(); if (m_policy_names.exists(name)) return 0; m_policy_names[name] = 1; return 1; endfunction function bit uvm_reg_field::m_predefine_policies(); if (m_predefined) return 1; m_predefined = 1; void'(define_access("RO")); void'(define_access("RW")); void'(define_access("RC")); void'(define_access("RS")); void'(define_access("WRC")); void'(define_access("WRS")); void'(define_access("WC")); void'(define_access("WS")); void'(define_access("WSRC")); void'(define_access("WCRS")); void'(define_access("W1C")); void'(define_access("W1S")); void'(define_access("W1T")); void'(define_access("W0C")); void'(define_access("W0S")); void'(define_access("W0T")); void'(define_access("W1SRC")); void'(define_access("W1CRS")); void'(define_access("W0SRC")); void'(define_access("W0CRS")); void'(define_access("WO")); void'(define_access("WOC")); void'(define_access("WOS")); void'(define_access("W1")); void'(define_access("WO1")); return 1; endfunction function void uvm_reg_field::set_volatility(bit volatile); m_volatile = volatile; endfunction function bit uvm_reg_field::is_volatile(); return m_volatile; endfunction function uvm_reg_data_t uvm_reg_field::XpredictX (uvm_reg_data_t cur_val, uvm_reg_data_t wr_val, uvm_reg_map map); uvm_reg_data_t mask = ('b1 << m_size)-1; case (get_access(map)) "RO": return cur_val; "RW": return wr_val; "RC": return cur_val; "RS": return cur_val; "WC": return '0; "WS": return mask; "WRC": return wr_val; "WRS": return wr_val; "WSRC": return mask; "WCRS": return '0; "W1C": return cur_val & (~wr_val); "W1S": return cur_val | wr_val; "W1T": return cur_val ^ wr_val; "W0C": return cur_val & wr_val; "W0S": return cur_val | (~wr_val & mask); "W0T": return cur_val ^ (~wr_val & mask); "W1SRC": return cur_val | wr_val; "W1CRS": return cur_val & (~wr_val); "W0SRC": return cur_val | (~wr_val & mask); "W0CRS": return cur_val & wr_val; "WO": return wr_val; "WOC": return '0; "WOS": return mask; "W1": return (m_written) ? cur_val : wr_val; "WO1": return (m_written) ? cur_val : wr_val; "NOACCESS": return cur_val; default: return wr_val; endcase begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "uvm_reg_field::XpredictX(): Internal error", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 691, "", 1); end return 0; endfunction: XpredictX function bit uvm_reg_field::predict (uvm_reg_data_t value, uvm_reg_byte_en_t be = -1, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_door_e path = UVM_FRONTDOOR, uvm_reg_map map = null, string fname = "", int lineno = 0); uvm_reg_item rw = new; rw.value[0] = value; rw.path = path; rw.map = map; rw.fname = fname; rw.lineno = lineno; do_predict(rw, kind, be); predict = (rw.status == UVM_NOT_OK) ? 0 : 1; endfunction: predict function void uvm_reg_field::do_predict(uvm_reg_item rw, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_reg_byte_en_t be = -1); uvm_reg_data_t field_val = rw.value[0] & ((1 << m_size)-1); if (rw.status != UVM_NOT_OK) rw.status = UVM_IS_OK; if (!be[0]) return; m_fname = rw.fname; m_lineno = rw.lineno; case (kind) UVM_PREDICT_WRITE: begin uvm_reg_field_cb_iter cbs = new(this); if (rw.path == UVM_FRONTDOOR || rw.path == UVM_PREDICT) field_val = XpredictX(m_mirrored, field_val, rw.map); m_written = 1; for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) cb.post_predict(this, m_mirrored, field_val, UVM_PREDICT_WRITE, rw.path, rw.map); field_val &= ('b1 << m_size)-1; end UVM_PREDICT_READ: begin uvm_reg_field_cb_iter cbs = new(this); if (rw.path == UVM_FRONTDOOR || rw.path == UVM_PREDICT) begin string acc = get_access(rw.map); if (acc == "RC" || acc == "WRC" || acc == "WSRC" || acc == "W1SRC" || acc == "W0SRC") field_val = 0; else if (acc == "RS" || acc == "WRS" || acc == "WCRS" || acc == "W1CRS" || acc == "W0CRS") field_val = ('b1 << m_size)-1; else if (acc == "WO" || acc == "WOC" || acc == "WOS" || acc == "WO1" || acc == "NOACCESS") return; end for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) cb.post_predict(this, m_mirrored, field_val, UVM_PREDICT_READ, rw.path, rw.map); field_val &= ('b1 << m_size)-1; end UVM_PREDICT_DIRECT: begin if (m_parent.is_busy()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Trying to predict value of field '", get_name(),"' while register '",m_parent.get_full_name(), "' is being accessed"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 797, "", 1); end rw.status = UVM_NOT_OK; end end endcase m_mirrored = field_val; m_desired = field_val; this.value = field_val; endfunction: do_predict function uvm_reg_data_t uvm_reg_field::XupdateX(); XupdateX = 0; case (m_access) "RO": XupdateX = m_desired; "RW": XupdateX = m_desired; "RC": XupdateX = m_desired; "RS": XupdateX = m_desired; "WRC": XupdateX = m_desired; "WRS": XupdateX = m_desired; "WC": XupdateX = m_desired; "WS": XupdateX = m_desired; "WSRC": XupdateX = m_desired; "WCRS": XupdateX = m_desired; "W1C": XupdateX = ~m_desired; "W1S": XupdateX = m_desired; "W1T": XupdateX = m_desired ^ m_mirrored; "W0C": XupdateX = m_desired; "W0S": XupdateX = ~m_desired; "W0T": XupdateX = ~(m_desired ^ m_mirrored); "W1SRC": XupdateX = m_desired; "W1CRS": XupdateX = ~m_desired; "W0SRC": XupdateX = ~m_desired; "W0CRS": XupdateX = m_desired; "WO": XupdateX = m_desired; "WOC": XupdateX = m_desired; "WOS": XupdateX = m_desired; "W1": XupdateX = m_desired; "WO1": XupdateX = m_desired; default: XupdateX = m_desired; endcase XupdateX &= (1 << m_size) - 1; endfunction: XupdateX function void uvm_reg_field::set(uvm_reg_data_t value, string fname = "", int lineno = 0); uvm_reg_data_t mask = ('b1 << m_size)-1; m_fname = fname; m_lineno = lineno; if (value >> m_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", $sformatf("Specified value (0x%h) greater than field \"%s\" size (%0d bits)", value, get_name(), m_size), UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 863, "", 1); end value &= mask; end if (m_parent.is_busy()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/FLD/SET/BSY")) uvm_report_warning ("UVM/FLD/SET/BSY", $sformatf("Setting the value of field \"%s\" while containing register \"%s\" is being accessed may result in loss of desired field value. A race condition between threads concurrently accessing the register model is the likely cause of the problem.", get_name(), m_parent.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 870, "", 1); end end case (m_access) "RO": m_desired = m_desired; "RW": m_desired = value; "RC": m_desired = m_desired; "RS": m_desired = m_desired; "WC": m_desired = '0; "WS": m_desired = mask; "WRC": m_desired = value; "WRS": m_desired = value; "WSRC": m_desired = mask; "WCRS": m_desired = '0; "W1C": m_desired = m_desired & (~value); "W1S": m_desired = m_desired | value; "W1T": m_desired = m_desired ^ value; "W0C": m_desired = m_desired & value; "W0S": m_desired = m_desired | (~value & mask); "W0T": m_desired = m_desired ^ (~value & mask); "W1SRC": m_desired = m_desired | value; "W1CRS": m_desired = m_desired & (~value); "W0SRC": m_desired = m_desired | (~value & mask); "W0CRS": m_desired = m_desired & value; "WO": m_desired = value; "WOC": m_desired = '0; "WOS": m_desired = mask; "W1": m_desired = (m_written) ? m_desired : value; "WO1": m_desired = (m_written) ? m_desired : value; default: m_desired = value; endcase this.value = m_desired; endfunction: set function uvm_reg_data_t uvm_reg_field::get(string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; get = m_desired; endfunction: get function uvm_reg_data_t uvm_reg_field::get_mirrored_value(string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; get_mirrored_value = m_mirrored; endfunction: get_mirrored_value function void uvm_reg_field::reset(string kind = "HARD"); if (!m_reset.exists(kind)) return; m_mirrored = m_reset[kind]; m_desired = m_mirrored; value = m_mirrored; if (kind == "HARD") m_written = 0; endfunction: reset function bit uvm_reg_field::has_reset(string kind = "HARD", bit delete = 0); if (!m_reset.exists(kind)) return 0; if (delete) m_reset.delete(kind); return 1; endfunction: has_reset function uvm_reg_data_t uvm_reg_field::get_reset(string kind = "HARD"); if (!m_reset.exists(kind)) return m_desired; return m_reset[kind]; endfunction: get_reset function void uvm_reg_field::set_reset(uvm_reg_data_t value, string kind = "HARD"); m_reset[kind] = value & ((1<> m_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"uvm_reg_field::write(): Value greater than field '", get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1096, "", 1); end rw.value[0] &= ((1<> m_lsb) & ((1<0) begin prev_lsb = fields[fld_idx-1].get_lsb_pos(); prev_sz = fields[fld_idx-1].get_n_bits(); end if (fld_idx < fields.size()-1) begin next_lsb = fields[fld_idx+1].get_lsb_pos(); next_sz = fields[fld_idx+1].get_n_bits(); end if (fld_idx == 0 && ((next_lsb % bus_sz) == 0 || (next_lsb - this_sz) > (next_lsb % bus_sz))) return 1; else if (fld_idx == (fields.size()-1) && ((this_lsb % bus_sz) == 0 || (this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz))) return 1; else begin if ((this_lsb % bus_sz) == 0) begin if ((next_lsb % bus_sz) == 0 || (next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz)) return 1; end else begin if ( (next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz) && ((this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz)) ) return 1; end end end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Target bus does not support byte enabling, and the field '", get_full_name(),"' is not the only field within the entire bus width. ", "Individual field access will not be available. ", "Accessing complete register instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1430, "", 1); end return 0; endfunction task uvm_reg_field::poke(output uvm_status_e status, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t tmp; m_fname = fname; m_lineno = lineno; if (value >> m_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"uvm_reg_field::poke(): Value exceeds size of field '", get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1454, "", 1); end value &= value & ((1<> m_lsb) & ((1< 64) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual field \"%s\" cannot have more than %0d bits", this.get_full_name(), 64), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 327, "", 1); end size = 64; end this.size = size; this.lsb = lsb_pos; this.parent.add_field(this); endfunction: configure function string uvm_vreg_field::get_full_name(); get_full_name = {this.parent.get_full_name(), ".", this.get_name()}; endfunction: get_full_name function uvm_vreg uvm_vreg_field::get_register(); get_register = this.parent; endfunction: get_register function uvm_vreg uvm_vreg_field::get_parent(); get_parent = this.parent; endfunction: get_parent function int unsigned uvm_vreg_field::get_lsb_pos_in_register(); get_lsb_pos_in_register = this.lsb; endfunction: get_lsb_pos_in_register function int unsigned uvm_vreg_field::get_n_bits(); get_n_bits = this.size; endfunction: get_n_bits function string uvm_vreg_field::get_access(uvm_reg_map map = null); if (this.parent.get_memory() == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg_field::get_rights() on unimplemented virtual field \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 368, "", 1); end return "RW"; end return this.parent.get_access(map); endfunction: get_access task uvm_vreg_field::write(input longint unsigned idx, output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t tmp; uvm_reg_data_t segval; uvm_reg_addr_t segoff; uvm_status_e st; int flsb, fmsb, rmwbits; int segsiz, segn; uvm_mem mem; uvm_door_e rm_path; uvm_vreg_field_cb_iter cbs = new(this); this.fname = fname; this.lineno = lineno; write_in_progress = 1'b1; mem = this.parent.get_memory(); if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg_field::write() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 404, "", 1); end status = UVM_NOT_OK; return; end if (path == UVM_DEFAULT_DOOR) begin uvm_reg_block blk = this.parent.get_block(); path = blk.get_default_door(); end status = UVM_IS_OK; this.parent.XatomicX(1); if (value >> this.size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", $sformatf("Writing value 'h%h that is greater than field \"%s\" size (%0d bits)", value, this.get_full_name(), this.get_n_bits()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 419, "", 1); end value &= value & ((1< 0) begin uvm_reg_addr_t segn; mem.read(st, segoff, tmp, rm_path, map, parent, , extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Unable to read LSB bits in %s[%0d] to for RMW cycle on virtual field %s.", mem.get_full_name(), segoff, this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 453, "", 1); end status = UVM_NOT_OK; this.parent.XatomicX(0); return; end value = (value << rmwbits) | (tmp & ((1< 0) begin if (segn > 0) begin mem.read(st, segoff + segn - 1, tmp, rm_path, map, parent,, extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Unable to read MSB bits in %s[%0d] to for RMW cycle on virtual field %s.", mem.get_full_name(), segoff+segn-1, this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 472, "", 1); end status = UVM_NOT_OK; this.parent.XatomicX(0); return; end end value |= (tmp & ~((1<> segsiz; end this.post_write(idx, value, path, map, status); for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.post_write(this, idx, value, path, map, status); end this.parent.XatomicX(0); begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Wrote virtual field \"%s\"[%0d] via %s with: 'h%h", this.get_full_name(), idx, (path == UVM_FRONTDOOR) ? "frontdoor" : "backdoor", value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg_field.svh", 505, "", 1); end write_in_progress = 1'b0; this.fname = ""; this.lineno = 0; endtask: write task uvm_vreg_field::read(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t tmp; uvm_reg_data_t segval; uvm_reg_addr_t segoff; uvm_status_e st; int flsb, lsb; int segsiz, segn; uvm_mem mem; uvm_vreg_field_cb_iter cbs = new(this); this.fname = fname; this.lineno = lineno; read_in_progress = 1'b1; mem = this.parent.get_memory(); if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg_field::read() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 540, "", 1); end status = UVM_NOT_OK; return; end if (path == UVM_DEFAULT_DOOR) begin uvm_reg_block blk = this.parent.get_block(); path = blk.get_default_door(); end status = UVM_IS_OK; this.parent.XatomicX(1); value = 0; this.pre_read(idx, path, map); for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.pre_read(this, idx, path, map); end segsiz = mem.get_n_bytes() * 8; flsb = this.get_lsb_pos_in_register(); segoff = this.parent.get_offset_in_memory(idx) + (flsb / segsiz); lsb = flsb % segsiz; segn = (lsb + this.get_n_bits() - 1) / segsiz + 1; segoff += segn - 1; repeat (segn) begin value = value << segsiz; mem.read(st, segoff, tmp, path, map, parent, , extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) status = UVM_NOT_OK; segoff--; value |= tmp; end value = value >> lsb; value &= (1<> this.size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", $sformatf("Writing value 'h%h that is greater than field \"%s\" size (%0d bits)", value, this.get_full_name(), this.get_n_bits()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 644, "", 1); end value &= value & ((1< 0) begin uvm_reg_addr_t segn; mem.peek(st, segoff, tmp, "", parent, extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Unable to read LSB bits in %s[%0d] to for RMW cycle on virtual field %s.", mem.get_full_name(), segoff, this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 666, "", 1); end status = UVM_NOT_OK; this.parent.XatomicX(0); return; end value = (value << rmwbits) | (tmp & ((1< 0) begin if (segn > 0) begin mem.peek(st, segoff + segn - 1, tmp, "", parent, extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Unable to read MSB bits in %s[%0d] to for RMW cycle on virtual field %s.", mem.get_full_name(), segoff+segn-1, this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 685, "", 1); end status = UVM_NOT_OK; this.parent.XatomicX(0); return; end end value |= (tmp & ~((1<> segsiz; end this.parent.XatomicX(0); begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Wrote virtual field \"%s\"[%0d] with: 'h%h", this.get_full_name(), idx, value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg_field.svh", 707, "", 1); end this.fname = ""; this.lineno = 0; endtask: poke task uvm_vreg_field::peek(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t tmp; uvm_reg_data_t segval; uvm_reg_addr_t segoff; uvm_status_e st; int flsb, lsb; int segsiz, segn; uvm_mem mem; this.fname = fname; this.lineno = lineno; mem = this.parent.get_memory(); if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg_field::peek() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 735, "", 1); end status = UVM_NOT_OK; return; end status = UVM_IS_OK; this.parent.XatomicX(1); value = 0; segsiz = mem.get_n_bytes() * 8; flsb = this.get_lsb_pos_in_register(); segoff = this.parent.get_offset_in_memory(idx) + (flsb / segsiz); lsb = flsb % segsiz; segn = (lsb + this.get_n_bits() - 1) / segsiz + 1; segoff += segn - 1; repeat (segn) begin value = value << segsiz; mem.peek(st, segoff, tmp, "", parent, extension, fname, lineno); if (st != UVM_IS_OK && st != UVM_HAS_X) status = UVM_NOT_OK; segoff--; value |= tmp; end value = value >> lsb; value &= (1< m_max_size) m_max_size = n_bits; endfunction: new function void uvm_reg::configure (uvm_reg_block blk_parent, uvm_reg_file regfile_parent=null, string hdl_path = ""); if (blk_parent == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/CFG/NOBLK")) uvm_report_error ("UVM/REG/CFG/NOBLK", {"uvm_reg::configure() called without a parent block for instance \"", get_name(), "\" of register type \"", get_type_name(), "\"."}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 623, "", 1); end return; end m_parent = blk_parent; m_parent.add_reg(this); m_regfile_parent = regfile_parent; if (hdl_path != "") add_hdl_path_slice(hdl_path, -1, -1); endfunction: configure function void uvm_reg::add_field(uvm_reg_field field); int offset; int idx; if (m_locked) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot add field to locked register model", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 642, "", 1); end return; end if (field == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "Attempting to register NULL field", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 646, "", 1); end offset = field.get_lsb_pos(); idx = -1; foreach (m_fields[i]) begin if (offset < m_fields[i].get_lsb_pos()) begin int j = i; m_fields.insert(j, field); idx = i; break; end end if (idx < 0) begin m_fields.push_back(field); idx = m_fields.size()-1; end m_n_used_bits += field.get_n_bits(); if (m_n_used_bits > m_n_bits) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Fields use more bits (%0d) than available in register \"%s\" (%0d)", m_n_used_bits, get_name(), m_n_bits), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 671, "", 1); end end if (idx > 0) begin if (m_fields[idx-1].get_lsb_pos() + m_fields[idx-1].get_n_bits() > offset) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Field %s overlaps field %s in register \"%s\"", m_fields[idx-1].get_name(), field.get_name(), get_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 680, "", 1); end end end if (idx < m_fields.size()-1) begin if (offset + field.get_n_bits() > m_fields[idx+1].get_lsb_pos()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Field %s overlaps field %s in register \"%s\"", field.get_name(), m_fields[idx+1].get_name(), get_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 689, "", 1); end end end endfunction: add_field function void uvm_reg::Xlock_modelX(); if (m_locked) return; m_locked = 1; endfunction function void uvm_reg::set_frontdoor(uvm_reg_frontdoor ftdr, uvm_reg_map map = null, string fname = "", int lineno = 0); uvm_reg_map_info map_info; ftdr.fname = m_fname; ftdr.lineno = m_lineno; map = get_local_map(map); if (map == null) return; map_info = map.get_reg_map_info(this); if (map_info == null) map.add_reg(this, -1, "RW", 1, ftdr); else begin map_info.frontdoor = ftdr; end endfunction: set_frontdoor function uvm_reg_frontdoor uvm_reg::get_frontdoor(uvm_reg_map map = null); uvm_reg_map_info map_info; map = get_local_map(map); if (map == null) return null; map_info = map.get_reg_map_info(this); return map_info.frontdoor; endfunction: get_frontdoor function void uvm_reg::set_backdoor(uvm_reg_backdoor bkdr, string fname = "", int lineno = 0); bkdr.fname = fname; bkdr.lineno = lineno; if (m_backdoor != null && m_backdoor.has_update_threads()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", "Previous register backdoor still has update threads running. Backdoors with active mirroring should only be set before simulation starts.", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 750, "", 1); end end m_backdoor = bkdr; endfunction: set_backdoor function uvm_reg_backdoor uvm_reg::get_backdoor(bit inherited = 1); if (m_backdoor == null && inherited) begin uvm_reg_block blk = get_parent(); uvm_reg_backdoor bkdr; while (blk != null) begin bkdr = blk.get_backdoor(); if (bkdr != null) begin m_backdoor = bkdr; break; end blk = blk.get_parent(); end end return m_backdoor; endfunction: get_backdoor function void uvm_reg::clear_hdl_path(string kind = "RTL"); if (kind == "ALL") begin m_hdl_paths_pool = new("hdl_paths"); return; end if (kind == "") begin if (m_regfile_parent != null) kind = m_regfile_parent.get_default_hdl_path(); else kind = m_parent.get_default_hdl_path(); end if (!m_hdl_paths_pool.exists(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unknown HDL Abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 793, "", 1); end return; end m_hdl_paths_pool.delete(kind); endfunction function void uvm_reg::add_hdl_path(uvm_hdl_path_slice slices[], string kind = "RTL"); uvm_queue #(uvm_hdl_path_concat) paths = m_hdl_paths_pool.get(kind); uvm_hdl_path_concat concat = new(); concat.set(slices); paths.push_back(concat); endfunction function void uvm_reg::add_hdl_path_slice(string name, int offset, int size, bit first = 0, string kind = "RTL"); uvm_queue #(uvm_hdl_path_concat) paths = m_hdl_paths_pool.get(kind); uvm_hdl_path_concat concat; if (first || paths.size() == 0) begin concat = new(); paths.push_back(concat); end else concat = paths.get(paths.size()-1); concat.add_path(name, offset, size); endfunction function bit uvm_reg::has_hdl_path(string kind = ""); if (kind == "") begin if (m_regfile_parent != null) kind = m_regfile_parent.get_default_hdl_path(); else kind = m_parent.get_default_hdl_path(); end return m_hdl_paths_pool.exists(kind); endfunction function void uvm_reg::get_hdl_path_kinds (ref string kinds[$]); string kind; kinds.delete(); if (!m_hdl_paths_pool.first(kind)) return; do kinds.push_back(kind); while (m_hdl_paths_pool.next(kind)); endfunction function void uvm_reg::get_hdl_path(ref uvm_hdl_path_concat paths[$], input string kind = ""); uvm_queue #(uvm_hdl_path_concat) hdl_paths; if (kind == "") begin if (m_regfile_parent != null) kind = m_regfile_parent.get_default_hdl_path(); else kind = m_parent.get_default_hdl_path(); end if (!has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Register does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 877, "", 1); end return; end hdl_paths = m_hdl_paths_pool.get(kind); for (int i=0; i 1 && map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"set_offset requires a non-null map when register '", get_full_name(),"' belongs to more than one map."}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 949, "", 1); end return; end map = get_local_map(map); if (map == null) return; map.m_set_reg_offset(this, offset, unmapped); endfunction function void uvm_reg::set_parent(uvm_reg_block blk_parent, uvm_reg_file regfile_parent); if (m_parent != null) begin end m_parent = blk_parent; m_regfile_parent = regfile_parent; endfunction function uvm_reg_block uvm_reg::get_parent(); return get_block(); endfunction function uvm_reg_file uvm_reg::get_regfile(); return m_regfile_parent; endfunction function string uvm_reg::get_full_name(); if (m_regfile_parent != null) return {m_regfile_parent.get_full_name(), ".", get_name()}; if (m_parent != null) return {m_parent.get_full_name(), ".", get_name()}; return get_name(); endfunction: get_full_name function void uvm_reg::add_map(uvm_reg_map map); m_maps[map] = 1; endfunction function void uvm_reg::get_maps(ref uvm_reg_map maps[$]); foreach (m_maps[map]) maps.push_back(map); endfunction function int uvm_reg::get_n_maps(); return m_maps.num(); endfunction function bit uvm_reg::is_in_map(uvm_reg_map map); if (m_maps.exists(map)) return 1; foreach (m_maps[l]) begin uvm_reg_map local_map = l; uvm_reg_map parent_map = local_map.get_parent_map(); while (parent_map != null) begin if (parent_map == map) return 1; parent_map = parent_map.get_parent_map(); end end return 0; endfunction function uvm_reg_map uvm_reg::get_local_map(uvm_reg_map map); if (map == null) return get_default_map(); if (m_maps.exists(map)) return map; foreach (m_maps[l]) begin uvm_reg_map local_map=l; uvm_reg_map parent_map = local_map.get_parent_map(); while (parent_map != null) begin if (parent_map == map) return local_map; parent_map = parent_map.get_parent_map(); end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Register '",get_full_name(),"' is not contained within map '",map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1062, "", 1); end return null; endfunction function uvm_reg_map uvm_reg::get_default_map(); if (m_maps.num() == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Register '",get_full_name(),"' is not registered with any map"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1075, "", 1); end return null; end if (m_maps.num() == 1) begin uvm_reg_map map; void'(m_maps.first(map)); return map; end foreach (m_maps[l]) begin uvm_reg_map map = l; uvm_reg_block blk = map.get_parent(); uvm_reg_map default_map = blk.get_default_map(); if (default_map != null) begin uvm_reg_map local_map = get_local_map(default_map); if (local_map != null) return local_map; end end begin uvm_reg_map map; void'(m_maps.first(map)); return map; end endfunction function string uvm_reg::get_rights(uvm_reg_map map = null); uvm_reg_map_info info; map = get_local_map(map); if (map == null) return "RW"; info = map.get_reg_map_info(this); return info.rights; endfunction function uvm_reg_block uvm_reg::get_block(); get_block = m_parent; endfunction function uvm_reg_addr_t uvm_reg::get_offset(uvm_reg_map map = null); uvm_reg_map_info map_info; uvm_reg_map orig_map = map; map = get_local_map(map); if (map == null) return -1; map_info = map.get_reg_map_info(this); if (map_info.unmapped) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Register '",get_name(), "' is unmapped in map '", ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1151, "", 1); end return -1; end return map_info.offset; endfunction function int uvm_reg::get_addresses(uvm_reg_map map=null, ref uvm_reg_addr_t addr[]); uvm_reg_map_info map_info; uvm_reg_map orig_map = map; map = get_local_map(map); if (map == null) return -1; map_info = map.get_reg_map_info(this); if (map_info.unmapped) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Register '",get_name(), "' is unmapped in map '", ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1177, "", 1); end return -1; end addr = map_info.addr; return map.get_n_bytes(); endfunction function uvm_reg_addr_t uvm_reg::get_address(uvm_reg_map map = null); uvm_reg_addr_t addr[]; void'(get_addresses(map,addr)); return addr[0]; endfunction function int unsigned uvm_reg::get_n_bits(); return m_n_bits; endfunction function int unsigned uvm_reg::get_n_bytes(); return ((m_n_bits-1) / 8) + 1; endfunction function int unsigned uvm_reg::get_max_size(); return m_max_size; endfunction: get_max_size function void uvm_reg::get_fields(ref uvm_reg_field fields[$]); foreach(m_fields[i]) fields.push_back(m_fields[i]); endfunction function uvm_reg_field uvm_reg::get_field_by_name(string name); foreach (m_fields[i]) if (m_fields[i].get_name() == name) return m_fields[i]; begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate field '",name, "' in register '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1232, "", 1); end return null; endfunction function string uvm_reg::Xget_fields_accessX(uvm_reg_map map); bit is_R; bit is_W; foreach(m_fields[i]) begin case (m_fields[i].get_access(map)) "RO", "RC", "RS": is_R = 1; "WO", "WOC", "WOS", "WO1": is_W = 1; default: return "RW"; endcase if (is_R && is_W) return "RW"; end case ({is_R, is_W}) 2'b01: return "WO"; 2'b10: return "RO"; endcase return "RW"; endfunction function void uvm_reg::include_coverage(string scope, uvm_reg_cvr_t models, uvm_object accessor = null); uvm_reg_cvr_rsrc_db::set({"uvm_reg::", scope}, "include_coverage", models, accessor); endfunction function uvm_reg_cvr_t uvm_reg::build_coverage(uvm_reg_cvr_t models); build_coverage = UVM_NO_COVERAGE; void'(uvm_reg_cvr_rsrc_db::read_by_name({"uvm_reg::", get_full_name()}, "include_coverage", build_coverage, this)); return build_coverage & models; endfunction: build_coverage function void uvm_reg::add_coverage(uvm_reg_cvr_t models); m_has_cover |= models; endfunction: add_coverage function bit uvm_reg::has_coverage(uvm_reg_cvr_t models); return ((m_has_cover & models) == models); endfunction: has_coverage function uvm_reg_cvr_t uvm_reg::set_coverage(uvm_reg_cvr_t is_on); if (is_on == uvm_reg_cvr_t'(UVM_NO_COVERAGE)) begin m_cover_on = is_on; return m_cover_on; end m_cover_on = m_has_cover & is_on; return m_cover_on; endfunction: set_coverage function bit uvm_reg::get_coverage(uvm_reg_cvr_t is_on); if (has_coverage(is_on) == 0) return 0; return ((m_cover_on & is_on) == is_on); endfunction: get_coverage function void uvm_reg::set(uvm_reg_data_t value, string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; foreach (m_fields[i]) m_fields[i].set((value >> m_fields[i].get_lsb_pos()) & ((1 << m_fields[i].get_n_bits()) - 1)); endfunction: set function bit uvm_reg::predict (uvm_reg_data_t value, uvm_reg_byte_en_t be = -1, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_door_e path = UVM_FRONTDOOR, uvm_reg_map map = null, string fname = "", int lineno = 0); uvm_reg_item rw = new; rw.value[0] = value; rw.path = path; rw.map = map; rw.fname = fname; rw.lineno = lineno; do_predict(rw, kind, be); predict = (rw.status == UVM_NOT_OK) ? 0 : 1; endfunction: predict function void uvm_reg::do_predict(uvm_reg_item rw, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_reg_byte_en_t be = -1); uvm_reg_data_t reg_value = rw.value[0]; m_fname = rw.fname; m_lineno = rw.lineno; if (rw.status ==UVM_IS_OK ) rw.status = UVM_IS_OK; if (m_is_busy && kind == UVM_PREDICT_DIRECT) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Trying to predict value of register '", get_full_name(),"' while it is being accessed"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 1395, "", 1); end rw.status = UVM_NOT_OK; return; end foreach (m_fields[i]) begin rw.value[0] = (reg_value >> m_fields[i].get_lsb_pos()) & ((1 << m_fields[i].get_n_bits())-1); m_fields[i].do_predict(rw, kind, be>>(m_fields[i].get_lsb_pos()/8)); end rw.value[0] = reg_value; endfunction: do_predict function uvm_reg_data_t uvm_reg::get(string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; get = 0; foreach (m_fields[i]) get |= m_fields[i].get() << m_fields[i].get_lsb_pos(); endfunction: get function uvm_reg_data_t uvm_reg::get_mirrored_value(string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; get_mirrored_value = 0; foreach (m_fields[i]) get_mirrored_value |= m_fields[i].get_mirrored_value() << m_fields[i].get_lsb_pos(); endfunction: get_mirrored_value function void uvm_reg::reset(string kind = "HARD"); foreach (m_fields[i]) m_fields[i].reset(kind); void'(m_atomic.try_get(1)); m_atomic.put(1); m_process = null; Xset_busyX(0); endfunction: reset function uvm_reg_data_t uvm_reg::get_reset(string kind = "HARD"); get_reset = 0; foreach (m_fields[i]) get_reset |= m_fields[i].get_reset(kind) << m_fields[i].get_lsb_pos(); endfunction: get_reset function bit uvm_reg::has_reset(string kind = "HARD", bit delete = 0); has_reset = 0; foreach (m_fields[i]) begin has_reset |= m_fields[i].has_reset(kind, delete); if (!delete && has_reset) return 1; end endfunction: has_reset function void uvm_reg::set_reset(uvm_reg_data_t value, string kind = "HARD"); foreach (m_fields[i]) begin m_fields[i].set_reset(value >> m_fields[i].get_lsb_pos(), kind); end endfunction: set_reset function bit uvm_reg::needs_update(); needs_update = 0; foreach (m_fields[i]) begin if (m_fields[i].needs_update()) begin return 1; end end endfunction: needs_update task uvm_reg::update(output uvm_status_e status, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t upd; status = UVM_IS_OK; if (!needs_update()) return; upd = 0; foreach (m_fields[i]) upd |= m_fields[i].XupdateX() << m_fields[i].get_lsb_pos(); write(status, upd, path, map, parent, prior, extension, fname, lineno); endtask: update task uvm_reg::write(output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw; XatomicX(1); set(value); rw = uvm_reg_item::type_id_create("write_item",,get_full_name()); rw.element = this; rw.element_kind = UVM_REG; rw.kind = UVM_WRITE; rw.value[0] = value; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_write(rw); status = rw.status; XatomicX(0); endtask task uvm_reg::do_write (uvm_reg_item rw); uvm_reg_cb_iter cbs = new(this); uvm_reg_map_info map_info; uvm_reg_data_t value; m_fname = rw.fname; m_lineno = rw.lineno; if (!Xcheck_accessX(rw,map_info)) return; XatomicX(1); m_write_in_progress = 1'b1; rw.value[0] &= ((1 << m_n_bits)-1); value = rw.value[0]; rw.status = UVM_IS_OK; begin : pre_write_callbacks uvm_reg_data_t msk; int lsb; foreach (m_fields[i]) begin uvm_reg_field_cb_iter cbs = new(m_fields[i]); uvm_reg_field f = m_fields[i]; lsb = f.get_lsb_pos(); msk = ((1<> lsb; f.pre_write(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) begin rw.element = f; rw.element_kind = UVM_FIELD; cb.pre_write(rw); end value = (value & ~msk) | (rw.value[0] << lsb); end end rw.element = this; rw.element_kind = UVM_REG; rw.value[0] = value; pre_write(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) cb.pre_write(rw); if (rw.status != UVM_IS_OK) begin m_write_in_progress = 1'b0; XatomicX(0); return; end case (rw.path) UVM_BACKDOOR: begin uvm_reg_data_t final_val; uvm_reg_backdoor bkdr = get_backdoor(); if (rw.map != null) rw.local_map = rw.map; else rw.local_map = get_default_map(); value = rw.value[0]; rw.kind = UVM_READ; if (bkdr != null) bkdr.read(rw); else backdoor_read(rw); if (rw.status == UVM_NOT_OK) begin m_write_in_progress = 1'b0; return; end begin foreach (m_fields[i]) begin uvm_reg_data_t field_val; int lsb = m_fields[i].get_lsb_pos(); int sz = m_fields[i].get_n_bits(); field_val = m_fields[i].XpredictX((rw.value[0] >> lsb) & ((1<> lsb) & ((1<> f.get_lsb_pos()) & ((1<> f.get_lsb_pos()) & ((1<> hdl_concat.slices[j].offset; slice &= (1 << hdl_concat.slices[j].size)-1; ok &= uvm_hdl_deposit(hdl_concat.slices[j].path, slice); end end end rw.status = (ok ? UVM_IS_OK : UVM_NOT_OK); endtask task uvm_reg::backdoor_read (uvm_reg_item rw); rw.status = backdoor_read_func(rw); endtask function uvm_status_e uvm_reg::backdoor_read_func(uvm_reg_item rw); uvm_hdl_path_concat paths[$]; uvm_reg_data_t val; bit ok=1; get_full_hdl_path(paths,rw.bd_kind); foreach (paths[i]) begin uvm_hdl_path_concat hdl_concat = paths[i]; val = 0; foreach (hdl_concat.slices[j]) begin begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"RegMem")) uvm_report_info ("RegMem", $sformatf("backdoor_read from %s ", hdl_concat.slices[j].path), UVM_DEBUG, "t/uvm/src/reg/uvm_reg.svh", 2192, "", 1); end if (hdl_concat.slices[j].offset < 0) begin ok &= uvm_hdl_read(hdl_concat.slices[j].path,val); continue; end begin uvm_reg_data_t slice; int k = hdl_concat.slices[j].offset; ok &= uvm_hdl_read(hdl_concat.slices[j].path, slice); repeat (hdl_concat.slices[j].size) begin val[k++] = slice[0]; slice >>= 1; end end end val &= (1 << m_n_bits)-1; if (i == 0) rw.value[0] = val; if (val != rw.value[0]) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Backdoor read of register %s with multiple HDL copies: values are not the same: %0h at path '%s', and %0h at path '%s'. Returning first value.", get_full_name(), rw.value[0], uvm_hdl_concat2string(paths[0]), val, uvm_hdl_concat2string(paths[i])), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2220, "", 1); end return UVM_NOT_OK; end begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"RegMem")) uvm_report_info ("RegMem", $sformatf("returned backdoor value 0x%0x",rw.value[0]), UVM_DEBUG, "t/uvm/src/reg/uvm_reg.svh", 2224, "", 1); end end rw.status = (ok) ? UVM_IS_OK : UVM_NOT_OK; return rw.status; endfunction task uvm_reg::poke(output uvm_status_e status, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_backdoor bkdr = get_backdoor(); uvm_reg_item rw; m_fname = fname; m_lineno = lineno; if (bkdr == null && !has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"No backdoor access available to poke register '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2252, "", 1); end status = UVM_NOT_OK; return; end if (!m_is_locked_by_field) XatomicX(1); rw = uvm_reg_item::type_id_create("reg_poke_item",,get_full_name()); rw.element = this; rw.path = UVM_BACKDOOR; rw.element_kind = UVM_REG; rw.kind = UVM_WRITE; rw.bd_kind = kind; rw.value[0] = value & ((1 << m_n_bits)-1); rw.parent = parent; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; if (bkdr != null) bkdr.write(rw); else backdoor_write(rw); status = rw.status; begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Poked register \"%s\": 'h%h", get_full_name(), value), UVM_HIGH, "t/uvm/src/reg/uvm_reg.svh", 2285, "", 1); end do_predict(rw, UVM_PREDICT_WRITE); if (!m_is_locked_by_field) XatomicX(0); endtask: poke task uvm_reg::peek(output uvm_status_e status, output uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_backdoor bkdr = get_backdoor(); uvm_reg_item rw; m_fname = fname; m_lineno = lineno; if (bkdr == null && !has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("No backdoor access available to peek register \"%s\"", get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2313, "", 1); end status = UVM_NOT_OK; return; end if(!m_is_locked_by_field) XatomicX(1); rw = uvm_reg_item::type_id_create("mem_peek_item",,get_full_name()); rw.element = this; rw.path = UVM_BACKDOOR; rw.element_kind = UVM_REG; rw.kind = UVM_READ; rw.bd_kind = kind; rw.parent = parent; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; if (bkdr != null) bkdr.read(rw); else backdoor_read(rw); status = rw.status; value = rw.value[0]; begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Peeked register \"%s\": 'h%h", get_full_name(), value), UVM_HIGH, "t/uvm/src/reg/uvm_reg.svh", 2346, "", 1); end do_predict(rw, UVM_PREDICT_READ); if (!m_is_locked_by_field) XatomicX(0); endtask: peek function bit uvm_reg::do_check(input uvm_reg_data_t expected, input uvm_reg_data_t actual, uvm_reg_map map); uvm_reg_data_t valid_bits_mask = 0; foreach(m_fields[i]) begin string acc = m_fields[i].get_access(map); acc = acc.substr(0, 1); if (!(m_fields[i].get_compare() == UVM_NO_CHECK ||acc == "WO")) begin valid_bits_mask |= ((1 << m_fields[i].get_n_bits())-1)<< m_fields[i].get_lsb_pos(); end end if ((actual&valid_bits_mask) === (expected&valid_bits_mask)) return 1; begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Register \"%s\" value read from DUT (0x%h) does not match mirrored value (0x%h) (valid bit mask = 0x%h)", get_full_name(), actual, expected,valid_bits_mask), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2373, "", 1); end foreach(m_fields[i]) begin string acc = m_fields[i].get_access(map); acc = acc.substr(0, 1); if (!(m_fields[i].get_compare() == UVM_NO_CHECK || acc == "WO")) begin uvm_reg_data_t mask = ((1 << m_fields[i].get_n_bits())-1); uvm_reg_data_t val = actual >> m_fields[i].get_lsb_pos() & mask; uvm_reg_data_t exp = expected >> m_fields[i].get_lsb_pos() & mask; if (val !== exp) begin begin if (uvm_report_enabled(UVM_NONE,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Field %s (%s[%0d:%0d]) mismatch read=%0d'h%0h mirrored=%0d'h%0h ", m_fields[i].get_name(), get_full_name(), m_fields[i].get_lsb_pos() + m_fields[i].get_n_bits() - 1, m_fields[i].get_lsb_pos(), m_fields[i].get_n_bits(), val, m_fields[i].get_n_bits(), exp), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2392, "", 1); end end end end return 0; endfunction task uvm_reg::mirror(output uvm_status_e status, input uvm_check_e check = UVM_NO_CHECK, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t v; uvm_reg_data_t exp; uvm_reg_backdoor bkdr = get_backdoor(); XatomicX(1); m_fname = fname; m_lineno = lineno; if (path == UVM_DEFAULT_DOOR) path = m_parent.get_default_door(); if (path == UVM_BACKDOOR && (bkdr != null || has_hdl_path())) map = uvm_reg_map::backdoor(); else map = get_local_map(map); if (map == null) return; if (check == UVM_CHECK) exp = get_mirrored_value(); XreadX(status, v, path, map, parent, prior, extension, fname, lineno); if (status == UVM_NOT_OK) begin XatomicX(0); return; end if (check == UVM_CHECK) void'(do_check(exp, v, map)); XatomicX(0); endtask: mirror task uvm_reg::XatomicX(bit on); process m_reg_process; m_reg_process=process::self(); if (on) begin if (m_reg_process == m_process) return; m_atomic.get(1); m_process = m_reg_process; end else begin void'(m_atomic.try_get(1)); m_atomic.put(1); m_process = null; end endtask: XatomicX function string uvm_reg::convert2string(); string res_str; string t_str; bit with_debug_info; string prefix; $sformat(convert2string, "Register %s -- %0d bytes, mirror value:'h%h", get_full_name(), get_n_bytes(),get()); if (m_maps.num()==0) convert2string = {convert2string, " (unmapped)\n"}; else convert2string = {convert2string, "\n"}; foreach (m_maps[map]) begin uvm_reg_map parent_map = map; int unsigned offset; while (parent_map != null) begin uvm_reg_map this_map = parent_map; parent_map = this_map.get_parent_map(); offset = parent_map == null ? this_map.get_base_addr(UVM_NO_HIER) : parent_map.get_submap_offset(this_map); prefix = {prefix, " "}; begin uvm_endianness_e e = this_map.get_endian(); $sformat(convert2string, "%sMapped in '%s' -- %d bytes, %s, offset 'h%0h\n", prefix, this_map.get_full_name(), this_map.get_n_bytes(), e.name(), offset); end end end prefix = " "; foreach(m_fields[i]) begin $sformat(convert2string, "%s\n%s", convert2string, m_fields[i].convert2string()); end if (m_read_in_progress == 1'b1) begin if (m_fname != "" && m_lineno != 0) $sformat(res_str, "%s:%0d ",m_fname, m_lineno); convert2string = {convert2string, "\n", res_str, "currently executing read method"}; end if ( m_write_in_progress == 1'b1) begin if (m_fname != "" && m_lineno != 0) $sformat(res_str, "%s:%0d ",m_fname, m_lineno); convert2string = {convert2string, "\n", res_str, "currently executing write method"}; end endfunction: convert2string function void uvm_reg::do_print (uvm_printer printer); uvm_reg_field f[$]; super.do_print(printer); get_fields(f); foreach(f[i]) printer.print_generic(f[i].get_name(),f[i].get_type_name(),-2,f[i].convert2string()); endfunction function uvm_object uvm_reg::clone(); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "RegModel registers cannot be cloned", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2544, "", 1); end return null; endfunction function void uvm_reg::do_copy(uvm_object rhs); begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "RegModel registers cannot be copied", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2551, "", 1); end endfunction function bit uvm_reg::do_compare (uvm_object rhs, uvm_comparer comparer); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", "RegModel registers cannot be compared", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2559, "", 1); end return 0; endfunction function void uvm_reg::do_pack (uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", "RegModel registers cannot be packed", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2567, "", 1); end endfunction function void uvm_reg::do_unpack (uvm_packer packer); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", "RegModel registers cannot be unpacked", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2574, "", 1); end endfunction typedef class uvm_reg_indirect_ftdr_seq; class uvm_reg_indirect_data extends uvm_reg; protected uvm_reg m_idx; protected uvm_reg m_tbl[]; function new(string name = "uvm_reg_indirect", int unsigned n_bits, int has_cover); super.new(name,n_bits,has_cover); endfunction: new virtual function void build(); endfunction: build function void configure (uvm_reg idx, uvm_reg reg_a[], uvm_reg_block blk_parent, uvm_reg_file regfile_parent = null); super.configure(blk_parent, regfile_parent, ""); m_idx = idx; m_tbl = reg_a; uvm_resource_db#(bit)::set({"REG::", get_full_name()}, "NO_REG_TESTS", 1); foreach (m_maps[map]) begin add_frontdoors(map); end endfunction virtual function void add_map(uvm_reg_map map); super.add_map(map); add_frontdoors(map); endfunction local function void add_frontdoors(uvm_reg_map map); foreach (m_tbl[i]) begin uvm_reg_indirect_ftdr_seq fd; if (m_tbl[i] == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), $sformatf("Indirect register #%0d is NULL", i), UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 90, "", 1); end continue; end fd = new(m_idx, i, this); if (m_tbl[i].is_in_map(map)) m_tbl[i].set_frontdoor(fd, map); else map.add_reg(m_tbl[i], -1, "RW", 1, fd); end endfunction virtual function void do_predict (uvm_reg_item rw, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_reg_byte_en_t be = -1); if (m_idx.get() >= m_tbl.size()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), $sformatf("Address register %s has a value (%0d) greater than the maximum indirect register array size (%0d)", m_idx.get_full_name(), m_idx.get(), m_tbl.size()), UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 105, "", 1); end rw.status = UVM_NOT_OK; return; end begin int unsigned idx = m_idx.get(); m_tbl[idx].do_predict(rw, kind, be); end endfunction virtual function uvm_reg_map get_local_map(uvm_reg_map map); return m_idx.get_local_map(map); endfunction virtual function void add_field (uvm_reg_field field); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), "Cannot add field to an indirect data access register", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 126, "", 1); end endfunction virtual function void set (uvm_reg_data_t value, string fname = "", int lineno = 0); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), "Cannot set() an indirect data access register", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 132, "", 1); end endfunction virtual function uvm_reg_data_t get(string fname = "", int lineno = 0); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), "Cannot get() an indirect data access register", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 137, "", 1); end return 0; endfunction virtual function uvm_reg get_indirect_reg(string fname = "", int lineno = 0); int unsigned idx = m_idx.get_mirrored_value(); return(m_tbl[idx]); endfunction virtual function bit needs_update(); return 0; endfunction virtual task write(output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (path == UVM_DEFAULT_DOOR) begin uvm_reg_block blk = get_parent(); path = blk.get_default_door(); end if (path == UVM_BACKDOOR) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,get_full_name())) uvm_report_warning (get_full_name(), "Cannot backdoor-write an indirect data access register. Switching to frontdoor.", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 167, "", 1); end path = UVM_FRONTDOOR; end begin uvm_reg_item rw; XatomicX(1); rw = uvm_reg_item::type_id_create("write_item",,get_full_name()); rw.element = this; rw.element_kind = UVM_REG; rw.kind = UVM_WRITE; rw.value[0] = value; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_write(rw); status = rw.status; XatomicX(0); end endtask virtual task read(output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); if (path == UVM_DEFAULT_DOOR) begin uvm_reg_block blk = get_parent(); path = blk.get_default_door(); end if (path == UVM_BACKDOOR) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,get_full_name())) uvm_report_warning (get_full_name(), "Cannot backdoor-read an indirect data access register. Switching to frontdoor.", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 218, "", 1); end path = UVM_FRONTDOOR; end super.read(status, value, path, map, parent, prior, extension, fname, lineno); endtask virtual task poke(output uvm_status_e status, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), "Cannot poke() an indirect data access register", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 232, "", 1); end status = UVM_NOT_OK; endtask virtual task peek(output uvm_status_e status, output uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_full_name())) uvm_report_error (get_full_name(), "Cannot peek() an indirect data access register", UVM_NONE, "t/uvm/src/reg/uvm_reg_indirect.svh", 243, "", 1); end status = UVM_NOT_OK; endtask virtual task update(output uvm_status_e status, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); status = UVM_IS_OK; endtask virtual task mirror(output uvm_status_e status, input uvm_check_e check = UVM_NO_CHECK, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); status = UVM_IS_OK; endtask endclass : uvm_reg_indirect_data class uvm_reg_indirect_ftdr_seq extends uvm_reg_frontdoor; local uvm_reg m_addr_reg; local uvm_reg m_data_reg; local int m_idx; function new(uvm_reg addr_reg, int idx, uvm_reg data_reg); super.new("uvm_reg_indirect_ftdr_seq"); m_addr_reg = addr_reg; m_idx = idx; m_data_reg = data_reg; endfunction: new virtual task body(); uvm_reg_item rw; $cast(rw,rw_info.clone()); rw.element = m_addr_reg; rw.kind = UVM_WRITE; rw.value[0]= m_idx; m_addr_reg.XatomicX(1); m_data_reg.XatomicX(1); m_addr_reg.do_write(rw); if (rw.status == UVM_NOT_OK) return; $cast(rw,rw_info.clone()); rw.element = m_data_reg; if (rw_info.kind == UVM_WRITE) m_data_reg.do_write(rw); else begin m_data_reg.do_read(rw); rw_info.value[0] = rw.value[0]; end m_addr_reg.XatomicX(0); m_data_reg.XatomicX(0); rw_info.status = rw.status; endtask endclass class uvm_reg_fifo extends uvm_reg; local uvm_reg_field value; local int m_set_cnt; local int unsigned m_size; //TODO issue-4625 - Rand fields of dynamic array types //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'bit[$]' /*rand*/ uvm_reg_data_t fifo[$]; constraint valid_fifo_size { fifo.size() <= m_size; } function new(string name = "reg_fifo", int unsigned size, int unsigned n_bits, int has_cover); super.new(name,n_bits,has_cover); m_size = size; endfunction virtual function void build(); value = uvm_reg_field::type_id_create("value"); value.configure(this, get_n_bits(), 0, "RW", 0, 32'h0, 1, 0, 1); endfunction function void set_compare(uvm_check_e check=UVM_CHECK); value.set_compare(check); endfunction function int unsigned size(); return fifo.size(); endfunction function int unsigned capacity(); return m_size; endfunction virtual function void set(uvm_reg_data_t value, string fname = "", int lineno = 0); value &= ((1 << get_n_bits())-1); if (fifo.size() == m_size) begin return; end super.set(value,fname,lineno); m_set_cnt++; fifo.push_back(this.value.value); endfunction virtual task update(output uvm_status_e status, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_data_t upd; if (!m_set_cnt || fifo.size() == 0) return; m_update_in_progress = 1; for (int i=fifo.size()-m_set_cnt; m_set_cnt > 0; i++, m_set_cnt--) begin if (i >= 0) begin write(status,fifo[i],path,map,parent,prior,extension,fname,lineno); end end m_update_in_progress = 0; endtask virtual function uvm_reg_data_t get(string fname="", int lineno=0); return fifo[0]; endfunction virtual function void do_predict(uvm_reg_item rw, uvm_predict_e kind = UVM_PREDICT_DIRECT, uvm_reg_byte_en_t be = -1); super.do_predict(rw,kind,be); if (rw.status == UVM_NOT_OK) return; case (kind) UVM_PREDICT_WRITE, UVM_PREDICT_DIRECT: begin if (fifo.size() != m_size && !m_update_in_progress) fifo.push_back(this.value.value); end UVM_PREDICT_READ: begin uvm_reg_data_t value = rw.value[0] & ((1 << get_n_bits())-1); uvm_reg_data_t mirror_val; if (fifo.size() == 0) begin return; end mirror_val = fifo.pop_front(); if (this.value.get_compare() == UVM_CHECK && mirror_val != value) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"MIRROR_MISMATCH")) uvm_report_warning ("MIRROR_MISMATCH", $sformatf("Observed DUT read value 'h%0h != mirror value 'h%0h",value,mirror_val), UVM_NONE, "t/uvm/src/reg/uvm_reg_fifo.svh", 241, "", 1); end end end endcase endfunction virtual task pre_write(uvm_reg_item rw); if (m_set_cnt && !m_update_in_progress) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"Needs Update")) uvm_report_error ("Needs Update", "Must call update() after set() and before write()", UVM_NONE, "t/uvm/src/reg/uvm_reg_fifo.svh", 263, "", 1); end rw.status = UVM_NOT_OK; return; end if (fifo.size() >= m_size && !m_update_in_progress) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"FIFO Full")) uvm_report_error ("FIFO Full", "Write to full FIFO ignored", UVM_NONE, "t/uvm/src/reg/uvm_reg_fifo.svh", 268, "", 1); end rw.status = UVM_NOT_OK; return; end endtask virtual task pre_read(uvm_reg_item rw); if (fifo.size() == 0) begin rw.status = UVM_NOT_OK; return; end endtask function void post_randomize(); m_set_cnt = 0; endfunction endclass class 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; typedef uvm_object_registry#(uvm_reg_file,"uvm_reg_file") type_id; static function uvm_reg_file type_id_create (string name="", uvm_component parent=null, string contxt=""); return type_id::create(name, parent, contxt); endfunction static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction function uvm_object create (string name=""); uvm_reg_file tmp; if (name=="") tmp = new(); else tmp = new(name); return tmp; endfunction static function string type_name(); return "uvm_reg_file"; endfunction : type_name virtual function string get_type_name(); return "uvm_reg_file"; endfunction : get_type_name extern function new (string name=""); extern function void configure (uvm_reg_block blk_parent, uvm_reg_file regfile_parent, string hdl_path = ""); extern virtual function string get_full_name(); extern virtual function uvm_reg_block get_parent (); extern virtual function uvm_reg_block get_block (); extern virtual function uvm_reg_file get_regfile (); extern function void clear_hdl_path (string kind = "RTL"); extern function void add_hdl_path (string path, string kind = "RTL"); extern function bit has_hdl_path (string kind = ""); extern function void get_hdl_path (ref string paths[$], input string kind = ""); extern function void get_full_hdl_path (ref string paths[$], input string kind = "", input string separator = "."); extern function void set_default_hdl_path (string kind); extern function string get_default_hdl_path (); extern virtual function void do_print (uvm_printer printer); extern virtual function string convert2string(); extern virtual function uvm_object clone (); 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); endclass: uvm_reg_file function uvm_reg_file::new(string name=""); super.new(name); hdl_paths_pool = new("hdl_paths"); endfunction: new function void uvm_reg_file::configure(uvm_reg_block blk_parent, uvm_reg_file regfile_parent, string hdl_path = ""); if (blk_parent == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/RFILE/CFG/NOBLK")) uvm_report_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(), "\"."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 148, "", 1); end return; end this.parent = blk_parent; this.m_rf = regfile_parent; this.add_hdl_path(hdl_path); endfunction: configure function uvm_reg_block uvm_reg_file::get_block(); get_block = this.parent; endfunction: get_block function uvm_reg_file uvm_reg_file::get_regfile(); return m_rf; endfunction 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 begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unknown HDL Abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 188, "", 1); end return; end hdl_paths_pool.delete(kind); endfunction 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 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 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 begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Register does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 237, "", 1); end return; end hdl_paths = hdl_paths_pool.get(kind); for (int i=0; i= min_offset; start_offset <= max_offset - len + 1; } constraint uvm_mem_mam_policy_no_overlap { foreach (in_use[i]) { !(start_offset <= in_use[i].Xend_offsetX && start_offset + len - 1 >= in_use[i].Xstart_offsetX); } } endclass class uvm_mem_mam_cfg; rand int unsigned n_bytes; rand bit [63:0] start_offset; rand bit [63:0] end_offset; rand uvm_mem_mam::alloc_mode_e mode; rand uvm_mem_mam::locality_e locality; constraint uvm_mem_mam_cfg_valid { end_offset > start_offset; n_bytes < 64; } endclass function uvm_mem_region::new(bit [63:0] start_offset, bit [63:0] end_offset, int unsigned len, int unsigned n_bytes, uvm_mem_mam parent); this.Xstart_offsetX = start_offset; this.Xend_offsetX = end_offset; this.len = len; this.n_bytes = n_bytes; this.parent = parent; this.XvregX = null; endfunction: new function bit [63:0] uvm_mem_region::get_start_offset(); return this.Xstart_offsetX; endfunction: get_start_offset function bit [63:0] uvm_mem_region::get_end_offset(); return this.Xend_offsetX; endfunction: get_end_offset function int unsigned uvm_mem_region::get_len(); return this.len; endfunction: get_len function int unsigned uvm_mem_region::get_n_bytes(); return this.n_bytes; endfunction: get_n_bytes function string uvm_mem_region::convert2string(); $sformat(convert2string, "['h%h:'h%h]", this.Xstart_offsetX, this.Xend_offsetX); endfunction: convert2string function void uvm_mem_region::release_region(); this.parent.release_region(this); endfunction function uvm_mem uvm_mem_region::get_memory(); return this.parent.get_memory(); endfunction: get_memory function uvm_vreg uvm_mem_region::get_virtual_registers(); return this.XvregX; endfunction: get_virtual_registers function uvm_mem_mam::new(string name, uvm_mem_mam_cfg cfg, uvm_mem mem = null); this.cfg = cfg; this.memory = mem; this.default_alloc = new; endfunction: new function uvm_mem_mam_cfg uvm_mem_mam::reconfigure(uvm_mem_mam_cfg cfg = null); uvm_root top; uvm_coreservice_t cs; if (cfg == null) return this.cfg; cs = uvm_coreservice_t::get(); top = cs.get_root(); if (cfg.n_bytes !== this.cfg.n_bytes) begin top.uvm_report_error("uvm_mem_mam", $sformatf("Cannot reconfigure Memory Allocation Manager with a different number of bytes (%0d !== %0d)", cfg.n_bytes, this.cfg.n_bytes), UVM_LOW); return this.cfg; end foreach (this.in_use[i]) begin if (this.in_use[i].get_start_offset() < cfg.start_offset || this.in_use[i].get_end_offset() > cfg.end_offset) begin top.uvm_report_error("uvm_mem_mam", $sformatf("Cannot reconfigure Memory Allocation Manager with a currently allocated region outside of the managed address range ([%0d:%0d] outside of [%0d:%0d])", this.in_use[i].get_start_offset(), this.in_use[i].get_end_offset(), cfg.start_offset, cfg.end_offset), UVM_LOW); return this.cfg; end end reconfigure = this.cfg; this.cfg = cfg; endfunction: reconfigure function uvm_mem_region uvm_mem_mam::reserve_region(bit [63:0] start_offset, int unsigned n_bytes, string fname = "", int lineno = 0); bit [63:0] end_offset; this.fname = fname; this.lineno = lineno; if (n_bytes == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot reserve 0 bytes", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 638, "", 1); end return null; end if (start_offset < this.cfg.start_offset) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot reserve before start of memory space: 'h%h < 'h%h", start_offset, this.cfg.start_offset), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 644, "", 1); end return null; end end_offset = start_offset + ((n_bytes-1) / this.cfg.n_bytes); n_bytes = (end_offset - start_offset + 1) * this.cfg.n_bytes; if (end_offset > this.cfg.end_offset) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot reserve past end of memory space: 'h%h > 'h%h", end_offset, this.cfg.end_offset), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 653, "", 1); end return null; end begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Attempting to reserve ['h%h:'h%h]...", start_offset, end_offset), UVM_MEDIUM, "t/uvm/src/reg/uvm_mem_mam.svh", 658, "", 1); end foreach (this.in_use[i]) begin if (start_offset <= this.in_use[i].get_end_offset() && end_offset >= this.in_use[i].get_start_offset()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot reserve ['h%h:'h%h] because it overlaps with %s", start_offset, end_offset, this.in_use[i].convert2string()), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 669, "", 1); end return null; end if (start_offset > this.in_use[i].get_start_offset()) begin reserve_region = new(start_offset, end_offset, end_offset - start_offset + 1, n_bytes, this); this.in_use.insert(i, reserve_region); return reserve_region; end end reserve_region = new(start_offset, end_offset, end_offset - start_offset + 1, n_bytes, this); this.in_use.push_back(reserve_region); endfunction: reserve_region function uvm_mem_region uvm_mem_mam::request_region(int unsigned n_bytes, uvm_mem_mam_policy alloc = null, string fname = "", int lineno = 0); this.fname = fname; this.lineno = lineno; if (alloc == null) alloc = this.default_alloc; alloc.len = (n_bytes-1) / this.cfg.n_bytes + 1; alloc.min_offset = this.cfg.start_offset; alloc.max_offset = this.cfg.end_offset; alloc.in_use = this.in_use; if (!alloc.randomize()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Unable to randomize policy", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 702, "", 1); end return null; end return reserve_region(alloc.start_offset, n_bytes); endfunction: request_region function void uvm_mem_mam::release_region(uvm_mem_region region); if (region == null) return; foreach (this.in_use[i]) begin if (this.in_use[i] == region) begin this.in_use.delete(i); return; end end begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Attempting to release unallocated region\n", region.convert2string()}, UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 721, "", 1); end endfunction: release_region function void uvm_mem_mam::release_all_regions(); in_use.delete(); endfunction: release_all_regions function string uvm_mem_mam::convert2string(); convert2string = "Allocated memory regions:\n"; foreach (this.in_use[i]) begin $sformat(convert2string, "%s %s\n", convert2string, this.in_use[i].convert2string()); end endfunction: convert2string function uvm_mem_region uvm_mem_mam::for_each(bit reset = 0); if (reset) this.for_each_idx = -1; this.for_each_idx++; if (this.for_each_idx >= this.in_use.size()) begin return null; end return this.in_use[this.for_each_idx]; endfunction: for_each function uvm_mem uvm_mem_mam::get_memory(); return this.memory; endfunction: get_memory task uvm_mem_region::write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::write() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 773, "", 1); end status = UVM_NOT_OK; return; end if (offset > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to write to an offset outside of the allocated region (%0d > %0d)", offset, this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 781, "", 1); end status = UVM_NOT_OK; return; end mem.write(status, offset + this.get_start_offset(), value, path, map, parent, prior, extension); endtask: write task uvm_mem_region::read(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::read() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 806, "", 1); end status = UVM_NOT_OK; return; end if (offset > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to read from an offset outside of the allocated region (%0d > %0d)", offset, this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 814, "", 1); end status = UVM_NOT_OK; return; end mem.read(status, offset + this.get_start_offset(), value, path, map, parent, prior, extension); endtask: read task uvm_mem_region::burst_write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::burst_write() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 839, "", 1); end status = UVM_NOT_OK; return; end if (offset + value.size() > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to burst-write to an offset outside of the allocated region (burst to [%0d:%0d] > mem_size %0d)", offset,offset+value.size(),this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 847, "", 1); end status = UVM_NOT_OK; return; end mem.burst_write(status, offset + get_start_offset(), value, path, map, parent, prior, extension); endtask: burst_write task uvm_mem_region::burst_read(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::burst_read() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 873, "", 1); end status = UVM_NOT_OK; return; end if (offset + value.size() > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to burst-read to an offset outside of the allocated region (burst to [%0d:%0d] > mem_size %0d)", offset,offset+value.size(),this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 881, "", 1); end status = UVM_NOT_OK; return; end mem.burst_read(status, offset + get_start_offset(), value, path, map, parent, prior, extension); endtask: burst_read task uvm_mem_region::poke(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::poke() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 904, "", 1); end status = UVM_NOT_OK; return; end if (offset > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to poke to an offset outside of the allocated region (%0d > %0d)", offset, this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 912, "", 1); end status = UVM_NOT_OK; return; end mem.poke(status, offset + this.get_start_offset(), value, "", parent, extension); endtask: poke task uvm_mem_region::peek(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem = this.parent.get_memory(); this.fname = fname; this.lineno = lineno; if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot use uvm_mem_region::peek() on a region that was allocated by a Memory Allocation Manager that was not associated with a uvm_mem instance", UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 933, "", 1); end status = UVM_NOT_OK; return; end if (offset > this.len) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to peek from an offset outside of the allocated region (%0d > %0d)", offset, this.len), UVM_NONE, "t/uvm/src/reg/uvm_mem_mam.svh", 941, "", 1); end status = UVM_NOT_OK; return; end mem.peek(status, offset + this.get_start_offset(), value, "", parent, extension); endtask: peek typedef class uvm_mem_region; typedef class uvm_mem_mam; typedef class uvm_vreg_cbs; class uvm_vreg extends uvm_object; static local bit m_register_cb_uvm_vreg_cbs = uvm_callbacks#(uvm_vreg,uvm_vreg_cbs)::m_register_pair("uvm_vreg","uvm_vreg_cbs"); local bit locked; local uvm_reg_block parent; local int unsigned n_bits; local int unsigned n_used_bits; local uvm_vreg_field fields[$]; local uvm_mem mem; local uvm_reg_addr_t offset; local int unsigned incr; local longint unsigned size; local bit is_static; local uvm_mem_region region; local semaphore atomic; local string fname; local int lineno; local bit read_in_progress; local bit write_in_progress; extern function new(string name, int unsigned n_bits); extern function void configure(uvm_reg_block parent, uvm_mem mem = null, longint unsigned size = 0, uvm_reg_addr_t offset = 0, int unsigned incr = 0); extern virtual function bit implement(longint unsigned n, uvm_mem mem = null, uvm_reg_addr_t offset = 0, int unsigned incr = 0); extern virtual function uvm_mem_region allocate(longint unsigned n, uvm_mem_mam mam, uvm_mem_mam_policy alloc = null); extern virtual function uvm_mem_region get_region(); extern virtual function void release_region(); extern virtual function void set_parent(uvm_reg_block parent); extern function void Xlock_modelX(); extern function void add_field(uvm_vreg_field field); extern task XatomicX(bit on); extern virtual function string get_full_name(); extern virtual function uvm_reg_block get_parent(); extern virtual function uvm_reg_block get_block(); extern virtual function uvm_mem get_memory(); extern virtual function int get_n_maps (); extern function bit is_in_map (uvm_reg_map map); extern virtual function void get_maps (ref uvm_reg_map maps[$]); extern virtual function string get_rights(uvm_reg_map map = null); extern virtual function string get_access(uvm_reg_map map = null); extern virtual function int unsigned get_size(); extern virtual function int unsigned get_n_bytes(); extern virtual function int unsigned get_n_memlocs(); extern virtual function int unsigned get_incr(); extern virtual function void get_fields(ref uvm_vreg_field fields[$]); extern virtual function uvm_vreg_field get_field_by_name(string name); extern virtual function uvm_reg_addr_t get_offset_in_memory(longint unsigned idx); extern virtual function uvm_reg_addr_t get_address(longint unsigned idx, uvm_reg_map map = null); extern virtual task write(input longint unsigned idx, output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task read(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task poke(input longint unsigned idx, output uvm_status_e status, input uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task peek(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern function void reset(string kind = "HARD"); virtual task pre_write(longint unsigned idx, ref uvm_reg_data_t wdat, ref uvm_door_e path, ref uvm_reg_map map); endtask: pre_write virtual task post_write(longint unsigned idx, uvm_reg_data_t wdat, uvm_door_e path, uvm_reg_map map, ref uvm_status_e status); endtask: post_write virtual task pre_read(longint unsigned idx, ref uvm_door_e path, ref uvm_reg_map map); endtask: pre_read virtual task post_read(longint unsigned idx, ref uvm_reg_data_t rdat, input uvm_door_e path, input uvm_reg_map map, ref uvm_status_e status); endtask: post_read extern virtual function void do_print (uvm_printer printer); extern virtual function string convert2string; extern virtual function uvm_object clone(); 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); endclass: uvm_vreg virtual class uvm_vreg_cbs extends uvm_callback; typedef uvm_abstract_object_registry#(uvm_vreg_cbs,"uvm_vreg_cbs") type_id; static function type_id get_type(); return type_id::get(); endfunction virtual function uvm_object_wrapper get_object_type(); return type_id::get(); endfunction static function string type_name(); return "uvm_vreg_cbs"; endfunction : type_name virtual function string get_type_name(); return "uvm_vreg_cbs"; endfunction : get_type_name string fname; int lineno; function new(string name = "uvm_reg_cbs"); super.new(name); endfunction virtual task pre_write(uvm_vreg rg, longint unsigned idx, ref uvm_reg_data_t wdat, ref uvm_door_e path, ref uvm_reg_map map); endtask: pre_write virtual task post_write(uvm_vreg rg, longint unsigned idx, uvm_reg_data_t wdat, uvm_door_e path, uvm_reg_map map, ref uvm_status_e status); endtask: post_write virtual task pre_read(uvm_vreg rg, longint unsigned idx, ref uvm_door_e path, ref uvm_reg_map map); endtask: pre_read virtual task post_read(uvm_vreg rg, longint unsigned idx, ref uvm_reg_data_t rdat, input uvm_door_e path, input uvm_reg_map map, ref uvm_status_e status); endtask: post_read endclass: uvm_vreg_cbs typedef uvm_callbacks#(uvm_vreg, uvm_vreg_cbs) uvm_vreg_cb ; typedef uvm_callback_iter#(uvm_vreg, uvm_vreg_cbs) uvm_vreg_cb_iter ; function uvm_vreg::new(string name, int unsigned n_bits); super.new(name); if (n_bits == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" cannot have 0 bits", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 425, "", 1); end n_bits = 1; end if (n_bits > 64) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" cannot have more than %0d bits (%0d)", this.get_full_name(), 64, n_bits), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 429, "", 1); end n_bits = 64; end this.n_bits = n_bits; this.locked = 0; endfunction: new function void uvm_vreg::configure(uvm_reg_block parent, uvm_mem mem = null, longint unsigned size = 0, uvm_reg_addr_t offset = 0, int unsigned incr = 0); this.parent = parent; this.n_used_bits = 0; if (mem != null) begin void'(this.implement(size, mem, offset, incr)); this.is_static = 1; end else begin this.mem = null; this.is_static = 0; end this.parent.add_vreg(this); this.atomic = new(1); endfunction: configure function void uvm_vreg::Xlock_modelX(); if (this.locked) return; this.locked = 1; endfunction: Xlock_modelX function void uvm_vreg::add_field(uvm_vreg_field field); int offset; int idx; if (this.locked) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot add virtual field to locked virtual register model", UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 473, "", 1); end return; end if (field == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", "Attempting to register NULL virtual field", UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 477, "", 1); end offset = field.get_lsb_pos_in_register(); idx = -1; foreach (this.fields[i]) begin if (offset < this.fields[i].get_lsb_pos_in_register()) begin int j = i; this.fields.insert(j, field); idx = i; break; end end if (idx < 0) begin this.fields.push_back(field); idx = this.fields.size()-1; end this.n_used_bits += field.get_n_bits(); if (this.n_used_bits > this.n_bits) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual fields use more bits (%0d) than available in virtual register \"%s\" (%0d)", this.n_used_bits, this.get_full_name(), this.n_bits), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 501, "", 1); end end if (idx > 0) begin if (this.fields[idx-1].get_lsb_pos_in_register() + this.fields[idx-1].get_n_bits() > offset) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Field %s overlaps field %s in virtual register \"%s\"", this.fields[idx-1].get_name(), field.get_name(), this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 511, "", 1); end end end if (idx < this.fields.size()-1) begin if (offset + field.get_n_bits() > this.fields[idx+1].get_lsb_pos_in_register()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Field %s overlaps field %s in virtual register \"%s\"", field.get_name(), this.fields[idx+1].get_name(), this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 520, "", 1); end end end endfunction: add_field task uvm_vreg::XatomicX(bit on); if (on) this.atomic.get(1); else begin void'(this.atomic.try_get(1)); this.atomic.put(1); end endtask: XatomicX function void uvm_vreg::reset(string kind = "HARD"); void'(this.atomic.try_get(1)); this.atomic.put(1); endfunction: reset function string uvm_vreg::get_full_name(); uvm_reg_block blk; get_full_name = this.get_name(); blk = this.get_block(); if (blk == null) return get_full_name; if (blk.get_parent() == null) return get_full_name; get_full_name = {this.parent.get_full_name(), ".", get_full_name}; endfunction: get_full_name function void uvm_vreg::set_parent(uvm_reg_block parent); this.parent = parent; endfunction: set_parent function uvm_reg_block uvm_vreg::get_parent(); get_parent = this.parent; endfunction: get_parent function uvm_reg_block uvm_vreg::get_block(); get_block = this.parent; endfunction: get_block function bit uvm_vreg::implement(longint unsigned n, uvm_mem mem = null, uvm_reg_addr_t offset = 0, int unsigned incr = 0); uvm_mem_region region; if(n < 1) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to implement virtual register \"%s\" with a subscript less than one doesn't make sense",this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 579, "", 1); end return 0; end if (mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to implement virtual register \"%s\" using a NULL uvm_mem reference", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 584, "", 1); end return 0; end if (this.is_static) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically implemented", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 589, "", 1); end return 0; end if (mem.get_block() != this.parent) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to implement virtual register \"%s\" on memory \"%s\" in a different block", this.get_full_name(), mem.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 596, "", 1); end return 0; end begin int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1; if (incr == 0) incr = min_incr; if (min_incr > incr) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".", this.get_full_name(), incr, min_incr, mem.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 606, "", 1); end return 0; end end if (offset + (n * incr) > mem.get_size()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Given Offset for Virtual register \"%s[%0d]\" is too big for memory %s@'h%0h", this.get_full_name(), n, mem.get_full_name(), offset), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 613, "", 1); end return 0; end region = mem.mam.reserve_region(offset,n*incr*mem.get_n_bytes()); if (region == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Could not allocate a memory region for virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 620, "", 1); end return 0; end if (this.mem != null) begin begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Virtual register \"%s\" is being moved re-implemented from %s@'h%0h to %s@'h%0h", this.get_full_name(), this.mem.get_full_name(), this.offset, mem.get_full_name(), offset), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 629, "", 1); end this.release_region(); end this.region = region; this.mem = mem; this.size = n; this.offset = offset; this.incr = incr; this.mem.Xadd_vregX(this); return 1; endfunction: implement function uvm_mem_region uvm_vreg::allocate(longint unsigned n, uvm_mem_mam mam, uvm_mem_mam_policy alloc=null); uvm_mem mem; if(n < 1) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to implement virtual register \"%s\" with a subscript less than one doesn't make sense",this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 652, "", 1); end return null; end if (mam == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to implement virtual register \"%s\" using a NULL uvm_mem_mam reference", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 657, "", 1); end return null; end if (this.is_static) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically allocated", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 662, "", 1); end return null; end mem = mam.get_memory(); if (mem.get_block() != this.parent) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Attempting to allocate virtual register \"%s\" on memory \"%s\" in a different block", this.get_full_name(), mem.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 670, "", 1); end return null; end begin int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1; if (incr == 0) incr = min_incr; if (min_incr < incr) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".", this.get_full_name(), incr, min_incr, mem.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 680, "", 1); end return null; end end allocate = mam.request_region(n*incr*mem.get_n_bytes(), alloc); if (allocate == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Could not allocate a memory region for virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 688, "", 1); end return null; end if (this.mem != null) begin begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Virtual register \"%s\" is being moved from %s@'h%0h to %s@'h%0h", this.get_full_name(), this.mem.get_full_name(), this.offset, mem.get_full_name(), allocate.get_start_offset()), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 698, "", 1); end this.release_region(); end this.region = allocate; this.mem = mam.get_memory(); this.offset = allocate.get_start_offset(); this.size = n; this.incr = incr; this.mem.Xadd_vregX(this); endfunction: allocate function uvm_mem_region uvm_vreg::get_region(); return this.region; endfunction: get_region function void uvm_vreg::release_region(); if (this.is_static) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically released", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 721, "", 1); end return; end if (this.mem != null) this.mem.Xdelete_vregX(this); if (this.region != null) begin this.region.release_region(); end this.region = null; this.mem = null; this.size = 0; this.offset = 0; this.reset(); endfunction: release_region function uvm_mem uvm_vreg::get_memory(); return this.mem; endfunction: get_memory function uvm_reg_addr_t uvm_vreg::get_offset_in_memory(longint unsigned idx); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_offset_in_memory() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 749, "", 1); end return 0; end return this.offset + idx * this.incr; endfunction function uvm_reg_addr_t uvm_vreg::get_address(longint unsigned idx, uvm_reg_map map = null); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot get address of of unimplemented virtual register \"%s\".", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 760, "", 1); end return 0; end return this.mem.get_address(this.get_offset_in_memory(idx), map); endfunction: get_address function int unsigned uvm_vreg::get_size(); if (this.size == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_size() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 771, "", 1); end return 0; end return this.size; endfunction: get_size function int unsigned uvm_vreg::get_n_bytes(); return ((this.n_bits-1) / 8) + 1; endfunction: get_n_bytes function int unsigned uvm_vreg::get_n_memlocs(); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_n_memlocs() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 787, "", 1); end return 0; end return (this.get_n_bytes()-1) / this.mem.get_n_bytes() + 1; endfunction: get_n_memlocs function int unsigned uvm_vreg::get_incr(); if (this.incr == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_incr() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 798, "", 1); end return 0; end return this.incr; endfunction: get_incr function int uvm_vreg::get_n_maps(); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_n_maps() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 809, "", 1); end return 0; end return this.mem.get_n_maps(); endfunction: get_n_maps function void uvm_vreg::get_maps(ref uvm_reg_map maps[$]); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_maps() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 820, "", 1); end return; end this.mem.get_maps(maps); endfunction: get_maps function bit uvm_vreg::is_in_map(uvm_reg_map map); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::is_in_map() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 831, "", 1); end return 0; end return this.mem.is_in_map(map); endfunction function string uvm_vreg::get_access(uvm_reg_map map = null); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_rights() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 842, "", 1); end return "RW"; end return this.mem.get_access(map); endfunction: get_access function string uvm_vreg::get_rights(uvm_reg_map map = null); if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot call uvm_vreg::get_rights() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 853, "", 1); end return "RW"; end return this.mem.get_rights(map); endfunction: get_rights function void uvm_vreg::get_fields(ref uvm_vreg_field fields[$]); foreach(this.fields[i]) fields.push_back(this.fields[i]); endfunction: get_fields function uvm_vreg_field uvm_vreg::get_field_by_name(string name); foreach (this.fields[i]) begin if (this.fields[i].get_name() == name) begin return this.fields[i]; end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", $sformatf("Unable to locate field \"%s\" in virtual register \"%s\".", name, this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 874, "", 1); end get_field_by_name = null; endfunction: get_field_by_name task uvm_vreg::write(input longint unsigned idx, output uvm_status_e status, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_vreg_cb_iter cbs = new(this); uvm_reg_addr_t addr; uvm_reg_data_t tmp; uvm_reg_data_t msk; int lsb; this.write_in_progress = 1'b1; this.fname = fname; this.lineno = lineno; if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot write to unimplemented virtual register \"%s\".", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 899, "", 1); end status = UVM_NOT_OK; return; end if (path == UVM_DEFAULT_DOOR) path = this.parent.get_default_door(); foreach (fields[i]) begin uvm_vreg_field_cb_iter cbs = new(fields[i]); uvm_vreg_field f = fields[i]; lsb = f.get_lsb_pos_in_register(); msk = ((1<> lsb; f.pre_write(idx, tmp, path, map); for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.pre_write(f, idx, tmp, path, map); end value = (value & ~msk) | (tmp << lsb); end this.pre_write(idx, value, path, map); for (uvm_vreg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.pre_write(this, idx, value, path, map); end addr = this.offset + (idx * this.incr); lsb = 0; status = UVM_IS_OK; for (int i = 0; i < this.get_n_memlocs(); i++) begin uvm_status_e s; msk = ((1<<(this.mem.get_n_bytes()*8))-1) << lsb; tmp = (value & msk) >> lsb; this.mem.write(s, addr + i, tmp, path, map , parent, , extension, fname, lineno); if (s != UVM_IS_OK && s != UVM_HAS_X) status = s; lsb += this.mem.get_n_bytes() * 8; end for (uvm_vreg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.post_write(this, idx, value, path, map, status); end this.post_write(idx, value, path, map, status); foreach (fields[i]) begin uvm_vreg_field_cb_iter cbs = new(fields[i]); uvm_vreg_field f = fields[i]; lsb = f.get_lsb_pos_in_register(); msk = ((1<> lsb; for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.post_write(f, idx, tmp, path, map, status); end f.post_write(idx, tmp, path, map, status); value = (value & ~msk) | (tmp << lsb); end begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Wrote virtual register \"%s\"[%0d] via %s with: 'h%h", this.get_full_name(), idx, (path == UVM_FRONTDOOR) ? "frontdoor" : "backdoor", value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 976, "", 1); end this.write_in_progress = 1'b0; this.fname = ""; this.lineno = 0; endtask: write task uvm_vreg::read(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_vreg_cb_iter cbs = new(this); uvm_reg_addr_t addr; uvm_reg_data_t tmp; uvm_reg_data_t msk; int lsb; this.read_in_progress = 1'b1; this.fname = fname; this.lineno = lineno; if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot read from unimplemented virtual register \"%s\".", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 1005, "", 1); end status = UVM_NOT_OK; return; end if (path == UVM_DEFAULT_DOOR) path = this.parent.get_default_door(); foreach (fields[i]) begin uvm_vreg_field_cb_iter cbs = new(fields[i]); uvm_vreg_field f = fields[i]; f.pre_read(idx, path, map); for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.pre_read(f, idx, path, map); end end this.pre_read(idx, path, map); for (uvm_vreg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.pre_read(this, idx, path, map); end addr = this.offset + (idx * this.incr); lsb = 0; value = 0; status = UVM_IS_OK; for (int i = 0; i < this.get_n_memlocs(); i++) begin uvm_status_e s; this.mem.read(s, addr + i, tmp, path, map, parent, , extension, fname, lineno); if (s != UVM_IS_OK && s != UVM_HAS_X) status = s; value |= tmp << lsb; lsb += this.mem.get_n_bytes() * 8; end for (uvm_vreg_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.post_read(this, idx, value, path, map, status); end this.post_read(idx, value, path, map, status); foreach (fields[i]) begin uvm_vreg_field_cb_iter cbs = new(fields[i]); uvm_vreg_field f = fields[i]; lsb = f.get_lsb_pos_in_register(); msk = ((1<> lsb; for (uvm_vreg_field_cbs cb = cbs.first(); cb != null; cb = cbs.next()) begin cb.fname = this.fname; cb.lineno = this.lineno; cb.post_read(f, idx, tmp, path, map, status); end f.post_read(idx, tmp, path, map, status); value = (value & ~msk) | (tmp << lsb); end begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Read virtual register \"%s\"[%0d] via %s: 'h%h", this.get_full_name(), idx, (path == UVM_FRONTDOOR) ? "frontdoor" : "backdoor", value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 1078, "", 1); end this.read_in_progress = 1'b0; this.fname = ""; this.lineno = 0; endtask: read task uvm_vreg::poke(input longint unsigned idx, output uvm_status_e status, input uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_addr_t addr; uvm_reg_data_t tmp; uvm_reg_data_t msk; int lsb; this.fname = fname; this.lineno = lineno; if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot poke in unimplemented virtual register \"%s\".", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 1101, "", 1); end status = UVM_NOT_OK; return; end addr = this.offset + (idx * this.incr); lsb = 0; status = UVM_IS_OK; for (int i = 0; i < this.get_n_memlocs(); i++) begin uvm_status_e s; msk = ((1<<(this.mem.get_n_bytes() * 8))-1) << lsb; tmp = (value & msk) >> lsb; this.mem.poke(status, addr + i, tmp, "", parent, extension, fname, lineno); if (s != UVM_IS_OK && s != UVM_HAS_X) status = s; lsb += this.mem.get_n_bytes() * 8; end begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Poked virtual register \"%s\"[%0d] with: 'h%h", this.get_full_name(), idx, value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 1123, "", 1); end this.fname = ""; this.lineno = 0; endtask: poke task uvm_vreg::peek(input longint unsigned idx, output uvm_status_e status, output uvm_reg_data_t value, input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_addr_t addr; uvm_reg_data_t tmp; uvm_reg_data_t msk; int lsb; this.fname = fname; this.lineno = lineno; if (this.mem == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot peek in from unimplemented virtual register \"%s\".", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg.svh", 1145, "", 1); end status = UVM_NOT_OK; return; end addr = this.offset + (idx * this.incr); lsb = 0; value = 0; status = UVM_IS_OK; for (int i = 0; i < this.get_n_memlocs(); i++) begin uvm_status_e s; this.mem.peek(status, addr + i, tmp, "", parent, extension, fname, lineno); if (s != UVM_IS_OK && s != UVM_HAS_X) status = s; value |= tmp << lsb; lsb += this.mem.get_n_bytes() * 8; end begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Peeked virtual register \"%s\"[%0d]: 'h%h", this.get_full_name(), idx, value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg.svh", 1166, "", 1); end this.fname = ""; this.lineno = 0; endtask: peek function void uvm_vreg::do_print (uvm_printer printer); super.do_print(printer); printer.print_generic("initiator", parent.get_type_name(), -1, convert2string()); endfunction function string uvm_vreg::convert2string(); string res_str; string t_str; bit with_debug_info; $sformat(convert2string, "Virtual register %s -- ", this.get_full_name()); if (this.size == 0) $sformat(convert2string, "%sunimplemented", convert2string); else begin uvm_reg_map maps[$]; mem.get_maps(maps); $sformat(convert2string, "%s[%0d] in %0s['h%0h+'h%0h]\n", convert2string, this.size, this.mem.get_full_name(), this.offset, this.incr); foreach (maps[i]) begin uvm_reg_addr_t addr0 = this.get_address(0, maps[i]); $sformat(convert2string, " Address in map '%s' -- @'h%0h+%0h", maps[i].get_full_name(), addr0, this.get_address(1, maps[i]) - addr0); end end foreach(this.fields[i]) begin $sformat(convert2string, "%s\n%s", convert2string, this.fields[i].convert2string()); end endfunction: convert2string function uvm_object uvm_vreg::clone(); return null; endfunction function void uvm_vreg::do_copy (uvm_object rhs); endfunction function bit uvm_vreg::do_compare (uvm_object rhs, uvm_comparer comparer); return 0; endfunction function void uvm_vreg::do_pack (uvm_packer packer); endfunction function void uvm_vreg::do_unpack (uvm_packer packer); endfunction class uvm_mem extends uvm_object; typedef enum {UNKNOWNS, ZEROES, ONES, ADDRESS, VALUE, INCR, DECR} init_e; local bit m_locked; local bit m_read_in_progress; local bit m_write_in_progress; local string m_access; local longint unsigned m_size; local uvm_reg_block m_parent; local bit m_maps[uvm_reg_map]; local int unsigned m_n_bits; local uvm_reg_backdoor m_backdoor; local bit m_is_powered_down; local int m_has_cover; local int m_cover_on; local string m_fname; local int m_lineno; local bit m_vregs[uvm_vreg]; local uvm_object_string_pool #(uvm_queue #(uvm_hdl_path_concat)) m_hdl_paths_pool; local static int unsigned m_max_size; extern function new (string name, longint unsigned size, int unsigned n_bits, string access = "RW", int has_coverage = UVM_NO_COVERAGE); extern function void configure (uvm_reg_block parent, string hdl_path = ""); extern virtual function void set_offset (uvm_reg_map map, uvm_reg_addr_t offset, bit unmapped = 0); extern virtual function void set_parent(uvm_reg_block parent); extern function void add_map(uvm_reg_map map); extern function void Xlock_modelX(); extern function void Xadd_vregX(uvm_vreg vreg); extern function void Xdelete_vregX(uvm_vreg vreg); uvm_mem_mam mam; extern virtual function string get_full_name(); extern virtual function uvm_reg_block get_parent (); extern virtual function uvm_reg_block get_block (); extern virtual function int get_n_maps (); extern function bit is_in_map (uvm_reg_map map); extern virtual function void get_maps (ref uvm_reg_map maps[$]); extern function uvm_reg_map get_local_map (uvm_reg_map map); extern function uvm_reg_map get_default_map (); extern virtual function string get_rights (uvm_reg_map map = null); extern virtual function string get_access(uvm_reg_map map = null); extern function longint unsigned get_size(); extern function int unsigned get_n_bytes(); extern function int unsigned get_n_bits(); extern static function int unsigned get_max_size(); extern virtual function void get_virtual_registers(ref uvm_vreg regs[$]); extern virtual function void get_virtual_fields(ref uvm_vreg_field fields[$]); extern virtual function uvm_vreg get_vreg_by_name(string name); extern virtual function uvm_vreg_field get_vfield_by_name(string name); extern virtual function uvm_vreg get_vreg_by_offset(uvm_reg_addr_t offset, uvm_reg_map map = null); extern virtual function uvm_reg_addr_t get_offset (uvm_reg_addr_t offset = 0, uvm_reg_map map = null); extern virtual function uvm_reg_addr_t get_address(uvm_reg_addr_t offset = 0, uvm_reg_map map = null); extern virtual function int get_addresses(uvm_reg_addr_t offset = 0, uvm_reg_map map=null, ref uvm_reg_addr_t addr[]); extern virtual task write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task read(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task burst_write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task burst_read(output uvm_status_e status, input uvm_reg_addr_t offset, ref uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task poke(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern virtual task peek(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); extern protected function bit Xcheck_accessX (input uvm_reg_item rw, output uvm_reg_map_info map_info); extern virtual task do_write (uvm_reg_item rw); extern virtual task do_read (uvm_reg_item rw); extern function void set_frontdoor(uvm_reg_frontdoor ftdr, uvm_reg_map map = null, string fname = "", int lineno = 0); extern function uvm_reg_frontdoor get_frontdoor(uvm_reg_map map = null); extern function void set_backdoor (uvm_reg_backdoor bkdr, string fname = "", int lineno = 0); extern function uvm_reg_backdoor get_backdoor(bit inherited = 1); extern function void clear_hdl_path (string kind = "RTL"); extern function void add_hdl_path (uvm_hdl_path_slice slices[], string kind = "RTL"); extern function void add_hdl_path_slice(string name, int offset, int size, bit first = 0, string kind = "RTL"); extern function bit has_hdl_path (string kind = ""); extern function void get_hdl_path (ref uvm_hdl_path_concat paths[$], input string kind = ""); extern function void get_full_hdl_path (ref uvm_hdl_path_concat paths[$], input string kind = "", input string separator = "."); extern function void get_hdl_path_kinds (ref string kinds[$]); extern virtual protected task backdoor_read(uvm_reg_item rw); extern virtual task backdoor_write(uvm_reg_item rw); extern virtual function uvm_status_e backdoor_read_func(uvm_reg_item rw); static local bit m_register_cb_uvm_reg_cbs = uvm_callbacks#(uvm_mem,uvm_reg_cbs)::m_register_pair("uvm_mem","uvm_reg_cbs"); virtual task pre_write(uvm_reg_item rw); endtask virtual task post_write(uvm_reg_item rw); endtask virtual task pre_read(uvm_reg_item rw); endtask virtual task post_read(uvm_reg_item rw); endtask extern protected function uvm_reg_cvr_t build_coverage(uvm_reg_cvr_t models); extern virtual protected function void add_coverage(uvm_reg_cvr_t models); extern virtual function bit has_coverage(uvm_reg_cvr_t models); extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on); extern virtual function bit get_coverage(uvm_reg_cvr_t is_on); protected virtual function void sample(uvm_reg_addr_t offset, bit is_read, uvm_reg_map map); endfunction function void XsampleX(uvm_reg_addr_t addr, bit is_read, uvm_reg_map map); sample(addr, is_read, map); endfunction extern virtual function void do_print (uvm_printer printer); extern virtual function string convert2string(); extern virtual function uvm_object clone(); 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); endclass: uvm_mem function uvm_mem::new (string name, longint unsigned size, int unsigned n_bits, string access = "RW", int has_coverage = UVM_NO_COVERAGE); super.new(name); m_locked = 0; if (n_bits == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(),"' cannot have 0 bits"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 537, "", 1); end n_bits = 1; end m_size = size; m_n_bits = n_bits; m_backdoor = null; m_access = access.toupper(); m_has_cover = has_coverage; m_hdl_paths_pool = new("hdl_paths"); if (n_bits > m_max_size) m_max_size = n_bits; endfunction: new function void uvm_mem::configure(uvm_reg_block parent, string hdl_path=""); if (parent == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/NULL_PARENT")) uvm_report_fatal ("REG/NULL_PARENT", "configure: parent argument is null", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 559, "", 1); end m_parent = parent; if (m_access != "RW" && m_access != "RO") begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(),"' can only be RW or RO"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 564, "", 1); end m_access = "RW"; end begin uvm_mem_mam_cfg cfg = new; cfg.n_bytes = ((m_n_bits-1) / 8) + 1; cfg.start_offset = 0; cfg.end_offset = m_size-1; cfg.mode = uvm_mem_mam::GREEDY; cfg.locality = uvm_mem_mam::BROAD; mam = new(get_full_name(), cfg, this); end m_parent.add_mem(this); if (hdl_path != "") add_hdl_path_slice(hdl_path, -1, -1); endfunction: configure function void uvm_mem::set_offset (uvm_reg_map map, uvm_reg_addr_t offset, bit unmapped = 0); uvm_reg_map orig_map = map; if (m_maps.num() > 1 && map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"set_offset requires a non-null map when memory '", get_full_name(),"' belongs to more than one map."}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 597, "", 1); end return; end map = get_local_map(map); if (map == null) return; map.m_set_mem_offset(this, offset, unmapped); endfunction function void uvm_mem::add_map(uvm_reg_map map); m_maps[map] = 1; endfunction function void uvm_mem::Xlock_modelX(); m_locked = 1; endfunction: Xlock_modelX function string uvm_mem::get_full_name(); if (m_parent == null) return get_name(); return {m_parent.get_full_name(), ".", get_name()}; endfunction: get_full_name function uvm_reg_block uvm_mem::get_block(); return m_parent; endfunction: get_block function int uvm_mem::get_n_maps(); return m_maps.num(); endfunction: get_n_maps function void uvm_mem::get_maps(ref uvm_reg_map maps[$]); foreach (m_maps[map]) maps.push_back(map); endfunction function bit uvm_mem::is_in_map(uvm_reg_map map); if (m_maps.exists(map)) return 1; foreach (m_maps[l]) begin uvm_reg_map local_map=l; uvm_reg_map parent_map = local_map.get_parent_map(); while (parent_map != null) begin if (parent_map == map) return 1; parent_map = parent_map.get_parent_map(); end end return 0; endfunction function uvm_reg_map uvm_mem::get_local_map(uvm_reg_map map); if (map == null) return get_default_map(); if (m_maps.exists(map)) return map; foreach (m_maps[l]) begin uvm_reg_map local_map = l; uvm_reg_map parent_map = local_map.get_parent_map(); while (parent_map != null) begin if (parent_map == map) return local_map; parent_map = parent_map.get_parent_map(); end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Memory '",get_full_name(),"' is not contained within map '",map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 694, "", 1); end return null; endfunction function uvm_reg_map uvm_mem::get_default_map(); if (m_maps.num() == 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Memory '",get_full_name(),"' is not registered with any map"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 706, "", 1); end return null; end if (m_maps.num() == 1) begin void'(m_maps.first(get_default_map)); end foreach (m_maps[l]) begin uvm_reg_map map = l; uvm_reg_block blk = map.get_parent(); uvm_reg_map default_map = blk.get_default_map(); if (default_map != null) begin uvm_reg_map local_map = get_local_map(default_map); if (local_map != null) return local_map; end end void'(m_maps.first(get_default_map)); endfunction function string uvm_mem::get_access(uvm_reg_map map = null); get_access = m_access; if (get_n_maps() == 1) return get_access; map = get_local_map(map); if (map == null) return get_access; case (get_rights(map)) "RW": return get_access; "RO": case (get_access) "RW", "RO": get_access = "RO"; "WO": begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"WO memory '",get_full_name(), "' restricted to RO in map '",map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 754, "", 1); end default: begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(), "' has invalid access mode, '",get_access,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 757, "", 1); end endcase "WO": case (get_access) "RW", "WO": get_access = "WO"; "RO": begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"RO memory '",get_full_name(), "' restricted to WO in map '",map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 765, "", 1); end default: begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(), "' has invalid access mode, '",get_access,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 768, "", 1); end endcase default: begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Shared memory '",get_full_name(), "' is not shared in map '",map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 772, "", 1); end endcase endfunction: get_access function string uvm_mem::get_rights(uvm_reg_map map = null); uvm_reg_map_info info; if (m_maps.num() <= 1) begin return "RW"; end map = get_local_map(map); if (map == null) return "RW"; info = map.get_mem_map_info(this); return info.rights; endfunction: get_rights function uvm_reg_addr_t uvm_mem::get_offset(uvm_reg_addr_t offset = 0, uvm_reg_map map = null); uvm_reg_map_info map_info; uvm_reg_map orig_map = map; map = get_local_map(map); if (map == null) return -1; map_info = map.get_mem_map_info(this); if (map_info.unmapped) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Memory '",get_name(), "' is unmapped in map '", ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 817, "", 1); end return -1; end return map_info.offset; endfunction: get_offset function void uvm_mem::get_virtual_registers(ref uvm_vreg regs[$]); foreach (m_vregs[vreg]) regs.push_back(vreg); endfunction function void uvm_mem::get_virtual_fields(ref uvm_vreg_field fields[$]); foreach (m_vregs[l]) begin uvm_vreg vreg = l; vreg.get_fields(fields); end endfunction: get_virtual_fields function uvm_vreg_field uvm_mem::get_vfield_by_name(string name); uvm_vreg_field vfields[$]; get_virtual_fields(vfields); foreach (vfields[i]) if (vfields[i].get_name() == name) return vfields[i]; begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to find virtual field '",name, "' in memory '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 860, "", 1); end return null; endfunction: get_vfield_by_name function uvm_vreg uvm_mem::get_vreg_by_name(string name); foreach (m_vregs[l]) begin uvm_vreg vreg = l; if (vreg.get_name() == name) return vreg; end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to find virtual register '",name, "' in memory '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 877, "", 1); end return null; endfunction: get_vreg_by_name function uvm_vreg uvm_mem::get_vreg_by_offset(uvm_reg_addr_t offset, uvm_reg_map map = null); begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "uvm_mem::get_vreg_by_offset() not yet implemented", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 887, "", 1); end return null; endfunction: get_vreg_by_offset function int uvm_mem::get_addresses(uvm_reg_addr_t offset = 0, uvm_reg_map map=null, ref uvm_reg_addr_t addr[]); uvm_reg_map_info map_info; uvm_reg_map system_map; uvm_reg_map orig_map = map; map = get_local_map(map); if (map == null) return 0; map_info = map.get_mem_map_info(this); if (map_info.unmapped) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Memory '",get_name(), "' is unmapped in map '", ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 913, "", 1); end return 0; end addr = map_info.addr; foreach (addr[i]) addr[i] = addr[i] + map_info.mem_range.stride * offset; return map.get_n_bytes(); endfunction function uvm_reg_addr_t uvm_mem::get_address(uvm_reg_addr_t offset = 0, uvm_reg_map map = null); uvm_reg_addr_t addr[]; void'(get_addresses(offset, map, addr)); return addr[0]; endfunction function longint unsigned uvm_mem::get_size(); return m_size; endfunction: get_size function int unsigned uvm_mem::get_n_bits(); return m_n_bits; endfunction: get_n_bits function int unsigned uvm_mem::get_max_size(); return m_max_size; endfunction: get_max_size function int unsigned uvm_mem::get_n_bytes(); return (m_n_bits - 1) / 8 + 1; endfunction: get_n_bytes function uvm_reg_cvr_t uvm_mem::build_coverage(uvm_reg_cvr_t models); build_coverage = UVM_NO_COVERAGE; void'(uvm_reg_cvr_rsrc_db::read_by_name({"uvm_reg::", get_full_name()}, "include_coverage", build_coverage, this)); return build_coverage & models; endfunction: build_coverage function void uvm_mem::add_coverage(uvm_reg_cvr_t models); m_has_cover |= models; endfunction: add_coverage function bit uvm_mem::has_coverage(uvm_reg_cvr_t models); return ((m_has_cover & models) == models); endfunction: has_coverage function uvm_reg_cvr_t uvm_mem::set_coverage(uvm_reg_cvr_t is_on); if (is_on == uvm_reg_cvr_t'(UVM_NO_COVERAGE)) begin m_cover_on = is_on; return m_cover_on; end m_cover_on = m_has_cover & is_on; return m_cover_on; endfunction: set_coverage function bit uvm_mem::get_coverage(uvm_reg_cvr_t is_on); if (has_coverage(is_on) == 0) return 0; return ((m_cover_on & is_on) == is_on); endfunction: get_coverage task uvm_mem::write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw = uvm_reg_item::type_id_create("mem_write",,get_full_name()); rw.element = this; rw.element_kind = UVM_MEM; rw.kind = UVM_WRITE; rw.offset = offset; rw.value[0] = value; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_write(rw); status = rw.status; endtask: write task uvm_mem::read(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw; rw = uvm_reg_item::type_id_create("mem_read",,get_full_name()); rw.element = this; rw.element_kind = UVM_MEM; rw.kind = UVM_READ; rw.value[0] = 0; rw.offset = offset; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_read(rw); status = rw.status; value = rw.value[0]; endtask: read task uvm_mem::burst_write(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw; rw = uvm_reg_item::type_id_create("mem_burst_write",,get_full_name()); rw.element = this; rw.element_kind = UVM_MEM; rw.kind = UVM_BURST_WRITE; rw.offset = offset; rw.value = value; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_write(rw); status = rw.status; endtask: burst_write task uvm_mem::burst_read(output uvm_status_e status, input uvm_reg_addr_t offset, ref uvm_reg_data_t value[], input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw; rw = uvm_reg_item::type_id_create("mem_burst_read",,get_full_name()); rw.element = this; rw.element_kind = UVM_MEM; rw.kind = UVM_BURST_READ; rw.offset = offset; rw.value = value; rw.path = path; rw.map = map; rw.parent = parent; rw.prior = prior; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; do_read(rw); status = rw.status; value = rw.value; endtask: burst_read task uvm_mem::do_write(uvm_reg_item rw); uvm_mem_cb_iter cbs = new(this); uvm_reg_map_info map_info; m_fname = rw.fname; m_lineno = rw.lineno; if (!Xcheck_accessX(rw, map_info)) return; m_write_in_progress = 1'b1; rw.status = UVM_IS_OK; pre_write(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) cb.pre_write(rw); if (rw.status != UVM_IS_OK) begin m_write_in_progress = 1'b0; return; end rw.status = UVM_NOT_OK; if (rw.path == UVM_FRONTDOOR) begin uvm_reg_map system_map = rw.local_map.get_root_map(); if (map_info.frontdoor != null) begin uvm_reg_frontdoor fd = map_info.frontdoor; fd.rw_info = rw; if (fd.sequencer == null) fd.sequencer = system_map.get_sequencer(); fd.start(fd.sequencer, rw.parent); end else begin rw.local_map.do_write(rw); end if (rw.status != UVM_NOT_OK) for (uvm_reg_addr_t idx = rw.offset; idx <= rw.offset + rw.value.size(); idx++) begin XsampleX(map_info.mem_range.stride * idx, 0, rw.map); m_parent.XsampleX(map_info.offset + (map_info.mem_range.stride * idx), 0, rw.map); end end else begin if (get_access(rw.map) inside {"RW", "WO"}) begin uvm_reg_backdoor bkdr = get_backdoor(); if (bkdr != null) bkdr.write(rw); else backdoor_write(rw); end else rw.status = UVM_NOT_OK; end post_write(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) cb.post_write(rw); if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin string path_s,value_s,pre_s,range_s; if (rw.path == UVM_FRONTDOOR) path_s = (map_info.frontdoor != null) ? "user frontdoor" : {"map ",rw.map.get_full_name()}; else path_s = (get_backdoor() != null) ? "user backdoor" : "DPI backdoor"; if (rw.value.size() > 1) begin value_s = "='{"; pre_s = "Burst "; foreach (rw.value[i]) value_s = {value_s,$sformatf("%0h,",rw.value[i])}; value_s[value_s.len()-1]="}"; range_s = $sformatf("[%0d:%0d]",rw.offset,rw.offset+rw.value.size()); end else begin value_s = $sformatf("=%0h",rw.value[0]); range_s = $sformatf("[%0d]",rw.offset); end begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", {pre_s,"Wrote memory via ",path_s,": ", get_full_name(),range_s,value_s}, UVM_HIGH, "t/uvm/src/reg/uvm_mem.svh", 1281, "", 1); end end m_write_in_progress = 1'b0; endtask: do_write task uvm_mem::do_read(uvm_reg_item rw); uvm_mem_cb_iter cbs = new(this); uvm_reg_map_info map_info; m_fname = rw.fname; m_lineno = rw.lineno; if (!Xcheck_accessX(rw, map_info)) return; m_read_in_progress = 1'b1; rw.status = UVM_IS_OK; pre_read(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) cb.pre_read(rw); if (rw.status != UVM_IS_OK) begin m_read_in_progress = 1'b0; return; end rw.status = UVM_NOT_OK; if (rw.path == UVM_FRONTDOOR) begin uvm_reg_map system_map = rw.local_map.get_root_map(); if (map_info.frontdoor != null) begin uvm_reg_frontdoor fd = map_info.frontdoor; fd.rw_info = rw; if (fd.sequencer == null) fd.sequencer = system_map.get_sequencer(); fd.start(fd.sequencer, rw.parent); end else begin rw.local_map.do_read(rw); end if (rw.status != UVM_NOT_OK) for (uvm_reg_addr_t idx = rw.offset; idx <= rw.offset + rw.value.size(); idx++) begin XsampleX(map_info.mem_range.stride * idx, 1, rw.map); m_parent.XsampleX(map_info.offset + (map_info.mem_range.stride * idx), 1, rw.map); end end else begin if (get_access(rw.map) inside {"RW", "RO"}) begin uvm_reg_backdoor bkdr = get_backdoor(); if (bkdr != null) bkdr.read(rw); else backdoor_read(rw); end else rw.status = UVM_NOT_OK; end post_read(rw); for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next()) cb.post_read(rw); if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin string path_s,value_s,pre_s,range_s; if (rw.path == UVM_FRONTDOOR) path_s = (map_info.frontdoor != null) ? "user frontdoor" : {"map ",rw.map.get_full_name()}; else path_s = (get_backdoor() != null) ? "user backdoor" : "DPI backdoor"; if (rw.value.size() > 1) begin value_s = "='{"; pre_s = "Burst "; foreach (rw.value[i]) value_s = {value_s,$sformatf("%0h,",rw.value[i])}; value_s[value_s.len()-1]="}"; range_s = $sformatf("[%0d:%0d]",rw.offset,(rw.offset+rw.value.size())); end else begin value_s = $sformatf("=%0h",rw.value[0]); range_s = $sformatf("[%0d]",rw.offset); end begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", {pre_s,"Read memory via ",path_s,": ", get_full_name(),range_s,value_s}, UVM_HIGH, "t/uvm/src/reg/uvm_mem.svh", 1389, "", 1); end end m_read_in_progress = 1'b0; endtask: do_read function bit uvm_mem::Xcheck_accessX(input uvm_reg_item rw, output uvm_reg_map_info map_info); if (rw.offset >= m_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) uvm_report_error (get_type_name(), $sformatf("Offset 'h%0h exceeds size of memory, 'h%0h", rw.offset, m_size), UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1405, "", 1); end rw.status = UVM_NOT_OK; return 0; end if (rw.path == UVM_DEFAULT_DOOR) rw.path = m_parent.get_default_door(); if (rw.path == UVM_BACKDOOR) begin if (get_backdoor() == null && !has_hdl_path()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"No backdoor access available for memory '",get_full_name(), "' . Using frontdoor instead."}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1417, "", 1); end rw.path = UVM_FRONTDOOR; end else if (rw.map == null) begin if (get_default_map() != null) rw.map = get_default_map(); else rw.map = uvm_reg_map::backdoor(); end end if (rw.path != UVM_BACKDOOR) begin rw.local_map = get_local_map(rw.map); if (rw.local_map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name())) uvm_report_error (get_type_name(), {"No transactor available to physically access memory from map '", rw.map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1436, "", 1); end rw.status = UVM_NOT_OK; return 0; end map_info = rw.local_map.get_mem_map_info(this); if (map_info.frontdoor == null) begin if (map_info.unmapped) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(), "' unmapped in map '", rw.map.get_full_name(), "' and does not have a user-defined frontdoor"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1448, "", 1); end rw.status = UVM_NOT_OK; return 0; end if ((rw.value.size() > 1)) begin if (get_n_bits() > rw.local_map.get_n_bytes()*8) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot burst a %0d-bit memory through a narrower data path (%0d bytes)", get_n_bits(), rw.local_map.get_n_bytes()*8), UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1457, "", 1); end rw.status = UVM_NOT_OK; return 0; end if (rw.offset + rw.value.size() > m_size) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Burst of size 'd%0d starting at offset 'd%0d exceeds size of memory, 'd%0d", rw.value.size(), rw.offset, m_size), UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1464, "", 1); end return 0; end end end if (rw.map == null) rw.map = rw.local_map; end return 1; endfunction task uvm_mem::poke(output uvm_status_e status, input uvm_reg_addr_t offset, input uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_item rw; uvm_reg_backdoor bkdr = get_backdoor(); m_fname = fname; m_lineno = lineno; if (bkdr == null && !has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"No backdoor access available in memory '", get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1500, "", 1); end status = UVM_NOT_OK; return; end rw = uvm_reg_item::type_id_create("mem_poke_item",,get_full_name()); rw.element = this; rw.path = UVM_BACKDOOR; rw.element_kind = UVM_MEM; rw.kind = UVM_WRITE; rw.offset = offset; rw.value[0] = value & ((1 << m_n_bits)-1); rw.bd_kind = kind; rw.parent = parent; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; if (bkdr != null) bkdr.write(rw); else backdoor_write(rw); status = rw.status; begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Poked memory '%s[%0d]' with value 'h%h", get_full_name(), offset, value), UVM_HIGH, "t/uvm/src/reg/uvm_mem.svh", 1531, "", 1); end endtask: poke task uvm_mem::peek(output uvm_status_e status, input uvm_reg_addr_t offset, output uvm_reg_data_t value, input string kind = "", input uvm_sequence_base parent = null, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg_backdoor bkdr = get_backdoor(); uvm_reg_item rw; m_fname = fname; m_lineno = lineno; if (bkdr == null && !has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"No backdoor access available in memory '", get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1554, "", 1); end status = UVM_NOT_OK; return; end rw = uvm_reg_item::type_id_create("mem_peek_item",,get_full_name()); rw.element = this; rw.path = UVM_BACKDOOR; rw.element_kind = UVM_MEM; rw.kind = UVM_READ; rw.offset = offset; rw.bd_kind = kind; rw.parent = parent; rw.extension = extension; rw.fname = fname; rw.lineno = lineno; if (bkdr != null) bkdr.read(rw); else backdoor_read(rw); status = rw.status; value = rw.value[0]; begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("Peeked memory '%s[%0d]' has value 'h%h", get_full_name(), offset, value), UVM_HIGH, "t/uvm/src/reg/uvm_mem.svh", 1585, "", 1); end endtask: peek function void uvm_mem::set_frontdoor(uvm_reg_frontdoor ftdr, uvm_reg_map map = null, string fname = "", int lineno = 0); uvm_reg_map_info map_info; m_fname = fname; m_lineno = lineno; map = get_local_map(map); if (map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(), "' not found in map '", map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1607, "", 1); end return; end map_info = map.get_mem_map_info(this); map_info.frontdoor = ftdr; endfunction: set_frontdoor function uvm_reg_frontdoor uvm_mem::get_frontdoor(uvm_reg_map map = null); uvm_reg_map_info map_info; map = get_local_map(map); if (map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",get_full_name(), "' not found in map '", map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1626, "", 1); end return null; end map_info = map.get_mem_map_info(this); return map_info.frontdoor; endfunction: get_frontdoor function void uvm_mem::set_backdoor(uvm_reg_backdoor bkdr, string fname = "", int lineno = 0); m_fname = fname; m_lineno = lineno; m_backdoor = bkdr; endfunction: set_backdoor function uvm_reg_backdoor uvm_mem::get_backdoor(bit inherited = 1); if (m_backdoor == null && inherited) begin uvm_reg_block blk = get_parent(); uvm_reg_backdoor bkdr; while (blk != null) begin bkdr = blk.get_backdoor(); if (bkdr != null) begin m_backdoor = bkdr; break; end blk = blk.get_parent(); end end return m_backdoor; endfunction: get_backdoor function uvm_status_e uvm_mem::backdoor_read_func(uvm_reg_item rw); uvm_hdl_path_concat paths[$]; uvm_hdl_data_t val; bit ok=1; get_full_hdl_path(paths,rw.bd_kind); foreach (rw.value[mem_idx]) begin string idx; idx.itoa(rw.offset + mem_idx); foreach (paths[i]) begin uvm_hdl_path_concat hdl_concat = paths[i]; val = 0; foreach (hdl_concat.slices[j]) begin string hdl_path = {hdl_concat.slices[j].path, "[", idx, "]"}; begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", {"backdoor_read from ",hdl_path}, UVM_DEBUG, "t/uvm/src/reg/uvm_mem.svh", 1691, "", 1); end if (hdl_concat.slices[j].offset < 0) begin ok &= uvm_hdl_read(hdl_path, val); continue; end begin uvm_reg_data_t slice; int k = hdl_concat.slices[j].offset; ok &= uvm_hdl_read(hdl_path, slice); repeat (hdl_concat.slices[j].size) begin val[k++] = slice[0]; slice >>= 1; end end end val &= (1 << m_n_bits)-1; if (i == 0) rw.value[mem_idx] = val; if (val != rw.value[mem_idx]) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Backdoor read of register %s with multiple HDL copies: values are not the same: %0h at path '%s', and %0h at path '%s'. Returning first value.", get_full_name(), rw.value[mem_idx], uvm_hdl_concat2string(paths[0]), val, uvm_hdl_concat2string(paths[i])), UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1716, "", 1); end return UVM_NOT_OK; end end end rw.status = (ok) ? UVM_IS_OK : UVM_NOT_OK; return rw.status; endfunction task uvm_mem::backdoor_read(uvm_reg_item rw); rw.status = backdoor_read_func(rw); endtask task uvm_mem::backdoor_write(uvm_reg_item rw); uvm_hdl_path_concat paths[$]; bit ok=1; get_full_hdl_path(paths,rw.bd_kind); foreach (rw.value[mem_idx]) begin string idx; idx.itoa(rw.offset + mem_idx); foreach (paths[i]) begin uvm_hdl_path_concat hdl_concat = paths[i]; foreach (hdl_concat.slices[j]) begin begin if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("backdoor_write to %s ",hdl_concat.slices[j].path), UVM_DEBUG, "t/uvm/src/reg/uvm_mem.svh", 1751, "", 1); end if (hdl_concat.slices[j].offset < 0) begin ok &= uvm_hdl_deposit({hdl_concat.slices[j].path,"[", idx, "]"},rw.value[mem_idx]); continue; end begin uvm_reg_data_t slice; slice = rw.value[mem_idx] >> hdl_concat.slices[j].offset; slice &= (1 << hdl_concat.slices[j].size)-1; ok &= uvm_hdl_deposit({hdl_concat.slices[j].path, "[", idx, "]"}, slice); end end end end rw.status = (ok ? UVM_IS_OK : UVM_NOT_OK); endtask function void uvm_mem::clear_hdl_path(string kind = "RTL"); if (kind == "ALL") begin m_hdl_paths_pool = new("hdl_paths"); return; end if (kind == "") kind = m_parent.get_default_hdl_path(); if (!m_hdl_paths_pool.exists(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unknown HDL Abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1784, "", 1); end return; end m_hdl_paths_pool.delete(kind); endfunction function void uvm_mem::add_hdl_path(uvm_hdl_path_slice slices[], string kind = "RTL"); uvm_queue #(uvm_hdl_path_concat) paths = m_hdl_paths_pool.get(kind); uvm_hdl_path_concat concat = new(); concat.set(slices); paths.push_back(concat); endfunction function void uvm_mem::add_hdl_path_slice(string name, int offset, int size, bit first = 0, string kind = "RTL"); uvm_queue #(uvm_hdl_path_concat) paths=m_hdl_paths_pool.get(kind); uvm_hdl_path_concat concat; if (first || paths.size() == 0) begin concat = new(); paths.push_back(concat); end else concat = paths.get(paths.size()-1); concat.add_path(name, offset, size); endfunction function bit uvm_mem::has_hdl_path(string kind = ""); if (kind == "") kind = m_parent.get_default_hdl_path(); return m_hdl_paths_pool.exists(kind); endfunction function void uvm_mem::get_hdl_path(ref uvm_hdl_path_concat paths[$], input string kind = ""); uvm_queue #(uvm_hdl_path_concat) hdl_paths; if (kind == "") kind = m_parent.get_default_hdl_path(); if (!has_hdl_path(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1846, "", 1); end return; end hdl_paths = m_hdl_paths_pool.get(kind); for (int i=0; i= range.min && addrs[i] <= range.max) begin string a; a = $sformatf("%0h",addrs[i]); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' register '", rg.get_full_name(), "' overlaps with address range of memory '", top_map.m_mems_by_offset[range].get_full_name(),"': 'h",a}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 716, "", 1); end end end end info.addr = addrs; end end if (unmapped) begin info.offset = -1; info.unmapped = 1; end else begin info.offset = offset; info.unmapped = 0; end end endfunction function void uvm_reg_map::add_mem(uvm_mem mem, uvm_reg_addr_t offset, string rights = "RW", bit unmapped=0, uvm_reg_frontdoor frontdoor=null); if (m_mems_info.exists(mem)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",mem.get_name(), "' has already been added to map '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 746, "", 1); end return; end if (mem.get_parent() != get_parent()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Memory '",mem.get_full_name(),"' may not be added to address map '", get_full_name(),"' : they are not in the same block"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 753, "", 1); end return; end mem.add_map(this); begin uvm_reg_map_info info = new; info.offset = offset; info.rights = rights; info.unmapped = unmapped; info.frontdoor = frontdoor; m_mems_info[mem] = info; end endfunction: add_mem function void uvm_reg_map::m_set_mem_offset(uvm_mem mem, uvm_reg_addr_t offset, bit unmapped); if (!m_mems_info.exists(mem)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Cannot modify offset of memory '",mem.get_full_name(), "' in address map '",get_full_name(), "' : memory not mapped in that address map"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 781, "", 1); end return; end begin uvm_reg_map_info info = m_mems_info[mem]; uvm_reg_block blk = get_parent(); uvm_reg_map top_map = get_root_map(); uvm_reg_addr_t addrs[]; if (blk.is_locked()) begin if (!info.unmapped) begin foreach (top_map.m_mems_by_offset[range]) begin if (top_map.m_mems_by_offset[range] == mem) top_map.m_mems_by_offset.delete(range); end end if (!unmapped) begin uvm_reg_addr_t addrs[],addrs_max[]; uvm_reg_addr_t min, max, min2, max2; int unsigned stride; void'(get_physical_addresses(offset,0,mem.get_n_bytes(),addrs)); min = (addrs[0] < addrs[addrs.size()-1]) ? addrs[0] : addrs[addrs.size()-1]; min2 = addrs[0]; void'(get_physical_addresses(offset,(mem.get_size()-1), mem.get_n_bytes(),addrs_max)); max = (addrs_max[0] > addrs_max[addrs_max.size()-1]) ? addrs_max[0] : addrs_max[addrs_max.size()-1]; max2 = addrs_max[0]; stride = mem.get_n_bytes()/get_addr_unit_bytes(); foreach (top_map.m_regs_by_offset[reg_addr]) begin if (reg_addr >= min && reg_addr <= max) begin string a,b; a = $sformatf("[%0h:%0h]",min,max); b = $sformatf("%0h",reg_addr); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' memory '", mem.get_full_name(), "' with range ",a, " overlaps with address of existing register '", top_map.m_regs_by_offset[reg_addr].get_full_name(),"': 'h",b}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 829, "", 1); end end end foreach (top_map.m_mems_by_offset[range]) begin if (min <= range.max && max >= range.max || min <= range.min && max >= range.min || min >= range.min && max <= range.max) begin string a,b; a = $sformatf("[%0h:%0h]",min,max); b = $sformatf("[%0h:%0h]",range.min,range.max); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' memory '", mem.get_full_name(), "' with range ",a, " overlaps existing memory with range '", top_map.m_mems_by_offset[range].get_full_name(),"': ",b}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 843, "", 1); end end end begin uvm_reg_map_addr_range range = '{ min, max, stride}; top_map.m_mems_by_offset[range] = mem; info.addr = addrs; info.mem_range = range; end end end if (unmapped) begin info.offset = -1; info.unmapped = 1; end else begin info.offset = offset; info.unmapped = 0; end end endfunction function void uvm_reg_map::add_submap (uvm_reg_map child_map, uvm_reg_addr_t offset); uvm_reg_map parent_map; if (child_map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Attempting to add NULL map to map '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 877, "", 1); end return; end parent_map = child_map.get_parent_map(); if (parent_map != null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Map '", child_map.get_full_name(), "' is already a child of map '", parent_map.get_full_name(), "'. Cannot also be a child of map '", get_full_name(), "'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 890, "", 1); end return; end begin : n_bytes_match_check if (m_n_bytes > child_map.get_n_bytes(UVM_NO_HIER)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", $sformatf("Adding %0d-byte submap '%s' to %0d-byte parent map '%s'", child_map.get_n_bytes(UVM_NO_HIER), child_map.get_full_name(), m_n_bytes, get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 900, "", 1); end end end child_map.add_parent_map(this,offset); set_submap_offset(child_map, offset); endfunction: add_submap function void uvm_reg_map::reset(string kind = "SOFT"); uvm_reg regs[$]; get_registers(regs); foreach (regs[i]) begin regs[i].reset(kind); end endfunction function void uvm_reg_map::add_parent_map(uvm_reg_map parent_map, uvm_reg_addr_t offset); if (parent_map == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Attempting to add NULL parent map to map '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 930, "", 1); end return; end if (m_parent_map != null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Map \"%s\" already a submap of map \"%s\" at offset 'h%h", get_full_name(), m_parent_map.get_full_name(), m_parent_map.get_submap_offset(this)), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 938, "", 1); end return; end m_parent_map = parent_map; parent_map.m_submaps[this] = offset; endfunction: add_parent_map function void uvm_reg_map::set_sequencer(uvm_sequencer_base sequencer, uvm_reg_adapter adapter=null); if (sequencer == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG_NULL_SQR")) uvm_report_error ("REG_NULL_SQR", "Null reference specified for bus sequencer", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 954, "", 1); end return; end if (adapter == null) begin begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"REG_NO_ADAPT")) uvm_report_info ("REG_NO_ADAPT", {"Adapter not specified for map '",get_full_name(), "'. Accesses via this map will send abstract 'uvm_reg_item' items to sequencer '", sequencer.get_full_name(),"'"}, UVM_MEDIUM, "t/uvm/src/reg/uvm_reg_map.svh", 961, "", 1); end end m_sequencer = sequencer; m_adapter = adapter; endfunction function uvm_reg_block uvm_reg_map::get_parent(); return m_parent; endfunction function uvm_reg_map uvm_reg_map::get_parent_map(); return m_parent_map; endfunction function uvm_reg_map uvm_reg_map::get_root_map(); return (m_parent_map == null) ? this : m_parent_map.get_root_map(); endfunction: get_root_map function uvm_reg_addr_t uvm_reg_map::get_base_addr(uvm_hier_e hier=UVM_HIER); uvm_reg_map child = this; if (hier == UVM_NO_HIER || m_parent_map == null) return m_base_addr; get_base_addr = m_parent_map.get_submap_offset(this); get_base_addr += m_parent_map.get_base_addr(UVM_HIER); endfunction function int unsigned uvm_reg_map::get_n_bytes(uvm_hier_e hier=UVM_HIER); if (hier == UVM_NO_HIER) return m_n_bytes; return m_system_n_bytes; endfunction function int unsigned uvm_reg_map::get_addr_unit_bytes(); return (m_byte_addressing) ? 1 : m_n_bytes; endfunction function uvm_endianness_e uvm_reg_map::get_endian(uvm_hier_e hier=UVM_HIER); if (hier == UVM_NO_HIER || m_parent_map == null) return m_endian; return m_parent_map.get_endian(hier); endfunction function uvm_sequencer_base uvm_reg_map::get_sequencer(uvm_hier_e hier=UVM_HIER); if (hier == UVM_NO_HIER || m_parent_map == null) return m_sequencer; return m_parent_map.get_sequencer(hier); endfunction function uvm_reg_adapter uvm_reg_map::get_adapter(uvm_hier_e hier=UVM_HIER); if (hier == UVM_NO_HIER || m_parent_map == null) return m_adapter; return m_parent_map.get_adapter(hier); endfunction function void uvm_reg_map::get_submaps(ref uvm_reg_map maps[$], input uvm_hier_e hier=UVM_HIER); foreach (m_submaps[submap]) maps.push_back(submap); if (hier == UVM_HIER) foreach (m_submaps[submap_]) begin uvm_reg_map submap=submap_; submap.get_submaps(maps); end endfunction function void uvm_reg_map::get_registers(ref uvm_reg regs[$], input uvm_hier_e hier=UVM_HIER); foreach (m_regs_info[rg]) regs.push_back(rg); if (hier == UVM_HIER) foreach (m_submaps[submap_]) begin uvm_reg_map submap=submap_; submap.get_registers(regs); end endfunction function void uvm_reg_map::get_fields(ref uvm_reg_field fields[$], input uvm_hier_e hier=UVM_HIER); foreach (m_regs_info[rg_]) begin uvm_reg rg = rg_; rg.get_fields(fields); end if (hier == UVM_HIER) foreach (this.m_submaps[submap_]) begin uvm_reg_map submap=submap_; submap.get_fields(fields); end endfunction function void uvm_reg_map::get_memories(ref uvm_mem mems[$], input uvm_hier_e hier=UVM_HIER); foreach (m_mems_info[mem]) mems.push_back(mem); if (hier == UVM_HIER) foreach (m_submaps[submap_]) begin uvm_reg_map submap=submap_; submap.get_memories(mems); end endfunction function void uvm_reg_map::get_virtual_registers(ref uvm_vreg regs[$], input uvm_hier_e hier=UVM_HIER); uvm_mem mems[$]; get_memories(mems,hier); foreach (mems[i]) mems[i].get_virtual_registers(regs); endfunction function void uvm_reg_map::get_virtual_fields(ref uvm_vreg_field fields[$], input uvm_hier_e hier=UVM_HIER); uvm_vreg regs[$]; get_virtual_registers(regs,hier); foreach (regs[i]) regs[i].get_fields(fields); endfunction function string uvm_reg_map::get_full_name(); if (m_parent == null) return get_name(); else return {m_parent.get_full_name(), ".", get_name()}; endfunction function uvm_reg_map_info uvm_reg_map::get_mem_map_info(uvm_mem mem, bit error=1); if (!m_mems_info.exists(mem)) begin if (error) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG_NO_MAP")) uvm_report_error ("REG_NO_MAP", {"Memory '",mem.get_name(),"' not in map '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1157, "", 1); end return null; end return m_mems_info[mem]; endfunction function uvm_reg_map_info uvm_reg_map::get_reg_map_info(uvm_reg rg, bit error=1); uvm_reg_map_info result; if (!m_regs_info.exists(rg)) begin if (error) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG_NO_MAP")) uvm_report_error ("REG_NO_MAP", {"Register '",rg.get_name(),"' not in map '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1170, "", 1); end return null; end result = m_regs_info[rg]; if(!result.is_initialized) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"map '",get_name(),"' does not seem to be initialized correctly, check that the top register model is locked()"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1175, "", 1); end return result; endfunction function void uvm_reg_map::set_base_addr(uvm_reg_addr_t offset); if (m_parent_map != null) begin m_parent_map.set_submap_offset(this, offset); end else begin m_base_addr = offset; if (m_parent.is_locked()) begin uvm_reg_map top_map = get_root_map(); top_map.Xinit_address_mapX(); end end endfunction function int unsigned uvm_reg_map::get_size(); int unsigned max_addr; int unsigned addr; foreach (m_regs_info[rg_]) begin uvm_reg rg = rg_; addr = m_regs_info[rg].offset + ((rg.get_n_bytes()-1)/m_n_bytes); if (addr > max_addr) max_addr = addr; end foreach (m_mems_info[mem_]) begin uvm_mem mem = mem_; addr = m_mems_info[mem].offset + (mem.get_size() * (((mem.get_n_bytes()-1)/m_n_bytes)+1)) -1; if (addr > max_addr) max_addr = addr; end foreach (m_submaps[submap_]) begin uvm_reg_map submap=submap_; addr = m_submaps[submap] + submap.get_size(); if (addr > max_addr) max_addr = addr; end return max_addr + 1; endfunction function void uvm_reg_map::Xverify_map_configX(); bit error; uvm_reg_map root_map = get_root_map(); if (root_map.get_adapter() == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Map '",root_map.get_full_name(), "' does not have an adapter registered"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1243, "", 1); end error++; end if (root_map.get_sequencer() == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Map '",root_map.get_full_name(), "' does not have a sequencer registered"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1248, "", 1); end error++; end if (error) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", {"Must register an adapter and sequencer ", "for each top-level map in RegModel model"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1253, "", 1); end return; end endfunction function int uvm_reg_map::get_physical_addresses_to_map( uvm_reg_addr_t base_addr, uvm_reg_addr_t mem_offset, int unsigned n_bytes, ref uvm_reg_addr_t addr[], input uvm_reg_map parent_map, ref int unsigned byte_offset, input uvm_mem mem=null ); int bus_width = get_n_bytes(UVM_NO_HIER); uvm_reg_map up_map; uvm_reg_addr_t local_addr[]; uvm_reg_addr_t lbase_addr; up_map = get_parent_map(); lbase_addr = up_map==null ? get_base_addr(UVM_NO_HIER): up_map.get_submap_offset(this); if(up_map!=parent_map) begin uvm_reg_addr_t lb; uvm_reg_addr_t laddr; begin if(mem_offset) begin base_addr+=mem_offset*mem.get_n_bytes()/get_addr_unit_bytes(); end laddr=lbase_addr + base_addr*get_addr_unit_bytes()/up_map.get_addr_unit_bytes(); lb = (base_addr*get_addr_unit_bytes()) % up_map.get_addr_unit_bytes(); byte_offset += lb; end return up_map.get_physical_addresses_to_map(laddr, 0, n_bytes+lb, addr,parent_map,byte_offset); end else begin uvm_reg_addr_t lbase_addr2; local_addr= new[ceil(n_bytes,bus_width)]; lbase_addr2 = base_addr; if(mem_offset) if(mem!=null && (mem.get_n_bytes() >= get_addr_unit_bytes())) begin lbase_addr2 = base_addr + mem_offset*mem.get_n_bytes()/get_addr_unit_bytes(); byte_offset += (mem_offset*mem.get_n_bytes() % get_addr_unit_bytes()); end else begin lbase_addr2 = base_addr + mem_offset; end case (get_endian(UVM_NO_HIER)) UVM_LITTLE_ENDIAN: begin foreach (local_addr[i]) begin local_addr[i] = lbase_addr2 + i*bus_width/get_addr_unit_bytes(); end end UVM_BIG_ENDIAN: begin foreach (local_addr[i]) begin local_addr[i] = lbase_addr2 + (local_addr.size()-1-i)*bus_width/get_addr_unit_bytes() ; end end UVM_LITTLE_FIFO: begin foreach (local_addr[i]) begin local_addr[i] = lbase_addr2; end end UVM_BIG_FIFO: begin foreach (local_addr[i]) begin local_addr[i] = lbase_addr2; end end default: begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/MAPNOENDIANESS")) uvm_report_error ("UVM/REG/MAPNOENDIANESS", {"Map has no specified endianness. ", $sformatf("Cannot access %0d bytes register via its %0d byte \"%s\" interface", n_bytes, bus_width, get_full_name())}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1347, "", 1); end end endcase addr = new [local_addr.size()] (local_addr); foreach(addr[idx]) addr[idx] += lbase_addr; end endfunction function int uvm_reg_map::get_physical_addresses(uvm_reg_addr_t base_addr, uvm_reg_addr_t mem_offset, int unsigned n_bytes, ref uvm_reg_addr_t addr[]); int unsigned skip; return get_physical_addresses_to_map(base_addr, mem_offset, n_bytes, addr,null,skip); endfunction function void uvm_reg_map::set_submap_offset(uvm_reg_map submap, uvm_reg_addr_t offset); if (submap == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG/NULL")) uvm_report_error ("REG/NULL", "set_submap_offset: submap handle is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1385, "", 1); end return; end m_submaps[submap] = offset; if (m_parent.is_locked()) begin uvm_reg_map root_map = get_root_map(); root_map.Xinit_address_mapX(); end endfunction function uvm_reg_addr_t uvm_reg_map::get_submap_offset(uvm_reg_map submap); if (submap == null) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"REG/NULL")) uvm_report_error ("REG/NULL", "set_submap_offset: submap handle is null", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1400, "", 1); end return -1; end if (!m_submaps.exists(submap)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Map '",submap.get_full_name(), "' is not a submap of '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1405, "", 1); end return -1; end return m_submaps[submap]; endfunction function uvm_reg uvm_reg_map::get_reg_by_offset(uvm_reg_addr_t offset, bit read = 1); if (!m_parent.is_locked()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot get register by offset: Block %s is not locked.", m_parent.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1417, "", 1); end return null; end if (!read && m_regs_by_offset_wo.exists(offset)) return m_regs_by_offset_wo[offset]; if (m_regs_by_offset.exists(offset)) return m_regs_by_offset[offset]; return null; endfunction function uvm_mem uvm_reg_map::get_mem_by_offset(uvm_reg_addr_t offset); if (!m_parent.is_locked()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Cannot memory register by offset: Block %s is not locked.", m_parent.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1435, "", 1); end return null; end foreach (m_mems_by_offset[range]) begin if (range.min <= offset && offset <= range.max) begin return m_mems_by_offset[range]; end end return null; endfunction function void uvm_reg_map::Xinit_address_mapX(); int unsigned bus_width; uvm_reg_map top_map = get_root_map(); if (this == top_map) begin top_map.m_regs_by_offset.delete(); top_map.m_regs_by_offset_wo.delete(); top_map.m_mems_by_offset.delete(); end foreach (m_submaps[l]) begin uvm_reg_map map=l; map.Xinit_address_mapX(); end foreach (m_regs_info[rg_]) begin uvm_reg rg = rg_; m_regs_info[rg].is_initialized=1; if (!m_regs_info[rg].unmapped) begin string rg_acc = rg.Xget_fields_accessX(this); uvm_reg_addr_t addrs[]; bus_width = get_physical_addresses(m_regs_info[rg].offset,0,rg.get_n_bytes(),addrs); foreach (addrs[i]) begin uvm_reg_addr_t addr = addrs[i]; if (top_map.m_regs_by_offset.exists(addr) && (top_map.m_regs_by_offset[addr] != rg)) begin uvm_reg rg2 = top_map.m_regs_by_offset[addr]; string rg2_acc = rg2.Xget_fields_accessX(this); if (rg_acc == "RO" && rg2_acc == "WO") begin top_map.m_regs_by_offset[addr] = rg; uvm_reg_read_only_cbs::add(rg); top_map.m_regs_by_offset_wo[addr] = rg2; uvm_reg_write_only_cbs::add(rg2); end else if (rg_acc == "WO" && rg2_acc == "RO") begin top_map.m_regs_by_offset_wo[addr] = rg; uvm_reg_write_only_cbs::add(rg); uvm_reg_read_only_cbs::add(rg2); end else begin string a; a = $sformatf("%0h",addr); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' register '", rg.get_full_name(), "' maps to same address as register '", top_map.m_regs_by_offset[addr].get_full_name(),"': 'h",a}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1503, "", 1); end end end else top_map.m_regs_by_offset[addr] = rg; foreach (top_map.m_mems_by_offset[range]) begin if (addr >= range.min && addr <= range.max) begin string a,b; a = $sformatf("%0h",addr); b = $sformatf("[%0h:%0h]",range.min,range.max); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' register '", rg.get_full_name(), "' with address ",a, "maps to same address as memory '", top_map.m_mems_by_offset[range].get_full_name(),"': ",b}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1517, "", 1); end end end end m_regs_info[rg].addr = addrs; end end foreach (m_mems_info[mem_]) begin uvm_mem mem = mem_; if (!m_mems_info[mem].unmapped) begin uvm_reg_addr_t addrs[],addrs_max[]; uvm_reg_addr_t min, max, min2, max2; int unsigned stride; int unsigned bo; bus_width = get_physical_addresses_to_map(m_mems_info[mem].offset,0,mem.get_n_bytes(),addrs,null,bo,mem); min = (addrs[0] < addrs[addrs.size()-1]) ? addrs[0] : addrs[addrs.size()-1]; void'(get_physical_addresses_to_map(m_mems_info[mem].offset,(mem.get_size()-1),mem.get_n_bytes(),addrs_max,null,bo,mem)); max = (addrs_max[0] > addrs_max[addrs_max.size()-1]) ? addrs_max[0] : addrs_max[addrs_max.size()-1]; stride = mem.get_n_bytes()/get_addr_unit_bytes(); if(mem.get_n_bytes() get_addr_unit_bytes()) if(mem.get_n_bytes() % get_addr_unit_bytes()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REG/ADDR")) uvm_report_warning ("UVM/REG/ADDR", $sformatf("memory %s is not matching the word width of the enclosing map %s \ (one memory word not fitting into k map addresses)", mem.get_full_name(),get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1571, "", 1); end end if(mem.get_n_bytes() < get_addr_unit_bytes()) if(get_addr_unit_bytes() % mem.get_n_bytes()) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REG/ADDR")) uvm_report_warning ("UVM/REG/ADDR", $sformatf("the memory %s is not matching the word width of the enclosing map %s \ (one map address doesnt cover k memory words)", mem.get_full_name(),get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1578, "", 1); end if(mem.get_n_bits() % 8) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REG/ADDR")) uvm_report_warning ("UVM/REG/ADDR", $sformatf("this implementation of UVM requires memory words to be k*8 bits (mem %s \ has %0d bit words)",mem.get_full_name(),mem.get_n_bits()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1582, "", 1); end foreach (top_map.m_regs_by_offset[reg_addr]) begin if (reg_addr >= min && reg_addr <= max) begin string a; a = $sformatf("%0h",reg_addr); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' memory '", mem.get_full_name(), "' maps to same address as register '", top_map.m_regs_by_offset[reg_addr].get_full_name(),"': 'h",a}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1590, "", 1); end end end foreach (top_map.m_mems_by_offset[range]) begin if (min <= range.max && max >= range.max || min <= range.min && max >= range.min || min >= range.min && max <= range.max) if(top_map.m_mems_by_offset[range]!=mem) begin string a; a = $sformatf("[%0h:%0h]",min,max); begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"In map '",get_full_name(),"' memory '", mem.get_full_name(), "' overlaps with address range of memory '", top_map.m_mems_by_offset[range].get_full_name(),"': 'h",a}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1604, "", 1); end end end begin uvm_reg_map_addr_range range = '{ min, max, stride}; top_map.m_mems_by_offset[ range ] = mem; m_mems_info[mem].addr = addrs; m_mems_info[mem].mem_range = range; end end end if (bus_width == 0) bus_width = m_n_bytes; m_system_n_bytes = bus_width; endfunction function void uvm_reg_map::Xget_bus_infoX(uvm_reg_item rw, output uvm_reg_map_info map_info, output int size, output int lsb, output int addr_skip); if (rw.element_kind == UVM_MEM) begin uvm_mem mem; if(rw.element == null || !$cast(mem,rw.element)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CAST")) uvm_report_fatal ("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_MEM, ", "but 'element' does not point to a memory: ",rw.get_name()}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1639, "", 1); end map_info = get_mem_map_info(mem); size = mem.get_n_bits(); end else if (rw.element_kind == UVM_REG) begin uvm_reg rg; if(rw.element == null || !$cast(rg,rw.element)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CAST")) uvm_report_fatal ("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_REG, ", "but 'element' does not point to a register: ",rw.get_name()}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1647, "", 1); end map_info = get_reg_map_info(rg); size = rg.get_n_bits(); end else if (rw.element_kind == UVM_FIELD) begin uvm_reg_field field; if(rw.element == null || !$cast(field,rw.element)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CAST")) uvm_report_fatal ("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_FIELD, ", "but 'element' does not point to a field: ",rw.get_name()}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1655, "", 1); end map_info = get_reg_map_info(field.get_parent()); size = field.get_n_bits(); lsb = field.get_lsb_pos(); addr_skip = lsb/(get_n_bytes()*8); end endfunction task uvm_reg_map::do_write(uvm_reg_item rw); uvm_sequence_base tmp_parent_seq; uvm_reg_map system_map = get_root_map(); uvm_reg_adapter adapter = system_map.get_adapter(); uvm_sequencer_base sequencer = system_map.get_sequencer(); uvm_reg_seq_base parent_proxy; if (adapter != null && adapter.parent_sequence != null) begin uvm_object o; uvm_sequence_base seq; o = adapter.parent_sequence.clone(); if (o == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CLONE")) uvm_report_fatal ("REG/CLONE", {"failed to clone adapter's parent sequence: '", adapter.parent_sequence.get_full_name(), "' (of type '", adapter.parent_sequence.get_type_name(), "')"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1686, "", 1); end if (!$cast(seq, o)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CAST")) uvm_report_fatal ("REG/CAST", {"failed to cast: '", o.get_full_name(), "' (of type '", o.get_type_name(), "') to uvm_sequence_base!"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1693, "", 1); end seq.set_parent_sequence(rw.parent); rw.parent = seq; tmp_parent_seq = seq; end if (rw.parent == null) begin parent_proxy = new("default_parent_seq"); rw.parent = parent_proxy; tmp_parent_seq = rw.parent; end if (adapter == null) begin uvm_event#(uvm_object) end_event ; uvm_event_pool ep; ep = rw.get_event_pool(); end_event = ep.get("end") ; rw.set_sequencer(sequencer); rw.parent.start_item(rw,rw.prior); rw.parent.finish_item(rw); end_event.wait_on(); end else begin do_bus_write(rw, sequencer, adapter); end if (tmp_parent_seq != null) sequencer.m_sequence_exiting(tmp_parent_seq); endtask task uvm_reg_map::do_read(uvm_reg_item rw); uvm_sequence_base tmp_parent_seq; uvm_reg_map system_map = get_root_map(); uvm_reg_adapter adapter = system_map.get_adapter(); uvm_sequencer_base sequencer = system_map.get_sequencer(); uvm_reg_seq_base parent_proxy; if (adapter != null && adapter.parent_sequence != null) begin uvm_object o; uvm_sequence_base seq; o = adapter.parent_sequence.clone(); if (o == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CLONE")) uvm_report_fatal ("REG/CLONE", {"failed to clone adapter's parent sequence: '", adapter.parent_sequence.get_full_name(), "' (of type '", adapter.parent_sequence.get_type_name(), "')"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1745, "", 1); end if (!$cast(seq, o)) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"REG/CAST")) uvm_report_fatal ("REG/CAST", {"failed to cast: '", o.get_full_name(), "' (of type '", o.get_type_name(), "') to uvm_sequence_base!"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1752, "", 1); end seq.set_parent_sequence(rw.parent); rw.parent = seq; tmp_parent_seq = seq; end if (rw.parent == null) begin parent_proxy = new("default_parent_seq"); rw.parent = parent_proxy; tmp_parent_seq = rw.parent; end if (adapter == null) begin uvm_event#(uvm_object) end_event ; uvm_event_pool ep; ep = rw.get_event_pool(); end_event = ep.get("end") ; rw.set_sequencer(sequencer); rw.parent.start_item(rw,rw.prior); rw.parent.finish_item(rw); end_event.wait_on(); end else begin do_bus_read(rw, sequencer, adapter); end if (tmp_parent_seq != null) sequencer.m_sequence_exiting(tmp_parent_seq); endtask task uvm_reg_map::do_bus_write (uvm_reg_item rw, uvm_sequencer_base sequencer, uvm_reg_adapter adapter); do_bus_access(rw, sequencer, adapter); endtask task uvm_reg_map::perform_accesses(ref uvm_reg_bus_op accesses[$], input uvm_reg_item rw, input uvm_reg_adapter adapter, input uvm_sequencer_base sequencer); string op; uvm_reg_data_logic_t data; uvm_endianness_e endian; op=(rw.kind inside {UVM_READ,UVM_BURST_READ}) ? "Read" : "Wrote"; endian=get_endian(UVM_NO_HIER); if(policy!=null) policy.order(accesses); foreach(accesses[i]) begin uvm_reg_bus_op rw_access=accesses[i]; uvm_sequence_item bus_req; if ((rw_access.kind == UVM_WRITE) && (endian == UVM_BIG_ENDIAN)) begin { >> { rw_access.data }} = { << byte { rw_access.data}}; end adapter.m_set_item(rw); bus_req = adapter.reg2bus(rw_access); adapter.m_set_item(null); if (bus_req == null) begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegMem")) uvm_report_fatal ("RegMem", {"adapter [",adapter.get_name(),"] didnt return a bus transaction"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1823, "", 1); end bus_req.set_sequencer(sequencer); rw.parent.start_item(bus_req,rw.prior); if (rw.parent != null && i == 0) rw.parent.mid_do(rw); rw.parent.finish_item(bus_req); begin uvm_event#(uvm_object) end_event ; uvm_event_pool ep; ep = bus_req.get_event_pool(); end_event = ep.get("end") ; end_event.wait_on(); end if (adapter.provides_responses) begin uvm_sequence_item bus_rsp; uvm_access_e op; rw.parent.get_base_response(bus_rsp,bus_req.get_transaction_id()); adapter.bus2reg(bus_rsp,rw_access); end else begin adapter.bus2reg(bus_req,rw_access); end if ((rw_access.kind == UVM_READ) && (endian == UVM_BIG_ENDIAN)) begin { >> { rw_access.data }} = { << byte { rw_access.data}}; end rw.status = rw_access.status; begin data = rw_access.data & ((1<>bit_shift) & 'hff; p[idx]=n; end if(extra_byte) p.push_back(ac); end accesses.delete(); foreach(adr[i]) begin uvm_reg_bus_op rw_access; uvm_reg_data_t data; for(int i0=0;i0=0;i--) begin if(rw_access.byte_en[i]==0) rw_access.n_bits-=8; else break; end accesses.push_back(rw_access); end perform_accesses(accesses, rw, adapter, sequencer); if(rw.kind inside {UVM_READ,UVM_BURST_READ}) begin p.delete(); foreach(accesses[i0]) for(int i1=0;i1 max_size) max_size = uvm_reg_field::get_max_size(); if (uvm_mem::get_max_size() > max_size) max_size = uvm_mem::get_max_size(); if (max_size > 64) begin begin if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel")) uvm_report_fatal ("RegModel", $sformatf("Register model requires that UVM_REG_DATA_WIDTH be defined as %0d or greater. Currently defined as %0d", max_size, 64), UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1153, "", 1); end end Xinit_address_mapsX(); if(m_root_names[get_name()]>1) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/DUPLROOT")) uvm_report_error ("UVM/REG/DUPLROOT", $sformatf("There are %0d root register models named \"%s\". The names of the root register models have to be unique", m_root_names[get_name()], get_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1162, "", 1); end -> m_uvm_lock_model_complete; end endfunction function string uvm_reg_block::get_full_name(); if (parent == null) return get_name(); return {parent.get_full_name(), ".", get_name()}; endfunction: get_full_name function void uvm_reg_block::get_fields(ref uvm_reg_field fields[$], input uvm_hier_e hier=UVM_HIER); foreach (regs[rg_]) begin 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 function void uvm_reg_block::get_virtual_fields(ref uvm_vreg_field fields[$], input uvm_hier_e hier=UVM_HIER); foreach (vregs[vreg_]) begin uvm_vreg vreg = vreg_; vreg.get_fields(fields); end if (hier == UVM_HIER) foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.get_virtual_fields(fields); end endfunction: get_virtual_fields function void uvm_reg_block::get_registers(ref uvm_reg regs[$], input uvm_hier_e hier=UVM_HIER); foreach (this.regs[rg]) regs.push_back(rg); if (hier == UVM_HIER) foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.get_registers(regs); end endfunction: get_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_]) begin uvm_reg_block blk = blk_; blk.get_virtual_registers(regs); end endfunction: get_virtual_registers function void uvm_reg_block::get_memories(ref uvm_mem mems[$], input uvm_hier_e hier=UVM_HIER); foreach (this.mems[mem_]) begin uvm_mem mem = mem_; mems.push_back(mem); end if (hier == UVM_HIER) foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.get_memories(mems); end endfunction: get_memories function void uvm_reg_block::get_blocks(ref uvm_reg_block blks[$], input uvm_hier_e hier=UVM_HIER); foreach (this.blks[blk_]) begin uvm_reg_block blk = blk_; blks.push_back(blk); if (hier == UVM_HIER) blk.get_blocks(blks); end endfunction: get_blocks function void uvm_reg_block::get_root_blocks(ref uvm_reg_block blks[$]); foreach (m_roots[blk]) begin blks.push_back(blk); end endfunction function int uvm_reg_block::find_blocks(input string name, ref uvm_reg_block blks[$], input uvm_reg_block root = null, input uvm_object accessor = null); uvm_reg_block r[$]; uvm_reg_block b[$]; if (root != null) begin name = {root.get_full_name(), ".", name}; b='{root}; end else begin get_root_blocks(b); end foreach(b[idx]) begin r.push_back(b[idx]); b[idx].get_blocks(r); end blks.delete(); foreach(r[idx]) begin if ( uvm_is_match( name, r[idx].get_full_name() ) ) blks.push_back(r[idx]); end return blks.size(); endfunction function uvm_reg_block uvm_reg_block::find_block(input string name, input uvm_reg_block root = null, input uvm_object accessor = null); uvm_reg_block blks[$]; if (!find_blocks(name, blks, root, accessor)) return null; if (blks.size() > 1) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"MRTH1BLK")) uvm_report_warning ("MRTH1BLK", {"More than one block matched the name \"", name, "\"."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1341, "", 1); end end return blks[0]; endfunction function void uvm_reg_block::get_maps(ref uvm_reg_map maps[$]); foreach (this.maps[map]) maps.push_back(map); endfunction function uvm_reg_block uvm_reg_block::get_parent(); get_parent = this.parent; endfunction: get_parent function uvm_reg_block uvm_reg_block::get_block_by_name(string name); if (get_name() == name) return this; foreach (blks[blk_]) begin uvm_reg_block blk = blk_; if (blk.get_name() == name) return blk; end foreach (blks[blk_]) begin 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 begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate block '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1395, "", 1); end return null; endfunction: get_block_by_name function uvm_reg uvm_reg_block::get_reg_by_name(string name); foreach (regs[rg_]) begin uvm_reg rg = rg_; if (rg.get_name() == name) return rg; end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; uvm_reg subregs[$]; blk_.get_registers(subregs, UVM_HIER); foreach (subregs[j]) if (subregs[j].get_name() == name) return subregs[j]; end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate register '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1422, "", 1); end return null; endfunction: get_reg_by_name function uvm_vreg uvm_reg_block::get_vreg_by_name(string name); foreach (vregs[rg_]) begin uvm_vreg rg = rg_; if (rg.get_name() == name) return rg; end foreach (blks[blk_]) begin 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 begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate virtual register '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1449, "", 1); end return null; endfunction: get_vreg_by_name function uvm_mem uvm_reg_block::get_mem_by_name(string name); foreach (mems[mem_]) begin uvm_mem mem = mem_; if (mem.get_name() == name) return mem; end foreach (blks[blk_]) begin 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 begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate memory '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1476, "", 1); end return null; endfunction: get_mem_by_name function uvm_reg_field uvm_reg_block::get_field_by_name(string name); foreach (regs[rg_]) begin 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_]) begin uvm_reg_block blk = blk_; uvm_reg subregs[$]; blk_.get_registers(subregs, UVM_HIER); foreach (subregs[j]) begin uvm_reg_field fields[$]; subregs[j].get_fields(fields); foreach (fields[i]) if (fields[i].get_name() == name) return fields[i]; end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate field '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1511, "", 1); end return null; endfunction: get_field_by_name function uvm_vreg_field uvm_reg_block::get_vfield_by_name(string name); foreach (vregs[rg_]) begin 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_]) begin uvm_reg_block blk = blk_; uvm_vreg subvregs[$]; blk_.get_virtual_registers(subvregs, UVM_HIER); foreach (subvregs[j]) begin uvm_vreg_field fields[$]; subvregs[j].get_fields(fields); foreach (fields[i]) if (fields[i].get_name() == name) return fields[i]; end end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unable to locate virtual field '",name, "' in block '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1547, "", 1); end return null; endfunction: get_vfield_by_name function uvm_reg_cvr_t uvm_reg_block::set_coverage(uvm_reg_cvr_t is_on); this.cover_on = this.has_cover & is_on; foreach (regs[rg_]) begin uvm_reg rg = rg_; void'(rg.set_coverage(is_on)); end foreach (mems[mem_]) begin uvm_mem mem = mem_; void'(mem.set_coverage(is_on)); end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; void'(blk.set_coverage(is_on)); end return this.cover_on; endfunction: set_coverage function void uvm_reg_block::sample_values(); foreach (regs[rg_]) begin uvm_reg rg = rg_; rg.sample_values(); end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.sample_values(); end endfunction function void uvm_reg_block::XsampleX(uvm_reg_addr_t addr, bit is_read, uvm_reg_map map); sample(addr, is_read, map); if (parent != null) begin end endfunction function uvm_reg_cvr_t uvm_reg_block::build_coverage(uvm_reg_cvr_t models); build_coverage = UVM_NO_COVERAGE; void'(uvm_reg_cvr_rsrc_db::read_by_name({"uvm_reg::", get_full_name()}, "include_coverage", build_coverage, this)); return build_coverage & models; endfunction: build_coverage function void uvm_reg_block::add_coverage(uvm_reg_cvr_t models); this.has_cover |= models; endfunction: add_coverage function bit uvm_reg_block::has_coverage(uvm_reg_cvr_t models); return ((this.has_cover & models) == models); endfunction: has_coverage function bit uvm_reg_block::get_coverage(uvm_reg_cvr_t is_on = UVM_CVR_ALL); if (this.has_coverage(is_on) == 0) return 0; return ((this.cover_on & is_on) == is_on); endfunction: get_coverage function void uvm_reg_block::reset(string kind = "HARD"); foreach (regs[rg_]) begin uvm_reg rg = rg_; rg.reset(kind); end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.reset(kind); end endfunction function bit uvm_reg_block::needs_update(); needs_update = 0; foreach (regs[rg_]) begin uvm_reg rg = rg_; if (rg.needs_update()) return 1; end foreach (blks[blk_]) begin uvm_reg_block blk =blk_; if (blk.needs_update()) return 1; end endfunction: needs_update task uvm_reg_block::update(output uvm_status_e status, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); status = UVM_IS_OK; if (!needs_update()) begin begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("%s:%0d - RegModel block %s does not need updating", fname, lineno, this.get_name()), UVM_HIGH, "t/uvm/src/reg/uvm_reg_block.svh", 1694, "", 1); end return; end begin if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"RegModel")) uvm_report_info ("RegModel", $sformatf("%s:%0d - Updating model block %s with %s path", fname, lineno, this.get_name(), path.name ), UVM_HIGH, "t/uvm/src/reg/uvm_reg_block.svh", 1699, "", 1); end foreach (regs[rg_]) begin uvm_reg rg = rg_; if (rg.needs_update()) begin rg.update(status, path, null, parent, prior, extension); if (status != UVM_IS_OK && status != UVM_HAS_X) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", $sformatf("Register \"%s\" could not be updated", rg.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1707, "", 1); end return; end end end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.update(status,path,parent,prior,extension,fname,lineno); end endtask: update task uvm_reg_block::mirror(output uvm_status_e status, input uvm_check_e check = UVM_NO_CHECK, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_status_e final_status = UVM_IS_OK; foreach (regs[rg_]) begin uvm_reg rg = rg_; rg.mirror(status, check, path, null, parent, prior, extension, fname, lineno); if (status != UVM_IS_OK && status != UVM_HAS_X) begin final_status = status; end end foreach (blks[blk_]) begin uvm_reg_block blk = blk_; blk.mirror(status, check, path, parent, prior, extension, fname, lineno); if (status != UVM_IS_OK && status != UVM_HAS_X) begin final_status = status; end end endtask: mirror task uvm_reg_block::write_reg_by_name(output uvm_status_e status, input string name, input uvm_reg_data_t data, input uvm_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg rg; this.fname = fname; this.lineno = lineno; status = UVM_NOT_OK; rg = this.get_reg_by_name(name); if (rg != null) rg.write(status, data, path, map, parent, prior, extension); endtask: write_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_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_reg rg; this.fname = fname; this.lineno = lineno; status = UVM_NOT_OK; rg = this.get_reg_by_name(name); if (rg != null) rg.read(status, data, path, map, parent, prior, extension); endtask: read_reg_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_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem; this.fname = fname; this.lineno = lineno; status = UVM_NOT_OK; mem = get_mem_by_name(name); if (mem != null) mem.write(status, offset, data, path, map, parent, prior, extension); endtask: write_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_door_e path = UVM_DEFAULT_DOOR, input uvm_reg_map map = null, input uvm_sequence_base parent = null, input int prior = -1, input uvm_object extension = null, input string fname = "", input int lineno = 0); uvm_mem mem; this.fname = fname; this.lineno = lineno; status = UVM_NOT_OK; mem = get_mem_by_name(name); if (mem != null) mem.read(status, offset, data, path, map, parent, prior, extension); endtask: read_mem_by_name task uvm_reg_block::readmemh(string filename); endtask: readmemh task uvm_reg_block::writememh(string filename); endtask: writememh function uvm_reg_map uvm_reg_block::create_map(string name, uvm_reg_addr_t base_addr, int unsigned n_bytes, uvm_endianness_e endian, bit byte_addressing=1); uvm_reg_map map; map = uvm_reg_map::type_id_create(name,,this.get_full_name()); map.configure(this,base_addr,n_bytes,endian,byte_addressing); add_map(map); return map; endfunction function void uvm_reg_block::add_map(uvm_reg_map map); if (this.locked) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", "Cannot add map to locked model", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1894, "", 1); end return; end if (this.maps.exists(map)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Map '",map.get_name(), "' already exists in '",get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1900, "", 1); end return; end this.maps[map] = 1; if (maps.num() == 1) default_map = map; endfunction: add_map function uvm_reg_map uvm_reg_block::get_map_by_name(string name); uvm_reg_map maps[$]; this.get_maps(maps); foreach (maps[i]) if (maps[i].get_name() == name) return maps[i]; foreach (maps[i]) begin uvm_reg_map submaps[$]; maps[i].get_submaps(submaps, UVM_HIER); foreach (submaps[j]) if (submaps[j].get_name() == name) return submaps[j]; end begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Map with name '",name,"' does not exist in block"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1932, "", 1); end return null; endfunction function void uvm_reg_block::set_default_map(uvm_reg_map map); if (!maps.exists(map)) begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Map '",map.get_full_name(),"' does not exist in block"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1941, "", 1); end default_map = map; endfunction function uvm_reg_map uvm_reg_block::get_default_map(); return default_map; endfunction function uvm_door_e uvm_reg_block::get_default_door(); if (this.default_path != UVM_DEFAULT_DOOR) return this.default_path; if (this.parent != null) return this.parent.get_default_door(); return UVM_FRONTDOOR; endfunction function void uvm_reg_block::set_default_door(uvm_door_e door); this.default_path = door; endfunction function void uvm_reg_block::Xinit_address_mapsX(); foreach (maps[map_]) begin uvm_reg_map map = map_; map.Xinit_address_mapX(); end endfunction function void uvm_reg_block::set_backdoor(uvm_reg_backdoor bkdr, string fname = "", int lineno = 0); bkdr.fname = fname; bkdr.lineno = lineno; if (this.backdoor != null && this.backdoor.has_update_threads()) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", "Previous register backdoor still has update threads running. Backdoors with active mirroring should only be set before simulation starts.", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2004, "", 1); end end this.backdoor = bkdr; endfunction: set_backdoor function uvm_reg_backdoor uvm_reg_block::get_backdoor(bit inherited = 1); if (backdoor == null && inherited) begin uvm_reg_block blk = get_parent(); while (blk != null) begin uvm_reg_backdoor bkdr = blk.get_backdoor(); if (bkdr != null) return bkdr; blk = blk.get_parent(); end end return this.backdoor; endfunction: get_backdoor function void uvm_reg_block::clear_hdl_path(string kind = "RTL"); if (kind == "ALL") begin hdl_paths_pool = new("hdl_paths"); return; end if (kind == "") kind = get_default_hdl_path(); if (!hdl_paths_pool.exists(kind)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel")) uvm_report_warning ("RegModel", {"Unknown HDL Abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2040, "", 1); end return; end hdl_paths_pool.delete(kind); endfunction function void uvm_reg_block::add_hdl_path(string path, string kind = "RTL"); uvm_queue #(string) paths; paths = hdl_paths_pool.get(kind); paths.push_back(path); endfunction function bit uvm_reg_block::has_hdl_path(string kind = ""); if (kind == "") begin kind = get_default_hdl_path(); end return hdl_paths_pool.exists(kind); endfunction 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)) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel")) uvm_report_error ("RegModel", {"Block does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2081, "", 1); end return; end hdl_paths = hdl_paths_pool.get(kind); for (int i=0; i 0) begin mem.read(status, k-1, val, UVM_FRONTDOOR, maps[j], this); if (status != UVM_IS_OK) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_walk_seq")) uvm_report_error ("uvm_mem_walk_seq", $sformatf("Status was %s when reading \"%s[%0d]\" through map \"%s\".", status.name(), mem.get_full_name(), k, maps[j].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 143, "", 1); end end else begin exp = ~(k-1) & ((1'b1< 32) val = uvm_reg_data_t'(val << 32) | $random; if (mode == "RO") begin mem.peek(status, k, exp); if (status != UVM_IS_OK) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq")) uvm_report_error ("uvm_mem_access_seq", $sformatf("Status was %s when reading \"%s[%0d]\" through backdoor.", status.name(), mem.get_full_name(), k), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 124, "", 1); end end end else exp = val; mem.write(status, k, val, UVM_FRONTDOOR, maps[j], this); if (status != UVM_IS_OK) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq")) uvm_report_error ("uvm_mem_access_seq", $sformatf("Status was %s when writing \"%s[%0d]\" through map \"%s\".", status.name(), mem.get_full_name(), k, maps[j].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 132, "", 1); end end #1; val = 'x; mem.peek(status, k, val); if (status != UVM_IS_OK) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq")) uvm_report_error ("uvm_mem_access_seq", $sformatf("Status was %s when reading \"%s[%0d]\" through backdoor.", status.name(), mem.get_full_name(), k), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 140, "", 1); end end else begin if (val !== exp) begin begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq")) uvm_report_error ("uvm_mem_access_seq", $sformatf("Backdoor \"%s[%0d]\" read back as 'h%h instead of 'h%h.", mem.get_full_name(), k, val, exp), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 145, "", 1); end end end exp = ~exp & ((1'b1< local_size__) abstractions = abstractions[0:local_size__-1]; else while (abstractions.size() < local_size__) abstractions.push_back(abstractions[local_size__]); foreach (abstractions[i]) abstractions[i] = __local_packer__.unpack_string(); end UVM_RECORD: if (!((UVM_DEFAULT)&UVM_NORECORD)) begin begin int sz__; foreach (abstractions[i]) sz__ = i; if(sz__ == 0) begin if (__local_recorder__ != null && __local_recorder__.is_open()) begin if (__local_recorder__.use_record_attribute()) __local_recorder__.record_generic("abstractions", $sformatf("%p", 0)); else if (32 > 64) __local_recorder__.record_field("abstractions", 0, 32, UVM_DEC); else __local_recorder__.record_field_int("abstractions", 0, 32, UVM_DEC); end end else if(sz__ < 10) begin foreach(abstractions[i]) begin string nm__ = $sformatf("%s[%0d]", "abstractions", i); if (__local_recorder__ != null && __local_recorder__.is_open()) begin if (__local_recorder__.use_record_attribute()) __local_recorder__.record_generic(nm__, $sformatf("%p", abstractions[i])); else __local_recorder__.record_string(nm__,abstractions[i]); end end end else begin for(int i=0; i<5; ++i) begin string nm__ = $sformatf("%s[%0d]", "abstractions", i); if (__local_recorder__ != null && __local_recorder__.is_open()) begin if (__local_recorder__.use_record_attribute()) __local_recorder__.record_generic(nm__, $sformatf("%p", abstractions[i])); else __local_recorder__.record_string(nm__,abstractions[i]); end end for(int i=sz__-5; i __tmp_curr) __tmp_curr = __tmp_max - __tmp_end_elements; if (__tmp_curr < __tmp_begin_elements) __tmp_curr = __tmp_begin_elements; else __local_printer__.print_array_range(__tmp_begin_elements, __tmp_curr-1); while (__tmp_curr < __tmp_max) begin __local_printer__.print_string($sformatf("[%0d]", __tmp_curr), abstractions[__tmp_curr]); __tmp_curr++; end end end end __local_printer__.print_array_footer(__tmp_max); end end UVM_SET: if (!((UVM_DEFAULT)&UVM_NOSET)) begin if(local_rsrc_name__ == "abstractions") begin begin begin uvm_resource#(uvm_integral_t) __tmp_rsrc__; local_success__ = $cast(__tmp_rsrc__, local_rsrc__); if (local_success__) begin local_size__ = __tmp_rsrc__.read(this); end end if (!local_success__) begin uvm_resource#(uvm_bitstream_t) __tmp_rsrc__; local_success__ = $cast(__tmp_rsrc__, local_rsrc__); if (local_success__) begin local_size__ = __tmp_rsrc__.read(this); end end if (!local_success__) begin uvm_resource#(int) __tmp_rsrc__; local_success__ = $cast(__tmp_rsrc__, local_rsrc__); if (local_success__) begin local_size__ = __tmp_rsrc__.read(this); end end if (!local_success__) begin uvm_resource#(int unsigned) __tmp_rsrc__; local_success__ = $cast(__tmp_rsrc__, local_rsrc__); if (local_success__) begin local_size__ = __tmp_rsrc__.read(this); end end end if (local_success__) if (abstractions.size() > local_size__) abstractions = abstractions[0:local_size__-1]; else while (abstractions.size() < local_size__) abstractions.push_back(abstractions[local_size__]); end else begin string local_name__ = {"abstractions", "["}; if (local_rsrc_name__.len() && local_rsrc_name__[local_rsrc_name__.len()-1] == "]" && local_rsrc_name__.substr(0, local_name__.len()-1) == local_name__) begin string local_index_str__ = local_rsrc_name__.substr(local_name__.len(), local_rsrc_name__.len()-2); int local_index__; int local_code__ = $sscanf(local_index_str__, "%d", local_index__); if (local_code__ > 0) begin if (local_index__ < 0) begin begin if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/FIELDS/QDA_IDX")) uvm_report_warning ("UVM/FIELDS/QDA_IDX", $sformatf("Index '%0d' is not valid for field '%s.%s' of size '%0d'", local_index__, get_full_name(), "abstractions", abstractions.size() ), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 59, "", 1); end end else begin string tmp_string__; begin uvm_resource#(string) __tmp_rsrc__; local_success__ = $cast(__tmp_rsrc__, local_rsrc__); if (local_success__) begin tmp_string__ = __tmp_rsrc__.read(this); end end if (local_success__) begin if (local_index__ >= abstractions.size()) if (abstractions.size() > local_index__ + 1) abstractions = abstractions[0:local_index__ + 1-1]; else while (abstractions.size() < local_index__ + 1) abstractions.push_back(abstractions[local_index__ + 1]); abstractions[local_index__] = tmp_string__; end end end end end end endcase end endfunction : __m_uvm_execute_field_op function new(string name="uvm_reg_mem_hdl_paths_seq"); super.new(name); endfunction virtual task body(); if (model == null) begin uvm_report_error("uvm_reg_mem_hdl_paths_seq", "Register model handle is null"); return; end begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_mem_hdl_paths_seq")) uvm_report_info ("uvm_reg_mem_hdl_paths_seq", {"checking HDL paths for all registers/memories in ", model.get_full_name()}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 76, "", 1); end if (abstractions.size() == 0) do_block(model, ""); else begin foreach (abstractions[i]) do_block(model, abstractions[i]); end begin if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_mem_hdl_paths_seq")) uvm_report_info ("uvm_reg_mem_hdl_paths_seq", "HDL path validation completed ", UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 85, "", 1); end endtask: body virtual task reset_blk(uvm_reg_block blk); endtask protected virtual function void do_block(uvm_reg_block blk, string kind); uvm_reg regs[$]; uvm_mem mems[$]; begin if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"uvm_reg_mem_hdl_paths_seq")) uvm_report_info ("uvm_reg_mem_hdl_paths_seq", {"Validating HDL paths in ", blk.get_full_name(), " for ", (kind == "") ? "default" : kind, " design abstraction"}, UVM_MEDIUM, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 104, "", 1); end blk.get_registers(regs, UVM_NO_HIER); foreach (regs[i]) check_reg(regs[i], kind); blk.get_memories(mems, UVM_NO_HIER); foreach (mems[i]) check_mem(mems[i], kind); begin uvm_reg_block blks[$]; blk.get_blocks(blks); foreach (blks[i]) begin do_block(blks[i], kind); end end endfunction: do_block protected virtual function void check_reg(uvm_reg r, string kind); uvm_hdl_path_concat paths[$]; if(!r.has_hdl_path(kind)) return; r.get_full_hdl_path(paths, kind); if (paths.size() == 0) return; foreach(paths[p]) begin uvm_hdl_path_concat path=paths[p]; foreach (path.slices[j]) begin string p_ = path.slices[j].path; uvm_reg_data_t d; if (!uvm_hdl_read(p_,d)) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_hdl_paths_seq")) uvm_report_error ("uvm_reg_mem_hdl_paths_seq", $sformatf("HDL path \"%s\" for register \"%s\" is not readable", p_, r.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 145, "", 1); end if (!uvm_hdl_check_path(p_)) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_hdl_paths_seq")) uvm_report_error ("uvm_reg_mem_hdl_paths_seq", $sformatf("HDL path \"%s\" for register \"%s\" is not accessible", p_, r.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 149, "", 1); end end end endfunction protected virtual function void check_mem(uvm_mem m, string kind); uvm_hdl_path_concat paths[$]; if(!m.has_hdl_path(kind)) return; m.get_full_hdl_path(paths, kind); if (paths.size() == 0) return; foreach(paths[p]) begin uvm_hdl_path_concat path=paths[p]; foreach (path.slices[j]) begin string p_ = path.slices[j].path; if(!uvm_hdl_check_path(p_)) begin if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_hdl_paths_seq")) uvm_report_error ("uvm_reg_mem_hdl_paths_seq", $sformatf("HDL path \"%s\" for memory \"%s\" is not accessible", p_, m.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_hdl_paths_seq.svh", 174, "", 1); end end end endfunction endclass: uvm_reg_mem_hdl_paths_seq endpackage