[regtool] Extend RTL backend to support alias definitions

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/util/reggen/gen_rtl.py b/util/reggen/gen_rtl.py
index ec13e67..83aa0cd 100644
--- a/util/reggen/gen_rtl.py
+++ b/util/reggen/gen_rtl.py
@@ -98,22 +98,29 @@
     reg_pkg_tpl = Template(
         filename=resource_filename('reggen', 'reg_pkg.sv.tpl'))
 
+    # In case the generated package contains alias definitions, we add
+    # the alias implementation identifier to the package name so that it
+    # becomes unique.
+    alias_impl = "_" + block.alias_impl if block.alias_impl else ""
+
     # Generate <block>_reg_pkg.sv
     #
     # This defines the various types used to interface between the *_reg_top
     # module(s) and the block itself.
-    reg_pkg_path = os.path.join(outdir, block.name.lower() + "_reg_pkg.sv")
+    reg_pkg_path = os.path.join(outdir, block.name.lower() + alias_impl +
+                                "_reg_pkg.sv")
     with open(reg_pkg_path, 'w', encoding='UTF-8') as fout:
         try:
-            fout.write(reg_pkg_tpl.render(block=block))
+            fout.write(reg_pkg_tpl.render(block=block,
+                                          alias_impl=alias_impl))
         except:  # noqa F722 for template Exception handling
             log.error(exceptions.text_error_template().render())
             return 1
 
     # Generate the register block implementation(s). For a device interface
-    # with no name we generate the register module "<block>_reg_top" (writing
-    # to <block>_reg_top.sv). In any other case, we also need the interface
-    # name, giving <block>_<ifname>_reg_top.
+    # with no name we generate the register module "<block>_reg_top"
+    # (writing to <block>_reg_top.sv). In any other case, we also need the
+    # interface name, giving <block>_<ifname>_reg_top.
     lblock = block.name.lower()
     for if_name, rb in block.reg_blocks.items():
         if if_name is None:
@@ -121,7 +128,7 @@
         else:
             mod_base = lblock + '_' + if_name.lower()
 
-        mod_name = mod_base + '_reg_top'
+        mod_name = mod_base + alias_impl + '_reg_top'
         reg_top_path = os.path.join(outdir, mod_name + '.sv')
         with open(reg_top_path, 'w', encoding='UTF-8') as fout:
             try:
diff --git a/util/reggen/reg_pkg.sv.tpl b/util/reggen/reg_pkg.sv.tpl
index 7c3eb47..789471b 100644
--- a/util/reggen/reg_pkg.sv.tpl
+++ b/util/reggen/reg_pkg.sv.tpl
@@ -350,8 +350,8 @@
 % endif
 </%def>\
 
-package ${lblock}_reg_pkg;
-% if localparams:
+package ${lblock}${"_" + block.alias_impl if block.alias_impl else ""}_reg_pkg;
+% if localparams and not block.alias_impl:
 
   // Param list
 % for param in localparams:
diff --git a/util/reggen/reg_top.sv.tpl b/util/reggen/reg_top.sv.tpl
index 15b9aaa..d1a5c6d 100644
--- a/util/reggen/reg_top.sv.tpl
+++ b/util/reggen/reg_top.sv.tpl
@@ -11,6 +11,8 @@
   from reggen.multi_register import MultiRegister
   from reggen.bits import Bits
 
+  alias_impl = "_" + block.alias_impl if block.alias_impl else ""
+
   num_wins = len(rb.windows)
   num_reg_dsp = 1 if rb.all_regs else 0
   num_dsp  = num_wins + num_reg_dsp
@@ -134,10 +136,10 @@
 % endif
   // To HW
 % if rb.get_n_bits(["q","qe","re"]):
-  output ${lblock}_reg_pkg::${reg2hw_t} reg2hw, // Write
+  output ${lblock}${alias_impl}_reg_pkg::${reg2hw_t} reg2hw, // Write
 % endif
 % if rb.get_n_bits(["d","de"]):
-  input  ${lblock}_reg_pkg::${hw2reg_t} hw2reg, // Read
+  input  ${lblock}${alias_impl}_reg_pkg::${hw2reg_t} hw2reg, // Read
 % endif
 
 % if rb.has_internal_shadowed_reg():
@@ -152,7 +154,7 @@
   input devmode_i // If 1, explicit error return for unmapped register access
 );
 
-  import ${lblock}_reg_pkg::* ;
+  import ${lblock}${alias_impl}_reg_pkg::* ;
 
 % if needs_aw:
   localparam int AW = ${addr_width};