[dv_base_reg] Extend search by name functions

This is in preparation for the alias register implementation and allows
to search a register or field by alias or generic name.

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/dv/sv/dv_base_reg/dv_base_reg.sv b/hw/dv/sv/dv_base_reg/dv_base_reg.sv
index 123c720..24864df 100644
--- a/hw/dv/sv/dv_base_reg/dv_base_reg.sv
+++ b/hw/dv/sv/dv_base_reg/dv_base_reg.sv
@@ -19,6 +19,11 @@
   local string         update_err_alert_name;
   local string         storage_err_alert_name;
 
+  // This is used for get_alias_name
+  string alias_name = "";
+  // Lookup table for alias fields (used for get_field_by_name)
+  string field_alias_lookup[string];
+
   // atomic_en_shadow_wr: semaphore to guarantee setting or resetting en_shadow_wr is unchanged
   // through the 1st/2nd (or both) writes
   semaphore            atomic_en_shadow_wr;
@@ -30,6 +35,21 @@
     atomic_en_shadow_wr = new(1);
   endfunction : new
 
+  // this is similar to get_name, but it gets the
+  // simple name of the aliased register instead.
+  function string get_alias_name ();
+    return this.alias_name;
+  endfunction: get_alias_name
+
+  // this is similar to set_name, but it sets the
+  // simple name of the aliased register instead.
+  function void set_alias_name (string alias_name);
+    dv_base_reg_block reg_block;
+    `downcast(reg_block, get_parent())
+    reg_block.register_alias_lookup[alias_name] = this.get_name();
+    this.alias_name = alias_name;
+  endfunction: set_alias_name
+
   function void get_dv_base_reg_fields(ref dv_base_reg_field dv_fields[$]);
     foreach (m_fields[i]) `downcast(dv_fields[i], m_fields[i])
   endfunction
@@ -381,4 +401,15 @@
     return ($sformatf("%0s_%0s", get_dv_base_reg_block().get_ip_name(), storage_err_alert_name));
   endfunction
 
+  // this overrides the get_field_by_name function
+  function dv_base_reg_field get_field_by_name(string name);
+    dv_base_reg_field retval;
+    if (field_alias_lookup.exists(name)) begin
+      `downcast(retval, super.get_field_by_name(field_alias_lookup[name]))
+    end else begin
+      `downcast(retval, super.get_field_by_name(name))
+    end
+    return retval;
+  endfunction
+
 endclass
diff --git a/hw/dv/sv/dv_base_reg/dv_base_reg_block.sv b/hw/dv/sv/dv_base_reg/dv_base_reg_block.sv
index dcd50c5..7adc55b 100644
--- a/hw/dv/sv/dv_base_reg/dv_base_reg_block.sv
+++ b/hw/dv/sv/dv_base_reg/dv_base_reg_block.sv
@@ -59,6 +59,10 @@
   bit has_unmapped_addrs;
   addr_range_t unmapped_addr_ranges[$];
 
+  // Lookup table for alias registers and fields.
+  string register_alias_lookup[string];
+  string field_alias_lookup[string];
+
   function new (string name = "", int has_coverage = UVM_NO_COVERAGE);
     super.new(name, has_coverage);
   endfunction
@@ -378,4 +382,27 @@
     foreach (subblks[i]) subblks[i].set_default_map_w_subblks_by_name(map_name);
   endfunction
 
+  // this overrides the get_reg_by_name function
+  function dv_base_reg get_reg_by_name(string name);
+    dv_base_reg retval;
+    if (register_alias_lookup.exists(name)) begin
+      `downcast(retval, super.get_reg_by_name(register_alias_lookup[name]))
+    end else begin
+      `downcast(retval, super.get_reg_by_name(name))
+    end
+    return retval;
+  endfunction
+
+  // this overrides the get_field_by_name function
+  // note however that this function is only meaningful if the fields are unique within a regblock!
+  function dv_base_reg_field get_field_by_name(string name);
+    dv_base_reg_field retval;
+    if (field_alias_lookup.exists(name)) begin
+      `downcast(retval, super.get_field_by_name(field_alias_lookup[name]))
+    end else begin
+      `downcast(retval, super.get_field_by_name(name))
+    end
+    return retval;
+  endfunction
+
 endclass
diff --git a/hw/dv/sv/dv_base_reg/dv_base_reg_field.sv b/hw/dv/sv/dv_base_reg/dv_base_reg_field.sv
index c6998d8..8b401a6 100644
--- a/hw/dv/sv/dv_base_reg/dv_base_reg_field.sv
+++ b/hw/dv/sv/dv_base_reg/dv_base_reg_field.sv
@@ -14,12 +14,38 @@
   local dv_base_reg_field regwen_fld;
   local dv_base_lockable_field_cov lockable_field_cov;
 
+  // This is used for get_field_by_name
+  string alias_name = "";
+
   // variable for mubi coverage, which is only created when this is a mubi reg
   dv_base_mubi_cov mubi_cov;
 
   `uvm_object_utils(dv_base_reg_field)
   `uvm_object_new
 
+  // this is similar to get_name, but it gets the
+  // simple name of the aliased field instead.
+  function string get_alias_name ();
+     return this.alias_name;
+  endfunction: get_alias_name
+
+  // this is similar to set_name, but it sets the
+  // simple name of the aliased field instead.
+  function void set_alias_name (string alias_name);
+    dv_base_reg register;
+    dv_base_reg_block reg_block;
+    `downcast(register, this.get_parent())
+    register.field_alias_lookup[alias_name] = this.get_name();
+    // We also add the name to the lookup table inside the reg_block to enable get_field_by_name at
+    // that level. Note: in order for the get_field_by_name function of dv_base_reg_block to
+    // produce meaningful results, all field names within the reg block have to be unique - which
+    // cannot always guaranteed. If the fields are not unique at that level, the get_field_by_name
+    // of dv_base_reg should be used instead.
+    `downcast(reg_block, register.get_parent())
+    reg_block.field_alias_lookup[alias_name] = this.get_name();
+    this.alias_name = alias_name;
+  endfunction: set_alias_name
+
   // Issue #5105: UVM forces the value member to be non-randomizable for certain access policies.
   // We restore it in this extended class.
   virtual function void configure(uvm_reg        parent,