mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 20:22:41 +00:00
34251 lines
1.3 MiB
34251 lines
1.3 MiB
// DESCRIPTION: Verilator: Concatenated UVM header for internal testing
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//------------------------------------------------------------------------------
|
|
// To recreate:
|
|
// Using verilator_ext_tests
|
|
// t/t_uvm_parse.py --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_MACRO_NUMFLAGS);
|
|
parameter uvm_field_flag_t UVM_FLAGS = UVM_MACRO_EXTRAS+1;
|
|
parameter uvm_field_flag_t UVM_CHECK_FIELDS = UVM_MACRO_EXTRAS+2;
|
|
parameter uvm_field_flag_t UVM_END_DATA_EXTRA = UVM_MACRO_EXTRAS+3;
|
|
parameter uvm_field_flag_t UVM_START_FUNCS = UVM_END_DATA_EXTRA+1;
|
|
parameter uvm_field_flag_t UVM_END_FUNCS = UVM_START_FUNCS+1;
|
|
string uvm_aa_string_key;
|
|
typedef enum bit [1:0]
|
|
{
|
|
UVM_INFO,
|
|
UVM_WARNING,
|
|
UVM_ERROR,
|
|
UVM_FATAL
|
|
} uvm_severity;
|
|
typedef int uvm_action;
|
|
typedef enum
|
|
{
|
|
UVM_NO_ACTION = 'b0000000,
|
|
UVM_DISPLAY = 'b0000001,
|
|
UVM_LOG = 'b0000010,
|
|
UVM_COUNT = 'b0000100,
|
|
UVM_EXIT = 'b0001000,
|
|
UVM_CALL_HOOK = 'b0010000,
|
|
UVM_STOP = 'b0100000,
|
|
UVM_RM_RECORD = 'b1000000
|
|
} uvm_action_type;
|
|
typedef enum
|
|
{
|
|
UVM_NONE = 0,
|
|
UVM_LOW = 100,
|
|
UVM_MEDIUM = 200,
|
|
UVM_HIGH = 300,
|
|
UVM_FULL = 400,
|
|
UVM_DEBUG = 500
|
|
} uvm_verbosity;
|
|
typedef enum
|
|
{
|
|
UVM_PORT ,
|
|
UVM_EXPORT ,
|
|
UVM_IMPLEMENTATION
|
|
} uvm_port_type_e;
|
|
typedef enum
|
|
{
|
|
UVM_SEQ_ARB_FIFO,
|
|
UVM_SEQ_ARB_WEIGHTED,
|
|
UVM_SEQ_ARB_RANDOM,
|
|
UVM_SEQ_ARB_STRICT_FIFO,
|
|
UVM_SEQ_ARB_STRICT_RANDOM,
|
|
UVM_SEQ_ARB_USER
|
|
} uvm_sequencer_arb_mode;
|
|
typedef uvm_sequencer_arb_mode UVM_SEQ_ARB_TYPE;
|
|
typedef enum
|
|
{
|
|
UVM_CREATED = 1,
|
|
UVM_PRE_START = 2,
|
|
UVM_PRE_BODY = 4,
|
|
UVM_BODY = 8,
|
|
UVM_POST_BODY = 16,
|
|
UVM_POST_START= 32,
|
|
UVM_ENDED = 64,
|
|
UVM_STOPPED = 128,
|
|
UVM_FINISHED = 256
|
|
} uvm_sequence_state;
|
|
typedef uvm_sequence_state uvm_sequence_state_enum;
|
|
typedef enum
|
|
{
|
|
UVM_SEQ_LIB_RAND,
|
|
UVM_SEQ_LIB_RANDC,
|
|
UVM_SEQ_LIB_ITEM,
|
|
UVM_SEQ_LIB_USER
|
|
} uvm_sequence_lib_mode;
|
|
typedef enum { UVM_PHASE_IMP,
|
|
UVM_PHASE_NODE,
|
|
UVM_PHASE_TERMINAL,
|
|
UVM_PHASE_SCHEDULE,
|
|
UVM_PHASE_DOMAIN,
|
|
UVM_PHASE_GLOBAL
|
|
} uvm_phase_type;
|
|
typedef enum { UVM_PHASE_UNINITIALIZED = 0,
|
|
UVM_PHASE_DORMANT = 1,
|
|
UVM_PHASE_SCHEDULED = 2,
|
|
UVM_PHASE_SYNCING = 4,
|
|
UVM_PHASE_STARTED = 8,
|
|
UVM_PHASE_EXECUTING = 16,
|
|
UVM_PHASE_READY_TO_END = 32,
|
|
UVM_PHASE_ENDED = 64,
|
|
UVM_PHASE_CLEANUP = 128,
|
|
UVM_PHASE_DONE = 256,
|
|
UVM_PHASE_JUMPING = 512
|
|
} uvm_phase_state;
|
|
typedef enum { UVM_LT,
|
|
UVM_LTE,
|
|
UVM_NE,
|
|
UVM_EQ,
|
|
UVM_GT,
|
|
UVM_GTE
|
|
} uvm_wait_op;
|
|
typedef enum { UVM_RAISED = 'h01,
|
|
UVM_DROPPED = 'h02,
|
|
UVM_ALL_DROPPED = 'h04
|
|
} uvm_objection_event;
|
|
typedef int UVM_FILE;
|
|
parameter UVM_FILE UVM_STDIN = 32'h8000_0000;
|
|
parameter UVM_FILE UVM_STDOUT = 32'h8000_0001;
|
|
parameter UVM_FILE UVM_STDERR = 32'h8000_0002;
|
|
typedef enum {
|
|
UVM_CORE_UNINITIALIZED,
|
|
UVM_CORE_PRE_INIT,
|
|
UVM_CORE_INITIALIZING,
|
|
UVM_CORE_INITIALIZED,
|
|
UVM_CORE_PRE_RUN,
|
|
UVM_CORE_RUNNING,
|
|
UVM_CORE_POST_RUN,
|
|
UVM_CORE_FINISHED,
|
|
UVM_CORE_PRE_ABORT,
|
|
UVM_CORE_ABORTED
|
|
} uvm_core_state;
|
|
uvm_core_state m_uvm_core_state = UVM_CORE_UNINITIALIZED;
|
|
parameter uvm_core_state UVM_CORE_POST_INIT = UVM_CORE_INITIALIZED;
|
|
typedef class uvm_object_wrapper;
|
|
uvm_object_wrapper uvm_deferred_init[$];
|
|
virtual class uvm_void;
|
|
endclass
|
|
typedef enum {UVM_APPEND, UVM_PREPEND} uvm_apprepend;
|
|
typedef class uvm_object;
|
|
typedef class uvm_coreservice_t;
|
|
typedef class uvm_factory;
|
|
typedef class uvm_config_db;
|
|
typedef uvm_config_db#(uvm_object) m_uvm_config_obj_misc;
|
|
typedef class uvm_comparer ;
|
|
typedef class uvm_packer ;
|
|
typedef class uvm_recorder ;
|
|
typedef class uvm_printer ;
|
|
int unsigned uvm_global_random_seed = $urandom;
|
|
class uvm_seed_map;
|
|
int unsigned seed_table [string];
|
|
int unsigned count [string];
|
|
endclass
|
|
uvm_seed_map uvm_random_seed_table_lookup [string];
|
|
function string uvm_instance_scope();
|
|
byte c;
|
|
int pos;
|
|
if(uvm_instance_scope != "")
|
|
return uvm_instance_scope;
|
|
$swrite(uvm_instance_scope, "%m");
|
|
pos = uvm_instance_scope.len()-1;
|
|
c = uvm_instance_scope[pos];
|
|
while(pos && (c != ".") && (c != ":"))
|
|
c = uvm_instance_scope[--pos];
|
|
if(pos == 0)
|
|
uvm_report_error("SCPSTR", $sformatf("Illegal name %s in scope string",uvm_instance_scope));
|
|
uvm_instance_scope = uvm_instance_scope.substr(0,pos);
|
|
endfunction
|
|
parameter UVM_STR_CRC_POLYNOMIAL = 32'h04c11db6;
|
|
function int unsigned uvm_oneway_hash ( string string_in, int unsigned seed=0 );
|
|
bit msb;
|
|
bit [7:0] current_byte;
|
|
bit [31:0] crc1;
|
|
if(!seed) seed = uvm_global_random_seed;
|
|
uvm_oneway_hash = seed;
|
|
crc1 = 32'hffffffff;
|
|
for (int _byte=0; _byte < string_in.len(); _byte++) begin
|
|
current_byte = string_in[_byte];
|
|
if (current_byte == 0) break;
|
|
for (int _bit=0; _bit < 8; _bit++) begin
|
|
msb = crc1[31];
|
|
crc1 <<= 1;
|
|
if (msb ^ current_byte[_bit]) begin
|
|
crc1 ^= UVM_STR_CRC_POLYNOMIAL;
|
|
crc1[0] = 1;
|
|
end
|
|
end
|
|
end
|
|
uvm_oneway_hash += ~{crc1[7:0], crc1[15:8], crc1[23:16], crc1[31:24]};
|
|
endfunction
|
|
function int unsigned uvm_create_random_seed ( string type_id, string inst_id="" );
|
|
uvm_seed_map seed_map;
|
|
if(inst_id == "")
|
|
inst_id = "__global__";
|
|
if(!uvm_random_seed_table_lookup.exists(inst_id))
|
|
uvm_random_seed_table_lookup[inst_id] = new;
|
|
seed_map = uvm_random_seed_table_lookup[inst_id];
|
|
type_id = {uvm_instance_scope(),type_id};
|
|
if(!seed_map.seed_table.exists(type_id)) begin
|
|
seed_map.seed_table[type_id] = uvm_oneway_hash ({type_id,"::",inst_id}, uvm_global_random_seed);
|
|
end
|
|
if (!seed_map.count.exists(type_id)) begin
|
|
seed_map.count[type_id] = 0;
|
|
end
|
|
seed_map.seed_table[type_id] = seed_map.seed_table[type_id]+seed_map.count[type_id];
|
|
seed_map.count[type_id]++;
|
|
return seed_map.seed_table[type_id];
|
|
endfunction
|
|
function string uvm_object_value_str(uvm_object v);
|
|
if (v == null)
|
|
return "<null>";
|
|
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<size;idx++)
|
|
_t[idx]=value[idx];
|
|
value=_t;
|
|
end
|
|
else
|
|
value &= (1 << size)-1;
|
|
case(radix)
|
|
UVM_BIN: return $sformatf("%0s%0b", radix_str, value);
|
|
UVM_OCT: return $sformatf("%0s%0o", radix_str, value);
|
|
UVM_UNSIGNED: return $sformatf("%0s%0d", radix_str, value);
|
|
UVM_STRING: return $sformatf("%0s%0s", radix_str, value);
|
|
UVM_TIME: return $sformatf("%0s%0t", radix_str, value);
|
|
UVM_DEC: return $sformatf("%0s%0d", radix_str, value);
|
|
default: return $sformatf("%0s%0x", radix_str, value);
|
|
endcase
|
|
endfunction
|
|
function string uvm_integral_to_string (uvm_integral_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_integral_t _t;
|
|
_t=0;
|
|
for(int idx=0;idx<size;idx++)
|
|
_t[idx]=value[idx];
|
|
value=_t;
|
|
end
|
|
else
|
|
value &= (1 << size)-1;
|
|
case(radix)
|
|
UVM_BIN: return $sformatf("%0s%0b", radix_str, value);
|
|
UVM_OCT: return $sformatf("%0s%0o", radix_str, value);
|
|
UVM_UNSIGNED: return $sformatf("%0s%0d", radix_str, value);
|
|
UVM_STRING: return $sformatf("%0s%0s", radix_str, value);
|
|
UVM_TIME: return $sformatf("%0s%0t", radix_str, value);
|
|
UVM_DEC: return $sformatf("%0s%0d", radix_str, value);
|
|
default: return $sformatf("%0s%0x", radix_str, value);
|
|
endcase
|
|
endfunction
|
|
function int uvm_get_array_index_int(string arg, output bit is_wildcard);
|
|
int i;
|
|
uvm_get_array_index_int = 0;
|
|
is_wildcard = 1;
|
|
i = arg.len() - 1;
|
|
if(arg[i] == "]")
|
|
while(i > 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<str.len(); ++e)
|
|
if(str[e] == sep) break;
|
|
if(s != e)
|
|
values.push_back(str.substr(s,e-1));
|
|
e++;
|
|
end
|
|
endfunction
|
|
class uvm_enum_wrapper#(type T=uvm_active_passive_enum);
|
|
protected static T map[string];
|
|
static function bit from_name(string name, ref T value);
|
|
if (map.size() == 0)
|
|
m_init_map();
|
|
if (map.exists(name)) begin
|
|
value = map[name];
|
|
return 1;
|
|
end
|
|
else begin
|
|
return 0;
|
|
end
|
|
endfunction : from_name
|
|
protected static function void m_init_map();
|
|
T e = e.first();
|
|
do
|
|
begin
|
|
map[e.name()] = e;
|
|
e = e.next();
|
|
end
|
|
while (e != e.first());
|
|
endfunction : m_init_map
|
|
protected function new();
|
|
endfunction : new
|
|
endclass : uvm_enum_wrapper
|
|
typedef class uvm_report_object;
|
|
typedef class uvm_object_wrapper;
|
|
typedef class uvm_objection;
|
|
typedef class uvm_component;
|
|
typedef class uvm_resource_base;
|
|
typedef class uvm_resource;
|
|
typedef class uvm_field_op;
|
|
virtual class uvm_object extends uvm_void;
|
|
extern function new (string name="");
|
|
extern static function bit get_uvm_seeding();
|
|
extern static function void set_uvm_seeding(bit enable);
|
|
extern function void reseed ();
|
|
extern virtual function void set_name (string name);
|
|
extern virtual function string get_name ();
|
|
extern virtual function string get_full_name ();
|
|
extern virtual function int get_inst_id ();
|
|
extern static function int get_inst_count();
|
|
extern static function uvm_object_wrapper get_type ();
|
|
extern virtual function uvm_object_wrapper get_object_type ();
|
|
virtual function string get_type_name (); return "<unknown>"; 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() == "<unknown>") 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() != "<unknown>") 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() != "<unknown>")
|
|
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() == "<unknown>")
|
|
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 <unknown>\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(" <type override>");
|
|
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 <unknown>\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 != "<unknown>" &&
|
|
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="<unknown>")
|
|
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="<unknown>")
|
|
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="<unknown>")
|
|
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="<unknown>")
|
|
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="<unknown>" );
|
|
typedef uvm_registry_common#(Tregistry,Tcreator,Tcreated,Tname) this_type;
|
|
local static string m__type_aliases[$];
|
|
static function string type_name();
|
|
if((Tname == "<unknown>") && (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 = "<empty>";
|
|
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<q_size; i++) begin
|
|
if (ttab[type_handle].get(i) == rsrc) begin
|
|
ttab[type_handle].delete(i);
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if (ri_tab.exists(rsrc))
|
|
ri_tab.delete(rsrc);
|
|
end
|
|
endfunction
|
|
function void push_get_record(string name, string scope,
|
|
uvm_resource_base rsrc);
|
|
get_t impt;
|
|
if(!uvm_resource_options::is_auditing())
|
|
return;
|
|
impt = new();
|
|
impt.name = name;
|
|
impt.scope = scope;
|
|
impt.rsrc = rsrc;
|
|
impt.t = $realtime;
|
|
get_record.push_back(impt);
|
|
endfunction
|
|
function void dump_get_records();
|
|
get_t record;
|
|
bit success;
|
|
string qs[$];
|
|
qs.push_back("--- resource get records ---\n");
|
|
foreach (get_record[i]) begin
|
|
record = get_record[i];
|
|
success = (record.rsrc != null);
|
|
qs.push_back($sformatf("get: name=%s scope=%s %s @ %0t\n",
|
|
record.name, record.scope,
|
|
((success)?"success":"fail"),
|
|
record.t));
|
|
end
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_INFO,"UVM/RESOURCE/GETRECORD"))
|
|
uvm_report_info ("UVM/RESOURCE/GETRECORD", uvm_pkg::m_uvm_string_queue_join(qs), UVM_NONE, "t/uvm/src/base/uvm_resource.svh", 423, "", 1);
|
|
end
|
|
endfunction
|
|
function uvm_resource_types::rsrc_q_t lookup_name(string scope = "",
|
|
string name,
|
|
uvm_resource_base type_handle = null,
|
|
bit rpterr = 1);
|
|
uvm_resource_types::rsrc_q_t rq;
|
|
uvm_resource_types::rsrc_q_t q;
|
|
uvm_resource_base rsrc;
|
|
uvm_resource_base r;
|
|
string rsrcs;
|
|
begin
|
|
process p = process::self();
|
|
string s;
|
|
if(p!=null) s=p.get_randstate();
|
|
q=new();
|
|
if(p!=null) p.set_randstate(s);
|
|
end
|
|
if(name == "")
|
|
return q;
|
|
if(!rtab.exists(name)) begin
|
|
if(rpterr) void'(spell_check(name));
|
|
return q;
|
|
end
|
|
rsrc = null;
|
|
rq = rtab[name];
|
|
for(int i=0; i<rq.size(); ++i) begin
|
|
r = rq.get(i);
|
|
rsrcs = ri_tab.exists(r) ? ri_tab[r].scope: "";
|
|
if(((type_handle == null) || (r.get_type_handle() == type_handle)) &&
|
|
uvm_is_match(rsrcs, scope))
|
|
q.push_back(r);
|
|
end
|
|
return q;
|
|
endfunction
|
|
static function uvm_resource_base get_highest_precedence(ref uvm_resource_types::rsrc_q_t q);
|
|
uvm_resource_base rsrc;
|
|
uvm_resource_base r;
|
|
int unsigned i;
|
|
int unsigned prec;
|
|
int unsigned c_prec;
|
|
if(q.size() == 0)
|
|
return null;
|
|
rsrc = q.get(0);
|
|
prec = (ri_tab.exists(rsrc)) ? ri_tab[rsrc].precedence: 0;
|
|
for(int i = 1; i < q.size(); ++i) begin
|
|
r = q.get(i);
|
|
c_prec = (ri_tab.exists(r)) ? ri_tab[r].precedence: 0;
|
|
if(c_prec > 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<q.size(); ++i) begin
|
|
r = q.get(i);
|
|
prec = (ri_tab.exists(r)) ? ri_tab[r].precedence: 0;
|
|
if(!all.exists(prec))
|
|
all[prec] = new;
|
|
all[prec].push_front(r);
|
|
end
|
|
q.delete();
|
|
foreach(all[i]) begin
|
|
for(int j=0; j<all[i].size(); ++j) begin
|
|
r = all[i].get(j);
|
|
q.push_front(r);
|
|
end
|
|
end
|
|
endfunction
|
|
function uvm_resource_base get_by_name(string scope = "",
|
|
string name,
|
|
uvm_resource_base type_handle,
|
|
bit rpterr = 1);
|
|
uvm_resource_types::rsrc_q_t q;
|
|
uvm_resource_base rsrc;
|
|
q = lookup_name(scope, name, type_handle, rpterr);
|
|
if(q.size() == 0) begin
|
|
push_get_record(name, scope, null);
|
|
return null;
|
|
end
|
|
rsrc = get_highest_precedence(q);
|
|
push_get_record(name, scope, rsrc);
|
|
return rsrc;
|
|
endfunction
|
|
function uvm_resource_types::rsrc_q_t lookup_type(string scope = "",
|
|
uvm_resource_base type_handle);
|
|
uvm_resource_types::rsrc_q_t q = new();
|
|
uvm_resource_types::rsrc_q_t rq;
|
|
uvm_resource_base r;
|
|
int unsigned i;
|
|
if(type_handle == null || !ttab.exists(type_handle)) begin
|
|
return q;
|
|
end
|
|
rq = ttab[type_handle];
|
|
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))
|
|
q.push_back(r);
|
|
end
|
|
return q;
|
|
endfunction
|
|
function uvm_resource_base get_by_type(string scope = "",
|
|
uvm_resource_base type_handle);
|
|
uvm_resource_types::rsrc_q_t q;
|
|
uvm_resource_base rsrc;
|
|
q = lookup_type(scope, type_handle);
|
|
if(q.size() == 0) begin
|
|
push_get_record("<type>", scope, null);
|
|
return null;
|
|
end
|
|
rsrc = q.get(0);
|
|
push_get_record("<type>", 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<rq.size(); ++i) begin
|
|
uvm_resource_base r;
|
|
string scope;
|
|
printer.push_element($sformatf("[%0d]", i),
|
|
"uvm_resource",
|
|
"-",
|
|
"-");
|
|
r = rq.get(i);
|
|
void'(get_scope(r, scope));
|
|
printer.print_string("name", r.get_name());
|
|
printer.print_generic_element("value",
|
|
r.m_value_type_name(),
|
|
"",
|
|
r.m_value_as_string());
|
|
printer.print_string("scope", scope);
|
|
printer.print_field_int("precedence", get_precedence(r), 32, UVM_UNSIGNED);
|
|
if (audit && r.access.size()) begin
|
|
printer.print_array_header("accesses",
|
|
r.access.size(),
|
|
"queue");
|
|
foreach(r.access[i]) begin
|
|
printer.print_string($sformatf("[%s]", i),
|
|
$sformatf("reads: %0d @ %0t writes: %0d @ %0t",
|
|
r.access[i].read_count,
|
|
r.access[i].read_time,
|
|
r.access[i].write_count,
|
|
r.access[i].write_time));
|
|
end
|
|
printer.print_array_footer(r.access.size());
|
|
end
|
|
printer.pop_element();
|
|
end
|
|
printer.pop_element();
|
|
endfunction : m_print_resources
|
|
function void print_resources(uvm_resource_types::rsrc_q_t rq, bit audit = 0);
|
|
int unsigned i;
|
|
string id;
|
|
static uvm_tree_printer printer = new();
|
|
printer.flush();
|
|
if (rq == null)
|
|
printer.print_generic_element("",
|
|
"uvm_queue#(uvm_resource_base)",
|
|
"",
|
|
"<null>");
|
|
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() : "<unknown>",
|
|
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; i<m_waiters[field_name].size(); ++i) begin
|
|
w = m_waiters[field_name].get(i);
|
|
if ( uvm_is_match(inst_name,w.inst_name) )
|
|
->w.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<m_waiters[field_name].size(); ++i) begin
|
|
if(m_waiters[field_name].get(i) == waiter) begin
|
|
m_waiters[field_name].delete(i);
|
|
break;
|
|
end
|
|
end
|
|
endtask
|
|
endclass
|
|
typedef uvm_config_db#(uvm_bitstream_t) uvm_config_int ;
|
|
typedef uvm_config_db#(string) uvm_config_string ;
|
|
typedef uvm_config_db#(uvm_object) uvm_config_object ;
|
|
typedef uvm_config_db#(uvm_object_wrapper) uvm_config_wrapper ;
|
|
class uvm_config_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_CONFIG_DB_TRACE", trace_args)) begin
|
|
tracing = 1;
|
|
end
|
|
ready = 1;
|
|
endfunction
|
|
endclass
|
|
typedef class uvm_root;
|
|
virtual class uvm_policy extends uvm_object;
|
|
typedef enum {
|
|
NEVER,
|
|
STARTED,
|
|
FINISHED
|
|
} recursion_state_e;
|
|
local uvm_object m_extensions[uvm_object_wrapper];
|
|
local uvm_object m_policy_stack[$];
|
|
function new (string name="");
|
|
super.new(name);
|
|
endfunction
|
|
virtual function void flush();
|
|
m_policy_stack.delete();
|
|
endfunction
|
|
virtual function bit extension_exists( uvm_object_wrapper ext_type );
|
|
if (m_extensions.exists(ext_type))
|
|
extension_exists = 1;
|
|
else
|
|
extension_exists = 0;
|
|
endfunction
|
|
virtual function uvm_object set_extension( uvm_object extension );
|
|
uvm_object m_set_extension;
|
|
if ( extension == null)
|
|
uvm_report_fatal("NULLEXT", "Attempting to set null extension ", UVM_NONE);
|
|
if(m_extensions.exists(extension.get_object_type())) begin
|
|
m_set_extension = m_extensions[extension.get_object_type()] ;
|
|
m_extensions[extension.get_object_type()] = extension;
|
|
return m_set_extension;
|
|
end
|
|
else begin
|
|
m_extensions[extension.get_object_type()] = extension;
|
|
return null;
|
|
end
|
|
endfunction
|
|
virtual function uvm_object get_extension(uvm_object_wrapper ext_type );
|
|
if (m_extensions.exists(ext_type)) begin
|
|
return m_extensions[ext_type];
|
|
end
|
|
else
|
|
return null;
|
|
endfunction
|
|
virtual function void clear_extension( uvm_object_wrapper ext_type );
|
|
m_extensions.delete(ext_type);
|
|
endfunction
|
|
virtual function void clear_extensions();
|
|
m_extensions.delete();
|
|
endfunction
|
|
virtual function void push_active_object( uvm_object obj );
|
|
if(obj != null)
|
|
m_policy_stack.push_front(obj);
|
|
else
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM_POLICY_PUSHNULL"))
|
|
uvm_report_error ("UVM_POLICY_PUSHNULL", "Attempting to push an null object push_active_object onto the policy stack", UVM_NONE, "t/uvm/src/base/uvm_policy.svh", 151, "", 1);
|
|
end
|
|
endfunction
|
|
virtual function uvm_object pop_active_object();
|
|
uvm_object m_tmp;
|
|
if(m_policy_stack.size() != 0) begin
|
|
m_tmp = m_policy_stack.pop_front();
|
|
return m_tmp;
|
|
end
|
|
else
|
|
begin
|
|
if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"UVM_POLICY_EMPTY_POPACTIVE_OBJECT"))
|
|
uvm_report_info ("UVM_POLICY_EMPTY_POPACTIVE_OBJECT", "Attempting to pop an empty policy stack", UVM_DEBUG, "t/uvm/src/base/uvm_policy.svh", 167, "", 1);
|
|
end
|
|
endfunction
|
|
virtual function uvm_object get_active_object();
|
|
if(m_policy_stack.size() != 0)
|
|
return m_policy_stack[0];
|
|
endfunction
|
|
virtual function int unsigned get_active_object_depth();
|
|
return m_policy_stack.size();
|
|
endfunction
|
|
endclass
|
|
class uvm_field_op extends uvm_object;
|
|
typedef uvm_object_registry#(uvm_field_op,"uvm_field_op") type_id;
|
|
static function uvm_field_op 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_field_op tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_field_op";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_field_op";
|
|
endfunction : get_type_name
|
|
local uvm_policy m_policy;
|
|
local bit m_user_hook;
|
|
local uvm_object m_object;
|
|
local bit m_is_set;
|
|
local uvm_field_flag_t m_op_type;
|
|
function new (string name="");
|
|
super.new(name);
|
|
m_is_set = 1'b0;
|
|
m_user_hook = 1'b1;
|
|
endfunction
|
|
virtual function void set( uvm_field_flag_t op_type, uvm_policy policy = null, uvm_object rhs = null);
|
|
string matching_ops[$];
|
|
if (op_type & UVM_COPY)
|
|
matching_ops.push_back("UVM_COPY");
|
|
if (op_type & UVM_COMPARE)
|
|
matching_ops.push_back("UVM_COMPARE");
|
|
if (op_type & UVM_PRINT)
|
|
matching_ops.push_back("UVM_PRINT");
|
|
if (op_type & UVM_RECORD)
|
|
matching_ops.push_back("UVM_RECORD");
|
|
if (op_type & UVM_PACK)
|
|
matching_ops.push_back("UVM_PACK");
|
|
if (op_type & UVM_UNPACK)
|
|
matching_ops.push_back("UVM_UNPACK");
|
|
if (op_type & UVM_SET)
|
|
matching_ops.push_back("UVM_SET");
|
|
if (matching_ops.size() > 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 = "<unnamed>";
|
|
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()<m) begin
|
|
dash = {m{"-"}};
|
|
m_space = {m{" "}};
|
|
end
|
|
end
|
|
begin
|
|
string header;
|
|
string dash_id, dash_typ, dash_sz;
|
|
string head_id, head_typ, head_sz;
|
|
if (get_name_enabled()) begin
|
|
dashes = {dash.substr(1,m_max_name+2)};
|
|
header = {"Name",m_space.substr(1,m_max_name-2)};
|
|
end
|
|
if (get_type_name_enabled()) begin
|
|
dashes = {dashes, dash.substr(1,m_max_type+2)};
|
|
header = {header, "Type",m_space.substr(1,m_max_type-2)};
|
|
end
|
|
if (get_size_enabled()) begin
|
|
dashes = {dashes, dash.substr(1,m_max_size+2)};
|
|
header = {header, "Size",m_space.substr(1,m_max_size-2)};
|
|
end
|
|
dashes = {dashes, dash.substr(1,m_max_value), linefeed};
|
|
header = {header, "Value", m_space.substr(1,m_max_value-5), linefeed};
|
|
s = {s, dashes, header, dashes};
|
|
end
|
|
s = {s, m_emit_element(get_bottom_element(),0)} ;
|
|
begin
|
|
s = {s, dashes};
|
|
end
|
|
emit = {get_line_prefix(), s};
|
|
endfunction
|
|
function string uvm_table_printer::m_emit_element(uvm_printer_element element, int unsigned level) ;
|
|
string result ;
|
|
static uvm_printer_element_proxy proxy = new("proxy") ;
|
|
uvm_printer_element element_children[$];
|
|
string linefeed;
|
|
linefeed = {"\n", get_line_prefix()};
|
|
begin
|
|
string row_str;
|
|
string name_str ;
|
|
string value_str ;
|
|
string type_name_str ;
|
|
string size_str ;
|
|
name_str = element.get_element_name() ;
|
|
value_str = element.get_element_value() ;
|
|
type_name_str = element.get_element_type_name() ;
|
|
size_str = element.get_element_size() ;
|
|
if (get_name_enabled())
|
|
result = {result, m_space.substr(1,level * get_indent()), name_str,
|
|
m_space.substr(1,m_max_name-name_str.len()-(level*get_indent())+2)};
|
|
if (get_type_name_enabled())
|
|
result = {result, type_name_str, m_space.substr(1,m_max_type-type_name_str.len()+2)};
|
|
if (get_size_enabled())
|
|
result = {result, size_str, m_space.substr(1,m_max_size-size_str.len()+2)};
|
|
result = {result, row_str, value_str, m_space.substr(1,m_max_value-value_str.len()), linefeed};
|
|
end
|
|
proxy.get_immediate_children(element,element_children) ;
|
|
foreach (element_children[i]) begin
|
|
result = {result, m_emit_element(element_children[i],level+1)} ;
|
|
end
|
|
return result ;
|
|
endfunction
|
|
function uvm_tree_printer::new(string name="");
|
|
super.new(name);
|
|
set_size_enabled(0);
|
|
set_type_name_enabled(0);
|
|
endfunction
|
|
function void uvm_tree_printer::set_indent(int indent) ;
|
|
m_uvm_printer_knobs _knobs = get_knobs();
|
|
_knobs.indent = indent ;
|
|
endfunction
|
|
function int uvm_tree_printer::get_indent() ;
|
|
m_uvm_printer_knobs _knobs = get_knobs();
|
|
return _knobs.indent ;
|
|
endfunction
|
|
function void uvm_tree_printer::set_separators(string separators) ;
|
|
m_uvm_printer_knobs _knobs = get_knobs();
|
|
_knobs.separator = separators ;
|
|
endfunction
|
|
function string uvm_tree_printer::get_separators() ;
|
|
m_uvm_printer_knobs _knobs = get_knobs();
|
|
return _knobs.separator ;
|
|
endfunction
|
|
function void uvm_tree_printer::flush() ;
|
|
super.flush() ;
|
|
endfunction
|
|
function string uvm_tree_printer::emit();
|
|
string s ;
|
|
string user_format;
|
|
int unsigned level ;
|
|
uvm_printer_element element ;
|
|
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", 1689, "", 1);
|
|
end
|
|
end
|
|
else m_flushed = 0 ;
|
|
s = get_line_prefix() ;
|
|
m_linefeed = m_newline == "" || m_newline == " " ? m_newline : {m_newline, get_line_prefix()};
|
|
s = {s,m_emit_element(get_bottom_element(),0)} ;
|
|
if (m_newline == "" || m_newline == " ")
|
|
s = {s, "\n"};
|
|
return(s);
|
|
endfunction
|
|
function string uvm_tree_printer::m_emit_element(uvm_printer_element element, int unsigned level) ;
|
|
string result ;
|
|
string space= " ";
|
|
static uvm_printer_element_proxy proxy = new("proxy") ;
|
|
uvm_printer_element element_children[$];
|
|
begin
|
|
string indent_str;
|
|
string separators;
|
|
string value_str ;
|
|
indent_str = space.substr(1,level * get_indent());
|
|
separators=get_separators() ;
|
|
proxy.get_immediate_children(element,element_children) ;
|
|
if (get_name_enabled()) begin
|
|
result = {result,indent_str, element.get_element_name()};
|
|
if (element.get_element_name() != "" && element.get_element_name() != "...")
|
|
result = {result, ": "};
|
|
end
|
|
value_str = element.get_element_value();
|
|
if ((value_str.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) ? "<null>" : lhs.get_name(),
|
|
(lhs == null) ? 0 : lhs.get_inst_id(),
|
|
(rhs == null) ? "<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<m_pack_iter;i++)
|
|
stream[i] = m_bits[i];
|
|
endfunction
|
|
function void uvm_packer::get_packed_bytes (ref byte unsigned stream[] );
|
|
int sz;
|
|
byte v;
|
|
sz = (m_pack_iter + $high(v)) / $bits(byte);
|
|
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(byte)) == 0)
|
|
v = m_bits[ i* $bits(byte) +: $bits(byte) ];
|
|
else
|
|
v = m_bits[ i* $bits(byte) +: $bits(byte) ] & ({$bits(byte){1'b1}} >> ($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<bit_size;i++)
|
|
m_bits[i] = stream[i];
|
|
m_pack_iter = m_bits[31:0];
|
|
m_unpack_iter = m_bits[63:32];
|
|
endfunction
|
|
function void uvm_packer::set_packed_bytes (ref byte unsigned stream []);
|
|
int count;
|
|
foreach(stream[i]) begin
|
|
m_bits[count +: $bits(byte)] = stream[i];
|
|
count += $bits(byte);
|
|
end
|
|
m_pack_iter = m_bits[31:0];
|
|
m_unpack_iter = m_bits[63:32];
|
|
endfunction
|
|
function void uvm_packer::set_packed_ints (ref int unsigned stream []);
|
|
int count;
|
|
foreach(stream[i]) begin
|
|
m_bits[count +: $bits(int)] = stream[i];
|
|
count += $bits(int);
|
|
end
|
|
m_pack_iter = m_bits[31:0];
|
|
m_unpack_iter = m_bits[63:32];
|
|
endfunction
|
|
function void uvm_packer::set_packed_longints (ref longint unsigned stream []);
|
|
int count;
|
|
foreach(stream[i]) begin
|
|
m_bits[count +: $bits(longint)] = stream[i];
|
|
count += $bits(longint);
|
|
end
|
|
m_pack_iter = m_bits[31:0];
|
|
m_unpack_iter = m_bits[63:32];
|
|
endfunction
|
|
function void uvm_packer::pack_object(uvm_object value);
|
|
uvm_field_op field_op;
|
|
if (value == null ) begin
|
|
m_bits[m_pack_iter +: 4] = 0;
|
|
m_pack_iter += 4;
|
|
return ;
|
|
end
|
|
else begin
|
|
m_bits[m_pack_iter +: 4] = 4'hF;
|
|
m_pack_iter += 4;
|
|
end
|
|
push_active_object(value);
|
|
field_op = uvm_field_op::m_get_available_op() ;
|
|
field_op.set(UVM_PACK,this,value);
|
|
value.do_execute_op(field_op);
|
|
if (field_op.user_hook_enabled()) begin
|
|
value.do_pack(this);
|
|
end
|
|
field_op.m_recycle();
|
|
void'(pop_active_object());
|
|
endfunction
|
|
function void uvm_packer::pack_object_with_meta(uvm_object value);
|
|
int reference_id;
|
|
foreach(m_object_references[i]) begin
|
|
if (m_object_references[i] == value) begin
|
|
pack_field_int(i,32);
|
|
return;
|
|
end
|
|
end
|
|
reference_id = m_object_references.size();
|
|
pack_field_int(reference_id,32);
|
|
m_object_references[reference_id] = value;
|
|
pack_object_wrapper(value.get_object_type());
|
|
pack_object(value);
|
|
endfunction
|
|
function void uvm_packer::pack_object_wrapper(uvm_object_wrapper value);
|
|
string type_name;
|
|
if (value != null) begin
|
|
pack_string(value.get_type_name());
|
|
end
|
|
endfunction
|
|
function void uvm_packer::pack_real(real value);
|
|
pack_field_int($realtobits(value), 64);
|
|
endfunction
|
|
function void uvm_packer::pack_time(time value);
|
|
pack_field_int(value, 64);
|
|
endfunction
|
|
function void uvm_packer::pack_field(uvm_bitstream_t value, int size);
|
|
for (int i=0; i<size; i++)
|
|
m_bits[m_pack_iter+i] = value[i];
|
|
m_pack_iter += size;
|
|
endfunction
|
|
function void uvm_packer::pack_field_int(uvm_integral_t value, int size);
|
|
for (int i=0; i<size; i++)
|
|
m_bits[m_pack_iter+i] = value[i];
|
|
m_pack_iter += size;
|
|
endfunction
|
|
function void uvm_packer::pack_bits(ref bit value[], input int size = -1);
|
|
if (size < 0)
|
|
size = value.size();
|
|
if (size > 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<size; i++)
|
|
m_bits[m_pack_iter+i] = value[i];
|
|
m_pack_iter += size;
|
|
endfunction
|
|
function void uvm_packer::pack_bytes(ref byte value[], input int size = -1);
|
|
int max_size = value.size() * $bits(byte);
|
|
if (size < 0)
|
|
size = max_size;
|
|
if (size > 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<size; i++) begin
|
|
idx_select = i;
|
|
m_bits[m_pack_iter+i] = value[idx_select / $bits(byte)][idx_select % $bits(byte)];
|
|
end
|
|
m_pack_iter += size;
|
|
end
|
|
endfunction
|
|
function void uvm_packer::pack_ints(ref int value[], input int size = -1);
|
|
int max_size = value.size() * $bits(int);
|
|
if (size < 0)
|
|
size = max_size;
|
|
if (size > 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<size; i++) begin
|
|
idx_select = i;
|
|
m_bits[m_pack_iter+i] = value[idx_select / $bits(int)][idx_select % $bits(int)];
|
|
end
|
|
m_pack_iter += size;
|
|
end
|
|
endfunction
|
|
function void uvm_packer::pack_string(string value);
|
|
byte b;
|
|
foreach (value[index]) begin
|
|
m_bits[m_pack_iter +: 8] = value[index];
|
|
m_pack_iter += 8;
|
|
end
|
|
m_bits[m_pack_iter +: 8] = 0;
|
|
m_pack_iter += 8;
|
|
endfunction
|
|
function bit uvm_packer::is_null();
|
|
return (m_bits[m_unpack_iter+:4]==0);
|
|
endfunction
|
|
function bit uvm_packer::is_object_wrapper();
|
|
return (m_bits[m_unpack_iter+:4]==1);
|
|
endfunction
|
|
function void uvm_packer::unpack_object(uvm_object value);
|
|
uvm_field_op field_op;
|
|
if (is_null()) begin
|
|
if (value != null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/UNPACK/N2NN"))
|
|
uvm_report_error ("UVM/BASE/PACKER/UNPACK/N2NN", "attempt to unpack a null object into a not-null object!", UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 929, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
m_unpack_iter += 4;
|
|
return;
|
|
end
|
|
else begin
|
|
if (value == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/BASE/PACKER/UNPACK/NN2N"))
|
|
uvm_report_error ("UVM/BASE/PACKER/UNPACK/NN2N", "attempt to unpack a non-null object into a null object!", UVM_NONE, "t/uvm/src/base/uvm_packer.svh", 937, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
m_unpack_iter += 4;
|
|
push_active_object(value);
|
|
field_op = uvm_field_op::m_get_available_op() ;
|
|
field_op.set(UVM_UNPACK,this,value);
|
|
value.do_execute_op(field_op);
|
|
if (field_op.user_hook_enabled()) begin
|
|
value.do_unpack(this);
|
|
end
|
|
field_op.m_recycle();
|
|
void'(pop_active_object());
|
|
end
|
|
endfunction
|
|
function void uvm_packer::unpack_object_with_meta(inout uvm_object value);
|
|
int reference_id;
|
|
reference_id = unpack_field_int(32);
|
|
if (m_object_references.exists(reference_id)) begin
|
|
value = m_object_references[reference_id];
|
|
return;
|
|
end
|
|
else begin
|
|
uvm_object_wrapper __wrapper = unpack_object_wrapper();
|
|
if ((__wrapper != null) &&
|
|
((value == null) || (value.get_object_type() != __wrapper))) begin
|
|
value = __wrapper.create_object("");
|
|
if (value == null) begin
|
|
value = __wrapper.create_component("",null);
|
|
end
|
|
end
|
|
end
|
|
m_object_references[reference_id] = value;
|
|
unpack_object(value);
|
|
endfunction
|
|
function uvm_object_wrapper uvm_packer::unpack_object_wrapper();
|
|
string type_name;
|
|
type_name = unpack_string();
|
|
if (m_factory == null)
|
|
m_factory = uvm_factory::get();
|
|
if (m_factory.is_type_name_registered(type_name)) begin
|
|
return m_factory.find_wrapper_by_name(type_name);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function real uvm_packer::unpack_real();
|
|
if (enough_bits(64,"real")) begin
|
|
return $bitstoreal(unpack_field_int(64));
|
|
end
|
|
endfunction
|
|
function time uvm_packer::unpack_time();
|
|
if (enough_bits(64,"time")) begin
|
|
return unpack_field_int(64);
|
|
end
|
|
endfunction
|
|
function uvm_bitstream_t uvm_packer::unpack_field(int size);
|
|
unpack_field = 'b0;
|
|
if (enough_bits(size,"integral")) begin
|
|
m_unpack_iter += size;
|
|
for (int i=0; i<size; i++)
|
|
unpack_field[i] = m_bits[m_unpack_iter-size+i];
|
|
end
|
|
endfunction
|
|
function uvm_integral_t uvm_packer::unpack_field_int(int size);
|
|
unpack_field_int = 'b0;
|
|
if (enough_bits(size,"integral")) begin
|
|
m_unpack_iter += size;
|
|
for (int i=0; i<size; i++)
|
|
unpack_field_int[i] = m_bits[m_unpack_iter-size+i];
|
|
end
|
|
endfunction
|
|
function void uvm_packer::unpack_bits(ref bit value[], input int size = -1);
|
|
if (size < 0)
|
|
size = value.size();
|
|
if (size > 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<size; i++)
|
|
value[i] = m_bits[m_unpack_iter-size+i];
|
|
end
|
|
endfunction
|
|
function void uvm_packer::unpack_bytes(ref byte value[], input int size = -1);
|
|
int max_size = value.size() * $bits(byte);
|
|
if (size < 0)
|
|
size = max_size;
|
|
if (size > 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<size; i++) begin
|
|
value[ i / $bits(byte) ][ i % $bits(byte) ] = m_bits[m_unpack_iter-size+i];
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function void uvm_packer::unpack_ints(ref int value[], input int size = -1);
|
|
int max_size = value.size() * $bits(int);
|
|
if (size < 0)
|
|
size = max_size;
|
|
if (size > 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<size; i++) begin
|
|
value[ i / $bits(int) ][ i % $bits(int) ] = m_bits[m_unpack_iter-size+i];
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function string uvm_packer::unpack_string();
|
|
byte b;
|
|
int i; i=0;
|
|
while(enough_bits(8,"string") &&
|
|
(m_bits[m_unpack_iter+:8] != 0) )
|
|
begin
|
|
unpack_string = {unpack_string," "};
|
|
unpack_string[i] = m_bits[m_unpack_iter +: 8];
|
|
m_unpack_iter += 8;
|
|
++i;
|
|
end
|
|
if(enough_bits(8,"string"))
|
|
m_unpack_iter += 8;
|
|
endfunction
|
|
function uvm_packer::new(string name="");
|
|
super.new(name);
|
|
flush();
|
|
endfunction
|
|
virtual class uvm_link_base extends uvm_object;
|
|
function new(string name="unnamed-uvm_link_base");
|
|
super.new(name);
|
|
endfunction : new
|
|
function void set_lhs(uvm_object lhs);
|
|
do_set_lhs(lhs);
|
|
endfunction : set_lhs
|
|
function uvm_object get_lhs();
|
|
return do_get_lhs();
|
|
endfunction : get_lhs
|
|
function void set_rhs(uvm_object rhs);
|
|
do_set_rhs(rhs);
|
|
endfunction : set_rhs
|
|
function uvm_object get_rhs();
|
|
return do_get_rhs();
|
|
endfunction : get_rhs
|
|
function void set(uvm_object lhs, rhs);
|
|
do_set_lhs(lhs);
|
|
do_set_rhs(rhs);
|
|
endfunction : set
|
|
pure virtual function void do_set_lhs(uvm_object lhs);
|
|
pure virtual function uvm_object do_get_lhs();
|
|
pure virtual function void do_set_rhs(uvm_object rhs);
|
|
pure virtual function uvm_object do_get_rhs();
|
|
endclass : uvm_link_base
|
|
class uvm_parent_child_link extends uvm_link_base;
|
|
local uvm_object m_lhs;
|
|
local uvm_object m_rhs;
|
|
typedef uvm_object_registry#(uvm_parent_child_link,"uvm_parent_child_link") type_id;
|
|
static function uvm_parent_child_link 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_parent_child_link tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_parent_child_link";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_parent_child_link";
|
|
endfunction : get_type_name
|
|
function new(string name="unnamed-uvm_parent_child_link");
|
|
super.new(name);
|
|
endfunction : new
|
|
static function uvm_parent_child_link get_link(uvm_object lhs,
|
|
uvm_object rhs,
|
|
string name="pc_link");
|
|
process p_;
|
|
string s_;
|
|
p_ = process::self();
|
|
if (p_ != null)
|
|
s_ = p_.get_randstate();
|
|
get_link = new(name);
|
|
if (p_ != null)
|
|
p_.set_randstate(s_);
|
|
get_link.set(lhs, rhs);
|
|
endfunction : get_link
|
|
virtual function void do_set_lhs(uvm_object lhs);
|
|
m_lhs = lhs;
|
|
endfunction : do_set_lhs
|
|
virtual function uvm_object do_get_lhs();
|
|
return m_lhs;
|
|
endfunction : do_get_lhs
|
|
virtual function void do_set_rhs(uvm_object rhs);
|
|
m_rhs = rhs;
|
|
endfunction : do_set_rhs
|
|
virtual function uvm_object do_get_rhs();
|
|
return m_rhs;
|
|
endfunction : do_get_rhs
|
|
endclass : uvm_parent_child_link
|
|
class uvm_cause_effect_link extends uvm_link_base;
|
|
local uvm_object m_lhs;
|
|
local uvm_object m_rhs;
|
|
typedef uvm_object_registry#(uvm_cause_effect_link,"uvm_cause_effect_link") type_id;
|
|
static function uvm_cause_effect_link 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_cause_effect_link tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_cause_effect_link";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_cause_effect_link";
|
|
endfunction : get_type_name
|
|
function new(string name="unnamed-uvm_cause_effect_link");
|
|
super.new(name);
|
|
endfunction : new
|
|
static function uvm_cause_effect_link get_link(uvm_object lhs,
|
|
uvm_object rhs,
|
|
string name="ce_link");
|
|
process p_;
|
|
string s_;
|
|
p_ = process::self();
|
|
if (p_ != null)
|
|
s_ = p_.get_randstate();
|
|
get_link = new(name);
|
|
if (p_ != null)
|
|
p_.set_randstate(s_);
|
|
get_link.set(lhs, rhs);
|
|
endfunction : get_link
|
|
virtual function void do_set_lhs(uvm_object lhs);
|
|
m_lhs = lhs;
|
|
endfunction : do_set_lhs
|
|
virtual function uvm_object do_get_lhs();
|
|
return m_lhs;
|
|
endfunction : do_get_lhs
|
|
virtual function void do_set_rhs(uvm_object rhs);
|
|
m_rhs = rhs;
|
|
endfunction : do_set_rhs
|
|
virtual function uvm_object do_get_rhs();
|
|
return m_rhs;
|
|
endfunction : do_get_rhs
|
|
endclass : uvm_cause_effect_link
|
|
class uvm_related_link extends uvm_link_base;
|
|
local uvm_object m_lhs;
|
|
local uvm_object m_rhs;
|
|
typedef uvm_object_registry#(uvm_related_link,"uvm_related_link") type_id;
|
|
static function uvm_related_link 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_related_link tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_related_link";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_related_link";
|
|
endfunction : get_type_name
|
|
function new(string name="unnamed-uvm_related_link");
|
|
super.new(name);
|
|
endfunction : new
|
|
static function uvm_related_link get_link(uvm_object lhs,
|
|
uvm_object rhs,
|
|
string name="ce_link");
|
|
process p_;
|
|
string s_;
|
|
p_ = process::self();
|
|
if (p_ != null)
|
|
s_ = p_.get_randstate();
|
|
get_link = new(name);
|
|
if (p_ != null)
|
|
p_.set_randstate(s_);
|
|
get_link.set(lhs, rhs);
|
|
endfunction : get_link
|
|
virtual function void do_set_lhs(uvm_object lhs);
|
|
m_lhs = lhs;
|
|
endfunction : do_set_lhs
|
|
virtual function uvm_object do_get_lhs();
|
|
return m_lhs;
|
|
endfunction : do_get_lhs
|
|
virtual function void do_set_rhs(uvm_object rhs);
|
|
m_rhs = rhs;
|
|
endfunction : do_set_rhs
|
|
virtual function uvm_object do_get_rhs();
|
|
return m_rhs;
|
|
endfunction : do_get_rhs
|
|
endclass : uvm_related_link
|
|
typedef class uvm_recorder;
|
|
typedef class uvm_tr_stream;
|
|
typedef class uvm_link_base;
|
|
virtual class uvm_tr_database extends uvm_object;
|
|
local bit m_is_opened;
|
|
local bit m_streams[uvm_tr_stream];
|
|
function new(string name="unnamed-uvm_tr_database");
|
|
super.new(name);
|
|
endfunction : new
|
|
function bit open_db();
|
|
if (!m_is_opened)
|
|
m_is_opened = do_open_db();
|
|
return m_is_opened;
|
|
endfunction : open_db
|
|
function bit close_db();
|
|
if (m_is_opened) begin
|
|
if (do_close_db())
|
|
m_is_opened = 0;
|
|
end
|
|
return (m_is_opened == 0);
|
|
endfunction : close_db
|
|
function bit is_open();
|
|
return m_is_opened;
|
|
endfunction : is_open
|
|
function uvm_tr_stream open_stream(string name,
|
|
string scope="",
|
|
string type_name="");
|
|
if (!open_db()) begin
|
|
return null;
|
|
end
|
|
else begin
|
|
process p = process::self();
|
|
string s;
|
|
if (p != null)
|
|
s = p.get_randstate();
|
|
open_stream = do_open_stream(name, scope, type_name);
|
|
if (open_stream != null) begin
|
|
m_streams[open_stream] = 1;
|
|
open_stream.m_do_open(this, scope, type_name);
|
|
end
|
|
if (p != null)
|
|
p.set_randstate(s);
|
|
end
|
|
endfunction : open_stream
|
|
function void m_free_stream(uvm_tr_stream stream);
|
|
if (m_streams.exists(stream))
|
|
m_streams.delete(stream);
|
|
endfunction : m_free_stream
|
|
function unsigned get_streams(ref uvm_tr_stream q[$]);
|
|
q.delete();
|
|
foreach (m_streams[idx])
|
|
q.push_back(idx);
|
|
return q.size();
|
|
endfunction : get_streams
|
|
function void establish_link(uvm_link_base link);
|
|
uvm_tr_stream s_lhs, s_rhs;
|
|
uvm_recorder r_lhs, r_rhs;
|
|
uvm_object lhs = link.get_lhs();
|
|
uvm_object rhs = link.get_rhs();
|
|
uvm_tr_database db;
|
|
if (lhs == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/TR_DB/BAD_LINK"))
|
|
uvm_report_warning ("UVM/TR_DB/BAD_LINK", "left hand side '<null>' 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 '<null>' 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 '<null>'", 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 '<null>'", 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<q.size(); ++i)
|
|
if(q.get(i) == cb)
|
|
return i;
|
|
return -1;
|
|
endfunction
|
|
static function int m_cb_find_name(uvm_queue#(uvm_callback) q, string name, string where);
|
|
uvm_callback cb;
|
|
for(int i=0; i<q.size(); ++i) begin
|
|
cb = q.get(i);
|
|
if(cb.get_name() == name) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/CB/NAM/SAM"))
|
|
uvm_report_warning ("UVM/CB/NAM/SAM", {"A callback named \"", name, "\" is already registered with ", where}, UVM_NONE, "t/uvm/src/base/uvm_callback.svh", 246, "", 1);
|
|
end
|
|
return 1;
|
|
end
|
|
end
|
|
return 0;
|
|
endfunction
|
|
virtual function void m_add_tw_cbs(uvm_callback cb, uvm_apprepend ordering);
|
|
super_type cb_pair;
|
|
uvm_object obj;
|
|
T me;
|
|
bit warned;
|
|
uvm_queue#(uvm_callback) q;
|
|
if(m_cb_find(m_t_inst.m_tw_cb_q,cb) == -1) begin
|
|
warned = m_cb_find_name(m_t_inst.m_tw_cb_q, cb.get_name(), "type");
|
|
if(ordering == UVM_APPEND)
|
|
m_t_inst.m_tw_cb_q.push_back(cb);
|
|
else
|
|
m_t_inst.m_tw_cb_q.push_front(cb);
|
|
end
|
|
if(m_t_inst.m_pool.first(obj)) begin
|
|
do begin
|
|
if($cast(me,obj)) begin
|
|
q = m_t_inst.m_pool.get(obj);
|
|
if(q==null) begin
|
|
q=new;
|
|
m_t_inst.m_pool.add(obj,q);
|
|
end
|
|
if(m_cb_find(q,cb) == -1) begin
|
|
if (!warned) begin
|
|
void'(m_cb_find_name(q, cb.get_name(), {"object instance ", me.get_full_name()}));
|
|
end
|
|
if(ordering == UVM_APPEND)
|
|
q.push_back(cb);
|
|
else
|
|
q.push_front(cb);
|
|
end
|
|
end
|
|
end while(m_t_inst.m_pool.next(obj));
|
|
end
|
|
foreach(m_derived_types[i]) begin
|
|
cb_pair = uvm_typeid_base::typeid_map[m_derived_types[i] ];
|
|
if(cb_pair != this)
|
|
cb_pair.m_add_tw_cbs(cb,ordering);
|
|
end
|
|
endfunction
|
|
virtual function bit m_delete_tw_cbs(uvm_callback cb);
|
|
super_type cb_pair;
|
|
uvm_object obj;
|
|
uvm_queue#(uvm_callback) q;
|
|
int pos = m_cb_find(m_t_inst.m_tw_cb_q,cb);
|
|
if(pos != -1) begin
|
|
m_t_inst.m_tw_cb_q.delete(pos);
|
|
m_delete_tw_cbs = 1;
|
|
end
|
|
if(m_t_inst.m_pool.first(obj)) begin
|
|
do begin
|
|
q = m_t_inst.m_pool.get(obj);
|
|
if(q==null) begin
|
|
q=new;
|
|
m_t_inst.m_pool.add(obj,q);
|
|
end
|
|
pos = m_cb_find(q,cb);
|
|
if(pos != -1) begin
|
|
q.delete(pos);
|
|
m_delete_tw_cbs = 1;
|
|
end
|
|
end while(m_t_inst.m_pool.next(obj));
|
|
end
|
|
foreach(m_derived_types[i]) begin
|
|
cb_pair = uvm_typeid_base::typeid_map[m_derived_types[i] ];
|
|
if(cb_pair != this)
|
|
m_delete_tw_cbs |= cb_pair.m_delete_tw_cbs(cb);
|
|
end
|
|
endfunction
|
|
static function void display(T obj=null);
|
|
T me;
|
|
string cbq[$];
|
|
string inst_q[$];
|
|
string mode_q[$];
|
|
uvm_callback cb;
|
|
string blanks = " ";
|
|
uvm_object bobj = obj;
|
|
string qs[$];
|
|
uvm_queue#(uvm_callback) q;
|
|
string tname, str;
|
|
int max_cb_name=0, max_inst_name=0;
|
|
m_tracing = 0;
|
|
if(m_typename != "") tname = m_typename;
|
|
else if(obj != null) tname = obj.get_type_name();
|
|
else tname = "*";
|
|
q = m_t_inst.m_tw_cb_q;
|
|
for(int i=0; i<q.size(); ++i) begin
|
|
cb = q.get(i);
|
|
cbq.push_back(cb.get_name());
|
|
inst_q.push_back("(*)");
|
|
if(cb.is_enabled()) mode_q.push_back("ON");
|
|
else mode_q.push_back("OFF");
|
|
str = cb.get_name();
|
|
max_cb_name = max_cb_name > 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<q.size(); ++i) begin
|
|
cb = q.get(i);
|
|
cbq.push_back(cb.get_name());
|
|
inst_q.push_back(bobj.get_full_name());
|
|
if(cb.is_enabled()) mode_q.push_back("ON");
|
|
else mode_q.push_back("OFF");
|
|
str = cb.get_name();
|
|
max_cb_name = max_cb_name > 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<q.size(); ++i) begin
|
|
cb = q.get(i);
|
|
cbq.push_back(cb.get_name());
|
|
inst_q.push_back(bobj.get_full_name());
|
|
if(cb.is_enabled()) mode_q.push_back("ON");
|
|
else mode_q.push_back("OFF");
|
|
str = cb.get_name();
|
|
max_cb_name = max_cb_name > 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<qr.size(); ++i)
|
|
q.push_back(qr.get(i));
|
|
end
|
|
for(int i=0; i<m_t_inst.m_tw_cb_q.size(); ++i)
|
|
q.push_back(m_t_inst.m_tw_cb_q.get(i));
|
|
end
|
|
if(m_cb_find(q,cb) != -1) begin
|
|
uvm_report_warning("CBPREG", { "Callback object ", cb.get_name(), " is already registered",
|
|
" with object ", obj.get_full_name() }, UVM_NONE);
|
|
end
|
|
else begin
|
|
void'(m_cb_find_name(q, cb.get_name(), {"object instance ", obj.get_full_name()}));
|
|
if(ordering == UVM_APPEND)
|
|
q.push_back(cb);
|
|
else
|
|
q.push_front(cb);
|
|
end
|
|
end
|
|
endfunction
|
|
static function void add_by_name(string name,
|
|
uvm_callback cb,
|
|
uvm_component root,
|
|
uvm_apprepend ordering=UVM_APPEND);
|
|
uvm_component cq[$];
|
|
uvm_root top;
|
|
uvm_coreservice_t cs;
|
|
T t;
|
|
void'(get());
|
|
cs = uvm_coreservice_t::get();
|
|
top = cs.get_root();
|
|
if(cb==null) begin
|
|
uvm_report_error("CBUNREG", { "Null callback object cannot be registered with object(s) ",
|
|
name }, UVM_NONE);
|
|
return;
|
|
end
|
|
top.find_all(name,cq,root);
|
|
if(cq.size() == 0) begin
|
|
uvm_report_warning("CBNOMTC", { "add_by_name failed to find any components matching the name ",
|
|
name, ", callback ", cb.get_name(), " will not be registered." }, UVM_NONE);
|
|
end
|
|
foreach(cq[i]) begin
|
|
if($cast(t,cq[i])) begin
|
|
add(t,cb,ordering);
|
|
end
|
|
end
|
|
endfunction
|
|
static function void delete(T obj, uvm_callback cb);
|
|
uvm_object b_obj = obj;
|
|
uvm_queue#(uvm_callback) q;
|
|
bit found;
|
|
int pos;
|
|
void'(get());
|
|
if(obj == null) begin
|
|
found = m_t_inst.m_delete_tw_cbs(cb);
|
|
end
|
|
else begin
|
|
q = m_base_inst.m_pool.get(b_obj);
|
|
pos = m_cb_find(q,cb);
|
|
if(pos != -1) begin
|
|
q.delete(pos);
|
|
found = 1;
|
|
end
|
|
end
|
|
if(!found) begin
|
|
string nm;
|
|
if(obj==null) nm = "(*)"; else nm = obj.get_full_name();
|
|
uvm_report_warning("CBUNREG", { "Callback ", cb.get_name(), " cannot be removed from object ",
|
|
nm, " because it is not currently registered to that object." }, UVM_NONE);
|
|
end
|
|
endfunction
|
|
static function void delete_by_name(string name, uvm_callback cb,
|
|
uvm_component root);
|
|
uvm_component cq[$];
|
|
uvm_root top;
|
|
T t;
|
|
uvm_coreservice_t cs;
|
|
void'(get());
|
|
cs = uvm_coreservice_t::get();
|
|
top = cs.get_root();
|
|
top.find_all(name,cq,root);
|
|
if(cq.size() == 0) begin
|
|
uvm_report_warning("CBNOMTC", { "delete_by_name failed to find any components matching the name ",
|
|
name, ", callback ", cb.get_name(), " will not be unregistered." }, UVM_NONE);
|
|
end
|
|
foreach(cq[i]) begin
|
|
if($cast(t,cq[i])) begin
|
|
delete(t,cb);
|
|
end
|
|
end
|
|
endfunction
|
|
static function void m_get_q (ref uvm_queue #(uvm_callback) q, input T obj);
|
|
if(!m_base_inst.m_pool.exists(obj)) begin
|
|
q = (obj == null) ? m_t_inst.m_tw_cb_q : m_t_inst.m_get_tw_cb_q(obj);
|
|
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
|
|
end
|
|
endfunction
|
|
static function CB get_first (ref int itr, input T obj);
|
|
uvm_queue#(uvm_callback) q;
|
|
CB cb;
|
|
void'(get());
|
|
m_get_q(q,obj);
|
|
for(itr = 0; itr<q.size(); ++itr)
|
|
if($cast(cb, q.get(itr)) && cb.callback_mode())
|
|
return cb;
|
|
return null;
|
|
endfunction
|
|
static function CB get_last (ref int itr, input T obj);
|
|
uvm_queue#(uvm_callback) q;
|
|
CB cb;
|
|
void'(get());
|
|
m_get_q(q,obj);
|
|
for(itr = q.size()-1; itr>=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<q.size(); ++itr)
|
|
if ($cast(cb, q.get(itr)) && cb.callback_mode())
|
|
return cb;
|
|
return null;
|
|
endfunction
|
|
static function CB get_prev (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_t_inst.m_tw_cb_q.size(); ++qi)
|
|
if ($cast(cb, m_t_inst.m_tw_cb_q.get(qi)))
|
|
callbacks_to_append.push_back( cb );
|
|
end
|
|
else begin
|
|
q = m_pool.get(obj);
|
|
for (int qi=0; qi < q.size(); qi++)
|
|
if ($cast(cb, q.get( qi )))
|
|
callbacks_to_append.push_back( cb );
|
|
end
|
|
unique_callbacks_to_append = callbacks_to_append.unique( cb_ ) with ( cb_.get_inst_id );
|
|
all_callbacks = { all_callbacks, unique_callbacks_to_append };
|
|
endfunction
|
|
static function void display(T obj=null);
|
|
void'(get());
|
|
super_type::display(obj);
|
|
endfunction
|
|
endclass
|
|
class uvm_derived_callbacks#(type T=uvm_object, type ST=uvm_object, type CB=uvm_callback)
|
|
extends uvm_callbacks#(T,CB);
|
|
typedef uvm_derived_callbacks#(T,ST,CB) this_type;
|
|
typedef uvm_callbacks#(T) this_user_type;
|
|
typedef uvm_callbacks#(ST) this_super_type;
|
|
static this_type m_d_inst;
|
|
static this_user_type m_user_inst;
|
|
static this_super_type m_super_inst;
|
|
static uvm_typeid_base m_s_typeid;
|
|
static function this_type get();
|
|
m_user_inst = this_user_type::get();
|
|
m_super_inst = this_super_type::get();
|
|
m_s_typeid = uvm_typeid#(ST)::get();
|
|
if(m_d_inst == null) begin
|
|
m_d_inst = new;
|
|
end
|
|
return m_d_inst;
|
|
endfunction
|
|
static function bit register_super_type(string tname="", sname="");
|
|
this_user_type u_inst = this_user_type::get();
|
|
uvm_callbacks_base s_obj;
|
|
void'(this_type::get());
|
|
this_user_type::m_t_inst.m_typename = tname;
|
|
if(sname != "") m_s_typeid.typename = sname;
|
|
if(u_inst.m_super_type != null) begin
|
|
if(u_inst.m_super_type == m_s_typeid) return 1;
|
|
uvm_report_warning("CBTPREG", { "Type ", tname, " is already registered to super type ",
|
|
this_super_type::m_t_inst.m_typename, ". Ignoring attempt to register to super type ",
|
|
sname}, UVM_NONE);
|
|
return 1;
|
|
end
|
|
if(this_super_type::m_t_inst.m_typename == "")
|
|
this_super_type::m_t_inst.m_typename = sname;
|
|
u_inst.m_super_type = m_s_typeid;
|
|
u_inst.m_base_inst.m_super_type = m_s_typeid;
|
|
s_obj = uvm_typeid_base::typeid_map[m_s_typeid];
|
|
s_obj.m_derived_types.push_back(m_typeid);
|
|
return 1;
|
|
endfunction
|
|
endclass
|
|
class uvm_callback_iter#(type T = uvm_object, type CB = uvm_callback);
|
|
local int m_i;
|
|
local T m_obj;
|
|
local CB m_cb;
|
|
function new(T obj);
|
|
m_obj = obj;
|
|
endfunction
|
|
function CB first();
|
|
m_cb = uvm_callbacks#(T,CB)::get_first(m_i, m_obj);
|
|
return m_cb;
|
|
endfunction
|
|
function CB last();
|
|
m_cb = uvm_callbacks#(T,CB)::get_last(m_i, m_obj);
|
|
return m_cb;
|
|
endfunction
|
|
function CB next();
|
|
m_cb = uvm_callbacks#(T,CB)::get_next(m_i, m_obj);
|
|
return m_cb;
|
|
endfunction
|
|
function CB prev();
|
|
m_cb = uvm_callbacks#(T,CB)::get_prev(m_i, m_obj);
|
|
return m_cb;
|
|
endfunction
|
|
function CB get_cb();
|
|
return m_cb;
|
|
endfunction
|
|
endclass
|
|
class uvm_callback extends uvm_object;
|
|
protected bit m_enabled = 1;
|
|
typedef uvm_object_registry#(uvm_callback,"uvm_callback") type_id;
|
|
static function uvm_callback 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_callback tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_callback";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_callback";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_callback");
|
|
super.new(name);
|
|
endfunction
|
|
function bit callback_mode(int on=-1);
|
|
if(on == 0 || on == 1) begin
|
|
end
|
|
else begin
|
|
end
|
|
callback_mode = m_enabled;
|
|
if(on==0) m_enabled=0;
|
|
if(on==1) m_enabled=1;
|
|
endfunction
|
|
function bit is_enabled();
|
|
return callback_mode();
|
|
endfunction
|
|
endclass
|
|
typedef class uvm_report_server;
|
|
typedef class uvm_report_handler;
|
|
typedef class uvm_root;
|
|
virtual class uvm_report_message_element_base;
|
|
protected uvm_action _action;
|
|
protected string _name;
|
|
virtual function string get_name();
|
|
return _name;
|
|
endfunction
|
|
virtual function void set_name(string name);
|
|
_name = name;
|
|
endfunction
|
|
virtual function uvm_action get_action();
|
|
return _action;
|
|
endfunction
|
|
virtual function void set_action(uvm_action action);
|
|
_action = action;
|
|
endfunction
|
|
function void print(uvm_printer printer);
|
|
if (_action & (UVM_LOG | UVM_DISPLAY))
|
|
do_print(printer);
|
|
endfunction : print
|
|
function void record(uvm_recorder recorder);
|
|
if (_action & UVM_RM_RECORD)
|
|
do_record(recorder);
|
|
endfunction : record
|
|
function void copy(uvm_report_message_element_base rhs);
|
|
do_copy(rhs);
|
|
endfunction : copy
|
|
function uvm_report_message_element_base clone();
|
|
return do_clone();
|
|
endfunction : clone
|
|
pure virtual function void do_print(uvm_printer printer);
|
|
pure virtual function void do_record(uvm_recorder recorder);
|
|
pure virtual function void do_copy(uvm_report_message_element_base rhs);
|
|
pure virtual function uvm_report_message_element_base do_clone();
|
|
endclass : uvm_report_message_element_base
|
|
class uvm_report_message_int_element extends uvm_report_message_element_base;
|
|
typedef uvm_report_message_int_element this_type;
|
|
protected uvm_bitstream_t _val;
|
|
protected int _size;
|
|
protected uvm_radix_enum _radix;
|
|
virtual function uvm_bitstream_t get_value(output int size,
|
|
output uvm_radix_enum radix);
|
|
size = _size;
|
|
radix = _radix;
|
|
return _val;
|
|
endfunction
|
|
virtual function void set_value(uvm_bitstream_t value,
|
|
int size,
|
|
uvm_radix_enum radix);
|
|
_size = size;
|
|
_radix = radix;
|
|
_val = value;
|
|
endfunction
|
|
virtual function void do_print(uvm_printer printer);
|
|
printer.print_field(_name, _val, _size, _radix);
|
|
endfunction : do_print
|
|
virtual function void do_record(uvm_recorder recorder);
|
|
recorder.record_field(_name, _val, _size, _radix);
|
|
endfunction : do_record
|
|
virtual function void do_copy(uvm_report_message_element_base rhs);
|
|
this_type _rhs;
|
|
$cast(_rhs, rhs);
|
|
_name = _rhs._name;
|
|
_val = _rhs._val;
|
|
_size = _rhs._size;
|
|
_radix = _rhs._radix;
|
|
_action = rhs._action;
|
|
endfunction : do_copy
|
|
virtual function uvm_report_message_element_base do_clone();
|
|
this_type tmp = new;
|
|
tmp.copy(this);
|
|
return tmp;
|
|
endfunction : do_clone
|
|
endclass : uvm_report_message_int_element
|
|
class uvm_report_message_string_element extends uvm_report_message_element_base;
|
|
typedef uvm_report_message_string_element this_type;
|
|
protected string _val;
|
|
virtual function string get_value();
|
|
return _val;
|
|
endfunction
|
|
virtual function void set_value(string value);
|
|
_val = value;
|
|
endfunction
|
|
virtual function void do_print(uvm_printer printer);
|
|
printer.print_string(_name, _val);
|
|
endfunction : do_print
|
|
virtual function void do_record(uvm_recorder recorder);
|
|
recorder.record_string(_name, _val);
|
|
endfunction : do_record
|
|
virtual function void do_copy(uvm_report_message_element_base rhs);
|
|
this_type _rhs;
|
|
$cast(_rhs, rhs);
|
|
_name = _rhs._name;
|
|
_val = _rhs._val;
|
|
_action = rhs._action;
|
|
endfunction : do_copy
|
|
virtual function uvm_report_message_element_base do_clone();
|
|
this_type tmp = new;
|
|
tmp.copy(this);
|
|
return tmp;
|
|
endfunction : do_clone
|
|
endclass : uvm_report_message_string_element
|
|
class uvm_report_message_object_element extends uvm_report_message_element_base;
|
|
typedef uvm_report_message_object_element this_type;
|
|
protected uvm_object _val;
|
|
virtual function uvm_object get_value();
|
|
return _val;
|
|
endfunction
|
|
virtual function void set_value(uvm_object value);
|
|
_val = value;
|
|
endfunction
|
|
virtual function void do_print(uvm_printer printer);
|
|
printer.print_object(_name, _val);
|
|
endfunction : do_print
|
|
virtual function void do_record(uvm_recorder recorder);
|
|
recorder.record_object(_name, _val);
|
|
endfunction : do_record
|
|
virtual function void do_copy(uvm_report_message_element_base rhs);
|
|
this_type _rhs;
|
|
$cast(_rhs, rhs);
|
|
_name = _rhs._name;
|
|
_val = _rhs._val;
|
|
_action = rhs._action;
|
|
endfunction : do_copy
|
|
virtual function uvm_report_message_element_base do_clone();
|
|
this_type tmp = new;
|
|
tmp.copy(this);
|
|
return tmp;
|
|
endfunction : do_clone
|
|
endclass : uvm_report_message_object_element
|
|
class uvm_report_message_element_container extends uvm_object;
|
|
protected uvm_report_message_element_base elements[$];
|
|
typedef uvm_object_registry#(uvm_report_message_element_container,"uvm_report_message_element_container") type_id;
|
|
static function uvm_report_message_element_container 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_message_element_container tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_report_message_element_container";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_report_message_element_container";
|
|
endfunction : get_type_name
|
|
function new(string name = "element_container");
|
|
super.new(name);
|
|
endfunction
|
|
virtual function int size();
|
|
return elements.size();
|
|
endfunction
|
|
virtual function void delete(int index);
|
|
elements.delete(index);
|
|
endfunction
|
|
virtual function void delete_elements();
|
|
elements.delete();
|
|
endfunction
|
|
typedef uvm_report_message_element_base queue_of_element[$];
|
|
virtual function queue_of_element get_elements();
|
|
return elements;
|
|
endfunction
|
|
virtual function void add_int(string name, uvm_bitstream_t value,
|
|
int size, uvm_radix_enum radix,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
process p;
|
|
string rand_state;
|
|
uvm_report_message_int_element urme;
|
|
p = process::self();
|
|
if (p != null)
|
|
rand_state = p.get_randstate();
|
|
urme = new();
|
|
if (p != null)
|
|
p.set_randstate(rand_state);
|
|
urme.set_name(name);
|
|
urme.set_value(value, size, radix);
|
|
urme.set_action(action);
|
|
elements.push_back(urme);
|
|
endfunction
|
|
virtual function void add_string(string name, string value,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
process p;
|
|
string rand_state;
|
|
uvm_report_message_string_element urme;
|
|
p = process::self();
|
|
if (p != null)
|
|
rand_state = p.get_randstate();
|
|
urme = new();
|
|
if (p != null)
|
|
p.set_randstate(rand_state);
|
|
urme.set_name(name);
|
|
urme.set_value(value);
|
|
urme.set_action(action);
|
|
elements.push_back(urme);
|
|
endfunction
|
|
virtual function void add_object(string name, uvm_object obj,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
process p;
|
|
string rand_state;
|
|
uvm_report_message_object_element urme;
|
|
p = process::self();
|
|
if (p != null)
|
|
rand_state = p.get_randstate();
|
|
urme = new();
|
|
if (p != null)
|
|
p.set_randstate(rand_state);
|
|
urme.set_name(name);
|
|
urme.set_value(obj);
|
|
urme.set_action(action);
|
|
elements.push_back(urme);
|
|
endfunction
|
|
virtual function void do_print(uvm_printer printer);
|
|
super.do_print(printer);
|
|
for(int i = 0; i < elements.size(); i++) begin
|
|
elements[i].print(printer);
|
|
end
|
|
endfunction
|
|
virtual function void do_record(uvm_recorder recorder);
|
|
super.do_record(recorder);
|
|
for(int i = 0; i < elements.size(); i++) begin
|
|
elements[i].record(recorder);
|
|
end
|
|
endfunction
|
|
virtual function void do_copy(uvm_object rhs);
|
|
uvm_report_message_element_container urme_container;
|
|
super.do_copy(rhs);
|
|
if(!$cast(urme_container, rhs) || (rhs==null))
|
|
return;
|
|
delete_elements();
|
|
foreach (urme_container.elements[i])
|
|
elements.push_back(urme_container.elements[i].clone());
|
|
endfunction
|
|
endclass
|
|
class uvm_report_message extends uvm_object;
|
|
protected uvm_report_object _report_object;
|
|
protected uvm_report_handler _report_handler;
|
|
protected uvm_report_server _report_server;
|
|
protected uvm_severity _severity;
|
|
protected string _id;
|
|
protected string _message;
|
|
protected int _verbosity;
|
|
protected string _filename;
|
|
protected int _line;
|
|
protected string _context_name;
|
|
protected uvm_action _action;
|
|
protected UVM_FILE _file;
|
|
protected uvm_report_message_element_container _report_message_element_container;
|
|
function new(string name = "uvm_report_message");
|
|
super.new(name);
|
|
_report_message_element_container = new();
|
|
endfunction
|
|
static function uvm_report_message new_report_message(string name = "uvm_report_message");
|
|
process p;
|
|
string rand_state;
|
|
p = process::self();
|
|
if (p != null)
|
|
rand_state = p.get_randstate();
|
|
new_report_message = new(name);
|
|
if (p != null)
|
|
p.set_randstate(rand_state);
|
|
endfunction
|
|
virtual function void do_print(uvm_printer printer);
|
|
uvm_verbosity l_verbosity;
|
|
super.do_print(printer);
|
|
printer.print_generic("severity", "uvm_severity",
|
|
$bits(_severity), _severity.name());
|
|
printer.print_string("id", _id);
|
|
printer.print_string("message",_message);
|
|
if ($cast(l_verbosity, _verbosity))
|
|
printer.print_generic("verbosity", "uvm_verbosity",
|
|
$bits(l_verbosity), l_verbosity.name());
|
|
else
|
|
printer.print_field("verbosity", _verbosity, $bits(_verbosity), UVM_HEX);
|
|
printer.print_string("filename", _filename);
|
|
printer.print_field("line", _line, $bits(_line), UVM_UNSIGNED);
|
|
printer.print_string("context_name", _context_name);
|
|
if (_report_message_element_container.size() != 0) begin
|
|
uvm_report_message_element_base elements[$];
|
|
elements = _report_message_element_container.get_elements();
|
|
foreach (elements[i])
|
|
elements[i].print(printer);
|
|
end
|
|
endfunction
|
|
typedef uvm_object_registry#(uvm_report_message,"uvm_report_message") type_id;
|
|
static function uvm_report_message 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_message tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_report_message";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_report_message";
|
|
endfunction : get_type_name
|
|
virtual function void do_copy (uvm_object rhs);
|
|
uvm_report_message report_message;
|
|
super.do_copy(rhs);
|
|
if(!$cast(report_message, rhs) || (rhs==null))
|
|
return;
|
|
_report_object = report_message.get_report_object();
|
|
_report_handler = report_message.get_report_handler();
|
|
_report_server = report_message.get_report_server();
|
|
_context_name = report_message.get_context();
|
|
_file = report_message.get_file();
|
|
_filename = report_message.get_filename();
|
|
_line = report_message.get_line();
|
|
_action = report_message.get_action();
|
|
_severity = report_message.get_severity();
|
|
_id = report_message.get_id();
|
|
_message = report_message.get_message();
|
|
_verbosity = report_message.get_verbosity();
|
|
_report_message_element_container.copy(report_message._report_message_element_container);
|
|
endfunction
|
|
virtual function uvm_report_object get_report_object();
|
|
return _report_object;
|
|
endfunction
|
|
virtual function void set_report_object(uvm_report_object ro);
|
|
_report_object = ro;
|
|
endfunction
|
|
virtual function uvm_report_handler get_report_handler();
|
|
return _report_handler;
|
|
endfunction
|
|
virtual function void set_report_handler(uvm_report_handler rh);
|
|
_report_handler = rh;
|
|
endfunction
|
|
virtual function uvm_report_server get_report_server();
|
|
return _report_server;
|
|
endfunction
|
|
virtual function void set_report_server(uvm_report_server rs);
|
|
_report_server = rs;
|
|
endfunction
|
|
virtual function uvm_severity get_severity();
|
|
return _severity;
|
|
endfunction
|
|
virtual function void set_severity(uvm_severity sev);
|
|
_severity = sev;
|
|
endfunction
|
|
virtual function string get_id();
|
|
return _id;
|
|
endfunction
|
|
virtual function void set_id(string id);
|
|
_id = id;
|
|
endfunction
|
|
virtual function string get_message();
|
|
return _message;
|
|
endfunction
|
|
virtual function void set_message(string msg);
|
|
_message = msg;
|
|
endfunction
|
|
virtual function int get_verbosity();
|
|
return _verbosity;
|
|
endfunction
|
|
virtual function void set_verbosity(int ver);
|
|
_verbosity = ver;
|
|
endfunction
|
|
virtual function string get_filename();
|
|
return _filename;
|
|
endfunction
|
|
virtual function void set_filename(string fname);
|
|
_filename = fname;
|
|
endfunction
|
|
virtual function int get_line();
|
|
return _line;
|
|
endfunction
|
|
virtual function void set_line(int ln);
|
|
_line = ln;
|
|
endfunction
|
|
virtual function string get_context();
|
|
return _context_name;
|
|
endfunction
|
|
virtual function void set_context(string cn);
|
|
_context_name = cn;
|
|
endfunction
|
|
virtual function uvm_action get_action();
|
|
return _action;
|
|
endfunction
|
|
virtual function void set_action(uvm_action act);
|
|
_action = act;
|
|
endfunction
|
|
virtual function UVM_FILE get_file();
|
|
return _file;
|
|
endfunction
|
|
virtual function void set_file(UVM_FILE fl);
|
|
_file = fl;
|
|
endfunction
|
|
virtual function uvm_report_message_element_container get_element_container();
|
|
return _report_message_element_container;
|
|
endfunction
|
|
virtual function void set_report_message(uvm_severity severity,
|
|
string id,
|
|
string message,
|
|
int verbosity,
|
|
string filename,
|
|
int line,
|
|
string context_name);
|
|
this._context_name = context_name;
|
|
this._filename = filename;
|
|
this._line = line;
|
|
this._severity = severity;
|
|
this._id = id;
|
|
this._message = message;
|
|
this._verbosity = verbosity;
|
|
endfunction
|
|
virtual function void m_record_message(uvm_recorder recorder);
|
|
recorder.record_string("message", _message);
|
|
endfunction
|
|
virtual function void m_record_core_properties(uvm_recorder recorder);
|
|
string l_string;
|
|
uvm_verbosity l_verbosity;
|
|
if (_context_name != "")
|
|
recorder.record_string("context_name", _context_name);
|
|
recorder.record_string("filename", _filename);
|
|
recorder.record_field("line", _line, $bits(_line), UVM_UNSIGNED);
|
|
recorder.record_string("severity", _severity.name());
|
|
if ($cast(l_verbosity, _verbosity))
|
|
recorder.record_string("verbosity", l_verbosity.name());
|
|
else begin
|
|
l_string.itoa(_verbosity);
|
|
recorder.record_string("verbosity", l_string);
|
|
end
|
|
recorder.record_string("id", _id);
|
|
m_record_message(recorder);
|
|
endfunction
|
|
virtual function void do_record(uvm_recorder recorder);
|
|
super.do_record(recorder);
|
|
m_record_core_properties(recorder);
|
|
_report_message_element_container.record(recorder);
|
|
endfunction
|
|
virtual function void add_int(string name, uvm_bitstream_t value,
|
|
int size, uvm_radix_enum radix,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
_report_message_element_container.add_int(name, value, size, radix, action);
|
|
endfunction
|
|
virtual function void add_string(string name, string value,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
_report_message_element_container.add_string(name, value, action);
|
|
endfunction
|
|
virtual function void add_object(string name, uvm_object obj,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
_report_message_element_container.add_object(name, obj, action);
|
|
endfunction
|
|
endclass
|
|
typedef class uvm_report_object;
|
|
typedef class uvm_report_handler;
|
|
typedef class uvm_report_server;
|
|
typedef class uvm_report_catcher;
|
|
typedef uvm_callbacks #(uvm_report_object, uvm_report_catcher) uvm_report_cb;
|
|
typedef uvm_callback_iter#(uvm_report_object, uvm_report_catcher) uvm_report_cb_iter ;
|
|
class sev_id_struct;
|
|
bit sev_specified ;
|
|
bit id_specified ;
|
|
uvm_severity sev ;
|
|
string id ;
|
|
bit is_on ;
|
|
endclass
|
|
virtual class uvm_report_catcher extends uvm_callback;
|
|
static local bit m_register_cb_uvm_report_catcher = uvm_callbacks#(uvm_report_object,uvm_report_catcher)::m_register_pair("uvm_report_object","uvm_report_catcher");
|
|
typedef enum { UNKNOWN_ACTION, THROW, CAUGHT} action_e;
|
|
local static uvm_report_message m_modified_report_message;
|
|
local static uvm_report_message m_orig_report_message;
|
|
local static bit m_set_action_called;
|
|
local static int m_demoted_fatal;
|
|
local static int m_demoted_error;
|
|
local static int m_demoted_warning;
|
|
local static int m_caught_fatal;
|
|
local static int m_caught_error;
|
|
local static int m_caught_warning;
|
|
const static int DO_NOT_CATCH = 1;
|
|
const static int DO_NOT_MODIFY = 2;
|
|
local static int m_debug_flags;
|
|
local static bit do_report;
|
|
function new(string name = "uvm_report_catcher");
|
|
super.new(name);
|
|
do_report = 1;
|
|
endfunction
|
|
function uvm_report_object get_client();
|
|
return m_modified_report_message.get_report_object();
|
|
endfunction
|
|
function uvm_severity get_severity();
|
|
return this.m_modified_report_message.get_severity();
|
|
endfunction
|
|
function string get_context();
|
|
string context_str;
|
|
context_str = this.m_modified_report_message.get_context();
|
|
if (context_str == "") begin
|
|
uvm_report_handler rh = this.m_modified_report_message.get_report_handler();
|
|
context_str = rh.get_full_name();
|
|
end
|
|
return context_str;
|
|
endfunction
|
|
function int get_verbosity();
|
|
return this.m_modified_report_message.get_verbosity();
|
|
endfunction
|
|
function string get_id();
|
|
return this.m_modified_report_message.get_id();
|
|
endfunction
|
|
function string get_message();
|
|
return this.m_modified_report_message.get_message();
|
|
endfunction
|
|
function uvm_action get_action();
|
|
return this.m_modified_report_message.get_action();
|
|
endfunction
|
|
function string get_fname();
|
|
return this.m_modified_report_message.get_filename();
|
|
endfunction
|
|
function int get_line();
|
|
return this.m_modified_report_message.get_line();
|
|
endfunction
|
|
function uvm_report_message_element_container get_element_container();
|
|
return this.m_modified_report_message.get_element_container();
|
|
endfunction
|
|
protected function void set_severity(uvm_severity severity);
|
|
this.m_modified_report_message.set_severity(severity);
|
|
endfunction
|
|
protected function void set_verbosity(int verbosity);
|
|
this.m_modified_report_message.set_verbosity(verbosity);
|
|
endfunction
|
|
protected function void set_id(string id);
|
|
this.m_modified_report_message.set_id(id);
|
|
endfunction
|
|
protected function void set_message(string message);
|
|
this.m_modified_report_message.set_message(message);
|
|
endfunction
|
|
protected function void set_action(uvm_action action);
|
|
this.m_modified_report_message.set_action(action);
|
|
this.m_set_action_called = 1;
|
|
endfunction
|
|
protected function void set_context(string context_str);
|
|
this.m_modified_report_message.set_context(context_str);
|
|
endfunction
|
|
protected function void add_int(string name,
|
|
uvm_bitstream_t value,
|
|
int size,
|
|
uvm_radix_enum radix,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
this.m_modified_report_message.add_int(name, value, size, radix, action);
|
|
endfunction
|
|
protected function void add_string(string name,
|
|
string value,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
this.m_modified_report_message.add_string(name, value, action);
|
|
endfunction
|
|
protected function void add_object(string name,
|
|
uvm_object obj,
|
|
uvm_action action = (UVM_LOG|UVM_RM_RECORD));
|
|
this.m_modified_report_message.add_object(name, obj, action);
|
|
endfunction
|
|
static function void print_catcher(UVM_FILE file = 0);
|
|
string msg;
|
|
string enabled;
|
|
uvm_report_catcher catcher;
|
|
static uvm_report_cb_iter iter = new(null);
|
|
string q[$];
|
|
q.push_back("-------------UVM REPORT CATCHERS----------------------------\n");
|
|
catcher = iter.first();
|
|
while(catcher != null) begin
|
|
if(catcher.callback_mode())
|
|
enabled = "ON";
|
|
else
|
|
enabled = "OFF";
|
|
q.push_back($sformatf("%20s : %s\n", catcher.get_name(),enabled));
|
|
catcher = iter.next();
|
|
end
|
|
q.push_back("--------------------------------------------------------------\n");
|
|
begin
|
|
if (uvm_root::get().uvm_report_enabled(UVM_LOW,UVM_INFO,"UVM/REPORT/CATCHER"))
|
|
uvm_root::get().uvm_report_info ("UVM/REPORT/CATCHER", uvm_pkg::m_uvm_string_queue_join(q), UVM_LOW, "t/uvm/src/base/uvm_report_catcher.svh", 371, "", 1);
|
|
end
|
|
endfunction
|
|
static function void debug_report_catcher(int what= 0);
|
|
m_debug_flags = what;
|
|
endfunction
|
|
pure virtual function action_e catch();
|
|
protected function void uvm_report_fatal(string id,
|
|
string message,
|
|
int verbosity,
|
|
string fname = "",
|
|
int line = 0,
|
|
string context_name = "",
|
|
bit report_enabled_checked = 0);
|
|
this.uvm_report(UVM_FATAL, id, message, UVM_NONE, fname, line,
|
|
context_name, report_enabled_checked);
|
|
endfunction
|
|
protected function void uvm_report_error(string id,
|
|
string message,
|
|
int verbosity,
|
|
string fname = "",
|
|
int line = 0,
|
|
string context_name = "",
|
|
bit report_enabled_checked = 0);
|
|
this.uvm_report(UVM_ERROR, id, message, UVM_NONE, fname, line,
|
|
context_name, report_enabled_checked);
|
|
endfunction
|
|
protected function void uvm_report_warning(string id,
|
|
string message,
|
|
int verbosity,
|
|
string fname = "",
|
|
int line = 0,
|
|
string context_name = "",
|
|
bit report_enabled_checked = 0);
|
|
this.uvm_report(UVM_WARNING, id, message, UVM_NONE, fname, line,
|
|
context_name, report_enabled_checked);
|
|
endfunction
|
|
protected function void uvm_report_info(string id,
|
|
string message,
|
|
int verbosity,
|
|
string fname = "",
|
|
int line = 0,
|
|
string context_name = "",
|
|
bit report_enabled_checked = 0);
|
|
this.uvm_report(UVM_INFO, id, message, verbosity, fname, line,
|
|
context_name, report_enabled_checked);
|
|
endfunction
|
|
protected function void uvm_report(uvm_severity severity,
|
|
string id,
|
|
string message,
|
|
int verbosity,
|
|
string fname = "",
|
|
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, fname, line, context_name);
|
|
this.uvm_process_report_message(l_report_message);
|
|
endfunction
|
|
protected function void uvm_process_report_message(uvm_report_message msg);
|
|
uvm_report_object ro = m_modified_report_message.get_report_object();
|
|
uvm_action a = ro.get_report_action(msg.get_severity(), msg.get_id());
|
|
if(a) begin
|
|
string composed_message;
|
|
uvm_report_server rs = m_modified_report_message.get_report_server();
|
|
msg.set_report_object(ro);
|
|
msg.set_report_handler(m_modified_report_message.get_report_handler());
|
|
msg.set_report_server(rs);
|
|
msg.set_file(ro.get_report_file_handle(msg.get_severity(), msg.get_id()));
|
|
msg.set_action(a);
|
|
if (a & (UVM_LOG|UVM_DISPLAY))
|
|
composed_message = rs.compose_report_message(msg);
|
|
rs.execute_report_message(msg, composed_message);
|
|
end
|
|
endfunction
|
|
protected function void issue();
|
|
string composed_message;
|
|
uvm_report_server rs = m_modified_report_message.get_report_server();
|
|
if(uvm_action_type'(m_modified_report_message.get_action()) != UVM_NO_ACTION)
|
|
begin
|
|
if (m_modified_report_message.get_action() & (UVM_LOG|UVM_DISPLAY))
|
|
composed_message = rs.compose_report_message(m_modified_report_message);
|
|
rs.execute_report_message(m_modified_report_message, composed_message);
|
|
end
|
|
endfunction
|
|
static function int process_all_report_catchers(uvm_report_message rm);
|
|
int iter;
|
|
uvm_report_catcher catcher;
|
|
int thrown = 1;
|
|
uvm_severity orig_severity;
|
|
static bit in_catcher;
|
|
uvm_report_object l_report_object = rm.get_report_object();
|
|
if(in_catcher == 1) begin
|
|
return 1;
|
|
end
|
|
in_catcher = 1;
|
|
uvm_callbacks_base::m_tracing = 0;
|
|
orig_severity = uvm_severity'(rm.get_severity());
|
|
m_modified_report_message = rm;
|
|
catcher = uvm_report_cb::get_first(iter,l_report_object);
|
|
if (catcher != null) begin
|
|
if(m_debug_flags & DO_NOT_MODIFY) begin
|
|
process p = process::self();
|
|
string randstate;
|
|
if (p != null)
|
|
randstate = p.get_randstate();
|
|
$cast(m_orig_report_message, rm.clone());
|
|
if (p != null)
|
|
p.set_randstate(randstate);
|
|
end
|
|
end
|
|
while(catcher != null) begin
|
|
uvm_severity prev_sev;
|
|
if (!catcher.callback_mode()) begin
|
|
catcher = uvm_report_cb::get_next(iter,l_report_object);
|
|
continue;
|
|
end
|
|
prev_sev = m_modified_report_message.get_severity();
|
|
m_set_action_called = 0;
|
|
thrown = catcher.process_report_catcher();
|
|
if (!m_set_action_called &&
|
|
m_modified_report_message.get_severity() != prev_sev &&
|
|
m_modified_report_message.get_action() ==
|
|
l_report_object.get_report_action(prev_sev, "*@&*^*^*#")) begin
|
|
m_modified_report_message.set_action(
|
|
l_report_object.get_report_action(m_modified_report_message.get_severity(), "*@&*^*^*#"));
|
|
end
|
|
if(thrown == 0) begin
|
|
case(orig_severity)
|
|
UVM_FATAL: m_caught_fatal++;
|
|
UVM_ERROR: m_caught_error++;
|
|
UVM_WARNING: m_caught_warning++;
|
|
endcase
|
|
break;
|
|
end
|
|
catcher = uvm_report_cb::get_next(iter,l_report_object);
|
|
end
|
|
case(orig_severity)
|
|
UVM_FATAL:
|
|
if(m_modified_report_message.get_severity() < orig_severity)
|
|
m_demoted_fatal++;
|
|
UVM_ERROR:
|
|
if(m_modified_report_message.get_severity() < orig_severity)
|
|
m_demoted_error++;
|
|
UVM_WARNING:
|
|
if(m_modified_report_message.get_severity() < orig_severity)
|
|
m_demoted_warning++;
|
|
endcase
|
|
in_catcher = 0;
|
|
uvm_callbacks_base::m_tracing = 1;
|
|
return thrown;
|
|
endfunction
|
|
local function int process_report_catcher();
|
|
action_e act;
|
|
act = this.catch();
|
|
if(act == UNKNOWN_ACTION)
|
|
this.uvm_report_error("RPTCTHR", {"uvm_report_this.catch() in catcher instance ",
|
|
this.get_name(), " must return THROW or CAUGHT"}, UVM_NONE, "t/uvm/src/base/uvm_report_catcher.svh", 642);
|
|
if(m_debug_flags & DO_NOT_MODIFY) begin
|
|
m_modified_report_message.copy(m_orig_report_message);
|
|
end
|
|
if(act == CAUGHT && !(m_debug_flags & DO_NOT_CATCH)) begin
|
|
return 0;
|
|
end
|
|
return 1;
|
|
endfunction
|
|
static function void summarize();
|
|
string s;
|
|
string q[$];
|
|
if(do_report) begin
|
|
q.push_back("\n--- UVM Report catcher Summary ---\n\n\n");
|
|
q.push_back($sformatf("Number of demoted UVM_FATAL reports :%5d\n", m_demoted_fatal));
|
|
q.push_back($sformatf("Number of demoted UVM_ERROR reports :%5d\n", m_demoted_error));
|
|
q.push_back($sformatf("Number of demoted UVM_WARNING reports:%5d\n", m_demoted_warning));
|
|
q.push_back($sformatf("Number of caught UVM_FATAL reports :%5d\n", m_caught_fatal));
|
|
q.push_back($sformatf("Number of caught UVM_ERROR reports :%5d\n", m_caught_error));
|
|
q.push_back($sformatf("Number of caught UVM_WARNING reports :%5d\n", m_caught_warning));
|
|
begin
|
|
if (uvm_root::get().uvm_report_enabled(UVM_LOW,UVM_INFO,"UVM/REPORT/CATCHER"))
|
|
uvm_root::get().uvm_report_info ("UVM/REPORT/CATCHER", uvm_pkg::m_uvm_string_queue_join(q), UVM_LOW, "t/uvm/src/base/uvm_report_catcher.svh", 675, "", 1);
|
|
end
|
|
end
|
|
endfunction
|
|
endclass
|
|
typedef class uvm_report_object;
|
|
typedef class uvm_default_report_server;
|
|
virtual class uvm_report_server extends uvm_object;
|
|
function string get_type_name();
|
|
return "uvm_report_server";
|
|
endfunction
|
|
function new(string name="base");
|
|
super.new(name);
|
|
endfunction
|
|
pure virtual function void set_max_quit_count(int count, bit overridable = 1);
|
|
pure virtual function int get_max_quit_count();
|
|
pure virtual function void set_quit_count(int quit_count);
|
|
pure virtual function int get_quit_count();
|
|
pure virtual function void set_severity_count(uvm_severity severity, int count);
|
|
pure virtual function int get_severity_count(uvm_severity severity);
|
|
pure virtual function void set_id_count(string id, int count);
|
|
pure virtual function int get_id_count(string id);
|
|
pure virtual function void get_id_set(output string q[$]);
|
|
pure virtual function void get_severity_set(output uvm_severity q[$]);
|
|
pure virtual function void set_message_database(uvm_tr_database database);
|
|
pure virtual function uvm_tr_database get_message_database();
|
|
function void do_copy (uvm_object rhs);
|
|
uvm_report_server rhs_;
|
|
super.do_copy(rhs);
|
|
if(!$cast(rhs_,rhs))
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REPORT/SERVER/RPTCOPY"))
|
|
uvm_report_error ("UVM/REPORT/SERVER/RPTCOPY", "cannot copy to report_server from the given datatype", UVM_NONE, "t/uvm/src/base/uvm_report_server.svh", 116, "", 1);
|
|
end
|
|
begin
|
|
uvm_severity q[$];
|
|
rhs_.get_severity_set(q);
|
|
foreach(q[s])
|
|
set_severity_count(q[s],rhs_.get_severity_count(q[s]));
|
|
end
|
|
begin
|
|
string q[$];
|
|
rhs_.get_id_set(q);
|
|
foreach(q[s])
|
|
set_id_count(q[s],rhs_.get_id_count(q[s]));
|
|
end
|
|
set_message_database(rhs_.get_message_database());
|
|
set_max_quit_count(rhs_.get_max_quit_count());
|
|
set_quit_count(rhs_.get_quit_count());
|
|
endfunction
|
|
pure virtual function void process_report_message(uvm_report_message report_message);
|
|
pure virtual function void execute_report_message(uvm_report_message report_message,
|
|
string composed_message);
|
|
pure virtual function string compose_report_message(uvm_report_message report_message,
|
|
string report_object_name = "");
|
|
pure virtual function void report_summarize(UVM_FILE file = UVM_STDOUT);
|
|
static function void set_server(uvm_report_server server);
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
|
server.copy(cs.get_report_server());
|
|
cs.set_report_server(server);
|
|
endfunction
|
|
static function uvm_report_server get_server();
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
|
return cs.get_report_server();
|
|
endfunction
|
|
endclass
|
|
class uvm_default_report_server extends uvm_report_server;
|
|
local int m_quit_count;
|
|
local int m_max_quit_count;
|
|
bit max_quit_overridable = 1;
|
|
local int m_severity_count[uvm_severity];
|
|
protected int m_id_count[string];
|
|
protected uvm_tr_database m_message_db;
|
|
protected uvm_tr_stream m_streams[string][string];
|
|
bit enable_report_id_count_summary=1;
|
|
bit record_all_messages = 0;
|
|
bit show_verbosity = 0;
|
|
bit show_terminator = 0;
|
|
function string get_type_name();
|
|
return "uvm_default_report_server";
|
|
endfunction
|
|
function new(string name = "uvm_report_server");
|
|
super.new(name);
|
|
set_max_quit_count(0);
|
|
reset_quit_count();
|
|
reset_severity_counts();
|
|
endfunction
|
|
virtual function void do_print (uvm_printer printer);
|
|
uvm_severity l_severity_count_index;
|
|
string l_id_count_index;
|
|
printer.print_field("quit_count", m_quit_count, $bits(m_quit_count), UVM_DEC,
|
|
".", "int");
|
|
printer.print_field("max_quit_count", m_max_quit_count,
|
|
$bits(m_max_quit_count), UVM_DEC, ".", "int");
|
|
printer.print_field("max_quit_overridable", max_quit_overridable,
|
|
$bits(max_quit_overridable), UVM_BIN, ".", "bit");
|
|
if (m_severity_count.first(l_severity_count_index)) begin
|
|
printer.print_array_header("severity_count",m_severity_count.size(),"severity counts");
|
|
do
|
|
printer.print_field($sformatf("[%s]",l_severity_count_index.name()),
|
|
m_severity_count[l_severity_count_index], 32, UVM_DEC);
|
|
while (m_severity_count.next(l_severity_count_index));
|
|
printer.print_array_footer();
|
|
end
|
|
if (m_id_count.first(l_id_count_index)) begin
|
|
printer.print_array_header("id_count",m_id_count.size(),"id counts");
|
|
do
|
|
printer.print_field($sformatf("[%s]",l_id_count_index),
|
|
m_id_count[l_id_count_index], 32, UVM_DEC);
|
|
while (m_id_count.next(l_id_count_index));
|
|
printer.print_array_footer();
|
|
end
|
|
printer.print_field("enable_report_id_count_summary", enable_report_id_count_summary,
|
|
$bits(enable_report_id_count_summary), UVM_BIN, ".", "bit");
|
|
printer.print_field("record_all_messages", record_all_messages,
|
|
$bits(record_all_messages), UVM_BIN, ".", "bit");
|
|
printer.print_field("show_verbosity", show_verbosity,
|
|
$bits(show_verbosity), UVM_BIN, ".", "bit");
|
|
printer.print_field("show_terminator", show_terminator,
|
|
$bits(show_terminator), UVM_BIN, ".", "bit");
|
|
endfunction
|
|
function int get_max_quit_count();
|
|
return m_max_quit_count;
|
|
endfunction
|
|
function void set_max_quit_count(int count, bit overridable = 1);
|
|
if (max_quit_overridable == 0) begin
|
|
uvm_report_info("NOMAXQUITOVR",
|
|
$sformatf("The max quit count setting of %0d is not overridable to %0d due to a previous setting.",
|
|
m_max_quit_count, count), UVM_NONE);
|
|
return;
|
|
end
|
|
max_quit_overridable = overridable;
|
|
m_max_quit_count = count < 0 ? 0 : count;
|
|
endfunction
|
|
function int get_quit_count();
|
|
return m_quit_count;
|
|
endfunction
|
|
function void set_quit_count(int quit_count);
|
|
m_quit_count = quit_count < 0 ? 0 : quit_count;
|
|
endfunction
|
|
function void incr_quit_count();
|
|
m_quit_count++;
|
|
endfunction
|
|
function void reset_quit_count();
|
|
m_quit_count = 0;
|
|
endfunction
|
|
function bit is_quit_count_reached();
|
|
return (m_quit_count >= 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 <requested_type>,<override_type>,<instance_path>"}, UVM_NONE);
|
|
return;
|
|
end
|
|
uvm_report_info("INSTOVR", {"Applying instance override from the command line: +uvm_set_inst_override=", ovr}, UVM_NONE);
|
|
factory.set_inst_override_by_name(split_val[0], split_val[1], split_val[2]);
|
|
endfunction
|
|
function void uvm_root::m_process_type_override(string ovr);
|
|
string split_val[$];
|
|
int replace=1;
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
|
uvm_factory factory=cs.get_factory();
|
|
uvm_split_string(ovr, ",", split_val);
|
|
if(split_val.size() > 3 || split_val.size() < 2) begin
|
|
uvm_report_error("UVM_CMDLINE_PROC", {"Invalid setting for +uvm_set_type_override=", ovr,
|
|
", setting must specify <requested_type>,<override_type>[,<replace>]"}, UVM_NONE);
|
|
return;
|
|
end
|
|
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=<comp>,<id>,<severity>,<action[|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=<comp>,<id>,<severity>,<action[|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=<comp>,<id>,<severity>,<action[|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=<comp>,<id>,<orig_severity>,<new_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=<comp>,<id>,<orig_severity>,<new_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=<comp>,<id>,<orig_severity>,<new_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);
|
|
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);
|
|
@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;
|
|
rand byte unsigned m_data[];
|
|
rand int unsigned m_length;
|
|
rand uvm_tlm_response_status_e m_response_status;
|
|
bit m_dmi;
|
|
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];
|
|
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<m_length; i++)
|
|
begin
|
|
bit __array[];
|
|
{ << bit { __array}} = m_data[i];
|
|
__array = new [8] (__array);
|
|
packer.pack_bits(__array, 8);
|
|
end
|
|
begin
|
|
bit __array[];
|
|
{ << bit { __array}} = m_response_status;
|
|
__array = new [32] (__array);
|
|
packer.pack_bits(__array, 32);
|
|
end
|
|
begin
|
|
bit __array[];
|
|
{ << bit { __array}} = m_byte_enable_length;
|
|
__array = new [32] (__array);
|
|
packer.pack_bits(__array, 32);
|
|
end
|
|
for (int i=0; i<m_byte_enable_length; i++)
|
|
begin
|
|
bit __array[];
|
|
{ << bit { __array}} = m_byte_enable[i];
|
|
__array = new [8] (__array);
|
|
packer.pack_bits(__array, 8);
|
|
end
|
|
begin
|
|
bit __array[];
|
|
{ << bit { __array}} = m_streaming_width;
|
|
__array = new [32] (__array);
|
|
packer.pack_bits(__array, 32);
|
|
end
|
|
endfunction
|
|
function void do_unpack(uvm_packer packer);
|
|
super.do_unpack(packer);
|
|
begin
|
|
bit __array[] = new [64];
|
|
packer.unpack_bits(__array, 64);
|
|
__array = new [$bits(m_address)] (__array);
|
|
m_address = { << bit { __array }};
|
|
end
|
|
begin
|
|
bit __array[] = new [32];
|
|
packer.unpack_bits(__array, 32);
|
|
__array = new [$bits(m_command)] (__array);
|
|
m_command = uvm_tlm_command_e'({ << bit { __array }});
|
|
end
|
|
begin
|
|
bit __array[] = new [32];
|
|
packer.unpack_bits(__array, 32);
|
|
__array = new [$bits(m_length)] (__array);
|
|
m_length = { << bit { __array }};
|
|
end
|
|
begin
|
|
bit __array[] = new [1];
|
|
packer.unpack_bits(__array, 1);
|
|
__array = new [$bits(m_dmi)] (__array);
|
|
m_dmi = { << bit { __array }};
|
|
end
|
|
if (m_data.size() < m_length)
|
|
m_data = new[m_length];
|
|
foreach (m_data[i])
|
|
begin
|
|
bit __array[] = new [8];
|
|
packer.unpack_bits(__array, 8);
|
|
__array = new [$bits(m_data[i])] (__array);
|
|
m_data[i] = { << bit { __array }};
|
|
end
|
|
begin
|
|
bit __array[] = new [32];
|
|
packer.unpack_bits(__array, 32);
|
|
__array = new [$bits(m_response_status)] (__array);
|
|
m_response_status = uvm_tlm_response_status_e'({ << bit { __array }});
|
|
end
|
|
begin
|
|
bit __array[] = new [32];
|
|
packer.unpack_bits(__array, 32);
|
|
__array = new [$bits(m_byte_enable_length)] (__array);
|
|
m_byte_enable_length = { << bit { __array }};
|
|
end
|
|
if (m_byte_enable.size() < m_byte_enable_length)
|
|
m_byte_enable = new[m_byte_enable_length];
|
|
for (int i=0; i<m_byte_enable_length; i++)
|
|
begin
|
|
bit __array[] = new [8];
|
|
packer.unpack_bits(__array, 8);
|
|
__array = new [$bits(m_byte_enable[i])] (__array);
|
|
m_byte_enable[i] = { << bit { __array }};
|
|
end
|
|
begin
|
|
bit __array[] = new [32];
|
|
packer.unpack_bits(__array, 32);
|
|
__array = new [$bits(m_streaming_width)] (__array);
|
|
m_streaming_width = { << bit { __array }};
|
|
end
|
|
endfunction
|
|
function void do_record(uvm_recorder recorder);
|
|
if (!is_recording_enabled())
|
|
return;
|
|
super.do_record(recorder);
|
|
if (recorder != null && recorder.is_open()) begin
|
|
if (recorder.use_record_attribute())
|
|
recorder.record_generic("address", $sformatf("%p", m_address));
|
|
else
|
|
if ($bits(m_address) > 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;
|
|
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) - 1);
|
|
endfunction: set_reset
|
|
function bit uvm_reg_field::needs_update();
|
|
needs_update = (m_mirrored != m_desired) | m_volatile;
|
|
endfunction: needs_update
|
|
typedef class uvm_reg_map_info;
|
|
function bit uvm_reg_field::Xcheck_accessX(input uvm_reg_item rw,
|
|
output uvm_reg_map_info map_info);
|
|
if (rw.path == UVM_DEFAULT_DOOR) begin
|
|
uvm_reg_block blk = m_parent.get_block();
|
|
rw.path = blk.get_default_door();
|
|
end
|
|
if (rw.path == UVM_BACKDOOR) begin
|
|
if (m_parent.get_backdoor() == null && !m_parent.has_hdl_path()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", {"No backdoor access available for field '",get_full_name(), "' . Using frontdoor instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1001, "", 1);
|
|
end
|
|
rw.path = UVM_FRONTDOOR;
|
|
end
|
|
else
|
|
rw.map = uvm_reg_map::backdoor();
|
|
end
|
|
if (rw.path != UVM_BACKDOOR) begin
|
|
rw.local_map = m_parent.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_reg_field.svh", 1015, "", 1);
|
|
end
|
|
rw.status = UVM_NOT_OK;
|
|
return 0;
|
|
end
|
|
map_info = rw.local_map.get_reg_map_info(m_parent);
|
|
if (map_info.frontdoor == null && map_info.unmapped) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Field '",get_full_name(), "' in register that is unmapped in map '", rw.map.get_full_name(), "' and does not have a user-defined frontdoor"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1026, "", 1);
|
|
end
|
|
rw.status = UVM_NOT_OK;
|
|
return 0;
|
|
end
|
|
if (rw.map == null)
|
|
rw.map = rw.local_map;
|
|
end
|
|
return 1;
|
|
endfunction
|
|
task uvm_reg_field::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;
|
|
rw = uvm_reg_item::type_id_create("field_write_item",,get_full_name());
|
|
rw.element = this;
|
|
rw.element_kind = UVM_FIELD;
|
|
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;
|
|
endtask
|
|
task uvm_reg_field::do_write(uvm_reg_item rw);
|
|
uvm_reg_data_t value_adjust;
|
|
uvm_reg_map_info map_info;
|
|
uvm_reg_field fields[$];
|
|
bit bad_side_effect;
|
|
m_parent.XatomicX(1);
|
|
m_fname = rw.fname;
|
|
m_lineno = rw.lineno;
|
|
if (!Xcheck_accessX(rw,map_info))
|
|
return;
|
|
m_write_in_progress = 1'b1;
|
|
if (rw.value[0] >> 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_size)-1);
|
|
end
|
|
m_parent.get_fields(fields);
|
|
foreach (fields[i]) begin
|
|
if (fields[i] == this) begin
|
|
value_adjust |= rw.value[0] << m_lsb;
|
|
continue;
|
|
end
|
|
case (fields[i].get_access(rw.local_map))
|
|
"RO", "RC", "RS", "W1C", "W1S", "W1T", "W1SRC", "W1CRC":
|
|
value_adjust |= 0;
|
|
"W0C", "W0S", "W0T", "W0SRC", "W0CRS":
|
|
value_adjust |= ((1<<fields[i].get_n_bits())-1) << fields[i].get_lsb_pos();
|
|
"WC", "WS", "WCRS", "WSRC", "WOC", "WOS":
|
|
bad_side_effect = 1;
|
|
default:
|
|
value_adjust |= fields[i].m_mirrored << fields[i].get_lsb_pos();
|
|
endcase
|
|
end
|
|
if (!is_indv_accessible(rw.path,rw.local_map)) begin
|
|
rw.element_kind = UVM_REG;
|
|
rw.element = m_parent;
|
|
rw.value[0] = value_adjust;
|
|
m_parent.do_write(rw);
|
|
if (bad_side_effect) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", $sformatf("Writing field \"%s\" will cause unintended side effects in adjoining Write-to-Clear or Write-to-Set fields in the same register", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1145, "", 1);
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
uvm_reg_map system_map = rw.local_map.get_root_map();
|
|
uvm_reg_field_cb_iter cbs = new(this);
|
|
m_parent.Xset_busyX(1);
|
|
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;
|
|
m_parent.Xset_busyX(0);
|
|
m_parent.XatomicX(0);
|
|
return;
|
|
end
|
|
rw.local_map.do_write(rw);
|
|
if (system_map.get_auto_predict())
|
|
do_predict(rw, UVM_PREDICT_WRITE);
|
|
post_write(rw);
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.post_write(rw);
|
|
m_parent.Xset_busyX(0);
|
|
end
|
|
m_write_in_progress = 1'b0;
|
|
m_parent.XatomicX(0);
|
|
endtask: do_write
|
|
task uvm_reg_field::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);
|
|
uvm_reg_item rw;
|
|
rw = uvm_reg_item::type_id_create("field_read_item",,get_full_name());
|
|
rw.element = this;
|
|
rw.element_kind = UVM_FIELD;
|
|
rw.kind = UVM_READ;
|
|
rw.value[0] = 0;
|
|
rw.path = path;
|
|
rw.map = map;
|
|
rw.parent = parent;
|
|
rw.prior = prior;
|
|
rw.extension = extension;
|
|
rw.fname = fname;
|
|
rw.lineno = lineno;
|
|
do_read(rw);
|
|
value = rw.value[0];
|
|
status = rw.status;
|
|
endtask: read
|
|
task uvm_reg_field::do_read(uvm_reg_item rw);
|
|
uvm_reg_map_info map_info;
|
|
bit bad_side_effect;
|
|
m_parent.XatomicX(1);
|
|
m_fname = rw.fname;
|
|
m_lineno = rw.lineno;
|
|
m_read_in_progress = 1'b1;
|
|
if (!Xcheck_accessX(rw,map_info))
|
|
return;
|
|
if (!is_indv_accessible(rw.path,rw.local_map)) begin
|
|
rw.element_kind = UVM_REG;
|
|
rw.element = m_parent;
|
|
bad_side_effect = 1;
|
|
m_parent.do_read(rw);
|
|
rw.value[0] = (rw.value[0] >> m_lsb) & ((1<<m_size))-1;
|
|
end
|
|
else begin
|
|
uvm_reg_map system_map = rw.local_map.get_root_map();
|
|
uvm_reg_field_cb_iter cbs = new(this);
|
|
m_parent.Xset_busyX(1);
|
|
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;
|
|
m_parent.Xset_busyX(0);
|
|
m_parent.XatomicX(0);
|
|
return;
|
|
end
|
|
rw.local_map.do_read(rw);
|
|
if (system_map.get_auto_predict())
|
|
do_predict(rw, UVM_PREDICT_READ);
|
|
post_read(rw);
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.post_read(rw);
|
|
m_parent.Xset_busyX(0);
|
|
end
|
|
m_read_in_progress = 1'b0;
|
|
m_parent.XatomicX(0);
|
|
if (bad_side_effect) begin
|
|
uvm_reg_field fields[$];
|
|
m_parent.get_fields(fields);
|
|
foreach (fields[i]) begin
|
|
string mode;
|
|
if (fields[i] == this)
|
|
continue;
|
|
mode = fields[i].get_access();
|
|
if (mode == "RC" ||
|
|
mode == "RS" ||
|
|
mode == "WRC" ||
|
|
mode == "WRS" ||
|
|
mode == "WSRC" ||
|
|
mode == "WCRS" ||
|
|
mode == "W1SRC" ||
|
|
mode == "W1CRS" ||
|
|
mode == "W0SRC" ||
|
|
mode == "W0CRS") begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", {"Reading field '",get_full_name(), "' will cause unintended side effects in adjoining ", "Read-to-Clear or Read-to-Set fields in the same register"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1320, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
endtask: do_read
|
|
function bit uvm_reg_field::is_indv_accessible(uvm_door_e path,
|
|
uvm_reg_map local_map);
|
|
if (path == UVM_BACKDOOR) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", {"Individual BACKDOOR field access not available for field '", get_full_name(), "'. Accessing complete register instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1335, "", 1);
|
|
end
|
|
return 0;
|
|
end
|
|
if (!m_individually_accessible) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", {"Individual field access not available for field '", get_full_name(), "'. Accessing complete register instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1342, "", 1);
|
|
end
|
|
return 0;
|
|
end
|
|
if (m_parent.get_frontdoor(local_map) != null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", {"Individual field access not available for field '", get_name(), "' because register '", m_parent.get_full_name(), "' has a user-defined front-door. Accessing complete register instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1351, "", 1);
|
|
end
|
|
return 0;
|
|
end
|
|
begin
|
|
uvm_reg_map system_map = local_map.get_root_map();
|
|
uvm_reg_adapter adapter = system_map.get_adapter();
|
|
if (adapter.supports_byte_enable)
|
|
return 1;
|
|
end
|
|
begin
|
|
int fld_idx;
|
|
int bus_width = local_map.get_n_bytes();
|
|
uvm_reg_field fields[$];
|
|
bit sole_field;
|
|
m_parent.get_fields(fields);
|
|
if (fields.size() == 1) begin
|
|
sole_field = 1;
|
|
end
|
|
else begin
|
|
int prev_lsb,this_lsb,next_lsb;
|
|
int prev_sz,this_sz,next_sz;
|
|
int bus_sz = bus_width*8;
|
|
foreach (fields[i]) begin
|
|
if (fields[i] == this) begin
|
|
fld_idx = i;
|
|
break;
|
|
end
|
|
end
|
|
this_lsb = fields[fld_idx].get_lsb_pos();
|
|
this_sz = fields[fld_idx].get_n_bits();
|
|
if (fld_idx>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_size)-1);
|
|
end
|
|
m_parent.XatomicX(1);
|
|
m_parent.m_is_locked_by_field = 1'b1;
|
|
tmp = 0;
|
|
m_parent.peek(status, tmp, kind, parent, extension, fname, lineno);
|
|
if (status == UVM_NOT_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"uvm_reg_field::poke(): Peek of register '", m_parent.get_full_name(),"' returned status ",status.name()}, UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1469, "", 1);
|
|
end
|
|
m_parent.XatomicX(0);
|
|
m_parent.m_is_locked_by_field = 1'b0;
|
|
return;
|
|
end
|
|
tmp &= ~(((1<<m_size)-1) << m_lsb);
|
|
tmp |= value << m_lsb;
|
|
m_parent.poke(status, tmp, kind, parent, extension, fname, lineno);
|
|
m_parent.XatomicX(0);
|
|
m_parent.m_is_locked_by_field = 1'b0;
|
|
endtask: poke
|
|
task uvm_reg_field::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_data_t reg_value;
|
|
m_fname = fname;
|
|
m_lineno = lineno;
|
|
m_parent.peek(status, reg_value, kind, parent, extension, fname, lineno);
|
|
value = (reg_value >> m_lsb) & ((1<<m_size))-1;
|
|
endtask: peek
|
|
task uvm_reg_field::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);
|
|
m_fname = fname;
|
|
m_lineno = lineno;
|
|
m_parent.mirror(status, check, path, map, parent, prior, extension,
|
|
fname, lineno);
|
|
endtask: mirror
|
|
function void uvm_reg_field::set_compare(uvm_check_e check=UVM_CHECK);
|
|
m_check = check;
|
|
endfunction
|
|
function uvm_check_e uvm_reg_field::get_compare();
|
|
return m_check;
|
|
endfunction
|
|
function void uvm_reg_field::pre_randomize();
|
|
value = m_desired;
|
|
endfunction: pre_randomize
|
|
function void uvm_reg_field::post_randomize();
|
|
m_desired = value;
|
|
endfunction: post_randomize
|
|
function void uvm_reg_field::do_print (uvm_printer printer);
|
|
printer.print_generic(get_name(), get_type_name(), -1, convert2string());
|
|
endfunction
|
|
function string uvm_reg_field::convert2string();
|
|
string fmt;
|
|
string res_str;
|
|
string t_str;
|
|
bit with_debug_info;
|
|
string prefix;
|
|
uvm_reg reg_=get_register();
|
|
$sformat(fmt, "%0d'h%%%0dh", get_n_bits(),
|
|
(get_n_bits()-1)/4 + 1);
|
|
$sformat(convert2string, {"%s %s %s[%0d:%0d]=",fmt,"%s"}, prefix,
|
|
get_access(),
|
|
reg_.get_name(),
|
|
get_lsb_pos() + get_n_bits() - 1,
|
|
get_lsb_pos(), m_desired,
|
|
(m_desired != m_mirrored) ? $sformatf({" (Mirror: ",fmt,")"},
|
|
m_mirrored) : "");
|
|
if (m_read_in_progress == 1'b1) begin
|
|
if (m_fname != "" && m_lineno != 0)
|
|
$sformat(res_str, " from %s:%0d",m_fname, m_lineno);
|
|
convert2string = {convert2string, "\n", "currently being read", res_str};
|
|
end
|
|
if (m_write_in_progress == 1'b1) begin
|
|
if (m_fname != "" && m_lineno != 0)
|
|
$sformat(res_str, " from %s:%0d",m_fname, m_lineno);
|
|
convert2string = {convert2string, "\n", res_str, "currently being written"};
|
|
end
|
|
endfunction: convert2string
|
|
function uvm_object uvm_reg_field::clone();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel field cannot be cloned", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1596, "", 1);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function void uvm_reg_field::do_copy(uvm_object rhs);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel field copy not yet implemented", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1603, "", 1);
|
|
end
|
|
endfunction
|
|
function bit uvm_reg_field::do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel field compare not yet implemented", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1612, "", 1);
|
|
end
|
|
return 0;
|
|
endfunction
|
|
function void uvm_reg_field::do_pack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel field cannot be packed", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1621, "", 1);
|
|
end
|
|
endfunction
|
|
function void uvm_reg_field::do_unpack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel field cannot be unpacked", UVM_NONE, "t/uvm/src/reg/uvm_reg_field.svh", 1628, "", 1);
|
|
end
|
|
endfunction
|
|
typedef class uvm_vreg_field_cbs;
|
|
class uvm_vreg_field extends uvm_object;
|
|
typedef uvm_object_registry#(uvm_vreg_field,"uvm_vreg_field") type_id;
|
|
static function uvm_vreg_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_vreg_field tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_vreg_field";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_vreg_field";
|
|
endfunction : get_type_name
|
|
static local bit m_register_cb_uvm_vreg_field_cbs = uvm_callbacks#(uvm_vreg_field,uvm_vreg_field_cbs)::m_register_pair("uvm_vreg_field","uvm_vreg_field_cbs");
|
|
local uvm_vreg parent;
|
|
local int unsigned lsb;
|
|
local int unsigned size;
|
|
local string fname;
|
|
local int lineno;
|
|
local bit read_in_progress;
|
|
local bit write_in_progress;
|
|
extern function new(string name = "uvm_vreg_field");
|
|
extern function void configure(uvm_vreg parent,
|
|
int unsigned size,
|
|
int unsigned lsb_pos);
|
|
extern virtual function string get_full_name();
|
|
extern virtual function uvm_vreg get_parent();
|
|
extern virtual function uvm_vreg get_register();
|
|
extern virtual function int unsigned get_lsb_pos_in_register();
|
|
extern virtual function int unsigned get_n_bits();
|
|
extern virtual function string get_access(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);
|
|
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,
|
|
uvm_door_e path,
|
|
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_field
|
|
virtual class uvm_vreg_field_cbs extends uvm_callback;
|
|
string fname;
|
|
int lineno;
|
|
typedef uvm_abstract_object_registry#(uvm_vreg_field_cbs,"uvm_vreg_field_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_field_cbs";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_vreg_field_cbs";
|
|
endfunction : get_type_name
|
|
function new(string name = "uvm_vreg_field_cbs");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task pre_write(uvm_vreg_field field,
|
|
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_field field,
|
|
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_field field,
|
|
longint unsigned idx,
|
|
ref uvm_door_e path,
|
|
ref uvm_reg_map map);
|
|
endtask: pre_read
|
|
virtual task post_read(uvm_vreg_field field,
|
|
longint unsigned idx,
|
|
ref uvm_reg_data_t rdat,
|
|
uvm_door_e path,
|
|
uvm_reg_map map,
|
|
ref uvm_status_e status);
|
|
endtask: post_read
|
|
endclass: uvm_vreg_field_cbs
|
|
typedef uvm_callbacks#(uvm_vreg_field, uvm_vreg_field_cbs) uvm_vreg_field_cb ;
|
|
typedef uvm_callback_iter#(uvm_vreg_field, uvm_vreg_field_cbs) uvm_vreg_field_cb_iter ;
|
|
function uvm_vreg_field::new(string name="uvm_vreg_field");
|
|
super.new(name);
|
|
endfunction: new
|
|
function void uvm_vreg_field::configure(uvm_vreg parent,
|
|
int unsigned size,
|
|
int unsigned lsb_pos);
|
|
this.parent = parent;
|
|
if (size == 0) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", $sformatf("Virtual field \"%s\" cannot have 0 bits", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 321, "", 1);
|
|
end
|
|
size = 1;
|
|
end
|
|
if (size > 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<<this.size)-1);
|
|
end
|
|
tmp = 0;
|
|
this.pre_write(idx, value, 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(this, idx, value, 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);
|
|
rm_path = UVM_DEFAULT_DOOR;
|
|
if (mem.get_backdoor() != null) rm_path = UVM_BACKDOOR;
|
|
rmwbits = flsb % segsiz;
|
|
segn = (rmwbits + this.get_n_bits() - 1) / segsiz + 1;
|
|
if (rmwbits > 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<<rmwbits)-1));
|
|
end
|
|
fmsb = rmwbits + this.get_n_bits() - 1;
|
|
rmwbits = (fmsb+1) % segsiz;
|
|
if (rmwbits > 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<<rmwbits)-1)) << ((segn-1)*segsiz);
|
|
end
|
|
tmp = value;
|
|
repeat (segn) begin
|
|
mem.write(st, segoff, tmp, path, map, parent,, extension, fname, lineno);
|
|
if (st != UVM_IS_OK && st != UVM_HAS_X) status = UVM_NOT_OK;
|
|
segoff++;
|
|
tmp = tmp >> 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.get_n_bits()) - 1;
|
|
this.post_read(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_read(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("Read virtual field \"%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_field.svh", 603, "", 1);
|
|
end
|
|
read_in_progress = 1'b0;
|
|
this.fname = "";
|
|
this.lineno = 0;
|
|
endtask: read
|
|
task uvm_vreg_field::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_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;
|
|
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::poke() on unimplemented virtual register \"%s\"", this.get_full_name()), UVM_NONE, "t/uvm/src/reg/uvm_vreg_field.svh", 634, "", 1);
|
|
end
|
|
status = UVM_NOT_OK;
|
|
return;
|
|
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", 644, "", 1);
|
|
end
|
|
value &= value & ((1<<this.size)-1);
|
|
end
|
|
tmp = 0;
|
|
segsiz = mem.get_n_bytes() * 8;
|
|
flsb = this.get_lsb_pos_in_register();
|
|
segoff = this.parent.get_offset_in_memory(idx) + (flsb / segsiz);
|
|
rmwbits = flsb % segsiz;
|
|
segn = (rmwbits + this.get_n_bits() - 1) / segsiz + 1;
|
|
if (rmwbits > 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<<rmwbits)-1));
|
|
end
|
|
fmsb = rmwbits + this.get_n_bits() - 1;
|
|
rmwbits = (fmsb+1) % segsiz;
|
|
if (rmwbits > 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<<rmwbits)-1)) << ((segn-1)*segsiz);
|
|
end
|
|
tmp = value;
|
|
repeat (segn) begin
|
|
mem.poke(st, segoff, tmp, "", parent, extension, fname, lineno);
|
|
if (st != UVM_IS_OK && st != UVM_HAS_X) status = UVM_NOT_OK;
|
|
segoff++;
|
|
tmp = tmp >> 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<<this.get_n_bits()) - 1;
|
|
this.parent.XatomicX(0);
|
|
begin
|
|
if (uvm_report_enabled(UVM_MEDIUM,UVM_INFO,"RegModel"))
|
|
uvm_report_info ("RegModel", $sformatf("Peeked virtual field \"%s\"[%0d]: 'h%h", this.get_full_name(), idx, value), UVM_MEDIUM, "t/uvm/src/reg/uvm_vreg_field.svh", 775, "", 1);
|
|
end
|
|
this.fname = "";
|
|
this.lineno = 0;
|
|
endtask: peek
|
|
function void uvm_vreg_field::do_print (uvm_printer printer);
|
|
super.do_print(printer);
|
|
printer.print_generic("initiator", parent.get_type_name(), -1, convert2string());
|
|
endfunction
|
|
function string uvm_vreg_field::convert2string();
|
|
string res_str;
|
|
string t_str;
|
|
bit with_debug_info = 1'b0;
|
|
$sformat(convert2string, {"%s[%0d-%0d]"},
|
|
this.get_name(),
|
|
this.get_lsb_pos_in_register() + this.get_n_bits() - 1,
|
|
this.get_lsb_pos_in_register());
|
|
if (read_in_progress == 1'b1) begin
|
|
if (fname != "" && lineno != 0)
|
|
$sformat(res_str, "%s:%0d ",fname, lineno);
|
|
convert2string = {convert2string, "\n", res_str, "currently executing read method"};
|
|
end
|
|
if ( write_in_progress == 1'b1) begin
|
|
if (fname != "" && lineno != 0)
|
|
$sformat(res_str, "%s:%0d ",fname, lineno);
|
|
convert2string = {convert2string, "\n", res_str, "currently executing write method"};
|
|
end
|
|
endfunction
|
|
function uvm_object uvm_vreg_field::clone();
|
|
return null;
|
|
endfunction
|
|
function void uvm_vreg_field::do_copy (uvm_object rhs);
|
|
endfunction
|
|
function bit uvm_vreg_field::do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
return 0;
|
|
endfunction
|
|
function void uvm_vreg_field::do_pack (uvm_packer packer);
|
|
endfunction
|
|
function void uvm_vreg_field::do_unpack (uvm_packer packer);
|
|
endfunction
|
|
typedef class uvm_reg_cbs;
|
|
typedef class uvm_reg_frontdoor;
|
|
class uvm_reg extends uvm_object;
|
|
local bit m_locked;
|
|
local uvm_reg_block m_parent;
|
|
local uvm_reg_file m_regfile_parent;
|
|
local int unsigned m_n_bits;
|
|
local int unsigned m_n_used_bits;
|
|
protected bit m_maps[uvm_reg_map];
|
|
protected uvm_reg_field m_fields[$];
|
|
local int m_has_cover;
|
|
local int m_cover_on;
|
|
local semaphore m_atomic;
|
|
local process m_process;
|
|
local string m_fname;
|
|
local int m_lineno;
|
|
local bit m_read_in_progress;
|
|
local bit m_write_in_progress;
|
|
protected bit m_update_in_progress;
|
|
bit m_is_busy;
|
|
bit m_is_locked_by_field;
|
|
local uvm_reg_backdoor m_backdoor;
|
|
local static int unsigned m_max_size;
|
|
local uvm_object_string_pool
|
|
#(uvm_queue #(uvm_hdl_path_concat)) m_hdl_paths_pool;
|
|
extern function new (string name="",
|
|
int unsigned n_bits,
|
|
int has_coverage);
|
|
extern function void configure (uvm_reg_block blk_parent,
|
|
uvm_reg_file regfile_parent = null,
|
|
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 blk_parent,
|
|
uvm_reg_file regfile_parent);
|
|
extern virtual function void add_field (uvm_reg_field field);
|
|
extern virtual function void add_map (uvm_reg_map map);
|
|
extern function void Xlock_modelX;
|
|
virtual function void unregister(uvm_reg_map map);
|
|
m_maps.delete(map);
|
|
endfunction
|
|
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 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 uvm_reg_map get_local_map (uvm_reg_map map);
|
|
extern virtual function uvm_reg_map get_default_map ();
|
|
extern virtual function string get_rights (uvm_reg_map map = null);
|
|
extern virtual function int unsigned get_n_bits ();
|
|
extern virtual function int unsigned get_n_bytes();
|
|
extern static function int unsigned get_max_size();
|
|
extern virtual function void get_fields (ref uvm_reg_field fields[$]);
|
|
extern virtual function uvm_reg_field get_field_by_name(string name);
|
|
extern function string Xget_fields_accessX(uvm_reg_map map);
|
|
extern virtual function uvm_reg_addr_t get_offset (uvm_reg_map map = null);
|
|
extern virtual function uvm_reg_addr_t get_address (uvm_reg_map map = null);
|
|
extern virtual function int get_addresses (uvm_reg_map map = null,
|
|
ref uvm_reg_addr_t addr[]);
|
|
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 bit needs_update();
|
|
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 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 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);
|
|
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 virtual 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 function bit is_busy();
|
|
extern function void Xset_busyX(bit busy);
|
|
extern task XreadX (output uvm_status_e status,
|
|
output uvm_reg_data_t value,
|
|
input uvm_door_e path,
|
|
input uvm_reg_map map,
|
|
input uvm_sequence_base parent = null,
|
|
input int prior = -1,
|
|
input uvm_object extension = null,
|
|
input string fname = "",
|
|
input int lineno = 0);
|
|
extern task XatomicX(bit on);
|
|
extern virtual function bit Xcheck_accessX
|
|
(input uvm_reg_item rw,
|
|
output uvm_reg_map_info map_info);
|
|
extern function bit Xis_locked_by_fieldX();
|
|
extern virtual function bit do_check(uvm_reg_data_t expected,
|
|
uvm_reg_data_t actual,
|
|
uvm_reg_map map);
|
|
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 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_hdl_path_kinds (ref string kinds[$]);
|
|
extern function void get_full_hdl_path (ref uvm_hdl_path_concat paths[$],
|
|
input string kind = "",
|
|
input string separator = ".");
|
|
extern virtual 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);
|
|
virtual task backdoor_watch(); endtask
|
|
extern static function void include_coverage(string scope,
|
|
uvm_reg_cvr_t models,
|
|
uvm_object accessor = null);
|
|
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_data_t data,
|
|
uvm_reg_data_t byte_en,
|
|
bit is_read,
|
|
uvm_reg_map map);
|
|
endfunction
|
|
virtual function void sample_values();
|
|
endfunction
|
|
function void XsampleX(uvm_reg_data_t data,
|
|
uvm_reg_data_t byte_en,
|
|
bit is_read,
|
|
uvm_reg_map map);
|
|
sample(data, byte_en, is_read, map);
|
|
endfunction
|
|
static local bit m_register_cb_uvm_reg_cbs = uvm_callbacks#(uvm_reg,uvm_reg_cbs)::m_register_pair("uvm_reg","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
|
|
function uvm_reg::new(string name="", int unsigned n_bits, int has_coverage);
|
|
super.new(name);
|
|
if (n_bits == 0) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", $sformatf("Register \"%s\" cannot have 0 bits", get_name()), UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 599, "", 1);
|
|
end
|
|
n_bits = 1;
|
|
end
|
|
m_n_bits = n_bits;
|
|
m_has_cover = has_coverage;
|
|
m_atomic = new(1);
|
|
m_n_used_bits = 0;
|
|
m_locked = 0;
|
|
m_is_busy = 0;
|
|
m_is_locked_by_field = 1'b0;
|
|
m_hdl_paths_pool = new("hdl_paths");
|
|
if (n_bits > 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<hdl_paths.size();i++) begin
|
|
paths.push_back(hdl_paths.get(i));
|
|
end
|
|
endfunction
|
|
function void uvm_reg::get_full_hdl_path(ref uvm_hdl_path_concat paths[$],
|
|
input string kind = "",
|
|
input string separator = ".");
|
|
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 ",get_full_name()," does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 905, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
begin
|
|
uvm_queue #(uvm_hdl_path_concat) hdl_paths = m_hdl_paths_pool.get(kind);
|
|
string parent_paths[$];
|
|
if (m_regfile_parent != null)
|
|
m_regfile_parent.get_full_hdl_path(parent_paths, kind, separator);
|
|
else
|
|
m_parent.get_full_hdl_path(parent_paths, kind, separator);
|
|
for (int i=0; i<hdl_paths.size();i++) begin
|
|
uvm_hdl_path_concat hdl_concat = hdl_paths.get(i);
|
|
foreach (parent_paths[j]) begin
|
|
uvm_hdl_path_concat t = new;
|
|
foreach (hdl_concat.slices[k]) begin
|
|
if (hdl_concat.slices[k].path == "")
|
|
t.add_path(parent_paths[j]);
|
|
else
|
|
t.add_path({ parent_paths[j], separator, hdl_concat.slices[k].path },
|
|
hdl_concat.slices[k].offset,
|
|
hdl_concat.slices[k].size);
|
|
end
|
|
paths.push_back(t);
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function void uvm_reg::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 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<<f.get_n_bits())-1) << lsb;
|
|
rw.value[0] = (value & msk) >> 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<<sz)-1),
|
|
(value >> lsb) & ((1<<sz)-1),
|
|
rw.local_map);
|
|
final_val |= field_val << lsb;
|
|
end
|
|
end
|
|
rw.kind = UVM_WRITE;
|
|
rw.value[0] = final_val;
|
|
if (get_rights(rw.local_map) inside {"RW", "WO"}) begin
|
|
if (bkdr != null)
|
|
bkdr.write(rw);
|
|
else
|
|
backdoor_write(rw);
|
|
do_predict(rw, UVM_PREDICT_WRITE);
|
|
end
|
|
else begin
|
|
rw.status = UVM_NOT_OK;
|
|
end
|
|
end
|
|
UVM_FRONTDOOR: begin
|
|
uvm_reg_map system_map = rw.local_map.get_root_map();
|
|
m_is_busy = 1;
|
|
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 : built_in_frontdoor
|
|
rw.local_map.do_write(rw);
|
|
end
|
|
m_is_busy = 0;
|
|
if (system_map.get_auto_predict()) begin
|
|
uvm_status_e status;
|
|
if (rw.status != UVM_NOT_OK) begin
|
|
sample(value, -1, 0, rw.map);
|
|
m_parent.XsampleX(map_info.offset, 0, rw.map);
|
|
end
|
|
status = rw.status;
|
|
do_predict(rw, UVM_PREDICT_WRITE);
|
|
rw.status = status;
|
|
end
|
|
end
|
|
endcase
|
|
value = rw.value[0];
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.post_write(rw);
|
|
post_write(rw);
|
|
foreach (m_fields[i]) begin
|
|
uvm_reg_field_cb_iter cbs = new(m_fields[i]);
|
|
uvm_reg_field f = m_fields[i];
|
|
rw.element = f;
|
|
rw.element_kind = UVM_FIELD;
|
|
rw.value[0] = (value >> f.get_lsb_pos()) & ((1<<f.get_n_bits())-1);
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.post_write(rw);
|
|
f.post_write(rw);
|
|
end
|
|
rw.value[0] = value;
|
|
rw.element = this;
|
|
rw.element_kind = UVM_REG;
|
|
if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin
|
|
string path_s,value_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";
|
|
value_s = $sformatf("=0x%0h",rw.value[0]);
|
|
uvm_report_info("RegModel", {"Wrote register via ",path_s,": ",
|
|
get_full_name(),value_s}, UVM_HIGH);
|
|
end
|
|
m_write_in_progress = 1'b0;
|
|
XatomicX(0);
|
|
endtask: do_write
|
|
task uvm_reg::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);
|
|
XatomicX(1);
|
|
XreadX(status, value, path, map, parent, prior, extension, fname, lineno);
|
|
XatomicX(0);
|
|
endtask: read
|
|
task uvm_reg::XreadX(output uvm_status_e status,
|
|
output uvm_reg_data_t value,
|
|
input uvm_door_e path,
|
|
input uvm_reg_map map,
|
|
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("read_item",,get_full_name());
|
|
rw.element = this;
|
|
rw.element_kind = UVM_REG;
|
|
rw.kind = UVM_READ;
|
|
rw.value[0] = 0;
|
|
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: XreadX
|
|
task uvm_reg::do_read(uvm_reg_item rw);
|
|
uvm_reg_cb_iter cbs = new(this);
|
|
uvm_reg_map_info map_info;
|
|
uvm_reg_data_t value;
|
|
uvm_reg_data_t exp;
|
|
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;
|
|
foreach (m_fields[i]) begin
|
|
uvm_reg_field_cb_iter cbs = new(m_fields[i]);
|
|
uvm_reg_field f = m_fields[i];
|
|
rw.element = f;
|
|
rw.element_kind = UVM_FIELD;
|
|
m_fields[i].pre_read(rw);
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.pre_read(rw);
|
|
end
|
|
rw.element = this;
|
|
rw.element_kind = UVM_REG;
|
|
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
|
|
case (rw.path)
|
|
UVM_BACKDOOR: begin
|
|
uvm_reg_backdoor bkdr = get_backdoor();
|
|
uvm_reg_map map;
|
|
if (rw.map != null)
|
|
rw.local_map = rw.map;
|
|
else
|
|
rw.local_map = get_default_map();
|
|
map = rw.local_map;
|
|
if (map.get_check_on_read()) exp = get();
|
|
if (get_rights(rw.local_map) inside {"RW", "RO"}) begin
|
|
if (bkdr != null)
|
|
bkdr.read(rw);
|
|
else
|
|
backdoor_read(rw);
|
|
end
|
|
else begin
|
|
rw.status = UVM_NOT_OK;
|
|
end
|
|
value = rw.value[0];
|
|
if (rw.status != UVM_NOT_OK) begin
|
|
uvm_reg_data_t wo_mask;
|
|
foreach (m_fields[i]) begin
|
|
string acc = m_fields[i].get_access(rw.local_map);
|
|
if (acc == "RC" ||
|
|
acc == "WRC" ||
|
|
acc == "WSRC" ||
|
|
acc == "W1SRC" ||
|
|
acc == "W0SRC") begin
|
|
value &= ~(((1<<m_fields[i].get_n_bits())-1)
|
|
<< m_fields[i].get_lsb_pos());
|
|
end
|
|
else if (acc == "RS" ||
|
|
acc == "WRS" ||
|
|
acc == "WCRS" ||
|
|
acc == "W1CRS" ||
|
|
acc == "W0CRS") begin
|
|
value |= (((1<<m_fields[i].get_n_bits())-1)
|
|
<< m_fields[i].get_lsb_pos());
|
|
end
|
|
else if (acc == "WO" ||
|
|
acc == "WOC" ||
|
|
acc == "WOS" ||
|
|
acc == "WO1") begin
|
|
wo_mask |= ((1<<m_fields[i].get_n_bits())-1)
|
|
<< m_fields[i].get_lsb_pos();
|
|
end
|
|
end
|
|
if (get_rights(rw.local_map) inside {"RW", "RO"}) begin
|
|
if (value != rw.value[0]) begin
|
|
uvm_reg_data_t saved;
|
|
saved = rw.value[0];
|
|
rw.value[0] = value;
|
|
if (bkdr != null)
|
|
bkdr.write(rw);
|
|
else
|
|
backdoor_write(rw);
|
|
rw.value[0] = saved;
|
|
end
|
|
rw.value[0] &= ~wo_mask;
|
|
if (map.get_check_on_read() &&
|
|
rw.status != UVM_NOT_OK) begin
|
|
void'(do_check(exp, rw.value[0], map));
|
|
end
|
|
do_predict(rw, UVM_PREDICT_READ);
|
|
end
|
|
else begin
|
|
rw.status = UVM_NOT_OK;
|
|
end
|
|
end
|
|
end
|
|
UVM_FRONTDOOR: begin
|
|
uvm_reg_map system_map = rw.local_map.get_root_map();
|
|
m_is_busy = 1;
|
|
if (rw.local_map.get_check_on_read()) exp = get();
|
|
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
|
|
m_is_busy = 0;
|
|
if (system_map.get_auto_predict()) begin
|
|
uvm_status_e status;
|
|
if (rw.local_map.get_check_on_read() &&
|
|
rw.status != UVM_NOT_OK) begin
|
|
void'(do_check(exp, rw.value[0], system_map));
|
|
end
|
|
if (rw.status != UVM_NOT_OK) begin
|
|
sample(rw.value[0], -1, 1, rw.map);
|
|
m_parent.XsampleX(map_info.offset, 1, rw.map);
|
|
end
|
|
status = rw.status;
|
|
do_predict(rw, UVM_PREDICT_READ);
|
|
rw.status = status;
|
|
end
|
|
end
|
|
endcase
|
|
value = rw.value[0];
|
|
for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next())
|
|
cb.post_read(rw);
|
|
post_read(rw);
|
|
foreach (m_fields[i]) begin
|
|
uvm_reg_field_cb_iter cbs = new(m_fields[i]);
|
|
uvm_reg_field f = m_fields[i];
|
|
rw.element = f;
|
|
rw.element_kind = UVM_FIELD;
|
|
rw.value[0] = (value >> f.get_lsb_pos()) & ((1<<f.get_n_bits())-1);
|
|
for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
|
|
cb.post_read(rw);
|
|
f.post_read(rw);
|
|
end
|
|
rw.value[0] = value;
|
|
rw.element = this;
|
|
rw.element_kind = UVM_REG;
|
|
if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin
|
|
string path_s,value_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";
|
|
value_s = $sformatf("=%0h",rw.value[0]);
|
|
uvm_report_info("RegModel", {"Read register via ",path_s,": ",
|
|
get_full_name(),value_s}, UVM_HIGH);
|
|
end
|
|
m_read_in_progress = 1'b0;
|
|
endtask: do_read
|
|
function bit uvm_reg::Xcheck_accessX (input uvm_reg_item rw,
|
|
output uvm_reg_map_info map_info);
|
|
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 register '",get_full_name(), "' . Using frontdoor instead."}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2077, "", 1);
|
|
end
|
|
rw.path = UVM_FRONTDOOR;
|
|
end
|
|
else if (rw.map == null) begin
|
|
uvm_reg_map bkdr_map = get_default_map();
|
|
if (bkdr_map != null)
|
|
rw.map = bkdr_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
|
|
if (rw.map == null)
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name()))
|
|
uvm_report_error (get_type_name(), "Unable to physically access register with null map", UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2097, "", 1);
|
|
end
|
|
else
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name()))
|
|
uvm_report_error (get_type_name(), {"No transactor available to physically access register on map '", rw.map.get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2101, "", 1);
|
|
end
|
|
rw.status = UVM_NOT_OK;
|
|
return 0;
|
|
end
|
|
map_info = rw.local_map.get_reg_map_info(this);
|
|
if (map_info.frontdoor == null && map_info.unmapped) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register '",get_full_name(), "' unmapped in map '", (rw.map==null)? rw.local_map.get_full_name():rw.map.get_full_name(), "' and does not have a user-defined frontdoor"}, UVM_NONE, "t/uvm/src/reg/uvm_reg.svh", 2112, "", 1);
|
|
end
|
|
rw.status = UVM_NOT_OK;
|
|
return 0;
|
|
end
|
|
if (rw.map == null)
|
|
rw.map = rw.local_map;
|
|
end
|
|
return 1;
|
|
endfunction
|
|
function bit uvm_reg::is_busy();
|
|
return m_is_busy;
|
|
endfunction
|
|
function void uvm_reg::Xset_busyX(bit busy);
|
|
m_is_busy = busy;
|
|
endfunction
|
|
function bit uvm_reg::Xis_locked_by_fieldX();
|
|
return m_is_locked_by_field;
|
|
endfunction
|
|
task uvm_reg::backdoor_write(uvm_reg_item rw);
|
|
uvm_hdl_path_concat paths[$];
|
|
bit ok=1;
|
|
get_full_hdl_path(paths,rw.bd_kind);
|
|
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,"RegMem"))
|
|
uvm_report_info ("RegMem", $sformatf("backdoor_write to %s", hdl_concat.slices[j].path), UVM_DEBUG, "t/uvm/src/reg/uvm_reg.svh", 2155, "", 1);
|
|
end
|
|
if (hdl_concat.slices[j].offset < 0) begin
|
|
ok &= uvm_hdl_deposit(hdl_concat.slices[j].path,rw.value[0]);
|
|
continue;
|
|
end
|
|
begin
|
|
uvm_reg_data_t slice;
|
|
slice = rw.value[0] >> 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;
|
|
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<hdl_paths.size();i++)
|
|
paths.push_back(hdl_paths.get(i));
|
|
endfunction
|
|
function void uvm_reg_file::get_full_hdl_path(ref string paths[$],
|
|
input string kind = "",
|
|
input string separator = ".");
|
|
if (kind == "")
|
|
kind = get_default_hdl_path();
|
|
if (!has_hdl_path(kind)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register file does not have hdl path defined for abstraction '",kind,"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 258, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
paths.delete();
|
|
begin
|
|
uvm_queue #(string) hdl_paths = hdl_paths_pool.get(kind);
|
|
string parent_paths[$];
|
|
if (m_rf != null)
|
|
m_rf.get_full_hdl_path(parent_paths, kind, separator);
|
|
else if (parent != null)
|
|
parent.get_full_hdl_path(parent_paths, kind, separator);
|
|
for (int i=0; i<hdl_paths.size();i++) begin
|
|
string hdl_path = hdl_paths.get(i);
|
|
if (parent_paths.size() == 0) begin
|
|
if (hdl_path != "")
|
|
paths.push_back(hdl_path);
|
|
continue;
|
|
end
|
|
foreach (parent_paths[j]) begin
|
|
if (hdl_path == "")
|
|
paths.push_back(parent_paths[j]);
|
|
else
|
|
paths.push_back({ parent_paths[j], separator, hdl_path });
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function string uvm_reg_file::get_default_hdl_path();
|
|
if (default_hdl_path == "") begin
|
|
if (m_rf != null)
|
|
return m_rf.get_default_hdl_path();
|
|
else
|
|
return parent.get_default_hdl_path();
|
|
end
|
|
return default_hdl_path;
|
|
endfunction
|
|
function void uvm_reg_file::set_default_hdl_path(string kind);
|
|
if (kind == "") begin
|
|
if (m_rf != null)
|
|
kind = m_rf.get_default_hdl_path();
|
|
else if (parent == null)
|
|
kind = parent.get_default_hdl_path();
|
|
else begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register file has no parent. ", "Must specify a valid HDL abstraction (kind)"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 319, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
default_hdl_path = kind;
|
|
endfunction
|
|
function uvm_reg_block uvm_reg_file::get_parent();
|
|
return get_block();
|
|
endfunction
|
|
function string uvm_reg_file::get_full_name();
|
|
uvm_reg_block blk;
|
|
get_full_name = this.get_name();
|
|
if (m_rf != null)
|
|
return {m_rf.get_full_name(), ".", get_full_name};
|
|
if (this.parent == null)
|
|
return get_full_name;
|
|
get_full_name = {this.parent.get_full_name(), ".", get_full_name};
|
|
endfunction: get_full_name
|
|
function string uvm_reg_file::convert2string();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel register files cannot be converted to strings", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 361, "", 1);
|
|
end
|
|
return "";
|
|
endfunction: convert2string
|
|
function void uvm_reg_file::do_print (uvm_printer printer);
|
|
super.do_print(printer);
|
|
endfunction
|
|
function uvm_object uvm_reg_file::clone();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel register files cannot be cloned", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 377, "", 1);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function void uvm_reg_file::do_copy(uvm_object rhs);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel register files cannot be copied", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 384, "", 1);
|
|
end
|
|
endfunction
|
|
function bit uvm_reg_file::do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel register files cannot be compared", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 392, "", 1);
|
|
end
|
|
return 0;
|
|
endfunction
|
|
function void uvm_reg_file::do_pack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel register files cannot be packed", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 400, "", 1);
|
|
end
|
|
endfunction
|
|
function void uvm_reg_file::do_unpack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel register files cannot be unpacked", UVM_NONE, "t/uvm/src/reg/uvm_reg_file.svh", 407, "", 1);
|
|
end
|
|
endfunction
|
|
typedef class uvm_mem_mam_cfg;
|
|
typedef class uvm_mem_region;
|
|
typedef class uvm_mem_mam_policy;
|
|
typedef class uvm_mem;
|
|
class uvm_mem_mam;
|
|
typedef enum {GREEDY, THRIFTY} alloc_mode_e;
|
|
typedef enum {BROAD, NEARBY} locality_e;
|
|
uvm_mem_mam_policy default_alloc;
|
|
local uvm_mem memory;
|
|
local uvm_mem_mam_cfg cfg;
|
|
local uvm_mem_region in_use[$];
|
|
local int for_each_idx = -1;
|
|
local string fname;
|
|
local int lineno;
|
|
extern function new(string name,
|
|
uvm_mem_mam_cfg cfg,
|
|
uvm_mem mem=null);
|
|
extern function uvm_mem_mam_cfg reconfigure(uvm_mem_mam_cfg cfg = null);
|
|
extern function uvm_mem_region reserve_region(bit [63:0] start_offset,
|
|
int unsigned n_bytes,
|
|
string fname = "",
|
|
int lineno = 0);
|
|
extern function uvm_mem_region request_region(int unsigned n_bytes,
|
|
uvm_mem_mam_policy alloc = null,
|
|
string fname = "",
|
|
int lineno = 0);
|
|
extern function void release_region(uvm_mem_region region);
|
|
extern function void release_all_regions();
|
|
extern function string convert2string();
|
|
extern function uvm_mem_region for_each(bit reset = 0);
|
|
extern function uvm_mem get_memory();
|
|
endclass: uvm_mem_mam
|
|
class uvm_mem_region;
|
|
bit [63:0] Xstart_offsetX;
|
|
bit [63:0] Xend_offsetX;
|
|
local int unsigned len;
|
|
local int unsigned n_bytes;
|
|
local uvm_mem_mam parent;
|
|
local string fname;
|
|
local int lineno;
|
|
uvm_vreg XvregX;
|
|
extern function new(bit [63:0] start_offset,
|
|
bit [63:0] end_offset,
|
|
int unsigned len,
|
|
int unsigned n_bytes,
|
|
uvm_mem_mam parent);
|
|
extern function bit [63:0] get_start_offset();
|
|
extern function bit [63:0] get_end_offset();
|
|
extern function int unsigned get_len();
|
|
extern function int unsigned get_n_bytes();
|
|
extern function void release_region();
|
|
extern function uvm_mem get_memory();
|
|
extern function uvm_vreg get_virtual_registers();
|
|
extern 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 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 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 task 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);
|
|
extern task 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);
|
|
extern task peek(output uvm_status_e status,
|
|
input uvm_reg_addr_t offset,
|
|
output uvm_reg_data_t value,
|
|
input uvm_sequence_base parent = null,
|
|
input uvm_object extension = null,
|
|
input string fname = "",
|
|
input int lineno = 0);
|
|
extern function string convert2string();
|
|
endclass
|
|
class uvm_mem_mam_policy;
|
|
int unsigned len;
|
|
rand bit [63:0] start_offset;
|
|
bit [63:0] min_offset;
|
|
bit [63:0] max_offset;
|
|
uvm_mem_region in_use[$];
|
|
constraint uvm_mem_mam_policy_valid {
|
|
start_offset >= min_offset;
|
|
start_offset <= max_offset - len + 1;
|
|
}
|
|
constraint uvm_mem_mam_policy_no_overlap {
|
|
foreach (in_use[i]) {
|
|
!(start_offset <= in_use[i].Xend_offsetX &&
|
|
start_offset + len - 1 >= in_use[i].Xstart_offsetX);
|
|
}
|
|
}
|
|
endclass
|
|
class uvm_mem_mam_cfg;
|
|
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<<f.get_n_bits())-1) << lsb;
|
|
tmp = (value & msk) >> 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<<f.get_n_bits())-1) << lsb;
|
|
tmp = (value & msk) >> 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<<f.get_n_bits())-1) << lsb;
|
|
tmp = (value & msk) >> 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<hdl_paths.size();i++) begin
|
|
uvm_hdl_path_concat t = hdl_paths.get(i);
|
|
paths.push_back(t);
|
|
end
|
|
endfunction
|
|
function void uvm_mem::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_mem::get_full_hdl_path(ref uvm_hdl_path_concat paths[$],
|
|
input string kind = "",
|
|
input string separator = ".");
|
|
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", 1883, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
begin
|
|
uvm_queue #(uvm_hdl_path_concat) hdl_paths = m_hdl_paths_pool.get(kind);
|
|
string parent_paths[$];
|
|
m_parent.get_full_hdl_path(parent_paths, kind, separator);
|
|
for (int i=0; i<hdl_paths.size();i++) begin
|
|
uvm_hdl_path_concat hdl_concat = hdl_paths.get(i);
|
|
foreach (parent_paths[j]) begin
|
|
uvm_hdl_path_concat t = new;
|
|
foreach (hdl_concat.slices[k]) begin
|
|
if (hdl_concat.slices[k].path == "")
|
|
t.add_path(parent_paths[j]);
|
|
else
|
|
t.add_path({ parent_paths[j], separator, hdl_concat.slices[k].path },
|
|
hdl_concat.slices[k].offset,
|
|
hdl_concat.slices[k].size);
|
|
end
|
|
paths.push_back(t);
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function void uvm_mem::set_parent(uvm_reg_block parent);
|
|
m_parent = parent;
|
|
endfunction
|
|
function uvm_reg_block uvm_mem::get_parent();
|
|
return get_block();
|
|
endfunction
|
|
function string uvm_mem::convert2string();
|
|
string res_str;
|
|
string prefix;
|
|
$sformat(convert2string, "%sMemory %s -- %0dx%0d bits", prefix,
|
|
get_full_name(), get_size(), get_n_bits());
|
|
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;
|
|
uvm_endianness_e endian_name;
|
|
parent_map = this_map.get_parent_map();
|
|
endian_name=this_map.get_endian();
|
|
offset = parent_map == null ? this_map.get_base_addr(UVM_NO_HIER) :
|
|
parent_map.get_submap_offset(this_map);
|
|
prefix = {prefix, " "};
|
|
$sformat(convert2string, "%sMapped in '%s' -- buswidth %0d bytes, %s, offset 'h%0h, size 'h%0h, %s\n", prefix,
|
|
this_map.get_full_name(), this_map.get_n_bytes(), endian_name.name(), offset,get_size(),get_access(this_map));
|
|
end
|
|
end
|
|
prefix = " ";
|
|
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, " ", 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, " ", res_str,
|
|
"currently executing write method"};
|
|
end
|
|
endfunction
|
|
function void uvm_mem::do_print (uvm_printer printer);
|
|
super.do_print(printer);
|
|
printer.print_field_int("n_bits",get_n_bits(),32, UVM_UNSIGNED);
|
|
printer.print_field_int("size",get_size(),32, UVM_UNSIGNED);
|
|
endfunction
|
|
function uvm_object uvm_mem::clone();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel memories cannot be cloned", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1987, "", 1);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function void uvm_mem::do_copy(uvm_object rhs);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel memories cannot be copied", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 1994, "", 1);
|
|
end
|
|
endfunction
|
|
function bit uvm_mem::do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel memories cannot be compared", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 2002, "", 1);
|
|
end
|
|
return 0;
|
|
endfunction
|
|
function void uvm_mem::do_pack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel memories cannot be packed", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 2010, "", 1);
|
|
end
|
|
endfunction
|
|
function void uvm_mem::do_unpack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel memories cannot be unpacked", UVM_NONE, "t/uvm/src/reg/uvm_mem.svh", 2017, "", 1);
|
|
end
|
|
endfunction
|
|
function void uvm_mem::Xadd_vregX(uvm_vreg vreg);
|
|
m_vregs[vreg] = 1;
|
|
endfunction
|
|
function void uvm_mem::Xdelete_vregX(uvm_vreg vreg);
|
|
if (m_vregs.exists(vreg))
|
|
m_vregs.delete(vreg);
|
|
endfunction
|
|
class uvm_reg_map_info;
|
|
uvm_reg_addr_t offset;
|
|
string rights;
|
|
bit unmapped;
|
|
uvm_reg_addr_t addr[];
|
|
uvm_reg_frontdoor frontdoor;
|
|
uvm_reg_map_addr_range mem_range;
|
|
bit is_initialized;
|
|
endclass
|
|
virtual class uvm_reg_transaction_order_policy extends uvm_object;
|
|
function new(string name = "policy");
|
|
super.new(name);
|
|
endfunction
|
|
pure virtual function void order(ref uvm_reg_bus_op q[$]);
|
|
endclass
|
|
class uvm_reg_seq_base extends uvm_sequence_base;
|
|
typedef uvm_object_registry#(uvm_reg_seq_base,"uvm_reg_seq_base") type_id;
|
|
static function uvm_reg_seq_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_seq_base tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_seq_base";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_seq_base";
|
|
endfunction : get_type_name
|
|
function new(string name = "uvm_reg_seq_base");
|
|
super.new(name);
|
|
endfunction
|
|
endclass
|
|
class uvm_reg_map extends uvm_object;
|
|
typedef uvm_object_registry#(uvm_reg_map,"uvm_reg_map") type_id;
|
|
static function uvm_reg_map 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_map tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_map";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_map";
|
|
endfunction : get_type_name
|
|
local uvm_reg_addr_t m_base_addr;
|
|
local int unsigned m_n_bytes;
|
|
local uvm_endianness_e m_endian;
|
|
local bit m_byte_addressing;
|
|
local uvm_object_wrapper m_sequence_wrapper;
|
|
local uvm_reg_adapter m_adapter;
|
|
local uvm_sequencer_base m_sequencer;
|
|
local bit m_auto_predict;
|
|
local bit m_check_on_read;
|
|
local uvm_reg_block m_parent;
|
|
local int unsigned m_system_n_bytes;
|
|
local uvm_reg_map m_parent_map;
|
|
local uvm_reg_addr_t m_submaps[uvm_reg_map];
|
|
local string m_submap_rights[uvm_reg_map];
|
|
local uvm_reg_map_info m_regs_info[uvm_reg];
|
|
local uvm_reg_map_info m_mems_info[uvm_mem];
|
|
local uvm_reg m_regs_by_offset[uvm_reg_addr_t];
|
|
local uvm_reg m_regs_by_offset_wo[uvm_reg_addr_t];
|
|
local uvm_mem m_mems_by_offset[uvm_reg_map_addr_range];
|
|
local uvm_reg_transaction_order_policy policy;
|
|
extern function void Xinit_address_mapX();
|
|
static local uvm_reg_map m_backdoor;
|
|
static function uvm_reg_map backdoor();
|
|
if (m_backdoor == null)
|
|
m_backdoor = new("Backdoor");
|
|
return m_backdoor;
|
|
endfunction
|
|
extern function new(string name="uvm_reg_map");
|
|
extern function void configure(uvm_reg_block parent,
|
|
uvm_reg_addr_t base_addr,
|
|
int unsigned n_bytes,
|
|
uvm_endianness_e endian,
|
|
bit byte_addressing = 1);
|
|
extern virtual function void add_reg (uvm_reg rg,
|
|
uvm_reg_addr_t offset,
|
|
string rights = "RW",
|
|
bit unmapped=0,
|
|
uvm_reg_frontdoor frontdoor=null);
|
|
extern virtual function void add_mem (uvm_mem mem,
|
|
uvm_reg_addr_t offset,
|
|
string rights = "RW",
|
|
bit unmapped=0,
|
|
uvm_reg_frontdoor frontdoor=null);
|
|
extern virtual function void add_submap (uvm_reg_map child_map,
|
|
uvm_reg_addr_t offset);
|
|
extern virtual function void set_sequencer (uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter=null);
|
|
extern virtual function void set_submap_offset (uvm_reg_map submap,
|
|
uvm_reg_addr_t offset);
|
|
extern virtual function uvm_reg_addr_t get_submap_offset (uvm_reg_map submap);
|
|
extern virtual function void set_base_addr (uvm_reg_addr_t offset);
|
|
extern virtual function void reset(string kind = "SOFT");
|
|
extern virtual function void add_parent_map(uvm_reg_map parent_map,
|
|
uvm_reg_addr_t offset);
|
|
extern virtual function void Xverify_map_configX();
|
|
extern virtual function void m_set_reg_offset(uvm_reg rg,
|
|
uvm_reg_addr_t offset,
|
|
bit unmapped);
|
|
extern virtual function void m_set_mem_offset(uvm_mem mem,
|
|
uvm_reg_addr_t offset,
|
|
bit unmapped);
|
|
extern virtual function string get_full_name();
|
|
extern virtual function uvm_reg_map get_root_map();
|
|
extern virtual function uvm_reg_block get_parent();
|
|
extern virtual function uvm_reg_map get_parent_map();
|
|
extern virtual function uvm_reg_addr_t get_base_addr (uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function int unsigned get_n_bytes (uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function int unsigned get_addr_unit_bytes();
|
|
extern virtual function uvm_endianness_e get_endian (uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function uvm_sequencer_base get_sequencer (uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function uvm_reg_adapter get_adapter (uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_submaps (ref uvm_reg_map maps[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_registers (ref uvm_reg regs[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_fields (ref uvm_reg_field fields[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_memories (ref uvm_mem mems[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_virtual_registers (ref uvm_vreg regs[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_virtual_fields (ref uvm_vreg_field fields[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function uvm_reg_map_info get_reg_map_info(uvm_reg rg, bit error=1);
|
|
extern virtual function uvm_reg_map_info get_mem_map_info(uvm_mem mem, bit error=1);
|
|
extern virtual function int unsigned get_size();
|
|
extern virtual function int 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[]);
|
|
extern virtual function uvm_reg get_reg_by_offset(uvm_reg_addr_t offset,
|
|
bit read = 1);
|
|
extern virtual function uvm_mem get_mem_by_offset(uvm_reg_addr_t offset);
|
|
function void set_auto_predict(bit on=1); m_auto_predict = on; endfunction
|
|
function bit get_auto_predict(); return m_auto_predict; endfunction
|
|
function void set_check_on_read(bit on=1);
|
|
m_check_on_read = on;
|
|
foreach (m_submaps[submap]) begin
|
|
submap.set_check_on_read(on);
|
|
end
|
|
endfunction
|
|
function bit get_check_on_read(); return m_check_on_read; endfunction
|
|
extern virtual task do_bus_write (uvm_reg_item rw,
|
|
uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter);
|
|
extern virtual task do_bus_read (uvm_reg_item rw,
|
|
uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter);
|
|
extern virtual task do_write(uvm_reg_item rw);
|
|
extern virtual task do_read(uvm_reg_item rw);
|
|
extern function void Xget_bus_infoX (uvm_reg_item rw,
|
|
output uvm_reg_map_info map_info,
|
|
output int size,
|
|
output int lsb,
|
|
output int addr_skip);
|
|
extern virtual function string convert2string();
|
|
extern virtual function uvm_object clone();
|
|
extern virtual function void do_print (uvm_printer printer);
|
|
extern virtual function void do_copy (uvm_object rhs);
|
|
function void set_transaction_order_policy(uvm_reg_transaction_order_policy pol);
|
|
policy = pol;
|
|
endfunction
|
|
function uvm_reg_transaction_order_policy get_transaction_order_policy();
|
|
return policy;
|
|
endfunction
|
|
local function automatic int unsigned ceil(int unsigned a, int unsigned b);
|
|
int r = a / b;
|
|
int r0 = a % b;
|
|
return r0 ? (r+1): r;
|
|
endfunction
|
|
extern virtual function int 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
|
|
);
|
|
extern task perform_accesses(ref uvm_reg_bus_op accesses[$],
|
|
input uvm_reg_item rw,
|
|
input uvm_reg_adapter adapter,
|
|
input uvm_sequencer_base sequencer);
|
|
extern task do_bus_access (uvm_reg_item rw,
|
|
uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter);
|
|
virtual function void unregister();
|
|
uvm_reg_block q[$];
|
|
uvm_reg_block::get_root_blocks(q);
|
|
foreach(q[idx])
|
|
q[idx].set_lock(0);
|
|
foreach(q[idx])
|
|
q[idx].unregister(this);
|
|
foreach (m_submaps[map_])
|
|
map_.unregister();
|
|
m_submaps.delete();
|
|
m_submap_rights.delete();
|
|
foreach(m_regs_by_offset[i])
|
|
m_regs_by_offset[i].unregister(this);
|
|
m_regs_by_offset.delete();
|
|
m_regs_by_offset_wo.delete();
|
|
m_mems_by_offset.delete();
|
|
m_regs_info.delete();
|
|
m_mems_info.delete();
|
|
m_parent_map =null;
|
|
endfunction
|
|
virtual function uvm_reg_map clone_and_update(string rights);
|
|
if(m_parent_map!=null)
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/CLONEMAPWITHPARENT"))
|
|
uvm_report_error ("UVM/REG/CLONEMAPWITHPARENT", "cannot clone a map which already has a parent", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 534, "", 1);
|
|
end
|
|
if(m_submaps.size() != 0)
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"UVM/REG/CLONEMAPWITHCHILDREN"))
|
|
uvm_report_error ("UVM/REG/CLONEMAPWITHCHILDREN", "cannot clone a map which already has children", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 535, "", 1);
|
|
end
|
|
begin
|
|
uvm_reg_map m;
|
|
uvm_reg_block b = get_parent();
|
|
uvm_reg qr[$];
|
|
uvm_mem qm[$];
|
|
m = b.create_map(get_name(),0,m_n_bytes,m_endian,m_byte_addressing);
|
|
foreach(m_regs_by_offset[i]) begin
|
|
uvm_reg rg=m_regs_by_offset[i];
|
|
uvm_reg_map_info info = get_reg_map_info(rg);
|
|
m.add_reg(rg,info.offset,rights, info.unmapped, info.frontdoor);
|
|
end
|
|
foreach(m_mems_by_offset[i]) begin
|
|
uvm_mem rg=m_mems_by_offset[i];
|
|
uvm_reg_map_info info = get_mem_map_info(rg);
|
|
m.add_mem(rg,info.offset,rights, info.unmapped, info.frontdoor);
|
|
end
|
|
return m;
|
|
end
|
|
endfunction
|
|
endclass: uvm_reg_map
|
|
function uvm_reg_map::new(string name = "uvm_reg_map");
|
|
super.new((name == "") ? "default_map" : name);
|
|
m_auto_predict = 0;
|
|
m_check_on_read = 0;
|
|
endfunction
|
|
function void uvm_reg_map::configure(uvm_reg_block parent,
|
|
uvm_reg_addr_t base_addr,
|
|
int unsigned n_bytes,
|
|
uvm_endianness_e endian,
|
|
bit byte_addressing=1);
|
|
m_parent = parent;
|
|
m_n_bytes = n_bytes;
|
|
m_endian = endian;
|
|
m_base_addr = base_addr;
|
|
m_byte_addressing = byte_addressing;
|
|
endfunction: configure
|
|
function void uvm_reg_map::add_reg(uvm_reg rg,
|
|
uvm_reg_addr_t offset,
|
|
string rights = "RW",
|
|
bit unmapped=0,
|
|
uvm_reg_frontdoor frontdoor=null);
|
|
if (m_regs_info.exists(rg)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register '",rg.get_name(), "' has already been added to map '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 600, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (rg.get_parent() != get_parent()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register '",rg.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", 607, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
rg.add_map(this);
|
|
begin
|
|
uvm_reg_map_info info = new;
|
|
info.offset = offset;
|
|
info.rights = rights;
|
|
info.unmapped = unmapped;
|
|
info.frontdoor = frontdoor;
|
|
info.is_initialized=0;
|
|
m_regs_info[rg]=info;
|
|
end
|
|
endfunction
|
|
function void uvm_reg_map::m_set_reg_offset(uvm_reg rg,
|
|
uvm_reg_addr_t offset,
|
|
bit unmapped);
|
|
if (!m_regs_info.exists(rg)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Cannot modify offset of register '",rg.get_full_name(), "' in address map '",get_full_name(), "' : register not mapped in that address map"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 635, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
begin
|
|
uvm_reg_map_info info = m_regs_info[rg];
|
|
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 (info.addr[i]) begin
|
|
if (!top_map.m_regs_by_offset_wo.exists(info.addr[i])) begin
|
|
top_map.m_regs_by_offset.delete(info.addr[i]);
|
|
end
|
|
else begin
|
|
if (top_map.m_regs_by_offset[info.addr[i]] == rg) begin
|
|
top_map.m_regs_by_offset[info.addr[i]] =
|
|
top_map.m_regs_by_offset_wo[info.addr[i]];
|
|
uvm_reg_read_only_cbs::remove(rg);
|
|
uvm_reg_write_only_cbs::remove(top_map.m_regs_by_offset[info.addr[i]]);
|
|
end
|
|
else begin
|
|
uvm_reg_write_only_cbs::remove(rg);
|
|
uvm_reg_read_only_cbs::remove(top_map.m_regs_by_offset[info.addr[i]]);
|
|
end
|
|
top_map.m_regs_by_offset_wo.delete(info.addr[i]);
|
|
end
|
|
end
|
|
end
|
|
if (!unmapped) begin
|
|
string rg_acc = rg.Xget_fields_accessX(this);
|
|
void'(get_physical_addresses(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)) 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", 704, "", 1);
|
|
end
|
|
end
|
|
end
|
|
else
|
|
top_map.m_regs_by_offset[addr] = rg;
|
|
foreach (top_map.m_mems_by_offset[range]) begin
|
|
if (addrs[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())
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"UVM/REG/ADDR"))
|
|
uvm_report_warning ("UVM/REG/ADDR", $sformatf("this version of UVM does not properly support memories with \
|
|
a smaller word width than the enclosing map. map %s has n_bytes=%0d aub=%0d while the mem has get_n_bytes %0d. \
|
|
multiple memory words fall into one bus address. if that happens memory addressing will be unpacked.", get_full_name(),get_n_bytes(UVM_NO_HIER),get_addr_unit_bytes(),mem.get_n_bytes()), UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 1565, "", 1);
|
|
end
|
|
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<<get_n_bytes()*8)-1);
|
|
if(rw.kind inside {UVM_READ,UVM_BURST_READ})
|
|
if (rw.status == UVM_IS_OK && (^data) === 1'bx)
|
|
rw.status = UVM_HAS_X;
|
|
rw_access.data=data;
|
|
end
|
|
begin
|
|
if (uvm_report_enabled(UVM_FULL,UVM_INFO,"UVM/REG/ADDR"))
|
|
uvm_report_info ("UVM/REG/ADDR", $sformatf("%s 'h%0h at 'h%0h via map \"%s\": %s...",op, rw_access.data, rw_access.addr, rw.map.get_full_name(), rw.status.name()), UVM_FULL, "t/uvm/src/reg/uvm_reg_map.svh", 1869, "", 1);
|
|
end
|
|
if (rw.status == UVM_NOT_OK)
|
|
break;
|
|
if (rw.parent != null && i == accesses.size()-1)
|
|
rw.parent.post_do(rw);
|
|
accesses[i]=rw_access;
|
|
end
|
|
endtask
|
|
task uvm_reg_map::do_bus_access (uvm_reg_item rw,
|
|
uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter);
|
|
uvm_reg_addr_t addrs[$];
|
|
uvm_reg_map system_map = get_root_map();
|
|
int unsigned bus_width = get_n_bytes();
|
|
uvm_reg_byte_en_t byte_en = -1;
|
|
uvm_reg_map_info map_info;
|
|
int n_bits;
|
|
int lsb;
|
|
int skip;
|
|
int unsigned curr_byte;
|
|
int n_access_extra, n_access;
|
|
uvm_reg_bus_op accesses[$];
|
|
string op;
|
|
uvm_reg_addr_t adr[];
|
|
int unsigned byte_offset;
|
|
int unsigned num_stream_bytes;
|
|
int unsigned n_bytes;
|
|
int unsigned bytes_per_value;
|
|
int unsigned bit_shift;
|
|
int unsigned extra_byte;
|
|
Xget_bus_infoX(rw, map_info, n_bits, lsb, skip);
|
|
addrs=map_info.addr;
|
|
op = (rw.kind inside {UVM_READ,UVM_BURST_READ} ? "Reading" : "Writing");
|
|
case(rw.element_kind)
|
|
UVM_MEM: begin
|
|
uvm_mem mem;
|
|
$cast(mem,rw.element);
|
|
void'(get_physical_addresses_to_map(m_mems_info[mem].offset,rw.offset,rw.value.size()*mem.get_n_bytes(),adr,null,byte_offset,mem));
|
|
num_stream_bytes =rw.value.size()*mem.get_n_bytes();
|
|
n_bytes=mem.get_n_bytes();
|
|
bytes_per_value=mem.get_n_bytes();
|
|
end
|
|
UVM_FIELD: begin
|
|
uvm_reg_field f;
|
|
uvm_reg_addr_t ad;
|
|
$cast(f,rw.element);
|
|
void'(get_physical_addresses_to_map(m_regs_info[f.get_parent()].offset+skip,0,ceil(f.get_n_bits(),8),adr,null,byte_offset));
|
|
num_stream_bytes =ceil(f.get_n_bits(),8);
|
|
n_bytes=get_n_bytes(UVM_NO_HIER);
|
|
bytes_per_value=ceil(f.get_n_bits(),8);
|
|
bit_shift=lsb % (get_n_bytes()*8);
|
|
if(((bit_shift+f.get_n_bits()) /8) != ((f.get_n_bits()) /8))
|
|
extra_byte=1;
|
|
end
|
|
UVM_REG: begin
|
|
uvm_reg r;
|
|
uvm_reg_addr_t ad;
|
|
$cast(r,rw.element);
|
|
void'(get_physical_addresses_to_map(m_regs_info[r].offset,0,r.get_n_bytes(),adr,null,byte_offset));
|
|
num_stream_bytes =r.get_n_bytes();
|
|
n_bytes=get_n_bytes(UVM_NO_HIER);
|
|
bytes_per_value=r.get_n_bytes();
|
|
end
|
|
endcase
|
|
begin
|
|
bit be[$];
|
|
byte p[$];
|
|
num_stream_bytes+=extra_byte;
|
|
repeat(byte_offset) be.push_back(1'b0);
|
|
repeat(num_stream_bytes) be.push_back(1'b1);
|
|
repeat(bus_width) be.push_back(1'b0);
|
|
repeat(byte_offset) p.push_back(8'b0);
|
|
foreach(rw.value[idx])
|
|
for(int i=0;i<bytes_per_value;i++)
|
|
p.push_back(rw.value[idx][8*i+:8]);
|
|
if(bit_shift) begin
|
|
uvm_reg_data_t ac;
|
|
ac='0;
|
|
foreach(p[idx]) begin
|
|
uvm_reg_data_t n;
|
|
n = (ac | (p[idx] << bit_shift)) & 'hff;
|
|
ac=(p[idx]>>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<bus_width;i0++)
|
|
data[i0*8+:8]=p[i*bus_width+i0];
|
|
begin
|
|
if (uvm_report_enabled(UVM_FULL,UVM_INFO,"UVM/REG/ADDR"))
|
|
uvm_report_info ("UVM/REG/ADDR", $sformatf("%s 'h%0h at 'h%0h via map \"%s\"...",op, data, adr[i], rw.map.get_full_name()), UVM_FULL, "t/uvm/src/reg/uvm_reg_map.svh", 2007, "", 1);
|
|
end
|
|
for (int z=0;z<bus_width;z++)
|
|
rw_access.byte_en[z] = be[bus_width*i+z];
|
|
rw_access.kind = rw.kind;
|
|
rw_access.addr = adr[i];
|
|
rw_access.data = data;
|
|
rw_access.n_bits=8*bus_width;
|
|
for(int i=bus_width-1;i>=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<bus_width;i1++)
|
|
p.push_back(accesses[i0].data[i1*8+:8]);
|
|
repeat(byte_offset) void'(p.pop_front());
|
|
foreach(rw.value[i]) rw.value[i]=0;
|
|
if(bit_shift) begin
|
|
uvm_reg_data_t ac;
|
|
ac='0;
|
|
for(int i=0;i<p.size();i++) begin
|
|
byte nv;
|
|
nv=(p[i] >> bit_shift);
|
|
if(i!=p.size()-1)
|
|
nv |= (p[i+1]<<bit_shift);
|
|
p[i] = nv;
|
|
end
|
|
if(extra_byte)
|
|
void'(p.pop_back());
|
|
end
|
|
foreach(rw.value[idx])
|
|
for(int i0=0;i0<bytes_per_value;i0++)
|
|
rw.value[idx][i0*8+:8]= p[idx*bytes_per_value+i0];
|
|
if(rw.element_kind == UVM_FIELD) begin
|
|
uvm_reg_field f;
|
|
uvm_reg_data_t m;
|
|
$cast(f,rw.element);
|
|
m = (1 << f.get_n_bits())-1;
|
|
foreach(rw.value[idx])
|
|
rw.value[idx] &= m;
|
|
end
|
|
end
|
|
end
|
|
endtask
|
|
task uvm_reg_map::do_bus_read (uvm_reg_item rw,
|
|
uvm_sequencer_base sequencer,
|
|
uvm_reg_adapter adapter);
|
|
do_bus_access(rw, sequencer, adapter);
|
|
endtask: do_bus_read
|
|
function void uvm_reg_map::do_print (uvm_printer printer);
|
|
uvm_reg regs[$];
|
|
uvm_vreg vregs[$];
|
|
uvm_mem mems[$];
|
|
uvm_endianness_e endian;
|
|
uvm_reg_map maps[$];
|
|
string prefix;
|
|
uvm_sequencer_base sqr=get_sequencer();
|
|
super.do_print(printer);
|
|
endian = get_endian(UVM_NO_HIER);
|
|
printer.print_generic("endian","",-2,endian.name());
|
|
printer.print_field_int("n_bytes", get_n_bytes(UVM_NO_HIER), 64, UVM_DEC);
|
|
printer.print_field_int("byte addressing",get_addr_unit_bytes()==1,64,UVM_DEC);
|
|
if(sqr!=null)
|
|
printer.print_generic("effective sequencer",sqr.get_type_name(),-2,sqr.get_full_name());
|
|
get_registers(regs,UVM_NO_HIER);
|
|
foreach (regs[j])
|
|
printer.print_generic(regs[j].get_name(), regs[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",regs[j].get_inst_id(),regs[j].get_address(this)));
|
|
get_memories(mems);
|
|
foreach (mems[j])
|
|
printer.print_generic(mems[j].get_name(), mems[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",mems[j].get_inst_id(),mems[j].get_address(0,this)));
|
|
get_virtual_registers(vregs);
|
|
foreach (vregs[j])
|
|
printer.print_generic(vregs[j].get_name(), vregs[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",vregs[j].get_inst_id(),vregs[j].get_address(0,this)));
|
|
get_submaps(maps);
|
|
foreach (maps[j])
|
|
printer.print_object(maps[j].get_name(),maps[j]);
|
|
endfunction
|
|
function string uvm_reg_map::convert2string();
|
|
uvm_reg regs[$];
|
|
uvm_vreg vregs[$];
|
|
uvm_mem mems[$];
|
|
uvm_endianness_e endian;
|
|
string prefix;
|
|
$sformat(convert2string, "%sMap %s", prefix, get_full_name());
|
|
endian = get_endian(UVM_NO_HIER);
|
|
$sformat(convert2string, "%s -- %0d bytes (%s)", convert2string,
|
|
get_n_bytes(UVM_NO_HIER), endian.name());
|
|
get_registers(regs);
|
|
foreach (regs[j]) begin
|
|
$sformat(convert2string, "%s\n%s", convert2string,
|
|
regs[j].convert2string());
|
|
end
|
|
get_memories(mems);
|
|
foreach (mems[j]) begin
|
|
$sformat(convert2string, "%s\n%s", convert2string,
|
|
mems[j].convert2string());
|
|
end
|
|
get_virtual_registers(vregs);
|
|
foreach (vregs[j]) begin
|
|
$sformat(convert2string, "%s\n%s", convert2string,
|
|
vregs[j].convert2string());
|
|
end
|
|
endfunction
|
|
function uvm_object uvm_reg_map::clone();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"UVM/REGMAP/NOCLONE"))
|
|
uvm_report_fatal ("UVM/REGMAP/NOCLONE", "uvm_reg_map doesnt support clone()", UVM_NONE, "t/uvm/src/reg/uvm_reg_map.svh", 2166, "", 1);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function void uvm_reg_map::do_copy (uvm_object rhs);
|
|
endfunction
|
|
class uvm_reg_block extends uvm_object;
|
|
typedef uvm_object_registry#(uvm_reg_block,"uvm_reg_block") type_id;
|
|
static function uvm_reg_block 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_block tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_block";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_block";
|
|
endfunction : get_type_name
|
|
local uvm_reg_block parent;
|
|
local static bit m_roots[uvm_reg_block];
|
|
local static int unsigned m_root_names[string];
|
|
local int unsigned blks[uvm_reg_block];
|
|
local int unsigned regs[uvm_reg];
|
|
local int unsigned vregs[uvm_vreg];
|
|
local int unsigned mems[uvm_mem];
|
|
local bit maps[uvm_reg_map];
|
|
local uvm_door_e default_path = UVM_DEFAULT_DOOR;
|
|
local string default_hdl_path = "RTL";
|
|
local uvm_reg_backdoor backdoor;
|
|
local uvm_object_string_pool #(uvm_queue #(string)) hdl_paths_pool;
|
|
local string root_hdl_paths[string];
|
|
local bit locked;
|
|
local int has_cover;
|
|
local int cover_on;
|
|
local string fname;
|
|
local int lineno;
|
|
local event m_uvm_lock_model_complete;
|
|
local static int id;
|
|
extern function new(string name="", int has_coverage=UVM_NO_COVERAGE);
|
|
extern function void configure(uvm_reg_block parent=null,
|
|
string hdl_path="");
|
|
extern virtual function uvm_reg_map create_map(string name,
|
|
uvm_reg_addr_t base_addr,
|
|
int unsigned n_bytes,
|
|
uvm_endianness_e endian,
|
|
bit byte_addressing = 1);
|
|
extern protected static function bit check_data_width(int unsigned width);
|
|
extern function void set_default_map (uvm_reg_map map);
|
|
uvm_reg_map default_map;
|
|
extern function uvm_reg_map get_default_map ();
|
|
extern virtual function void set_parent(uvm_reg_block parent);
|
|
extern function void add_block (uvm_reg_block blk);
|
|
extern function void add_map (uvm_reg_map map);
|
|
extern function void add_reg (uvm_reg rg);
|
|
extern function void add_vreg (uvm_vreg vreg);
|
|
extern function void add_mem (uvm_mem mem);
|
|
extern virtual function void lock_model();
|
|
virtual function void unlock_model();
|
|
bit s[uvm_reg_block]=m_roots;
|
|
m_roots.delete();
|
|
foreach (blks[blk_])
|
|
blk_.unlock_model();
|
|
m_roots=s;
|
|
foreach(m_roots[b])
|
|
m_roots[b]=0;
|
|
locked=0;
|
|
endfunction
|
|
virtual task wait_for_lock();
|
|
@m_uvm_lock_model_complete;
|
|
endtask
|
|
extern function bit is_locked();
|
|
extern virtual function string get_full_name();
|
|
extern virtual function uvm_reg_block get_parent();
|
|
extern static function void get_root_blocks(ref uvm_reg_block blks[$]);
|
|
extern static function int find_blocks(input string name,
|
|
ref uvm_reg_block blks[$],
|
|
input uvm_reg_block root = null,
|
|
input uvm_object accessor = null);
|
|
extern static function uvm_reg_block find_block(input string name,
|
|
input uvm_reg_block root = null,
|
|
input uvm_object accessor = null);
|
|
extern virtual function void get_blocks (ref uvm_reg_block blks[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_maps (ref uvm_reg_map maps[$]);
|
|
extern virtual function void get_registers (ref uvm_reg regs[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_fields (ref uvm_reg_field fields[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_memories (ref uvm_mem mems[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_virtual_registers(ref uvm_vreg regs[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function void get_virtual_fields (ref uvm_vreg_field fields[$],
|
|
input uvm_hier_e hier=UVM_HIER);
|
|
extern virtual function uvm_reg_block get_block_by_name (string name);
|
|
extern virtual function uvm_reg_map get_map_by_name (string name);
|
|
extern virtual function uvm_reg get_reg_by_name (string name);
|
|
extern virtual function uvm_reg_field get_field_by_name (string name);
|
|
extern virtual function uvm_mem get_mem_by_name (string name);
|
|
extern virtual function uvm_vreg get_vreg_by_name (string name);
|
|
extern virtual function uvm_vreg_field get_vfield_by_name (string name);
|
|
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 = UVM_CVR_ALL);
|
|
protected virtual function void sample(uvm_reg_addr_t offset,
|
|
bit is_read,
|
|
uvm_reg_map map);
|
|
endfunction
|
|
extern virtual function void sample_values();
|
|
extern function void XsampleX(uvm_reg_addr_t addr,
|
|
bit is_read,
|
|
uvm_reg_map map);
|
|
extern virtual function uvm_door_e get_default_door();
|
|
extern virtual function void set_default_door(uvm_door_e door);
|
|
extern virtual function void reset(string kind = "HARD");
|
|
extern virtual function bit needs_update();
|
|
extern virtual task 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);
|
|
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_sequence_base parent = null,
|
|
input int prior = -1,
|
|
input uvm_object extension = null,
|
|
input string fname = "",
|
|
input int lineno = 0);
|
|
extern virtual task 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);
|
|
extern virtual task 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);
|
|
extern virtual task write_mem_by_name(
|
|
output uvm_status_e status,
|
|
input string name,
|
|
input uvm_reg_addr_t offset,
|
|
input uvm_reg_data_t data,
|
|
input uvm_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_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);
|
|
extern virtual task readmemh(string filename);
|
|
extern virtual task writememh(string filename);
|
|
extern function uvm_reg_backdoor get_backdoor(bit inherited = 1);
|
|
extern function void set_backdoor (uvm_reg_backdoor bkdr,
|
|
string fname = "",
|
|
int lineno = 0);
|
|
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 = "",
|
|
string separator = ".");
|
|
extern function void set_default_hdl_path (string kind);
|
|
extern function string get_default_hdl_path ();
|
|
extern function void set_hdl_path_root (string path, string kind = "RTL");
|
|
extern function bit is_hdl_path_root (string kind = "");
|
|
extern virtual function void do_print (uvm_printer printer);
|
|
extern virtual function void do_copy (uvm_object rhs);
|
|
extern virtual function bit do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
extern virtual function void do_pack (uvm_packer packer);
|
|
extern virtual function void do_unpack (uvm_packer packer);
|
|
extern virtual function string convert2string ();
|
|
extern virtual function uvm_object clone();
|
|
extern local function void Xinit_address_mapsX();
|
|
virtual function void set_lock(bit v);
|
|
locked=v;
|
|
foreach(blks[idx])
|
|
idx.set_lock(v);
|
|
endfunction
|
|
virtual function void unregister(uvm_reg_map m);
|
|
foreach(regs[idx]) begin
|
|
if(idx.is_in_map(m))
|
|
regs.delete(idx);
|
|
end
|
|
foreach(mems[idx]) begin
|
|
if(idx.is_in_map(m))
|
|
mems.delete(idx);
|
|
end
|
|
foreach(vregs[idx]) begin
|
|
if(idx.is_in_map(m))
|
|
vregs.delete(idx);
|
|
end
|
|
maps.delete(m);
|
|
endfunction
|
|
endclass: uvm_reg_block
|
|
function bit uvm_reg_block::check_data_width(int unsigned width);
|
|
if (width <= $bits(uvm_reg_data_t)) return 1;
|
|
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", width, 64), UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 999, "", 1);
|
|
end
|
|
return 0;
|
|
endfunction
|
|
function uvm_reg_block::new(string name="", int has_coverage=UVM_NO_COVERAGE);
|
|
super.new(name);
|
|
hdl_paths_pool = new("hdl_paths");
|
|
this.has_cover = has_coverage;
|
|
m_roots[this] = 0;
|
|
if (m_root_names.exists(name))
|
|
m_root_names[name]++;
|
|
else
|
|
m_root_names[name] = 1;
|
|
endfunction: new
|
|
function void uvm_reg_block::configure(uvm_reg_block parent=null, string hdl_path="");
|
|
this.parent = parent;
|
|
if (parent != null)
|
|
this.parent.add_block(this);
|
|
add_hdl_path(hdl_path);
|
|
endfunction
|
|
function void uvm_reg_block::add_block (uvm_reg_block blk);
|
|
if (this.is_locked()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", "Cannot add subblock to locked block model", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1034, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (this.blks.exists(blk)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Subblock '",blk.get_name(), "' has already been registered with block '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1039, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
blks[blk] = id++;
|
|
if (m_roots.exists(blk)) m_roots.delete(blk);
|
|
begin
|
|
string name=blk.get_name();
|
|
if(m_root_names.exists(name)) m_root_names[name]--;
|
|
end
|
|
endfunction
|
|
function void uvm_reg_block::add_reg(uvm_reg rg);
|
|
if (this.is_locked()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", "Cannot add register to locked block model", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1056, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (this.regs.exists(rg)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Register '",rg.get_name(), "' has already been registered with block '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1062, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
regs[rg] = id++;
|
|
endfunction: add_reg
|
|
function void uvm_reg_block::add_vreg(uvm_vreg vreg);
|
|
if (this.is_locked()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", "Cannot add virtual register to locked block model", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1074, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (this.vregs.exists(vreg)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Virtual register '",vreg.get_name(), "' has already been registered with block '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1080, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
vregs[vreg] = id++;
|
|
endfunction: add_vreg
|
|
function void uvm_reg_block::add_mem(uvm_mem mem);
|
|
if (this.is_locked()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", "Cannot add memory to locked block model", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1091, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (this.mems.exists(mem)) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Memory '",mem.get_name(), "' has already been registered with block '",get_name(),"'"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 1097, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
mems[mem] = id++;
|
|
endfunction: add_mem
|
|
function void uvm_reg_block::set_parent(uvm_reg_block parent);
|
|
if (this != parent)
|
|
this.parent = parent;
|
|
endfunction
|
|
function bit uvm_reg_block::is_locked();
|
|
return this.locked;
|
|
endfunction: is_locked
|
|
function void uvm_reg_block::lock_model();
|
|
if (is_locked())
|
|
return;
|
|
locked = 1;
|
|
foreach (regs[rg_]) begin
|
|
uvm_reg rg = rg_;
|
|
rg.Xlock_modelX();
|
|
end
|
|
foreach (mems[mem_]) begin
|
|
uvm_mem mem = mem_;
|
|
mem.Xlock_modelX();
|
|
end
|
|
foreach (blks[blk_]) begin
|
|
uvm_reg_block blk=blk_;
|
|
blk.lock_model();
|
|
end
|
|
if (this.parent == null) begin
|
|
int max_size = uvm_reg::get_max_size();
|
|
if (uvm_reg_field::get_max_size() > 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<hdl_paths.size();i++)
|
|
paths.push_back(hdl_paths.get(i));
|
|
endfunction
|
|
function void uvm_reg_block::get_full_hdl_path(ref string paths[$],
|
|
input string kind = "",
|
|
string separator = ".");
|
|
if (kind == "")
|
|
kind = get_default_hdl_path();
|
|
paths.delete();
|
|
if (is_hdl_path_root(kind)) begin
|
|
if (root_hdl_paths[kind] != "")
|
|
paths.push_back(root_hdl_paths[kind]);
|
|
return;
|
|
end
|
|
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", 2110, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
begin
|
|
uvm_queue #(string) hdl_paths = hdl_paths_pool.get(kind);
|
|
string parent_paths[$];
|
|
if (parent != null)
|
|
parent.get_full_hdl_path(parent_paths, kind, separator);
|
|
for (int i=0; i<hdl_paths.size();i++) begin
|
|
string hdl_path = hdl_paths.get(i);
|
|
if (parent_paths.size() == 0) begin
|
|
if (hdl_path != "")
|
|
paths.push_back(hdl_path);
|
|
continue;
|
|
end
|
|
foreach (parent_paths[j]) begin
|
|
if (hdl_path == "")
|
|
paths.push_back(parent_paths[j]);
|
|
else
|
|
paths.push_back({ parent_paths[j], separator, hdl_path });
|
|
end
|
|
end
|
|
end
|
|
endfunction
|
|
function string uvm_reg_block::get_default_hdl_path();
|
|
if (default_hdl_path == "" && parent != null)
|
|
return parent.get_default_hdl_path();
|
|
return default_hdl_path;
|
|
endfunction
|
|
function void uvm_reg_block::set_default_hdl_path(string kind);
|
|
if (kind == "") begin
|
|
if (parent == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"RegModel"))
|
|
uvm_report_error ("RegModel", {"Block has no parent. ", "Must specify a valid HDL abstraction (kind)"}, UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2159, "", 1);
|
|
end
|
|
end
|
|
kind = parent.get_default_hdl_path();
|
|
end
|
|
default_hdl_path = kind;
|
|
endfunction
|
|
function void uvm_reg_block::set_hdl_path_root (string path, string kind = "RTL");
|
|
if (kind == "")
|
|
kind = get_default_hdl_path();
|
|
root_hdl_paths[kind] = path;
|
|
endfunction
|
|
function bit uvm_reg_block::is_hdl_path_root (string kind = "");
|
|
if (kind == "")
|
|
kind = get_default_hdl_path();
|
|
return root_hdl_paths.exists(kind);
|
|
endfunction
|
|
function void uvm_reg_block::do_print (uvm_printer printer);
|
|
super.do_print(printer);
|
|
foreach(blks[i]) begin
|
|
uvm_reg_block b = i;
|
|
uvm_object obj = b;
|
|
printer.print_object(obj.get_name(), obj);
|
|
end
|
|
foreach(regs[i]) begin
|
|
uvm_reg r = i;
|
|
uvm_object obj = r;
|
|
printer.print_object(obj.get_name(), obj);
|
|
end
|
|
foreach(vregs[i]) begin
|
|
uvm_vreg r = i;
|
|
uvm_object obj = r;
|
|
printer.print_object(obj.get_name(), obj);
|
|
end
|
|
foreach(mems[i]) begin
|
|
uvm_mem m = i;
|
|
uvm_object obj = m;
|
|
printer.print_object(obj.get_name(), obj);
|
|
end
|
|
foreach(maps[i]) begin
|
|
uvm_reg_map m = i;
|
|
uvm_object obj = m;
|
|
printer.print_object(obj.get_name(), obj);
|
|
end
|
|
endfunction
|
|
function uvm_object uvm_reg_block::clone();
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel blocks cannot be cloned", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2233, "", 1);
|
|
end
|
|
return null;
|
|
endfunction
|
|
function void uvm_reg_block::do_copy(uvm_object rhs);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_FATAL,"RegModel"))
|
|
uvm_report_fatal ("RegModel", "RegModel blocks cannot be copied", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2240, "", 1);
|
|
end
|
|
endfunction
|
|
function bit uvm_reg_block::do_compare (uvm_object rhs,
|
|
uvm_comparer comparer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel blocks cannot be compared", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2248, "", 1);
|
|
end
|
|
return 0;
|
|
endfunction
|
|
function void uvm_reg_block::do_pack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel blocks cannot be packed", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2256, "", 1);
|
|
end
|
|
endfunction
|
|
function void uvm_reg_block::do_unpack (uvm_packer packer);
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"RegModel"))
|
|
uvm_report_warning ("RegModel", "RegModel blocks cannot be unpacked", UVM_NONE, "t/uvm/src/reg/uvm_reg_block.svh", 2263, "", 1);
|
|
end
|
|
endfunction
|
|
function string uvm_reg_block::convert2string();
|
|
string image;
|
|
string maps[];
|
|
string blk_maps[];
|
|
bit single_map;
|
|
uvm_endianness_e endian;
|
|
string prefix = " ";
|
|
return image;
|
|
endfunction: convert2string
|
|
class uvm_reg_hw_reset_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
typedef uvm_object_registry#(uvm_reg_hw_reset_seq,"uvm_reg_hw_reset_seq") type_id;
|
|
static function uvm_reg_hw_reset_seq 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_hw_reset_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_hw_reset_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_hw_reset_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_hw_reset_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_hw_reset_seq"))
|
|
uvm_report_error ("uvm_reg_hw_reset_seq", "Not block or system specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_hw_reset_seq.svh", 80, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"STARTING_SEQ"))
|
|
uvm_report_info ("STARTING_SEQ", {"\n\nStarting ",get_name()," sequence...\n"}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_hw_reset_seq.svh", 83, "", 1);
|
|
end
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask: body
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_reg_map maps[$];
|
|
uvm_reg_map sub_maps[$];
|
|
uvm_reg regs[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_HW_RESET_TEST", 0) != null ) begin
|
|
return;
|
|
end
|
|
blk.get_registers(regs, UVM_NO_HIER);
|
|
foreach(regs[ridx]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[ridx].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
regs[ridx].has_reset() == 0 ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",regs[ridx].get_full_name()},
|
|
"NO_REG_HW_RESET_TEST", 0) != null )
|
|
continue;
|
|
begin
|
|
uvm_reg_map rm[$];
|
|
uvm_status_e status;
|
|
uvm_reg_field fields[$];
|
|
uvm_check_e field_check_restore[uvm_reg_field];
|
|
regs[ridx].get_maps(rm);
|
|
regs[ridx].get_fields(fields);
|
|
foreach(fields[fidx]) begin
|
|
if (fields[fidx].has_reset() == 0 ||
|
|
fields[fidx].get_compare() == UVM_NO_CHECK ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",fields[fidx].get_full_name()},
|
|
"NO_REG_HW_RESET_TEST", 0) != null) begin
|
|
field_check_restore[fields[fidx]] = fields[fidx].get_compare();
|
|
fields[fidx].set_compare(UVM_NO_CHECK);
|
|
end
|
|
end
|
|
if(fields.size() != field_check_restore.size()) begin
|
|
foreach(rm[midx]) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,get_type_name()))
|
|
uvm_report_info (get_type_name(), $sformatf("Verifying reset value of register %s in map \"%s\"...", regs[ridx].get_full_name(), rm[midx].get_full_name()), UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_hw_reset_seq.svh", 142, "", 1);
|
|
end
|
|
regs[ridx].mirror(status, UVM_CHECK, UVM_FRONTDOOR, rm[midx], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,get_type_name()))
|
|
uvm_report_error (get_type_name(), $sformatf("Status was %s when reading reset value of register \"%s\" through map \"%s\".", status.name(), regs[ridx].get_full_name(), rm[midx].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_hw_reset_seq.svh", 149, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
foreach(field_check_restore[field]) begin
|
|
field.set_compare(field_check_restore[field]);
|
|
end
|
|
end
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask:do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_reg_hw_reset_seq
|
|
class uvm_reg_single_bit_bash_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
uvm_reg rg;
|
|
typedef uvm_object_registry#(uvm_reg_single_bit_bash_seq,"uvm_reg_single_bit_bash_seq") type_id;
|
|
static function uvm_reg_single_bit_bash_seq 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_single_bit_bash_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_single_bit_bash_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_single_bit_bash_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_single_bit_bash_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
uvm_reg_field fields[$];
|
|
string mode[64];
|
|
uvm_reg_map maps[$];
|
|
uvm_reg_data_t dc_mask;
|
|
uvm_reg_data_t reset_val;
|
|
int n_bits;
|
|
string field_access;
|
|
if (rg == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_error ("uvm_reg_bit_bash_seq", "No register specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 82, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_BIT_BASH_TEST", 0) != null )
|
|
return;
|
|
n_bits = rg.get_n_bytes() * 8;
|
|
rg.get_fields(fields);
|
|
rg.get_maps(maps);
|
|
foreach (maps[j]) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t val, exp, v;
|
|
int next_lsb;
|
|
next_lsb = 0;
|
|
dc_mask = 0;
|
|
foreach (fields[k]) begin
|
|
int lsb, w, dc;
|
|
field_access = fields[k].get_access(maps[j]);
|
|
dc = (fields[k].get_compare() == UVM_NO_CHECK);
|
|
lsb = fields[k].get_lsb_pos();
|
|
w = fields[k].get_n_bits();
|
|
case (field_access)
|
|
"WO", "WOC", "WOS", "WO1", "NOACCESS": dc = 1;
|
|
endcase
|
|
while (next_lsb < lsb) mode[next_lsb++] = "RO";
|
|
repeat (w) begin
|
|
mode[next_lsb] = field_access;
|
|
dc_mask[next_lsb] = dc;
|
|
next_lsb++;
|
|
end
|
|
end
|
|
while (next_lsb < 64)
|
|
mode[next_lsb++] = "RO";
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_info ("uvm_reg_bit_bash_seq", $sformatf("Verifying bits in register %s in map \"%s\"...", rg.get_full_name(), maps[j].get_full_name()), UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 135, "", 1);
|
|
end
|
|
for (int k = 0; k < n_bits; k++) begin
|
|
if (dc_mask[k]) continue;
|
|
bash_kth_bit(rg, k, mode[k], maps[j], dc_mask);
|
|
end
|
|
end
|
|
endtask: body
|
|
task bash_kth_bit(uvm_reg rg,
|
|
int k,
|
|
string mode,
|
|
uvm_reg_map map,
|
|
uvm_reg_data_t dc_mask);
|
|
uvm_status_e status;
|
|
uvm_reg_data_t val, exp, v;
|
|
bit bit_val;
|
|
begin
|
|
if (uvm_report_enabled(UVM_HIGH,UVM_INFO,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_info ("uvm_reg_bit_bash_seq", $sformatf("...Bashing %s bit #%0d", mode, k), UVM_HIGH, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 158, "", 1);
|
|
end
|
|
repeat (2) begin
|
|
val = rg.get();
|
|
v = val;
|
|
exp = val;
|
|
val[k] = ~val[k];
|
|
bit_val = val[k];
|
|
rg.write(status, val, UVM_FRONTDOOR, map, this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_error ("uvm_reg_bit_bash_seq", $sformatf("Status was %s when writing to register \"%s\" through map \"%s\".", status.name(), rg.get_full_name(), map.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 170, "", 1);
|
|
end
|
|
end
|
|
exp = rg.get() & ~dc_mask;
|
|
rg.read(status, val, UVM_FRONTDOOR, map, this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_error ("uvm_reg_bit_bash_seq", $sformatf("Status was %s when reading register \"%s\" through map \"%s\".", status.name(), rg.get_full_name(), map.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 177, "", 1);
|
|
end
|
|
end
|
|
val &= ~dc_mask;
|
|
if (val !== exp) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_error ("uvm_reg_bit_bash_seq", $sformatf("Writing a %b in bit #%0d of register \"%s\" with initial value 'h%h yielded 'h%h instead of 'h%h", bit_val, k, rg.get_full_name(), v, val, exp), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 183, "", 1);
|
|
end
|
|
end
|
|
end
|
|
endtask: bash_kth_bit
|
|
endclass: uvm_reg_single_bit_bash_seq
|
|
class uvm_reg_bit_bash_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
protected uvm_reg_single_bit_bash_seq reg_seq;
|
|
typedef uvm_object_registry#(uvm_reg_bit_bash_seq,"uvm_reg_bit_bash_seq") type_id;
|
|
static function uvm_reg_bit_bash_seq 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_bit_bash_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_bit_bash_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_bit_bash_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_bit_bash_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_bit_bash_seq"))
|
|
uvm_report_error ("uvm_reg_bit_bash_seq", "No register model specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_bit_bash_seq.svh", 238, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
reg_seq = uvm_reg_single_bit_bash_seq::type_id_create("reg_single_bit_bash_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_reg regs[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_BIT_BASH_TEST", 0) != null )
|
|
return;
|
|
blk.get_registers(regs, UVM_NO_HIER);
|
|
foreach (regs[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_BIT_BASH_TEST", 0) != null )
|
|
continue;
|
|
reg_seq.rg = regs[i];
|
|
reg_seq.start(null,this);
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks,UVM_NO_HIER);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask: do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_reg_bit_bash_seq
|
|
class uvm_mem_single_walk_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
typedef uvm_object_registry#(uvm_mem_single_walk_seq,"uvm_mem_single_walk_seq") type_id;
|
|
static function uvm_mem_single_walk_seq 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_mem_single_walk_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_mem_single_walk_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_mem_single_walk_seq";
|
|
endfunction : get_type_name
|
|
uvm_mem mem;
|
|
function new(string name="uvm_mem_walk_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
uvm_reg_map maps[$];
|
|
int n_bits;
|
|
if (mem == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_walk_seq"))
|
|
uvm_report_error ("uvm_mem_walk_seq", "No memory specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 97, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_WALK_TEST", 0) != null )
|
|
return;
|
|
n_bits = mem.get_n_bits();
|
|
mem.get_maps(maps);
|
|
foreach (maps[j]) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t val, exp, v;
|
|
if (mem.get_access(maps[j]) != "RW") continue;
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_mem_walk_seq"))
|
|
uvm_report_info ("uvm_mem_walk_seq", $sformatf("Walking memory %s in map \"%s\"...", mem.get_full_name(), maps[j].get_full_name()), UVM_LOW, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 124, "", 1);
|
|
end
|
|
for (int k = 0; k < mem.get_size(); k++) begin
|
|
mem.write(status, k, ~k, 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 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_walk_seq.svh", 136, "", 1);
|
|
end
|
|
end
|
|
if (k > 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<<n_bits)-1);
|
|
if (val !== exp) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_walk_seq"))
|
|
uvm_report_error ("uvm_mem_walk_seq", $sformatf("\"%s[%0d]\" read back as 'h%h instead of 'h%h.", mem.get_full_name(), k-1, val, exp), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 149, "", 1);
|
|
end
|
|
end
|
|
end
|
|
mem.write(status, k-1, k-1, 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 writing \"%s[%0d]\" through map \"%s\".", status.name(), mem.get_full_name(), k-1, maps[j].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 157, "", 1);
|
|
end
|
|
end
|
|
end
|
|
if (k == mem.get_size() - 1) begin
|
|
mem.read(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_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", 165, "", 1);
|
|
end
|
|
end
|
|
else begin
|
|
exp = ~(k) & ((1'b1<<n_bits)-1);
|
|
if (val !== exp) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_walk_seq"))
|
|
uvm_report_error ("uvm_mem_walk_seq", $sformatf("\"%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_walk_seq.svh", 171, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_mem_single_walk_seq
|
|
class uvm_mem_walk_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
protected uvm_mem_single_walk_seq mem_seq;
|
|
typedef uvm_object_registry#(uvm_mem_walk_seq,"uvm_mem_walk_seq") type_id;
|
|
static function uvm_mem_walk_seq 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_mem_walk_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_mem_walk_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_mem_walk_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_mem_walk_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_walk_seq"))
|
|
uvm_report_error ("uvm_mem_walk_seq", "No register model specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_walk_seq.svh", 231, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
mem_seq = uvm_mem_single_walk_seq::type_id_create("single_mem_walk_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask: body
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_mem mems[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) != null )
|
|
return;
|
|
blk.get_memories(mems, UVM_NO_HIER);
|
|
foreach (mems[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_WALK_TEST", 0) != null )
|
|
continue;
|
|
mem_seq.mem = mems[i];
|
|
mem_seq.start(null, this);
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask: do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_mem_walk_seq
|
|
class uvm_mem_single_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
uvm_mem mem;
|
|
typedef uvm_object_registry#(uvm_mem_single_access_seq,"uvm_mem_single_access_seq") type_id;
|
|
static function uvm_mem_single_access_seq 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_mem_single_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_mem_single_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_mem_single_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uam_mem_single_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
string mode;
|
|
uvm_reg_map maps[$];
|
|
int n_bits;
|
|
if (mem == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq"))
|
|
uvm_report_error ("uvm_mem_access_seq", "No register specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 75, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) != null)
|
|
return;
|
|
if (mem.get_backdoor() == null && !mem.has_hdl_path()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq"))
|
|
uvm_report_error ("uvm_mem_access_seq", {"Memory '",mem.get_full_name(), "' does not have a backdoor mechanism available"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 91, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
n_bits = mem.get_n_bits();
|
|
mem.get_maps(maps);
|
|
foreach (maps[j]) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t val, exp, v;
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_mem_access_seq"))
|
|
uvm_report_info ("uvm_mem_access_seq", {"Verifying access of memory '", mem.get_full_name(),"' in map '", maps[j].get_full_name(), "' ..."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 107, "", 1);
|
|
end
|
|
mode = mem.get_access(maps[j]);
|
|
for (int k = 0; k < mem.get_size(); k++) begin
|
|
val = $random & uvm_reg_data_t'((1'b1<<n_bits)-1);
|
|
if (n_bits > 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<<n_bits)-1);
|
|
mem.poke(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 writing \"%s[%0d-1]\" through backdoor.", status.name(), mem.get_full_name(), k), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 153, "", 1);
|
|
end
|
|
end
|
|
mem.read(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 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_access_seq.svh", 159, "", 1);
|
|
end
|
|
end
|
|
else begin
|
|
if (mode == "WO") begin
|
|
if (val !== '0) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq"))
|
|
uvm_report_error ("uvm_mem_access_seq", $sformatf("Front door \"%s[%0d]\" read back as 'h%h instead of 'h%h.", mem.get_full_name(), k, val, 0), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 165, "", 1);
|
|
end
|
|
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("Front door \"%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", 171, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_mem_single_access_seq
|
|
class uvm_mem_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
protected uvm_mem_single_access_seq mem_seq;
|
|
typedef uvm_object_registry#(uvm_mem_access_seq,"uvm_mem_access_seq") type_id;
|
|
static function uvm_mem_access_seq 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_mem_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_mem_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_mem_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_mem_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_access_seq"))
|
|
uvm_report_error ("uvm_mem_access_seq", "No register model specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 228, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
mem_seq = uvm_mem_single_access_seq::type_id_create("single_mem_access_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask: body
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_mem mems[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) != null )
|
|
return;
|
|
blk.get_memories(mems, UVM_NO_HIER);
|
|
foreach (mems[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) != null )
|
|
continue;
|
|
if (mems[i].get_backdoor() == null &&
|
|
!mems[i].has_hdl_path()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"uvm_mem_access_seq"))
|
|
uvm_report_warning ("uvm_mem_access_seq", $sformatf("Memory \"%s\" does not have a backdoor mechanism available", mems[i].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_mem_access_seq.svh", 278, "", 1);
|
|
end
|
|
continue;
|
|
end
|
|
mem_seq.mem = mems[i];
|
|
mem_seq.start(null, this);
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask: do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_mem_access_seq
|
|
typedef class uvm_mem_access_seq;
|
|
class uvm_reg_single_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
uvm_reg rg;
|
|
typedef uvm_object_registry#(uvm_reg_single_access_seq,"uvm_reg_single_access_seq") type_id;
|
|
static function uvm_reg_single_access_seq 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_single_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_single_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_single_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_single_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
uvm_reg_map maps[$];
|
|
if (rg == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", "No register specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 82, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_ACCESS_TEST", 0) != null )
|
|
return;
|
|
if (rg.get_backdoor() == null && !rg.has_hdl_path()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", {"Register '",rg.get_full_name(), "' does not have a backdoor mechanism available"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 96, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
rg.get_maps(maps);
|
|
begin
|
|
uvm_reg_field fields[$];
|
|
rg.get_fields(fields);
|
|
foreach (maps[k]) begin
|
|
int ro;
|
|
ro=0;
|
|
foreach (fields[j]) begin
|
|
if (fields[j].get_access(maps[k]) == "RO") begin
|
|
ro++;
|
|
end
|
|
if (!fields[j].is_known_access(maps[k])) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"uvm_reg_access_seq"))
|
|
uvm_report_warning ("uvm_reg_access_seq", {"Register '",rg.get_full_name(), "' has field with unknown access type '", fields[j].get_access(maps[k]),"', skipping"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 118, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
if(ro==fields.size()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"uvm_reg_access_seq"))
|
|
uvm_report_warning ("uvm_reg_access_seq", {"Register '", rg.get_full_name(),"' has only RO fields in map ",maps[k].get_full_name(),", skipping"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 124, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
foreach (maps[j]) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t v, exp;
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_access_seq"))
|
|
uvm_report_info ("uvm_reg_access_seq", {"Verifying access of register '", rg.get_full_name(),"' in map '", maps[j].get_full_name(), "' ..."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 141, "", 1);
|
|
end
|
|
v = rg.get();
|
|
rg.write(status, ~v, UVM_FRONTDOOR, maps[j], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", {"Status was '",status.name(), "' when writing '",rg.get_full_name(), "' through map '",maps[j].get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 150, "", 1);
|
|
end
|
|
end
|
|
#1;
|
|
rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, uvm_reg_map::backdoor(), this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", {"Status was '",status.name(), "' when reading reset value of register '", rg.get_full_name(), "' through backdoor"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 158, "", 1);
|
|
end
|
|
end
|
|
rg.write(status, v, UVM_BACKDOOR, maps[j], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", {"Status was '",status.name(), "' when writing '",rg.get_full_name(), "' through backdoor"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 165, "", 1);
|
|
end
|
|
end
|
|
rg.mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[j], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", {"Status was '",status.name(), "' when reading reset value of register '", rg.get_full_name(), "' through map '", maps[j].get_full_name(),"'"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 173, "", 1);
|
|
end
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_reg_single_access_seq
|
|
class uvm_reg_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
protected uvm_reg_single_access_seq reg_seq;
|
|
typedef uvm_object_registry#(uvm_reg_access_seq,"uvm_reg_access_seq") type_id;
|
|
static function uvm_reg_access_seq 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_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_access_seq"))
|
|
uvm_report_error ("uvm_reg_access_seq", "No register model specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 228, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
reg_seq = uvm_reg_single_access_seq::type_id_create("single_reg_access_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask: body
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_reg regs[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_ACCESS_TEST", 0) != null )
|
|
return;
|
|
blk.get_registers(regs, UVM_NO_HIER);
|
|
foreach (regs[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_ACCESS_TEST", 0) != null )
|
|
continue;
|
|
if (regs[i].get_backdoor() == null && !regs[i].has_hdl_path()) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"uvm_reg_access_seq"))
|
|
uvm_report_warning ("uvm_reg_access_seq", {"Register '",regs[i].get_full_name(), "' does not have a backdoor mechanism available"}, UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 273, "", 1);
|
|
end
|
|
continue;
|
|
end
|
|
reg_seq.rg = regs[i];
|
|
reg_seq.start(null,this);
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask: do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_reg_access_seq
|
|
class uvm_reg_mem_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
typedef uvm_object_registry#(uvm_reg_mem_access_seq,"uvm_reg_mem_access_seq") type_id;
|
|
static function uvm_reg_mem_access_seq 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_mem_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_mem_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_mem_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_mem_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_access_seq"))
|
|
uvm_report_error ("uvm_reg_mem_access_seq", "Register model handle is null", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_access_seq.svh", 338, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",
|
|
{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_ACCESS_TEST", 0) == null) begin
|
|
uvm_reg_access_seq sub_seq = new("reg_access_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
sub_seq.model = model;
|
|
sub_seq.start(null,this);
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) == null) begin
|
|
uvm_mem_access_seq sub_seq = new("mem_access_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
sub_seq.model = model;
|
|
sub_seq.start(null,this);
|
|
end
|
|
end
|
|
endtask: body
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_reg_mem_access_seq
|
|
class uvm_reg_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
uvm_reg rg;
|
|
typedef uvm_object_registry#(uvm_reg_shared_access_seq,"uvm_reg_shared_access_seq") type_id;
|
|
static function uvm_reg_shared_access_seq 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_shared_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_shared_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_shared_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_shared_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
uvm_reg_data_t other_mask;
|
|
uvm_reg_data_t wo_mask[$];
|
|
uvm_reg_field fields[$];
|
|
uvm_reg_map maps[$];
|
|
if (rg == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_shared_access_seq"))
|
|
uvm_report_error ("uvm_reg_shared_access_seq", "No register specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 82, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) != null )
|
|
return;
|
|
if (rg.get_n_maps() < 2) return;
|
|
rg.get_maps(maps);
|
|
rg.get_fields(fields);
|
|
other_mask = 0;
|
|
foreach (fields[k]) begin
|
|
int lsb, w;
|
|
lsb = fields[k].get_lsb_pos();
|
|
w = fields[k].get_n_bits();
|
|
if (!fields[k].is_known_access(maps[0])) begin
|
|
repeat (w) begin
|
|
other_mask[lsb++] = 1'b1;
|
|
end
|
|
end
|
|
end
|
|
foreach (maps[j]) begin
|
|
uvm_reg_data_t wo;
|
|
wo = 0;
|
|
foreach (fields[k]) begin
|
|
int lsb, w;
|
|
lsb = fields[k].get_lsb_pos();
|
|
w = fields[k].get_n_bits();
|
|
if (fields[k].get_access(maps[j]) == "WO") begin
|
|
repeat (w) begin
|
|
wo[lsb++] = 1'b1;
|
|
end
|
|
end
|
|
end
|
|
wo_mask[j] = wo;
|
|
end
|
|
foreach (maps[j]) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t prev, v;
|
|
prev = rg.get();
|
|
v = ({$random, $random} & ~other_mask) | (prev & other_mask);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_shared_access_seq"))
|
|
uvm_report_info ("uvm_reg_shared_access_seq", $sformatf("Writing register %s via map \"%s\"...", rg.get_full_name(), maps[j].get_full_name), UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 148, "", 1);
|
|
end
|
|
begin
|
|
if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"uvm_reg_shared_access_seq"))
|
|
uvm_report_info ("uvm_reg_shared_access_seq", $sformatf("Writing 'h%h over 'h%h", v, prev), UVM_DEBUG, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 150, "", 1);
|
|
end
|
|
rg.write(status, v, UVM_FRONTDOOR, maps[j], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_shared_access_seq"))
|
|
uvm_report_error ("uvm_reg_shared_access_seq", $sformatf("Status was %s when writing register \"%s\" through map \"%s\".", status.name(), rg.get_full_name(), maps[j].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 155, "", 1);
|
|
end
|
|
end
|
|
foreach (maps[k]) begin
|
|
uvm_reg_data_t actual, exp;
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_reg_shared_access_seq"))
|
|
uvm_report_info ("uvm_reg_shared_access_seq", $sformatf("Reading register %s via map \"%s\"...", rg.get_full_name(), maps[k].get_full_name()), UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 162, "", 1);
|
|
end
|
|
exp = rg.get() & ~wo_mask[k];
|
|
rg.read(status, actual, UVM_FRONTDOOR, maps[k], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_shared_access_seq"))
|
|
uvm_report_error ("uvm_reg_shared_access_seq", $sformatf("Status was %s when reading register \"%s\" through map \"%s\".", status.name(), rg.get_full_name(), maps[k].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 170, "", 1);
|
|
end
|
|
end
|
|
begin
|
|
if (uvm_report_enabled(UVM_DEBUG,UVM_INFO,"uvm_reg_shared_access_seq"))
|
|
uvm_report_info ("uvm_reg_shared_access_seq", $sformatf("Read 'h%h, expecting 'h%h", actual, exp), UVM_DEBUG, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 174, "", 1);
|
|
end
|
|
if (actual !== exp) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_shared_access_seq"))
|
|
uvm_report_error ("uvm_reg_shared_access_seq", $sformatf("Register \"%s\" through map \"%s\" is 'h%h instead of 'h%h after writing 'h%h via map \"%s\" over 'h%h.", rg.get_full_name(), maps[k].get_full_name(), actual, exp, v, maps[j].get_full_name(), prev), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 179, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_reg_shared_access_seq
|
|
class uvm_mem_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
uvm_mem mem;
|
|
typedef uvm_object_registry#(uvm_mem_shared_access_seq,"uvm_mem_shared_access_seq") type_id;
|
|
static function uvm_mem_shared_access_seq 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_mem_shared_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_mem_shared_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_mem_shared_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_mem_shared_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
int read_from;
|
|
uvm_reg_map maps[$];
|
|
if (mem == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", "No memory specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 230, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},
|
|
"NO_MEM_SHARED_ACCESS_TEST", 0) != null )
|
|
return;
|
|
if (mem.get_n_maps() < 2) return;
|
|
mem.get_maps(maps);
|
|
read_from = -1;
|
|
if (mem.get_backdoor() == null) begin
|
|
foreach (maps[j]) begin
|
|
string right;
|
|
right = mem.get_access(maps[j]);
|
|
if (right == "RW" ||
|
|
right == "RO") begin
|
|
read_from = j;
|
|
break;
|
|
end
|
|
end
|
|
if (read_from < 0) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,"uvm_mem_shared_access_seq"))
|
|
uvm_report_warning ("uvm_mem_shared_access_seq", $sformatf("Memory \"%s\" cannot be read from any maps or backdoor. Shared access not verified.", mem.get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 263, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
foreach (maps[j]) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"uvm_mem_shared_access_seq"))
|
|
uvm_report_info ("uvm_mem_shared_access_seq", $sformatf("Writing shared memory \"%s\" via map \"%s\".", mem.get_full_name(), maps[j].get_full_name()), UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 272, "", 1);
|
|
end
|
|
for (int offset = 0; offset < mem.get_size(); offset++) begin
|
|
uvm_status_e status;
|
|
uvm_reg_data_t prev, v;
|
|
if (mem.get_backdoor() != null) begin
|
|
mem.peek(status, offset, prev);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading initial value of \"%s\"[%0d] through backdoor.", status.name(), mem.get_full_name(), offset), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 284, "", 1);
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
mem.read(status, offset, prev, UVM_FRONTDOOR, maps[read_from], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading initial value of \"%s\"[%0d] through map \"%s\".", status.name(), mem.get_full_name(), offset, maps[read_from].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 292, "", 1);
|
|
end
|
|
end
|
|
end
|
|
v = {$random, $random};
|
|
mem.write(status, offset, v, UVM_FRONTDOOR, maps[j], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", $sformatf("Status was %s when writing \"%s\"[%0d] through map \"%s\".", status.name(), mem.get_full_name(), offset, maps[j].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 303, "", 1);
|
|
end
|
|
end
|
|
foreach (maps[k]) begin
|
|
uvm_reg_data_t actual, exp;
|
|
mem.read(status, offset, actual, UVM_FRONTDOOR, maps[k], this);
|
|
if (status != UVM_IS_OK) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading %s[%0d] through map \"%s\".", status.name(), mem.get_full_name(), offset, maps[k].get_full_name()), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 313, "", 1);
|
|
end
|
|
end
|
|
exp = v;
|
|
if (mem.get_access(maps[j]) == "RO") begin
|
|
exp = prev;
|
|
end
|
|
if (mem.get_access(maps[k]) == "WO") begin
|
|
exp = 0;
|
|
end
|
|
exp &= (1 << mem.get_n_bits()) - 1;
|
|
if (actual !== exp) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_mem_shared_access_seq", $sformatf("%s[%0d] through map \"%s\" is 'h%h instead of 'h%h after writing 'h%h via map \"%s\" over 'h%h.", mem.get_full_name(), offset, maps[k].get_full_name(), actual, exp, v, maps[j].get_full_name(), prev), UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 329, "", 1);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_mem_shared_access_seq
|
|
class uvm_reg_mem_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
protected uvm_reg_shared_access_seq reg_seq;
|
|
protected uvm_mem_shared_access_seq mem_seq;
|
|
typedef uvm_object_registry#(uvm_reg_mem_shared_access_seq,"uvm_reg_mem_shared_access_seq") type_id;
|
|
static function uvm_reg_mem_shared_access_seq 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_mem_shared_access_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_mem_shared_access_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_mem_shared_access_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_mem_shared_access_seq");
|
|
super.new(name);
|
|
endfunction
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_shared_access_seq"))
|
|
uvm_report_error ("uvm_reg_mem_shared_access_seq", "No register model specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_shared_access_seq.svh", 397, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
reg_seq = uvm_reg_shared_access_seq::type_id_create("reg_shared_access_seq");
|
|
mem_seq = uvm_mem_shared_access_seq::type_id_create("reg_shared_access_seq");
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
do_block(model);
|
|
endtask: body
|
|
protected virtual task do_block(uvm_reg_block blk);
|
|
uvm_reg regs[$];
|
|
uvm_mem mems[$];
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},
|
|
"NO_MEM_SHARED_ACCESS_TEST", 0) != null )
|
|
return;
|
|
this.reset_blk(model);
|
|
model.reset();
|
|
blk.get_registers(regs, UVM_NO_HIER);
|
|
foreach (regs[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) != null )
|
|
continue;
|
|
reg_seq.rg = regs[i];
|
|
reg_seq.start(this.get_sequencer(), this);
|
|
end
|
|
blk.get_memories(mems, UVM_NO_HIER);
|
|
foreach (mems[i]) begin
|
|
if (uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_REG_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_TESTS", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) != null ||
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},
|
|
"NO_MEM_SHARED_ACCESS_TEST", 0) != null )
|
|
continue;
|
|
mem_seq.mem = mems[i];
|
|
mem_seq.start(this.get_sequencer(), this);
|
|
end
|
|
begin
|
|
uvm_reg_block blks[$];
|
|
blk.get_blocks(blks);
|
|
foreach (blks[i]) begin
|
|
do_block(blks[i]);
|
|
end
|
|
end
|
|
endtask: do_block
|
|
virtual task reset_blk(uvm_reg_block blk);
|
|
endtask
|
|
endclass: uvm_reg_mem_shared_access_seq
|
|
class uvm_reg_mem_built_in_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
typedef uvm_object_registry#(uvm_reg_mem_built_in_seq,"uvm_reg_mem_built_in_seq") type_id;
|
|
static function uvm_reg_mem_built_in_seq 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_mem_built_in_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_mem_built_in_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_mem_built_in_seq";
|
|
endfunction : get_type_name
|
|
function new(string name="uvm_reg_mem_built_in_seq");
|
|
super.new(name);
|
|
endfunction
|
|
bit [63:0] tests = UVM_DO_ALL_REG_MEM_TESTS;
|
|
virtual task body();
|
|
if (model == null) begin
|
|
begin
|
|
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,"uvm_reg_mem_built_in_seq"))
|
|
uvm_report_error ("uvm_reg_mem_built_in_seq", "Not block or system specified to run sequence on", UVM_NONE, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 67, "", 1);
|
|
end
|
|
return;
|
|
end
|
|
uvm_report_info("START_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);
|
|
if (tests & UVM_DO_REG_HW_RESET &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_HW_RESET_TEST", 0) == null ) begin
|
|
uvm_reg_hw_reset_seq seq = uvm_reg_hw_reset_seq::type_id_create("reg_hw_reset_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 85, "", 1);
|
|
end
|
|
end
|
|
if (tests & UVM_DO_REG_BIT_BASH &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_BIT_BASH_TEST", 0) == null ) begin
|
|
uvm_reg_bit_bash_seq seq = uvm_reg_bit_bash_seq::type_id_create("reg_bit_bash_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 100, "", 1);
|
|
end
|
|
end
|
|
if (tests & UVM_DO_REG_ACCESS &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_ACCESS_TEST", 0) == null ) begin
|
|
uvm_reg_access_seq seq = uvm_reg_access_seq::type_id_create("reg_access_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 115, "", 1);
|
|
end
|
|
end
|
|
if (tests & UVM_DO_MEM_ACCESS &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_MEM_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_MEM_ACCESS_TEST", 0) == null ) begin
|
|
uvm_mem_access_seq seq = uvm_mem_access_seq::type_id_create("mem_access_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 132, "", 1);
|
|
end
|
|
end
|
|
if (tests & UVM_DO_SHARED_ACCESS &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_SHARED_ACCESS_TEST", 0) == null ) begin
|
|
uvm_reg_mem_shared_access_seq seq = uvm_reg_mem_shared_access_seq::type_id_create("shared_access_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 147, "", 1);
|
|
end
|
|
end
|
|
if (tests & UVM_DO_MEM_WALK &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_REG_TESTS", 0) == null &&
|
|
uvm_resource_db#(bit)::get_by_name({"REG::",model.get_full_name()},
|
|
"NO_MEM_WALK_TEST", 0) == null ) begin
|
|
uvm_mem_walk_seq seq = uvm_mem_walk_seq::type_id_create("mem_walk_seq");
|
|
seq.model = model;
|
|
seq.start(null,this);
|
|
begin
|
|
if (uvm_report_enabled(UVM_LOW,UVM_INFO,"FINISH_SEQ"))
|
|
uvm_report_info ("FINISH_SEQ", {"Finished ",seq.get_name()," sequence."}, UVM_LOW, "t/uvm/src/reg/sequences/uvm_reg_mem_built_in_seq.svh", 162, "", 1);
|
|
end
|
|
end
|
|
endtask: body
|
|
endclass: uvm_reg_mem_built_in_seq
|
|
class uvm_reg_mem_hdl_paths_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
|
|
string abstractions[$];
|
|
typedef uvm_object_registry#(uvm_reg_mem_hdl_paths_seq,"uvm_reg_mem_hdl_paths_seq") type_id;
|
|
static function uvm_reg_mem_hdl_paths_seq 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_mem_hdl_paths_seq tmp;
|
|
if (name=="") tmp = new();
|
|
else tmp = new(name);
|
|
return tmp;
|
|
endfunction
|
|
static function string type_name();
|
|
return "uvm_reg_mem_hdl_paths_seq";
|
|
endfunction : type_name
|
|
virtual function string get_type_name();
|
|
return "uvm_reg_mem_hdl_paths_seq";
|
|
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_reg_mem_hdl_paths_seq local_rhs__;
|
|
uvm_resource_base local_rsrc__;
|
|
string local_rsrc_name__;
|
|
uvm_object local_obj__;
|
|
bit local_success__;
|
|
typedef uvm_reg_mem_hdl_paths_seq __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
|
|
begin
|
|
case (local_op_type__)
|
|
UVM_COPY:
|
|
if (!((UVM_DEFAULT)&UVM_NOCOPY)) begin
|
|
abstractions = local_rhs__.abstractions;
|
|
end
|
|
UVM_COMPARE:
|
|
if (!((UVM_DEFAULT)&UVM_NOCOMPARE)) begin
|
|
if ((!__local_comparer__.get_threshold() ||
|
|
(__local_comparer__.get_result() < __local_comparer__.get_threshold()))) begin
|
|
if ((abstractions) !== (local_rhs__.abstractions)) begin
|
|
if ((!__local_comparer__.get_threshold() ||
|
|
(__local_comparer__.get_result() < __local_comparer__.get_threshold()))) begin
|
|
if ((abstractions.size()) !== (local_rhs__.abstractions.size())) begin
|
|
if ($bits(abstractions.size()) <= 64)
|
|
void'(__local_comparer__.compare_field_int($sformatf("%s.size()", "abstractions") , abstractions.size(), local_rhs__.abstractions.size(), $bits(abstractions.size()), UVM_DEC));
|
|
else
|
|
void'(__local_comparer__.compare_field($sformatf("%s.size()", "abstractions") , abstractions.size(), local_rhs__.abstractions.size(), $bits(abstractions.size()), UVM_DEC));
|
|
end
|
|
end
|
|
if ((!__local_comparer__.get_threshold() ||
|
|
(__local_comparer__.get_result() < __local_comparer__.get_threshold()))) begin
|
|
if ((abstractions) !== (local_rhs__.abstractions)) begin
|
|
foreach (abstractions[i]) begin
|
|
if ((!__local_comparer__.get_threshold() ||
|
|
(__local_comparer__.get_result() < __local_comparer__.get_threshold()))) begin
|
|
if ((abstractions[i]) != (local_rhs__.abstractions[i])) begin
|
|
void'(__local_comparer__.compare_string($sformatf("%s[%0d]", "abstractions", i) , abstractions[i], local_rhs__.abstractions[i]));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
UVM_PACK:
|
|
if (!((UVM_DEFAULT)&UVM_NOPACK)) begin
|
|
__local_packer__.pack_field_int(abstractions.size(), 32);
|
|
foreach (abstractions[i])
|
|
__local_packer__.pack_string(abstractions[i]);
|
|
end
|
|
UVM_UNPACK:
|
|
if (!((UVM_DEFAULT)&UVM_NOUNPACK)) begin
|
|
local_size__ = __local_packer__.unpack_field_int(32);
|
|
if (abstractions.size() > 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<sz__; ++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
|
|
end
|
|
end
|
|
UVM_PRINT:
|
|
if (!((UVM_DEFAULT)&UVM_NOPRINT)) begin
|
|
begin
|
|
int __tmp_max = $right(abstractions) + 1;
|
|
__local_printer__.print_array_header("abstractions",
|
|
__tmp_max,
|
|
"queue(string)");
|
|
if ((__local_printer__.get_max_depth() == -1) ||
|
|
(__local_printer__.get_active_object_depth() < __local_printer__.get_max_depth()+1)) begin
|
|
int __tmp_begin_elements, __tmp_end_elements;
|
|
__tmp_begin_elements = __local_printer__.get_begin_elements();
|
|
__tmp_end_elements = __local_printer__.get_end_elements();
|
|
if (__tmp_begin_elements == -1 || __tmp_end_elements == -1) begin
|
|
foreach (abstractions[__tmp_index]) begin
|
|
__local_printer__.print_string($sformatf("[%0d]", __tmp_index), abstractions[__tmp_index]);
|
|
end
|
|
end
|
|
else begin
|
|
int __tmp_curr;
|
|
foreach(abstractions[__tmp_index]) begin
|
|
if (__tmp_curr < __tmp_begin_elements) begin
|
|
__local_printer__.print_string($sformatf("[%0d]", __tmp_index), abstractions[__tmp_index]);
|
|
end
|
|
else
|
|
break;
|
|
__tmp_curr++;
|
|
end
|
|
if (__tmp_curr < __tmp_max ) begin
|
|
if ((__tmp_max - __tmp_end_elements) > __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
|