#//
#// -------------------------------------------------------------
#//    Copyright 2004-2009 Synopsys, Inc.
#//    Copyright 2010 Mentor Graphics 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.
#// -------------------------------------------------------------
#//
#
#
#//------------------------------------------------------------------------------
#// Title: Virtual Register Field Classes
#//
#// This section defines the virtual field and callback classes.
#//
#// A virtual field is set of contiguous bits in one or more memory locations.
#// The semantics and layout of virtual fields comes from
#// an agreement between the software and the hardware,
#// not any physical structures in the DUT. 
#//
#//------------------------------------------------------------------------------
#
#typedef class uvm_vreg_field_cbs;
#
#
#//------------------------------------------------------------------------------
#// Class: uvm_vreg_field
#//
#// Virtual field abstraction class
#//
#// A virtual field represents a set of adjacent bits that are
#// logically implemented in consecutive memory locations.
#//
#//------------------------------------------------------------------------------
#
#class uvm_vreg_field extends uvm_object;
#
#   `uvm_object_utils(uvm_vreg_field)
#   `uvm_register_cb(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;
#
#
#   //
#   // Group: initialization
#   //
#
#   //
#   // Function: new
#   // Create a new virtual field instance
#   //
#   // This method should not be used directly.
#   // The uvm_vreg_field::type_id::create() method should be used instead.
#   //
#   extern function new(string name = "uvm_vreg_field");
#
#   //
#   // Function: configure
#   // Instance-specific configuration
#   //
#   // Specify the ~parent~ virtual register of this virtual field, its
#   // ~size~ in bits, and the position of its least-significant bit
#   // within the virtual register relative to the least-significant bit
#   // of the virtual register.
#   //
#   extern function void configure(uvm_vreg parent,
#                                  int unsigned size,
#                                  int unsigned lsb_pos);
#
#
#   //
#   // Group: Introspection
#   //
#
#   //
#   // Function: get_name
#   // Get the simple name
#   //
#   // Return the simple object name of this virtual field
#   //
#
#   //
#   // Function: get_full_name
#   // Get the hierarchical name
#   //
#   // Return the hierarchal name of this virtual field
#   // The base of the hierarchical name is the root block.
#   //
#   extern virtual function string        get_full_name();
#
#   //
#   // FUNCTION: get_parent
#   // Get the parent virtual register
#   //
#   extern virtual function uvm_vreg get_parent();
#   extern virtual function uvm_vreg get_register();
#
#   //
#   // FUNCTION: get_lsb_pos_in_register
#   // Return the position of the virtual field
#   ///
#   // Returns the index of the least significant bit of the virtual field
#   // in the virtual 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_in_register();
#
#   //
#   // FUNCTION: get_n_bits
#   // Returns the width, in bits, of the virtual field. 
#   //
#   extern virtual function int unsigned get_n_bits();
#
#   //
#   // FUNCTION: get_access
#   // Returns the access policy of the virtual field register
#   // when written and read via an address map.
#   //
#   // If the memory implementing the virtual field
#   // is mapped in more than one address map,
#   // an address ~map~ must be specified.
#   // If access restrictions are present when accessing a memory
#   // through the specified address map, the access mode returned
#   // takes the access restrictions into account.
#   // For example, a read-write memory accessed
#   // through an address map with read-only restrictions would return "RO". 
#   //
#   extern virtual function string get_access(uvm_reg_map map = null);
#
#
#   //
#   // Group: HDL Access
#   //
#
#   //
#   // TASK: write
#   // Write the specified value in a virtual field
#   //
#   // Write ~value~ in the DUT memory location(s) that implements
#   // the virtual field that corresponds to this
#   // abstraction class instance using the specified access
#   // ~path~. 
#   //
#   // If the memory implementing the virtual register array
#   // containing this virtual field
#   // is mapped in more than one address map, 
#   // an address ~map~ must be
#   // specified if a physical access is used (front-door access).
#   //
#   // The operation is eventually mapped into
#   // memory read-modify-write operations at the location
#   // where the virtual register
#   // specified by ~idx~ in the virtual register array is implemented.
#   // If a backdoor is available for the memory implementing the
#   // virtual field, it will be used for the memory-read operation.
#   //
#   extern virtual task write(input  longint unsigned   idx,
#                             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  uvm_object         extension = null,
#                             input  string             fname = "",
#                             input  int                lineno = 0);
#
#   //
#   // TASK: read
#   // Read the current value from a virtual field
#   //
#   // Read from the DUT memory location(s) that implements
#   // the virtual field that corresponds to this
#   // abstraction class instance using the specified access
#   // ~path~, and return the readback ~value~.
#   //
#   // If the memory implementing the virtual register array
#   // containing this virtual field
#   // is mapped in more than one address map, 
#   // an address ~map~ must be
#   // specified if a physical access is used (front-door access).
#   //
#   // The operation is eventually mapped into
#   // memory read operations at the location(s)
#   // where the virtual register
#   // specified by ~idx~ in the virtual register array is implemented.
#   //
#   extern virtual task read(input  longint unsigned    idx,
#                            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  uvm_object          extension = null,
#                            input  string              fname = "",
#                            input  int                 lineno = 0);
#               
#
#   //
#   // TASK: poke
#   // Deposit the specified value in a virtual field
#   //
#   // Deposit ~value~ in the DUT memory location(s) that implements
#   // the virtual field that corresponds to this
#   // abstraction class instance using the specified access
#   // ~path~. 
#   //
#   // The operation is eventually mapped into
#   // memory peek-modify-poke operations at the location
#   // where the virtual register
#   // specified by ~idx~ in the virtual register array is implemented.
#   //
#   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);
#
#   //
#   // TASK: peek
#   // Sample the current value from a virtual field
#   //
#   // Sample from the DUT memory location(s) that implements
#   // the virtual field that corresponds to this
#   // abstraction class instance using the specified access
#   // ~path~, and return the readback ~value~.
#   //
#   // If the memory implementing the virtual register array
#   // containing this virtual field
#   // is mapped in more than one address map, 
#   // an address ~map~ must be
#   // specified if a physical access is used (front-door access).
#   //
#   // The operation is eventually mapped into
#   // memory peek operations at the location(s)
#   // where the virtual register
#   // specified by ~idx~ in the virtual register array is implemented.
#   //
#   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);
#
#   //
#   // Group: Callbacks
#   //
#
#
#   //
#   // TASK: pre_write
#   // Called before virtual 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 virtual register operation.
#   //
#   // The virtual field callback methods are invoked before the callback methods
#   // on the containing virtual register.
#   // The registered callback methods are invoked after the invocation
#   // of this method.
#   // The pre-write virtual register and field callbacks are executed
#   // before the corresponding pre-write memory callbacks
#   //
#   virtual task pre_write(longint unsigned     idx,
#                          ref uvm_reg_data_t   wdat,
#                          ref uvm_path_e  path,
#                          ref uvm_reg_map   map);
#   endtask: pre_write
#
#   //
#   // TASK: post_write
#   // Called after virtual field write
#   //
#   // If the specified ~status~ is modified,
#   // the updated status will be
#   // returned by the virtual register operation.
#   //
#   // The virtual field callback methods are invoked after the callback methods
#   // on the containing virtual register.
#   // The registered callback methods are invoked before the invocation
#   // of this method.
#   // The post-write virtual register and field callbacks are executed
#   // after the corresponding post-write memory callbacks
#   //
#   virtual task post_write(longint unsigned       idx,
#                           uvm_reg_data_t         wdat,
#                           uvm_path_e        path,
#                           uvm_reg_map         map,
#                           ref uvm_status_e  status);
#   endtask: post_write
#
#   //
#   // TASK: pre_read
#   // Called before virtual field read.
#   //
#   // If the specified access ~path~ or address ~map~ are modified,
#   // the updated access path or address map will be used to perform
#   // the virtual register operation.
#   //
#   // The virtual field callback methods are invoked after the callback methods
#   // on the containing virtual register.
#   // The registered callback methods are invoked after the invocation
#   // of this method.
#   // The pre-read virtual register and field callbacks are executed
#   // before the corresponding pre-read memory callbacks
#   //
#   virtual task pre_read(longint unsigned      idx,
#                         ref uvm_path_e   path,
#                         ref uvm_reg_map    map);
#   endtask: pre_read
#
#   //
#   // TASK: post_read
#   // Called after virtual field read.
#   //
#   // If the specified readback data ~rdat~ or ~status~ is modified,
#   // the updated readback data or status will be
#   // returned by the virtual register operation.
#   //
#   // The virtual field callback methods are invoked after the callback methods
#   // on the containing virtual register.
#   // The registered callback methods are invoked before the invocation
#   // of this method.
#   // The post-read virtual register and field callbacks are executed
#   // after the corresponding post-read memory callbacks
#   //
#   virtual task post_read(longint unsigned       idx,
#                          ref uvm_reg_data_t     rdat,
#                          uvm_path_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
#
#
#//------------------------------------------------------------------------------
#// Class: uvm_vreg_field_cbs
#//
#// Pre/post read/write callback facade class
#//
#//------------------------------------------------------------------------------
#
#class uvm_vreg_field_cbs extends uvm_callback;
#   string fname;
#   int    lineno;
#
#   function new(string name = "uvm_vreg_field_cbs");
#      super.new(name);
#   endfunction
#   
#
#   //
#   // Task: pre_write
#   // Callback called before a write operation.
#   //
#   // The registered callback methods are invoked before the invocation
#   // of the virtual register pre-write callbacks and
#   // after the invocation of the <uvm_vreg_field::pre_write()> method.
#   //
#   // The written value ~wdat~, access ~path~ and address ~map~,
#   // if modified, modifies the actual value, access path or address map
#   // used in the register operation.
#   //
#   virtual task pre_write(uvm_vreg_field       field,
#                          longint unsigned     idx,
#                          ref uvm_reg_data_t   wdat,
#                          ref uvm_path_e  path,
#                          ref uvm_reg_map   map);
#   endtask: pre_write
#
#
#   //
#   // TASK: post_write
#   // Called after a write operation
#   //
#   // The registered callback methods are invoked after the invocation
#   // of the virtual register post-write callbacks and
#   // before the invocation of the <uvm_vreg_field::post_write()> method.
#   //
#   // The ~status~ of the operation,
#   // if modified, modifies the actual returned status.
#   //
#   virtual task post_write(uvm_vreg_field        field,
#                           longint unsigned      idx,
#                           uvm_reg_data_t        wdat,
#                           uvm_path_e       path,
#                           uvm_reg_map        map,
#                           ref uvm_status_e status);
#   endtask: post_write
#
#
#   //
#   // TASK: pre_read
#   // Called before a virtual field read.
#   //
#   // The registered callback methods are invoked after the invocation
#   // of the virtual register pre-read callbacks and
#   // after the invocation of the <uvm_vreg_field::pre_read()> method.
#   //
#   // The access ~path~ and address ~map~,
#   // if modified, modifies the actual access path or address map
#   // used in the register operation.
#   //
#   virtual task pre_read(uvm_vreg_field        field,
#                         longint unsigned      idx,
#                         ref uvm_path_e   path,
#                         ref uvm_reg_map    map);
#   endtask: pre_read
#
#
#   //
#   // TASK: post_read
#   // Called after a virtual field read.
#   //
#   // The registered callback methods are invoked after the invocation
#   // of the virtual register post-read callbacks and
#   // before the invocation of the <uvm_vreg_field::post_read()> method.
#   //
#   // The readback value ~rdat~ and the ~status~ of the operation,
#   // if modified, modifies the actual returned readback value and status.
#   //
#   virtual task post_read(uvm_vreg_field         field,
#                          longint unsigned       idx,
#                          ref uvm_reg_data_t     rdat,
#                          uvm_path_e        path,
#                          uvm_reg_map         map,
#                          ref uvm_status_e  status);
#   endtask: post_read
#endclass: uvm_vreg_field_cbs
#
#
#//
#// Type: uvm_vreg_field_cb
#// Convenience callback type declaration
#//
#// Use this declaration to register virtual field callbacks rather than
#// the more verbose parameterized class
#//
#typedef uvm_callbacks#(uvm_vreg_field, uvm_vreg_field_cbs) uvm_vreg_field_cb;
#
#//
#// Type: uvm_vreg_field_cb_iter
#// Convenience callback iterator type declaration
#//
#// Use this declaration to iterate over registered virtual field callbacks
#// rather than the more verbose parameterized class
#//
#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
#      `uvm_error("RegModel", $sformatf("Virtual field \"%s\" cannot have 0 bits", this.get_full_name()));
#      size = 1;
#   end
#   if (size > `UVM_REG_DATA_WIDTH) begin
#      `uvm_error("RegModel", $sformatf("Virtual field \"%s\" cannot have more than %0d bits",
#                                     this.get_full_name(),
#                                     `UVM_REG_DATA_WIDTH));
#      size = `UVM_REG_DATA_WIDTH;
#   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
#      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg_field::get_rights() on unimplemented virtual field \"%s\"",
#                                     this.get_full_name()));
#      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_path_e     path = UVM_DEFAULT_PATH,
#                           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_path_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
#      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg_field::write() on unimplemented virtual register \"%s\"",
#                                     this.get_full_name()));
#      status = UVM_NOT_OK;
#      return;
#   end
#
#   if (path == UVM_DEFAULT_PATH) begin
#      uvm_reg_block blk = this.parent.get_block();
#      path = blk.get_default_path();
#   end
#
#   status = UVM_IS_OK;
#
#   this.parent.XatomicX(1);
#
#   if (value >> this.size) begin
#      `uvm_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()));
#      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);
#
#   // Favor backdoor read to frontdoor read for the RMW operation
#   rm_path = UVM_DEFAULT_PATH;
#   if (mem.get_backdoor() != null) rm_path = UVM_BACKDOOR;
#
#   // Any bits on the LSB side we need to RMW?
#   rmwbits = flsb % segsiz;
#
#   // Total number of memory segment in this field
#   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
#         `uvm_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()));
#         status = UVM_NOT_OK;
#         this.parent.XatomicX(0);
#         return;
#      end
#
#      value = (value << rmwbits) | (tmp & ((1<<rmwbits)-1));
#   end
#
#   // Any bits on the MSB side we need to RMW?
#   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
#            `uvm_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()));
#            status = UVM_NOT_OK;
#            this.parent.XatomicX(0);
#            return;
#         end
#      end
#      value |= (tmp & ~((1<<rmwbits)-1)) << ((segn-1)*segsiz);
#   end
#
#   // Now write each of the segments
#   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);
#
#
#   `uvm_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); 
#   
#   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_path_e     path = UVM_DEFAULT_PATH,
#                          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
#      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg_field::read() on unimplemented virtual register \"%s\"",
#                                     this.get_full_name()));
#      status = UVM_NOT_OK;
#      return;
#   end
#
#   if (path == UVM_DEFAULT_PATH) begin
#      uvm_reg_block blk = this.parent.get_block();
#      path = blk.get_default_path();
#   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;
#
#   // Total number of memory segment in this field
#   segn = (lsb + this.get_n_bits() - 1) / segsiz + 1;
#
#   // Read each of the segments, MSB first
#   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
#
#   // Any bits on the LSB side we need to get rid of?
#   value = value >> lsb;
#
#   // Any bits on the MSB side we need to get rid of?
#   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);
#
#   `uvm_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);
#
#
#   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_path_e rm_path;
#   this.fname = fname;
#   this.lineno = lineno;
#
#   mem = this.parent.get_memory();
#   if (mem == null) begin
#      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg_field::poke() on unimplemented virtual register \"%s\"",
#                                     this.get_full_name()));
#      status = UVM_NOT_OK;
#      return;
#   end
#
#   status = UVM_IS_OK;
#
#   this.parent.XatomicX(1);
#
#   if (value >> this.size) begin
#      `uvm_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()));
#      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);
#
#   // Any bits on the LSB side we need to RMW?
#   rmwbits = flsb % segsiz;
#
#   // Total number of memory segment in this field
#   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
#         `uvm_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()));
#         status = UVM_NOT_OK;
#         this.parent.XatomicX(0);
#         return;
#      end
#
#      value = (value << rmwbits) | (tmp & ((1<<rmwbits)-1));
#   end
#
#   // Any bits on the MSB side we need to RMW?
#   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
#            `uvm_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()));
#            status = UVM_NOT_OK;
#            this.parent.XatomicX(0);
#            return;
#         end
#      end
#      value |= (tmp & ~((1<<rmwbits)-1)) << ((segn-1)*segsiz);
#   end
#
#   // Now write each of the segments
#   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);
#
#   `uvm_info("RegModel", $sformatf("Wrote virtual field \"%s\"[%0d] with: 'h%h",
#                              this.get_full_name(), idx, value),UVM_MEDIUM);
#
#   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
#      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg_field::peek() on unimplemented virtual register \"%s\"",
#                                     this.get_full_name()));
#      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;
#
#   // Total number of memory segment in this field
#   segn = (lsb + this.get_n_bits() - 1) / segsiz + 1;
#
#   // Read each of the segments, MSB first
#   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
#
#   // Any bits on the LSB side we need to get rid of?
#   value = value >> lsb;
#
#   // Any bits on the MSB side we need to get rid of?
#   value &= (1<<this.get_n_bits()) - 1;
#
#   this.parent.XatomicX(0);
#
#   `uvm_info("RegModel", $sformatf("Peeked virtual field \"%s\"[%0d]: 'h%h", this.get_full_name(), idx, value),UVM_MEDIUM);
#
#   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
#
#//TODO - add fatal messages
#
#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
#
#
