URL
https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk
Subversion Repositories uart2bus_testbench
[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [reg/] [uvm_reg_field.svh] - Rev 16
Compare with Previous | Blame | View Log
//// -------------------------------------------------------------// Copyright 2004-2009 Synopsys, Inc.// Copyright 2010-2011 Mentor Graphics Corporation// Copyright 2010-2011 Cadence Design Systems, Inc.// Copyright 2013 Semifore, Inc.// All Rights Reserved Worldwide//// Licensed under the Apache License, Version 2.0 (the// "License"); you may not use this file except in// compliance with the License. You may obtain a copy of// the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in// writing, software distributed under the License is// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR// CONDITIONS OF ANY KIND, either express or implied. See// the License for the specific language governing// permissions and limitations under the License.// -------------------------------------------------------------//typedef class uvm_reg_cbs;//-----------------------------------------------------------------// CLASS: uvm_reg_field// Field abstraction class//// A field represents a set of bits that behave consistently// as a single entity.//// A field is contained within a single register, but may// have different access policies depending on the address map// use the access the register (thus the field).//-----------------------------------------------------------------class uvm_reg_field extends uvm_object;// Variable: value// Mirrored field value.// This value can be sampled in a functional coverage model// or constrained when randomized.rand uvm_reg_data_t value; // Mirrored after randomize()local uvm_reg_data_t m_mirrored; // What we think is in the HWlocal uvm_reg_data_t m_desired; // Mirrored after set()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 (`UVM_REG_DATA_WIDTH > m_size) {value < (`UVM_REG_DATA_WIDTH'h1 << m_size);}}`uvm_object_utils(uvm_reg_field)//----------------------// Group: Initialization//----------------------// Function: new//// Create a new field instance//// This method should not be used directly.// The ~uvm_reg_field::type_id::create()~ factory method// should be used instead.//extern function new(string name = "uvm_reg_field");// Function: configure//// Instance-specific configuration//// Specify the ~parent~ register of this field, its// ~size~ in bits, the position of its least-significant bit// within the register relative to the least-significant bit// of the register, its ~access~ policy, volatility,// "HARD" ~reset~ value,// whether the field value is actually reset// (the ~reset~ value is ignored if ~FALSE~),// whether the field value may be randomized and// whether the field is the only one to occupy a byte lane in the register.//// See <set_access> for a specification of the pre-defined// field access policies.//// If the field access policy is a pre-defined policy and NOT one of// "RW", "WRC", "WRS", "WO", "W1", or "WO1",// the value of ~is_rand~ is ignored and the rand_mode() for the// field instance is turned off since it cannot be written.//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);//---------------------// Group: Introspection//---------------------// Function: get_name//// Get the simple name//// Return the simple object name of this field//// Function: get_full_name//// Get the hierarchical name//// Return the hierarchal name of this field// The base of the hierarchical name is the root block.//extern virtual function string get_full_name();// Function: get_parent//// Get the parent register//extern virtual function uvm_reg get_parent();extern virtual function uvm_reg get_register();// Function: get_lsb_pos//// Return the position of the field//// Returns the index of the least significant bit of the field// in the register that instantiates it.// An offset of 0 indicates a field that is aligned with the// least-significant bit of the register.//extern virtual function int unsigned get_lsb_pos();// Function: get_n_bits//// Returns the width, in number of bits, of the field.//extern virtual function int unsigned get_n_bits();//// FUNCTION: get_max_size// Returns the width, in number of bits, of the largest field.//extern static function int unsigned get_max_size();// Function: set_access//// Modify the access policy of the field//// Modify the access policy of the field to the specified one and// return the previous access policy.//// The pre-defined access policies are as follows.// The effect of a read operation are applied after the current// value of the field is sampled.// The read operation will return the current value,// not the value affected by the read operation (if any).//// "RO" - W: no effect, R: no effect// "RW" - W: as-is, R: no effect// "RC" - W: no effect, R: clears all bits// "RS" - W: no effect, R: sets all bits// "WRC" - W: as-is, R: clears all bits// "WRS" - W: as-is, R: sets all bits// "WC" - W: clears all bits, R: no effect// "WS" - W: sets all bits, R: no effect// "WSRC" - W: sets all bits, R: clears all bits// "WCRS" - W: clears all bits, R: sets all bits// "W1C" - W: 1/0 clears/no effect on matching bit, R: no effect// "W1S" - W: 1/0 sets/no effect on matching bit, R: no effect// "W1T" - W: 1/0 toggles/no effect on matching bit, R: no effect// "W0C" - W: 1/0 no effect on/clears matching bit, R: no effect// "W0S" - W: 1/0 no effect on/sets matching bit, R: no effect// "W0T" - W: 1/0 no effect on/toggles matching bit, R: no effect// "W1SRC" - W: 1/0 sets/no effect on matching bit, R: clears all bits// "W1CRS" - W: 1/0 clears/no effect on matching bit, R: sets all bits// "W0SRC" - W: 1/0 no effect on/sets matching bit, R: clears all bits// "W0CRS" - W: 1/0 no effect on/clears matching bit, R: sets all bits// "WO" - W: as-is, R: error// "WOC" - W: clears all bits, R: error// "WOS" - W: sets all bits, R: error// "W1" - W: first one after ~HARD~ reset is as-is, other W have no effects, R: no effect// "WO1" - W: first one after ~HARD~ reset is as-is, other W have no effects, R: error// "NOACCESS" - W: no effect, R: no effect//// It is important to remember that modifying the access of a field// will make the register model diverge from the specification// that was used to create it.//extern virtual function string set_access(string mode);// Function: define_access//// Define a new access policy value//// Because field access policies are specified using string values,// there is no way for SystemVerilog to verify if a specific access// value is valid or not.// To help catch typing errors, user-defined access values// must be defined using this method to avoid begin reported as an// invalid access policy.//// The name of field access policies are always converted to all uppercase.//// Returns TRUE if the new access policy was not previously// defined.// Returns FALSE otherwise but does not issue an error message.//extern static function bit define_access(string name);local static bit m_predefined = m_predefine_policies();extern local static function bit m_predefine_policies();// Function: get_access//// Get the access policy of the field//// Returns the current access policy of the field// when written and read through the specified address ~map~.// If the register containing the field is mapped in multiple// address map, an address map must be specified.// The access policy of a field from a specific// address map may be restricted by the register's access policy in that// address map.// For example, a RW field may only be writable through one of// the address maps and read-only through all of the other maps.// If the field access contradicts the map's access value// (field access of WO, and map access value of RO, etc), the// method's return value is NOACCESS.extern virtual function string get_access(uvm_reg_map map = null);// Function: is_known_access//// Check if access policy is a built-in one.//// Returns TRUE if the current access policy of the field,// when written and read through the specified address ~map~,// is a built-in access policy.//extern virtual function bit is_known_access(uvm_reg_map map = null);//// Function: set_volatility// Modify the volatility of the field to the specified one.//// It is important to remember that modifying the volatility of a field// will make the register model diverge from the specification// that was used to create it.//extern virtual function void set_volatility(bit volatile);//// Function: is_volatile// Indicates if the field value is volatile//// UVM uses the IEEE 1685-2009 IP-XACT definition of "volatility".// If TRUE, the value of the register is not predictable because it// may change between consecutive accesses.// This typically indicates a field whose value is updated by the DUT.// The nature or cause of the change is not specified.// If FALSE, the value of the register is not modified between// consecutive accesses.//extern virtual function bit is_volatile();//--------------// Group: Access//--------------// Function: set//// Set the desired value for this field//// It sets the desired value of the field to the specified ~value~// modified by the field access policy.// It does not actually set the value of the field in the design,// only the desired value in the abstraction class.// Use the <uvm_reg::update()> method to update the actual register// with the desired value or the <uvm_reg_field::write()> method// to actually write the field and update its mirrored value.//// The final desired value in the mirror is a function of the field access// policy and the set value, just like a normal physical write operation// to the corresponding bits in the hardware.// As such, this method (when eventually followed by a call to// <uvm_reg::update()>)// is a zero-time functional replacement for the <uvm_reg_field::write()>// method.// For example, the desired value of a read-only field is not modified// by this method and the desired value of a write-once field can only// be set if the field has not yet been// written to using a physical (for example, front-door) write operation.//// Use the <uvm_reg_field::predict()> to modify the mirrored value of// the field.//extern virtual function void set(uvm_reg_data_t value,string fname = "",int lineno = 0);// Function: get//// Return the desired value of the field//// It does not actually read the value// of the field in the design, only the desired value// in the abstraction class. Unless set to a different value// using the <uvm_reg_field::set()>, the desired value// and the mirrored value are identical.//// Use the <uvm_reg_field::read()> or <uvm_reg_field::peek()>// method to get the actual field value.//// If the field is write-only, the desired/mirrored// value is the value last written and assumed// to reside in the bits implementing it.// Although a physical read operation would something different,// the returned value is the actual content.//extern virtual function uvm_reg_data_t get(string fname = "",int lineno = 0);// Function: get_mirrored_value//// Return the mirrored value of the field//// It does not actually read the value of the field in the design, only the mirrored value// in the abstraction class.//// If the field is write-only, the desired/mirrored// value is the value last written and assumed// to reside in the bits implementing it.// Although a physical read operation would something different,// the returned value is the actual content.//extern virtual function uvm_reg_data_t get_mirrored_value(string fname = "",int lineno = 0);// Function: reset//// Reset the desired/mirrored value for this field.//// It sets the desired and mirror value of the field// to the reset event specified by ~kind~.// If the field does not have a reset value specified for the// specified reset ~kind~ the field is unchanged.//// It does not actually reset the value of the field in the design,// only the value mirrored in the field abstraction class.//// Write-once fields can be modified after// a "HARD" reset operation.//extern virtual function void reset(string kind = "HARD");// Function: get_reset//// Get the specified reset value for this field//// Return the reset value for this field// for the specified reset ~kind~.// Returns the current field value is no reset value has been// specified for the specified reset event.//extern virtual function uvm_reg_data_t get_reset(string kind = "HARD");// Function: has_reset//// Check if the field has a reset value specified//// Return TRUE if this field has a reset value specified// for the specified reset ~kind~.// If ~delete~ is TRUE, removes the reset value, if any.//extern virtual function bit has_reset(string kind = "HARD",bit delete = 0);// Function: set_reset//// Specify or modify the reset value for this field//// Specify or modify the reset value for this field corresponding// to the cause specified by ~kind~.//extern virtual function void set_reset(uvm_reg_data_t value,string kind = "HARD");// Function: needs_update//// Check if the abstract model contains different desired and mirrored values.//// If a desired field value has been modified in the abstraction class// without actually updating the field in the DUT,// the state of the DUT (more specifically what the abstraction class// ~thinks~ the state of the DUT is) is outdated.// This method returns TRUE// if the state of the field in the DUT needs to be updated// to match the desired value.// The mirror values or actual content of DUT field are not modified.// Use the <uvm_reg::update()> to actually update the DUT field.//extern virtual function bit needs_update();// Task: write//// Write the specified value in this field//// Write ~value~ in the DUT field that corresponds to this// abstraction class instance using the specified access// ~path~.// If the register containing this field is mapped in more// than one address map,// an address ~map~ must be// specified if a physical access is used (front-door access).// If a back-door access path is used, the effect of writing// the field through a physical access is mimicked. For// example, read-only bits in the field will not be written.//// The mirrored value will be updated using the <uvm_reg_field::predict()>// method.//// If a front-door access is used, and// if the field is the only field in a byte lane and// if the physical interface corresponding to the address map used// to access the field support byte-enabling,// then only the field is written.// Otherwise, the entire register containing the field is written,// and the mirrored values of the other fields in the same register// are used in a best-effort not to modify their value.//// If a backdoor access is used, a peek-modify-poke process is used.// in a best-effort not to modify the value of the other fields in the// register.//extern virtual task write (output uvm_status_e status,input uvm_reg_data_t value,input uvm_path_e path = UVM_DEFAULT_PATH,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);// Task: read//// Read the current value from this field//// Read and return ~value~ from the DUT field that corresponds to this// abstraction class instance using the specified access// ~path~.// If the register containing this field is mapped in more// than one address map, an address ~map~ must be// specified if a physical access is used (front-door access).// If a back-door access path is used, the effect of reading// the field through a physical access is mimicked. For// example, clear-on-read bits in the field will be set to zero.//// The mirrored value will be updated using the <uvm_reg_field::predict()>// method.//// If a front-door access is used, and// if the field is the only field in a byte lane and// if the physical interface corresponding to the address map used// to access the field support byte-enabling,// then only the field is read.// Otherwise, the entire register containing the field is read,// and the mirrored values of the other fields in the same register// are updated.//// If a backdoor access is used, the entire containing register is peeked// and the mirrored value of the other fields in the register is updated.//extern virtual task read (output uvm_status_e status,output uvm_reg_data_t value,input uvm_path_e path = UVM_DEFAULT_PATH,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);// Task: poke//// Deposit the specified value in this field//// Deposit the value in the DUT field corresponding to this// abstraction class instance, as-is, using a back-door access.// A peek-modify-poke process is used// in a best-effort not to modify the value of the other fields in the// register.//// The mirrored value will be updated using the <uvm_reg_field::predict()>// method.//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);// Task: peek//// Read the current value from this field//// Sample the value in the DUT field corresponding to this// abstraction class instance using a back-door access.// The field value is sampled, not modified.//// Uses the HDL path for the design abstraction specified by ~kind~.//// The entire containing register is peeked// and the mirrored value of the other fields in the register// are updated using the <uvm_reg_field::predict()> method.////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);// Task: mirror//// Read the field and update/check its mirror value//// Read the field and optionally compared the readback value// with the current mirrored value if ~check~ is <UVM_CHECK>.// The mirrored value will be updated using the <predict()>// method based on the readback value.//// The ~path~ argument specifies whether to mirror using// the <UVM_FRONTDOOR> (<read>) or// <UVM_BACKDOOR> (<peek()>).//// If ~check~ is specified as <UVM_CHECK>,// an error message is issued if the current mirrored value// does not match the readback value, unless <set_compare> was used// disable the check.//// If the containing register is mapped in multiple address maps and physical// access is used (front-door access), an address ~map~ must be specified.// For write-only fields, their content is mirrored and optionally// checked only if a UVM_BACKDOOR// access path is used to read the field.//extern virtual task mirror(output uvm_status_e status,input uvm_check_e check = UVM_NO_CHECK,input uvm_path_e path = UVM_DEFAULT_PATH,input uvm_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);// Function: set_compare//// Sets the compare policy during a mirror update.// The field value is checked against its mirror only when both the// ~check~ argument in <uvm_reg_block::mirror>, <uvm_reg::mirror>,// or <uvm_reg_field::mirror> and the compare policy for the// field is <UVM_CHECK>.//extern function void set_compare(uvm_check_e check=UVM_CHECK);// Function: get_compare//// Returns the compare policy for this field.//extern function uvm_check_e get_compare();// Function: is_indv_accessible//// Check if this field can be written individually, i.e. without// affecting other fields in the containing register.//extern function bit is_indv_accessible (uvm_path_e path,uvm_reg_map local_map);// Function: predict//// Update the mirrored and desired value for this field.//// Predict the mirror and desired value of the field based on the specified// observed ~value~ on a bus using the specified address ~map~.//// If ~kind~ is specified as <UVM_PREDICT_READ>, the value// was observed in a read transaction on the specified address ~map~ or// backdoor (if ~path~ is <UVM_BACKDOOR>).// If ~kind~ is specified as <UVM_PREDICT_WRITE>, the value// was observed in a write transaction on the specified address ~map~ or// backdoor (if ~path~ is <UVM_BACKDOOR>).// If ~kind~ is specified as <UVM_PREDICT_DIRECT>, the value// was computed and is updated as-is, without regard to any access policy.// For example, the mirrored value of a read-only field is modified// by this method if ~kind~ is specified as <UVM_PREDICT_DIRECT>.//// This method does not allow an update of the mirror (or desired)// when the register containing this field is busy executing// a transaction because the results are unpredictable and// indicative of a race condition in the testbench.//// Returns TRUE if the prediction was successful.//extern function bit predict (uvm_reg_data_t value,uvm_reg_byte_en_t be = -1,uvm_predict_e kind = UVM_PREDICT_DIRECT,uvm_path_e path = UVM_FRONTDOOR,uvm_reg_map map = null,string fname = "",int lineno = 0);/*local*/extern virtual function uvm_reg_data_t XpredictX (uvm_reg_data_t cur_val,uvm_reg_data_t wr_val,uvm_reg_map map);/*local*/extern virtual function uvm_reg_data_t XupdateX();/*local*/extern function bit Xcheck_accessX (input uvm_reg_item rw,output uvm_reg_map_info map_info,input string caller);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();//-----------------// Group: Callbacks//-----------------`uvm_register_cb(uvm_reg_field, uvm_reg_cbs)// Task: pre_write//// Called before field write.//// If the specified data value, access ~path~ or address ~map~ are modified,// the updated data value, access path or address map will be used// to perform the register operation.// If the ~status~ is modified to anything other than <UVM_IS_OK>,// the operation is aborted.//// The field callback methods are invoked after the callback methods// on the containing register.// The registered callback methods are invoked after the invocation// of this method.//virtual task pre_write (uvm_reg_item rw); endtask// Task: post_write//// Called after field write.//// If the specified ~status~ is modified,// the updated status will be// returned by the register operation.//// The field callback methods are invoked after the callback methods// on the containing register.// The registered callback methods are invoked before the invocation// of this method.//virtual task post_write (uvm_reg_item rw); endtask// Task: pre_read//// Called before field read.//// If the access ~path~ or address ~map~ in the ~rw~ argument are modified,// the updated access path or address map will be used to perform// the register operation.// If the ~status~ is modified to anything other than <UVM_IS_OK>,// the operation is aborted.//// The field callback methods are invoked after the callback methods// on the containing register.// The registered callback methods are invoked after the invocation// of this method.//virtual task pre_read (uvm_reg_item rw); endtask// Task: post_read//// Called after field read.//// If the specified readback data or~status~ in the ~rw~ argument is// modified, the updated readback data or status will be// returned by the register operation.//// The field callback methods are invoked after the callback methods// on the containing register.// The registered callback methods are invoked before the invocation// of this method.//virtual task post_read (uvm_reg_item rw); endtaskextern 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//------------------------------------------------------------------------------// IMPLEMENTATION//------------------------------------------------------------------------------// newfunction uvm_reg_field::new(string name = "uvm_reg_field");super.new(name);endfunction: new// configurefunction 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`uvm_error("RegModel",$sformatf("Field \"%s\" cannot have 0 bits", get_full_name()));size = 1;endm_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);elseuvm_resource_db#(bit)::set({"REG::", get_full_name()},"NO_REG_HW_RESET_TEST", 1);m_parent.add_field(this);if (!m_policy_names.exists(m_access)) begin`uvm_error("RegModel", {"Access policy '",access,"' for field '",get_full_name(),"' is not defined. Setting to RW"})m_access = "RW";endif (size > m_max_size)m_max_size = size;// Ignore is_rand if the field is known not to be writeable// i.e. not "RW", "WRC", "WRS", "WO", "W1", "WO1"case (access)"RO", "RC", "RS", "WC", "WS","W1C", "W1S", "W1T", "W0C", "W0S", "W0T","W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS","WOC", "WOS": is_rand = 0;endcaseif (!is_rand)value.rand_mode(0);endfunction: configure// get_parentfunction uvm_reg uvm_reg_field::get_parent();return m_parent;endfunction: get_parent// get_full_namefunction string uvm_reg_field::get_full_name();return {m_parent.get_full_name(), ".", get_name()};endfunction: get_full_name// get_registerfunction uvm_reg uvm_reg_field::get_register();return m_parent;endfunction: get_register// get_lsb_posfunction int unsigned uvm_reg_field::get_lsb_pos();return m_lsb;endfunction: get_lsb_pos// get_n_bitsfunction int unsigned uvm_reg_field::get_n_bits();return m_size;endfunction: get_n_bits// get_max_sizefunction int unsigned uvm_reg_field::get_max_size();return m_max_size;endfunction: get_max_size// is_known_accessfunction 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;endcasereturn 0;endfunction// get_accessfunction 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;// Is the register restricted in this map?case (m_parent.get_rights(map))"RW":// No restrictionsreturn 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": beginfield_access = "NOACCESS";end// No change for the other modesendcase"WO":case (field_access)"RW","WO": field_access = "WO";default: beginfield_access = "NOACCESS";end// No change for the other modesendcasedefault:beginfield_access = "NOACCESS";`uvm_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), "'"})endendcasereturn field_access;endfunction: get_access// set_accessfunction string uvm_reg_field::set_access(string mode);set_access = m_access;m_access = mode.toupper();if (!m_policy_names.exists(m_access)) begin`uvm_error("RegModel", {"Access policy '",m_access,"' is not a defined field access policy"})m_access = set_access;endendfunction: set_access// define_accessfunction 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// m_predefined_policiesfunction 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// set_volatilityfunction void uvm_reg_field::set_volatility(bit volatile);m_volatile = volatile;endfunction// is_volatilefunction bit uvm_reg_field::is_volatile();return m_volatile;endfunction// XpredictXfunction 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`uvm_fatal("RegModel", "uvm_reg_field::XpredictX(): Internal error");return 0;endfunction: XpredictX// predictfunction 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_path_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// do_predictfunction 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;// Assume that the entire field is enabledif (!be[0])return;m_fname = rw.fname;m_lineno = rw.lineno;case (kind)UVM_PREDICT_WRITE:beginuvm_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;endUVM_PREDICT_READ:beginuvm_reg_field_cb_iter cbs = new(this);if (rw.path == UVM_FRONTDOOR || rw.path == UVM_PREDICT) beginstring acc = get_access(rw.map);if (acc == "RC" ||acc == "WRC" ||acc == "WSRC" ||acc == "W1SRC" ||acc == "W0SRC")field_val = 0; // (clear)else if (acc == "RS" ||acc == "WRS" ||acc == "WCRS" ||acc == "W1CRS" ||acc == "W0CRS")field_val = ('b1 << m_size)-1; // all 1's (set)else if (acc == "WO" ||acc == "WOC" ||acc == "WOS" ||acc == "WO1" ||acc == "NOACCESS")return;endfor (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;endUVM_PREDICT_DIRECT:beginif (m_parent.is_busy()) begin`uvm_warning("RegModel", {"Trying to predict value of field '",get_name(),"' while register '",m_parent.get_full_name(),"' is being accessed"})rw.status = UVM_NOT_OK;endendendcase// update the mirror with predicted valuem_mirrored = field_val;m_desired = field_val;this.value = field_val;endfunction: do_predict// XupdateXfunction uvm_reg_data_t uvm_reg_field::XupdateX();// Figure out which value must be written to get the desired value// given what we think is the current value in the hardwareXupdateX = 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; // Warn if != 0"WS": XupdateX = m_desired; // Warn if != 1"WSRC": XupdateX = m_desired; // Warn if != 1"WCRS": XupdateX = m_desired; // Warn if != 0"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; // Warn if != 0"WOS": XupdateX = m_desired; // Warn if != 1"W1": XupdateX = m_desired;"WO1": XupdateX = m_desired;default: XupdateX = m_desired;endcaseXupdateX &= (1 << m_size) - 1;endfunction: XupdateX// setfunction 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`uvm_warning("RegModel",$sformatf("Specified value (0x%h) greater than field \"%s\" size (%0d bits)",value, get_name(), m_size));value &= mask;endif (m_parent.is_busy()) begin`uvm_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()))endcase (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;endcasethis.value = m_desired;endfunction: set// getfunction uvm_reg_data_t uvm_reg_field::get(string fname = "",int lineno = 0);m_fname = fname;m_lineno = lineno;get = m_desired;endfunction: get// get_mirrored_valuefunction 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// resetfunction 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// has_resetfunction 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// get_resetfunction uvm_reg_data_tuvm_reg_field::get_reset(string kind = "HARD");if (!m_reset.exists(kind))return m_desired;return m_reset[kind];endfunction: get_reset// set_resetfunction 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// needs_updatefunction bit uvm_reg_field::needs_update();needs_update = (m_mirrored != m_desired) | m_volatile;endfunction: needs_updatetypedef class uvm_reg_map_info;// Xcheck_accessXfunction bit uvm_reg_field::Xcheck_accessX(input uvm_reg_item rw,output uvm_reg_map_info map_info,input string caller);if (rw.path == UVM_DEFAULT_PATH) beginuvm_reg_block blk = m_parent.get_block();rw.path = blk.get_default_path();endif (rw.path == UVM_BACKDOOR) beginif (m_parent.get_backdoor() == null && !m_parent.has_hdl_path()) begin`uvm_warning("RegModel",{"No backdoor access available for field '",get_full_name(),"' . Using frontdoor instead."})rw.path = UVM_FRONTDOOR;endelserw.map = uvm_reg_map::backdoor();endif (rw.path != UVM_BACKDOOR) beginrw.local_map = m_parent.get_local_map(rw.map,caller);if (rw.local_map == null) begin`uvm_error(get_type_name(),{"No transactor available to physically access memory from map '",rw.map.get_full_name(),"'"})rw.status = UVM_NOT_OK;return 0;endmap_info = rw.local_map.get_reg_map_info(m_parent);if (map_info.frontdoor == null && map_info.unmapped) begin`uvm_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"})rw.status = UVM_NOT_OK;return 0;endif (rw.map == null)rw.map = rw.local_map;endreturn 1;endfunction// writetask uvm_reg_field::write(output uvm_status_e status,input uvm_reg_data_t value,input uvm_path_e path = UVM_DEFAULT_PATH,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// do_writetask 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,"write()"))return;m_write_in_progress = 1'b1;if (rw.value[0] >> m_size) begin`uvm_warning("RegModel", {"uvm_reg_field::write(): Value greater than field '",get_full_name(),"'"})rw.value[0] &= ((1<<m_size)-1);end// Get values to write to the other fields in registerm_parent.get_fields(fields);foreach (fields[i]) beginif (fields[i] == this) beginvalue_adjust |= rw.value[0] << m_lsb;continue;end// It depends on what kind of bits they are made of...case (fields[i].get_access(rw.local_map))// These..."RO", "RC", "RS", "W1C", "W1S", "W1T", "W1SRC", "W1CRC":// Use all 0'svalue_adjust |= 0;// These..."W0C", "W0S", "W0T", "W0SRC", "W0CRS":// Use all 1'svalue_adjust |= ((1<<fields[i].get_n_bits())-1) << fields[i].get_lsb_pos();// These might have side effects! Bad!"WC", "WS", "WCRS", "WSRC", "WOC", "WOS":bad_side_effect = 1;default:value_adjust |= fields[i].m_mirrored << fields[i].get_lsb_pos();endcaseend`ifdef UVM_REG_NO_INDIVIDUAL_FIELD_ACCESSrw.element_kind = UVM_REG;rw.element = m_parent;rw.value[0] = value_adjust;m_parent.do_write(rw);`elseif (!is_indv_accessible(rw.path,rw.local_map)) beginrw.element_kind = UVM_REG;rw.element = m_parent;rw.value[0] = value_adjust;m_parent.do_write(rw);if (bad_side_effect) begin`uvm_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()));endendelse beginuvm_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) beginm_write_in_progress = 1'b0;m_parent.Xset_busyX(0);m_parent.XatomicX(0);return;endrw.local_map.do_write(rw);if (system_map.get_auto_predict())// ToDo: Call parent.XsampleX();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`endifm_write_in_progress = 1'b0;m_parent.XatomicX(0);endtask: do_write// readtask uvm_reg_field::read(output uvm_status_e status,output uvm_reg_data_t value,input uvm_path_e path = UVM_DEFAULT_PATH,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// do_readtask 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,"read()"))return;`ifdef UVM_REG_NO_INDIVIDUAL_FIELD_ACCESSrw.element_kind = UVM_REG;rw.element = m_parent;m_parent.do_read(rw);rw.value[0] = (rw.value[0] >> m_lsb) & ((1<<m_size))-1;bad_side_effect = 1;`elseif (!is_indv_accessible(rw.path,rw.local_map)) beginrw.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;endelse beginuvm_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) beginm_read_in_progress = 1'b0;m_parent.Xset_busyX(0);m_parent.XatomicX(0);return;endrw.local_map.do_read(rw);if (system_map.get_auto_predict())// ToDo: Call parent.XsampleX();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`endifm_read_in_progress = 1'b0;m_parent.XatomicX(0);if (bad_side_effect) beginuvm_reg_field fields[$];m_parent.get_fields(fields);foreach (fields[i]) beginstring 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`uvm_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"})endendendendtask: do_read// is_indv_accessiblefunction bit uvm_reg_field::is_indv_accessible(uvm_path_e path,uvm_reg_map local_map);if (path == UVM_BACKDOOR) begin`uvm_warning("RegModel",{"Individual BACKDOOR field access not available for field '",get_full_name(), "'. Accessing complete register instead."})return 0;endif (!m_individually_accessible) begin`uvm_warning("RegModel",{"Individual field access not available for field '",get_full_name(), "'. Accessing complete register instead."})return 0;end// Cannot access individual fields if the container register// has a user-defined front-doorif (m_parent.get_frontdoor(local_map) != null) begin`uvm_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."})return 0;endbeginuvm_reg_map system_map = local_map.get_root_map();uvm_reg_adapter adapter = system_map.get_adapter();if (adapter.supports_byte_enable)return 1;endbeginint 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) beginsole_field = 1;endelse beginint prev_lsb,this_lsb,next_lsb;int prev_sz,this_sz,next_sz;int bus_sz = bus_width*8;foreach (fields[i]) beginif (fields[i] == this) beginfld_idx = i;break;endendthis_lsb = fields[fld_idx].get_lsb_pos();this_sz = fields[fld_idx].get_n_bits();if (fld_idx>0) beginprev_lsb = fields[fld_idx-1].get_lsb_pos();prev_sz = fields[fld_idx-1].get_n_bits();endif (fld_idx < fields.size()-1) beginnext_lsb = fields[fld_idx+1].get_lsb_pos();next_sz = fields[fld_idx+1].get_n_bits();end// if first field in registerif (fld_idx == 0 &&((next_lsb % bus_sz) == 0 ||(next_lsb - this_sz) > (next_lsb % bus_sz)))return 1;// if last field in registerelse if (fld_idx == (fields.size()-1) &&((this_lsb % bus_sz) == 0 ||(this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz)))return 1;// if somewhere in betweenelse beginif ((this_lsb % bus_sz) == 0) beginif ((next_lsb % bus_sz) == 0 ||(next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz))return 1;endelse beginif ( (next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz) &&((this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz)) )return 1;endendendend`uvm_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."})return 0;endfunction// poketask 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`uvm_warning("RegModel",{"uvm_reg_field::poke(): Value exceeds size of field '",get_name(),"'"})value &= value & ((1<<m_size)-1);endm_parent.XatomicX(1);m_parent.m_is_locked_by_field = 1'b1;tmp = 0;// What is the current values of the other fields???m_parent.peek(status, tmp, kind, parent, extension, fname, lineno);if (status == UVM_NOT_OK) begin`uvm_error("RegModel", {"uvm_reg_field::poke(): Peek of register '",m_parent.get_full_name(),"' returned status ",status.name()})m_parent.XatomicX(0);m_parent.m_is_locked_by_field = 1'b0;return;end// Force the value for this field then poke the resulting valuetmp &= ~(((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// peektask 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// mirrortask uvm_reg_field::mirror(output uvm_status_e status,input uvm_check_e check = UVM_NO_CHECK,input uvm_path_e path = UVM_DEFAULT_PATH,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// set_comparefunction void uvm_reg_field::set_compare(uvm_check_e check=UVM_CHECK);m_check = check;endfunction// get_comparefunction uvm_check_e uvm_reg_field::get_compare();return m_check;endfunction// pre_randomizefunction void uvm_reg_field::pre_randomize();// Update the only publicly known property with the current// desired value so it can be used as a state variable should// the rand_mode of the field be turned off.value = m_desired;endfunction: pre_randomize// post_randomizefunction void uvm_reg_field::post_randomize();m_desired = value;endfunction: post_randomize// do_printfunction void uvm_reg_field::do_print (uvm_printer printer);printer.print_generic(get_name(), get_type_name(), -1, convert2string());endfunction// convert2stringfunction 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) beginif (m_fname != "" && m_lineno != 0)$sformat(res_str, " from %s:%0d",m_fname, m_lineno);convert2string = {convert2string, "\n", "currently being read", res_str};endif (m_write_in_progress == 1'b1) beginif (m_fname != "" && m_lineno != 0)$sformat(res_str, " from %s:%0d",m_fname, m_lineno);convert2string = {convert2string, "\n", res_str, "currently being written"};endendfunction: convert2string// clonefunction uvm_object uvm_reg_field::clone();`uvm_fatal("RegModel","RegModel field cannot be cloned")return null;endfunction// do_copyfunction void uvm_reg_field::do_copy(uvm_object rhs);`uvm_warning("RegModel","RegModel field copy not yet implemented")// just a set(rhs.get()) ?endfunction// do_comparefunction bit uvm_reg_field::do_compare (uvm_object rhs,uvm_comparer comparer);`uvm_warning("RegModel","RegModel field compare not yet implemented")// just a return (get() == rhs.get()) ?return 0;endfunction// do_packfunction void uvm_reg_field::do_pack (uvm_packer packer);`uvm_warning("RegModel","RegModel field cannot be packed")endfunction// do_unpackfunction void uvm_reg_field::do_unpack (uvm_packer packer);`uvm_warning("RegModel","RegModel field cannot be unpacked")endfunction
