[dvsim] Added fusesoc generator for RAL

- Added fuseson generator `ralgen` for autogenerating RAL pkg. This was
originally done by `hw/dv/tools/gen_ral_pkg.sv`, which has now been
removed.
- Updated all fusesoc env core files that are dependent on its RAL pkg
to invoke the generator.
- Updated all documentation `uvmdvgen` templates to reflect these
updates.

- Fixes #1784.

Signed-off-by: Srikrishna Iyer <sriyer@google.com>
diff --git a/hw/dv/data/common_sim_cfg.hjson b/hw/dv/data/common_sim_cfg.hjson
index c86a013..1c70dff 100644
--- a/hw/dv/data/common_sim_cfg.hjson
+++ b/hw/dv/data/common_sim_cfg.hjson
@@ -12,7 +12,6 @@
   import_cfgs:      ["{proj_root}/hw/data/common_project_cfg.hjson",
                      "{proj_root}/hw/dv/data/common_modes.hjson",
                      "{proj_root}/hw/dv/data/fusesoc.hjson",
-                     "{proj_root}/hw/dv/data/gen_ral_pkg.hjson",
                      "{proj_root}/hw/dv/data/{tool}/{tool}.hjson"]
 
   // Default directory structure for the output
diff --git a/hw/dv/data/fusesoc.hjson b/hw/dv/data/fusesoc.hjson
index 2c664b5..39c59a0 100644
--- a/hw/dv/data/fusesoc.hjson
+++ b/hw/dv/data/fusesoc.hjson
@@ -4,8 +4,10 @@
 {
   sv_flist_gen_cmd:   fusesoc
   fusesoc_core_:      "{eval_cmd} echo \"{fusesoc_core}\" | tr ':' '_'"
-  sv_flist_gen_opts:  ["--cores-root {proj_root} --cores-root {gen_ral_pkg_dir}",
-                       "run --target=sim --build-root={build_dir}",
+  sv_flist_gen_opts:  ["--cores-root {proj_root}",
+                       "run",
+                       "--target=sim",
+                       "--build-root={build_dir}",
                        "--setup {fusesoc_core}"]
   sv_flist_gen_dir:   "{build_dir}/sim-vcs"
   sv_flist:           "{sv_flist_gen_dir}/{fusesoc_core_}.scr"
diff --git a/hw/dv/data/gen_ral_pkg.hjson b/hw/dv/data/gen_ral_pkg.hjson
deleted file mode 100644
index 867c816..0000000
--- a/hw/dv/data/gen_ral_pkg.hjson
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-{
-  gen_ral_pkg:      "{name}"
-  gen_ral_pkg_dir:  "{build_dir}/gen_ral_pkg"
-  gen_ral_pkg_cmd:  "{proj_root}/hw/dv/tools/gen_ral_pkg.py"
-  gen_ral_pkg_opts: ["{gen_ral_pkg} {ral_spec} -o {gen_ral_pkg_dir}"]
-}
diff --git a/hw/dv/data/sim.mk b/hw/dv/data/sim.mk
index fa70dce..7a81bad 100644
--- a/hw/dv/data/sim.mk
+++ b/hw/dv/data/sim.mk
@@ -6,16 +6,6 @@
 
 all: build run
 
-########################
-## RAL target         ##
-########################
-ral:
-ifneq (${skip_gen_ral_pkg},1)
-	mkdir -p ${gen_ral_pkg_dir} && \
-	${gen_ral_pkg_cmd} ${gen_ral_pkg_opts}
-endif
-
-
 ###############################
 ## sim build and run targets ##
 ###############################
@@ -27,7 +17,7 @@
 	mkdir -p ${tool_srcs_dir}
 	cp -Ru ${tool_srcs} ${tool_srcs_dir}/.
 
-gen_sv_flist: pre_compile ral
+gen_sv_flist: pre_compile
 	@echo "[make]: gen_sv_flist"
 	cd ${build_dir} && ${sv_flist_gen_cmd} ${sv_flist_gen_opts}
 
diff --git a/hw/dv/doc/dv_plan_template.md b/hw/dv/doc/dv_plan_template.md
index 3d90eae..5bfb43c 100644
--- a/hw/dv/doc/dv_plan_template.md
+++ b/hw/dv/doc/dv_plan_template.md
@@ -69,10 +69,9 @@
 [Describe here or add link to its README]
 
 ### UVM RAL Model
-The FOO RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The FOO RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Reference models
 [Describe reference models in use if applicable, example: SHA256/HMAC]
diff --git a/hw/dv/tools/Makefile b/hw/dv/tools/Makefile
index b266854..5815adc 100644
--- a/hw/dv/tools/Makefile
+++ b/hw/dv/tools/Makefile
@@ -78,9 +78,6 @@
 # common tests/seqs
 include ${MAKE_ROOT}/common_tests.mk
 
-# tool to generate ral
-include ${MAKE_ROOT}/ral_gen.mk
-
 # tool to generate file list
 include ${MAKE_ROOT}/fusesoc.mk
 
diff --git a/hw/dv/tools/gen_ral_pkg.py b/hw/dv/tools/gen_ral_pkg.py
deleted file mode 100755
index e90d668..0000000
--- a/hw/dv/tools/gen_ral_pkg.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python3
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-r"""Command line wrapper tool to generate RAL pkg using regtool as well as a corresponding
-fusesoc core file
-"""
-import argparse
-import os
-import sys
-from textwrap import dedent as dedent
-
-
-def main():
-    parser = argparse.ArgumentParser(
-        description=__doc__,
-        formatter_class=argparse.RawDescriptionHelpFormatter)
-    parser.add_argument("ip_name", metavar='<ip-name>', help='Name of the IP')
-    parser.add_argument(
-        "-t",
-        "--top",
-        default=False,
-        action='store_true',
-        help='Indicate whether the RAL model generation is for the top level')
-    parser.add_argument(
-        "csr_hjson",
-        metavar='<hjson-file>',
-        help='Input Hjson file capturing the CSR specification for the IP')
-    parser.add_argument(
-        '-o',
-        '--outdir',
-        default='.',
-        help=
-        'Target output directory for placing the RAL pkg as well as the fusesoc core file'
-    )
-    args = parser.parse_args()
-
-    # check if csr_hjson is a valid file
-    if not os.path.exists(args.csr_hjson):
-        print("RAL Hjson spec file " + args.csr_hjson + " does not exist!" + \
-              "\nExitting without error.")
-        sys.exit(0)
-
-    # check if outdir exists
-    if not os.path.exists(args.outdir):
-        print("ERROR: Outdir " + args.outdir + " does not exist! Create it first." + \
-              "\nExitting with error.")
-        sys.exit(1)
-
-    # generate the ral pkg
-    self_path = os.path.dirname(os.path.realpath(__file__))
-    ral_tool_path = os.path.abspath(os.path.join(self_path, "../../../util"))
-
-    if args.top:
-        os.system(ral_tool_path + "/topgen.py -r -o " + args.outdir + ' -t ' +
-                  args.csr_hjson)
-    else:
-        os.system(ral_tool_path + "/regtool.py -s -t " + args.outdir + ' ' +
-                  args.csr_hjson)
-
-    # create fusesoc core file
-    text = """
-           CAPI=2:
-           # Copyright lowRISC contributors.
-           # Licensed under the Apache License, Version 2.0, see LICENSE for details.
-           # SPDX-License-Identifier: Apache-2.0
-
-           name: "lowrisc:dv:gen_ral_pkg"
-           description: \"%s UVM RAL pkg
-                         Auto-generated by hw/dv/tools/gen_ral_pkg.py\"
-           filesets:
-             files_dv:
-               depend:
-                 - lowrisc:dv:dv_lib
-               files:
-                 - %s_ral_pkg.sv
-               file_type: systemVerilogSource
-
-           targets:
-             default:
-               filesets:
-                 - files_dv
-           """ % (args.ip_name.upper(), args.ip_name)
-    text = dedent(text).strip()
-
-    with open(args.outdir + "/" + "gen_ral_pkg.core", 'w') as fout:
-        try:
-            fout.write(text)
-        except IOError:
-            log.error(exceptions.text_error_template().render())
-
-
-if __name__ == '__main__':
-    main()
diff --git a/hw/dv/tools/modes.mk b/hw/dv/tools/modes.mk
index 65e2290..3c187b7 100644
--- a/hw/dv/tools/modes.mk
+++ b/hw/dv/tools/modes.mk
@@ -56,7 +56,3 @@
     XCELIUM_COV = 1
   endif
 endif
-
-# Simulation flow control options
-# Skip RAL model generation
-SKIP_RAL_GEN ?= 0
diff --git a/hw/dv/tools/ral_gen.mk b/hw/dv/tools/ral_gen.mk
deleted file mode 100644
index afe1159..0000000
--- a/hw/dv/tools/ral_gen.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-
-# tool and options for generating the UVM RAL model
-RAL_SPEC      ?= ${DV_DIR}/../data/${DUT_TOP}.hjson
-RAL_MODEL_DIR ?= ${BUILD_DIR}/gen_ral_pkg
-
-RAL_PKG_NAME  ?= ${DUT_TOP}
-RAL_TOOL      ?= ${MAKE_ROOT}/gen_ral_pkg.py
-RAL_TOOL_OPTS += ${RAL_PKG_NAME} ${RAL_SPEC} -o ${RAL_MODEL_DIR}
diff --git a/hw/dv/tools/ralgen/README.md b/hw/dv/tools/ralgen/README.md
new file mode 100644
index 0000000..9e49449
--- /dev/null
+++ b/hw/dv/tools/ralgen/README.md
@@ -0,0 +1,81 @@
+# `ralgen`: A FuseSoC generator for UVM RAL package
+
+The `ralgen.py` script is implemented as a
+[FuseSoC generator](https://fusesoc.readthedocs.io/en/master/user/generators.html).
+which enables the automatic creation of the SystemVerilog UVM RAL package and
+its insertion into the dependency tree when compiling the DV testbench.
+
+This approach is useful for DV simulation flows that use FuseSoC as the backend
+to generate the filelist for compilation. A separate RAL package generation
+step is no longer needed since it gets handled within FuseSoC.
+
+## Generator
+
+The adjoining `ralgen.core` file registers the `ralgen` generator. The FuseSoC
+core file that 'calls' the generator adds it as a dependency. When calling the
+generator, the following parameters are set:
+* **name (mandatory)**: Name of the RAL package (typically, same is the IP).
+* **ip_hjson**: Path to the hjson specification written for an IP which includes
+  the register descriptions. This needs to be a valid input for `reggen`.
+* **top_hjson**: Path to the hjson specification for a top level design. This
+  needs to be a valid input for `topgen`.
+
+Only one of the last two arguments is mandatory. If both are set, or if neither
+of them are, then the tool throws an error and exits.
+
+The following snippet shows how it is called:
+```
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: <name>
+      <ip_hjson|top_hjson>: <path-to-hjson-spec>
+
+targets:
+  default:
+    ...
+    generate:
+      - ral
+```
+
+Note that the path to `hjson` specification in the snippet above is relative
+to the core file in which the generator is called.
+
+## `ralgen` script
+
+When FuseSoC processes the dependency list and encounters a generator, it
+passes a YAML file containing the above parameters to the generator tool
+(the `ralgen.py`) as a single input. It then parses the YAML input to
+extract those parameters.
+
+`ralgen.py` really is just a wrapper around
+[`reggen`]({{< relref "util/reggen/README.md" >}}) and the `util/topgen.py`
+scripts, which are the ones that actually create the RAL package.
+Due to the way those scripts are implemented, RAL packages for the IP level
+testbenches are generated using
+[`reggen`](({{< relref "util/reggen/README.md" >}})), and for the chip level
+testbench, `util/topgen.py`. Which one to choose is decided by whether
+the `ip_hjson` or `top_hjson` parameter is supplied.
+
+In addition, the `ralgen.py` script also creates a FuseSoC core file. It uses
+the `name` parameter to derive the
+[VLNV](https://fusesoc.readthedocs.io/en/master/user/overview.html#core-naming-rules)
+name for the generated core file.
+
+The generated core file adds **`lowrisc:dv:dv_lib`** as a dependency for the
+generated RAL package. This is required because our DV register block, register
+and field models are derived from the
+[DV library]({{< relref "hw/dv/sv/dv_lib/README.md" >}}) of classes. This
+ensures the right compilation order is maintained.
+
+## Limitations
+
+The script is not designed to be manually invoked, but in theory, it can be, if
+a YAML file that contains the right set of parameters is presented to it
+(compliant with FuseSoC).
+
+If the user wishes to create the RAL package manually outside of the DV
+simulation flow, then the `make` command can be invoked in the `hw/'` area
+instead. It generates the RTL, DV and SW collaterals for all IPs, as well as
+the top level in a single step.
diff --git a/hw/dv/tools/ralgen/ralgen.core b/hw/dv/tools/ralgen/ralgen.core
new file mode 100644
index 0000000..b277f41
--- /dev/null
+++ b/hw/dv/tools/ralgen/ralgen.core
@@ -0,0 +1,11 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+name: "lowrisc:dv:ralgen"
+description: "Generator for UVM RAL package used in DV testbenches."
+generators:
+  ralgen:
+    interpreter: python3
+    command: ralgen.py
diff --git a/hw/dv/tools/ralgen/ralgen.py b/hw/dv/tools/ralgen/ralgen.py
new file mode 100755
index 0000000..edad129
--- /dev/null
+++ b/hw/dv/tools/ralgen/ralgen.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+r"""FuseSoc generator for UVM RAL package created with either regtool or
+topgen tools.
+"""
+import argparse
+import os
+import subprocess
+import sys
+
+import yaml
+
+try:
+    from yaml import CSafeLoader as YamlLoader, CSafeDumper as YamlDumper
+except ImportError:
+    from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
+
+# Repo root is 4 levels up. Note that this will require an update if the path to
+# this tool is changed.
+REPO_ROOT = "../../../.."
+
+
+# Given a root dir and partial path, this function returns the full path.
+def get_full_path(root_dir, partial_path):
+    full_path = os.path.abspath(os.path.join(root_dir, partial_path))
+    if not os.path.exists(full_path):
+        print("Error: path appears to be invalid: {}".format(full_path))
+        sys.exit(1)
+    return full_path
+
+
+def main():
+    if len(sys.argv) != 2:
+        print("ERROR: This script takes a single YAML file as input argument")
+        sys.exit(1)
+
+    gapi_filepath = sys.argv[1]
+    gapi = yaml.load(open(gapi_filepath), Loader=YamlLoader)
+
+    # This is just a wrapper around the reggen and topgen tools, which
+    # are referenced from proj_root area.
+    self_path = os.path.dirname(os.path.realpath(__file__))
+    util_path = os.path.abspath(os.path.join(self_path, REPO_ROOT, "util"))
+
+    # Retrieve the parameters from the yml.
+    root_dir = gapi['files_root']
+    name = gapi['parameters'].get('name')
+    ip_hjson = gapi['parameters'].get('ip_hjson')
+    top_hjson = gapi['parameters'].get('top_hjson')
+    if not name or (bool(ip_hjson) == bool(top_hjson)):
+        print("Error: ralgen requires the \"name\" and exactly one of "
+              "{\"ip_hjson\" and \"top_hjson\"} parameters to be set.")
+        sys.exit(1)
+
+    # Generate the RAL pkg.
+    ral_pkg_file = name + "_ral_pkg.sv"
+    if ip_hjson:
+        ral_spec = get_full_path(root_dir, ip_hjson)
+        cmd = os.path.join(util_path, "regtool.py")
+        args = [cmd, "-s", "-t", ".", ral_spec]
+    else:
+        ral_spec = get_full_path(root_dir, top_hjson)
+        cmd = os.path.join(util_path, "topgen.py")
+        args = [cmd, "-r", "-o", ".", "-t", ral_spec]
+
+    try:
+        subprocess.run(args, check=True)
+    except subprocess.CalledProcessError as e:
+        print("Error: RAL pkg generation failed:\n{}".format(str(e)))
+        sys.exit(e.returncode)
+    print("RAL pkg file written to {}".format(os.path.abspath(ral_pkg_file)))
+
+    # Generate the FuseSoc core file.
+    ral_pkg_core_text = {
+        'name': "lowrisc:dv:{}_ral_pkg".format(name),
+        'filesets': {
+            'files_dv': {
+                'depend': [
+                    "lowrisc:dv:dv_lib",
+                ],
+                'files': [
+                    ral_pkg_file,
+                ],
+                'file_type': 'systemVerilogSource'
+            },
+        },
+        'targets': {
+            'default': {
+                'filesets': [
+                    'files_dv',
+                ],
+            },
+        },
+    }
+    ral_pkg_core_file = os.path.abspath(name + "_ral_pkg.core")
+    with open(ral_pkg_core_file, 'w') as f:
+        f.write("CAPI=2:\n")
+        yaml.dump(ral_pkg_core_text,
+                  f,
+                  encoding="utf-8",
+                  default_flow_style=False,
+                  sort_keys=False)
+    print("RAL core file written to {}".format(ral_pkg_core_file))
+
+
+if __name__ == '__main__':
+    main()
diff --git a/hw/dv/tools/rules.mk b/hw/dv/tools/rules.mk
index a56d04e..5736971 100644
--- a/hw/dv/tools/rules.mk
+++ b/hw/dv/tools/rules.mk
@@ -6,15 +6,6 @@
 
 all: build run
 
-########################
-## RAL target         ##
-########################
-ral:
-ifneq (${SKIP_RAL_GEN},1)
-	mkdir -p ${RAL_MODEL_DIR} && \
-	${RAL_TOOL} ${RAL_TOOL_OPTS}
-endif
-
 ###############################
 ## sim build and run targets ##
 ###############################
@@ -24,7 +15,7 @@
 	mkdir -p ${BUILD_DIR} && \
 	env > ${BUILD_DIR}/env_vars
 
-gen_sv_flist: pre_compile ral
+gen_sv_flist: pre_compile
 	cd ${BUILD_DIR} && ${SV_FLIST_GEN_TOOL} ${SV_FLIST_GEN_OPTS}
 
 compile: gen_sv_flist
diff --git a/hw/ip/aes/doc/dv_plan/index.md b/hw/ip/aes/doc/dv_plan/index.md
index d4ae0b9..d06b4d9 100644
--- a/hw/ip/aes/doc/dv_plan/index.md
+++ b/hw/ip/aes/doc/dv_plan/index.md
@@ -50,8 +50,10 @@
 TL host interface into AES device.
 
 
-### RAL
-The AES RAL model is constructed using the [regtool.py script]({{< relref "util/reggen/README.md" >}}) and it is placed at `env/aes_reg_block.sv`.
+### UVM RAL model
+The AES RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
+
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/aes/dv/env/aes_env.core b/hw/ip/aes/dv/env/aes_env.core
index 50a7b3a..a60f994 100644
--- a/hw/ip/aes/dv/env/aes_env.core
+++ b/hw/ip/aes/dv/env/aes_env.core
@@ -10,9 +10,9 @@
         - lowrisc:ip:aes:0.6
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:csr_utils
-      - lowrisc:dv:gen_ral_pkg
       - lowrisc:dv:aes_model_dpi
     files:
       - aes_env_pkg.sv
@@ -29,8 +29,17 @@
       - seq_lib/aes_sanity_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: aes
+      ip_hjson: ../../data/aes.hjson
+
 targets:
   default:
     filesets:
       - files_rtl
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/alert_handler/doc/dv_plan/index.md b/hw/ip/alert_handler/doc/dv_plan/index.md
index a614db2..b0b59cf 100644
--- a/hw/ip/alert_handler/doc/dv_plan/index.md
+++ b/hw/ip/alert_handler/doc/dv_plan/index.md
@@ -57,10 +57,9 @@
 receiver pairs for the alerts and escalators.
 
 ### UVM RAL Model
-The ALERT_HANDLER RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The ALERT_HANDLER RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) `fusesoc` generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.core b/hw/ip/alert_handler/dv/env/alert_handler_env.core
index 70ca5ea..70d4d3d 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_env.core
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env.core
@@ -7,8 +7,8 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
-      - lowrisc:dv:gen_ral_pkg
       - lowrisc:ip:alert_handler_component
     files:
       - alert_handler_env_pkg.sv
@@ -29,7 +29,16 @@
       - seq_lib/alert_handler_stress_all_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: alert_handler
+      ip_hjson: ../../data/alert_handler.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/gpio/doc/dv_plan/index.md b/hw/ip/gpio/doc/dv_plan/index.md
index 9682670..61daf74 100644
--- a/hw/ip/gpio/doc/dv_plan/index.md
+++ b/hw/ip/gpio/doc/dv_plan/index.md
@@ -47,10 +47,9 @@
 GPIO testbench instantiates (handled in CIP base env) [tl_agent]({{< relref "hw/dv/sv/tl_agent/README.md" >}}) which provides the ability to drive and independently monitor random traffic via TL host interface into GPIO device.
 
 ### UVM RAL Model
-The GPIO RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The GPIO RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/gpio/dv/env/gpio_env.core b/hw/ip/gpio/dv/env/gpio_env.core
index cae41fe..70fdcdb 100644
--- a/hw/ip/gpio/dv/env/gpio_env.core
+++ b/hw/ip/gpio/dv/env/gpio_env.core
@@ -7,8 +7,8 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
-      - lowrisc:dv:gen_ral_pkg
     files:
       - gpio_env_pkg.sv
       - gpio_env_cfg.sv: {is_include_file: true}
@@ -30,7 +30,16 @@
       - seq_lib/gpio_intr_with_filter_rand_intr_event_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: gpio
+      ip_hjson: ../../data/gpio.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/hmac/doc/dv_plan/index.md b/hw/ip/hmac/doc/dv_plan/index.md
index 283b4ae..accb1b4 100644
--- a/hw/ip/hmac/doc/dv_plan/index.md
+++ b/hw/ip/hmac/doc/dv_plan/index.md
@@ -54,10 +54,9 @@
 TL host interface into HMAC device.
 
 ### UVM RAL Model
-The HMAC RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The HMAC RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Reference models
 To check the correctness of the output for SHA256 and HMAC, the testbench uses
diff --git a/hw/ip/hmac/dv/env/hmac_env.core b/hw/ip/hmac/dv/env/hmac_env.core
index 8d96a9c..779bc0c 100644
--- a/hw/ip/hmac/dv/env/hmac_env.core
+++ b/hw/ip/hmac/dv/env/hmac_env.core
@@ -7,10 +7,10 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:cryptoc_dpi:0.1
       - lowrisc:dv:test_vectors
-      - lowrisc:dv:gen_ral_pkg
     files:
       - hmac_env_pkg.sv
       - hmac_env_cfg.sv: {is_include_file: true}
@@ -30,7 +30,16 @@
       - seq_lib/hmac_stress_all_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: hmac
+      ip_hjson: ../../data/hmac.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/i2c/doc/dv_plan/index.md b/hw/ip/i2c/doc/dv_plan/index.md
index 5daa844..95ab282 100644
--- a/hw/ip/i2c/doc/dv_plan/index.md
+++ b/hw/ip/i2c/doc/dv_plan/index.md
@@ -57,10 +57,9 @@
 [describe or provide link to I2C agent documentation]
 
 ### UVM RAL Model
-The I2C RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The I2C RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/i2c/dv/env/i2c_env.core b/hw/ip/i2c/dv/env/i2c_env.core
index dd86831..8af27c3 100644
--- a/hw/ip/i2c/dv/env/i2c_env.core
+++ b/hw/ip/i2c/dv/env/i2c_env.core
@@ -7,9 +7,9 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:i2c_agent
-      - lowrisc:dv:gen_ral_pkg
       - lowrisc:ip:i2c
     files:
       - i2c_env_pkg.sv
@@ -23,7 +23,16 @@
       - seq_lib/i2c_common_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: i2c
+      ip_hjson: ../../data/i2c.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/rv_timer/doc/dv_plan/index.md b/hw/ip/rv_timer/doc/dv_plan/index.md
index 3cf45dc..03bdb19 100644
--- a/hw/ip/rv_timer/doc/dv_plan/index.md
+++ b/hw/ip/rv_timer/doc/dv_plan/index.md
@@ -49,10 +49,9 @@
 TL host interface into RV_TIMER device.
 
 ### UVM RAL Model
-The RV_TIMER RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The RV_TIMER RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/rv_timer/dv/env/rv_timer_env.core b/hw/ip/rv_timer/dv/env/rv_timer_env.core
index 6ee0677..d302d19 100644
--- a/hw/ip/rv_timer/dv/env/rv_timer_env.core
+++ b/hw/ip/rv_timer/dv/env/rv_timer_env.core
@@ -7,8 +7,8 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
-      - lowrisc:dv:gen_ral_pkg
     files:
       - rv_timer_env_pkg.sv
       - rv_timer_env_cfg.sv: {is_include_file: true}
@@ -25,7 +25,16 @@
       - seq_lib/rv_timer_stress_all_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: rv_timer
+      ip_hjson: ../../data/rv_timer.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/spi_device/doc/dv_plan/index.md b/hw/ip/spi_device/doc/dv_plan/index.md
index bff0b7a..bdc7320 100644
--- a/hw/ip/spi_device/doc/dv_plan/index.md
+++ b/hw/ip/spi_device/doc/dv_plan/index.md
@@ -60,10 +60,9 @@
 * During data transfer, there may be very long delay between each bit or byte of data
 
 ### UVM RAL Model
-The SPI Device RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The SPI Device RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/spi_device/dv/env/spi_device_env.core b/hw/ip/spi_device/dv/env/spi_device_env.core
index 5d611d1..2401159 100644
--- a/hw/ip/spi_device/dv/env/spi_device_env.core
+++ b/hw/ip/spi_device/dv/env/spi_device_env.core
@@ -7,9 +7,9 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:spi_agent
-      - lowrisc:dv:gen_ral_pkg
     files:
       - spi_device_env_pkg.sv
       - spi_device_env_cfg.sv: {is_include_file: true}
@@ -29,7 +29,16 @@
       - seq_lib/spi_device_intr_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: spi_device
+      ip_hjson: ../../data/spi_device.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/tlul/generic_dv/xbar_sim_cfg.hjson b/hw/ip/tlul/generic_dv/xbar_sim_cfg.hjson
index ce4b634..3775d4a 100644
--- a/hw/ip/tlul/generic_dv/xbar_sim_cfg.hjson
+++ b/hw/ip/tlul/generic_dv/xbar_sim_cfg.hjson
@@ -23,11 +23,6 @@
   // Add xbar specific exclusion files.
   vcs_cov_excl_files: ["{tool_srcs_dir}/xbar_cov_excl.el"]
 
-  // no reg in xbar. This is a make variable in hw/dv/data/sim.mk. Set it to skip make target (RAL)
-  exports: [
-    skip_gen_ral_pkg: 1
-  ]
-
   // Import additional common sim cfg files.
   import_cfgs: [// Project wide common sim cfg file
                 "{proj_root}/hw/dv/data/common_sim_cfg.hjson"]
diff --git a/hw/ip/uart/doc/dv_plan/index.md b/hw/ip/uart/doc/dv_plan/index.md
index 8554976..dafa64b 100644
--- a/hw/ip/uart/doc/dv_plan/index.md
+++ b/hw/ip/uart/doc/dv_plan/index.md
@@ -58,10 +58,9 @@
 These baud rates are supported: 9600, 115200, 230400, 1Mbps(1048576), 2Mbps(2097152)
 
 ### UVM RAL Model
-The UART RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The UART RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Stimulus strategy
 #### Test sequences
diff --git a/hw/ip/uart/dv/env/uart_env.core b/hw/ip/uart/dv/env/uart_env.core
index d180257..e123d6f 100644
--- a/hw/ip/uart/dv/env/uart_env.core
+++ b/hw/ip/uart/dv/env/uart_env.core
@@ -7,9 +7,9 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:uart_agent
       - lowrisc:dv:cip_lib
-      - lowrisc:dv:gen_ral_pkg
     files:
       - uart_env_pkg.sv
       - uart_env_cfg.sv: {is_include_file: true}
@@ -36,7 +36,16 @@
       - seq_lib/uart_tx_ovrd_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: uart
+      ip_hjson: ../../data/uart.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/ip/usbdev/doc/dv_plan/index.md b/hw/ip/usbdev/doc/dv_plan/index.md
index 91c186b..731e215 100644
--- a/hw/ip/usbdev/doc/dv_plan/index.md
+++ b/hw/ip/usbdev/doc/dv_plan/index.md
@@ -57,8 +57,9 @@
 It does not offer any functionality yet.
 
 ### UVM RAL Model
-The USBDEV RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The USBDEV RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
+
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ### Reference models
 There are no reference models in use currently.
diff --git a/hw/ip/usbdev/dv/env/usbdev_env.core b/hw/ip/usbdev/dv/env/usbdev_env.core
index 3ce973d..f3b8058 100644
--- a/hw/ip/usbdev/dv/env/usbdev_env.core
+++ b/hw/ip/usbdev/dv/env/usbdev_env.core
@@ -7,9 +7,9 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:usb20_agent
-      - lowrisc:dv:gen_ral_pkg
     files:
       - usbdev_env_pkg.sv
       - usbdev_env_cfg.sv: {is_include_file: true}
@@ -23,7 +23,16 @@
       - seq_lib/usbdev_sanity_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: usbdev
+      ip_hjson: ../../data/usbdev.hjson
+
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
index 02b3fd7..39ade5f 100644
--- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson
+++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
@@ -42,9 +42,6 @@
   uvm_test_seq: chip_base_vseq
   sw_build_device: sim_dv
 
-  // Additional option to RAL generation for top level.
-  gen_ral_pkg_opts: ["--top"]
-
   // Add default build_opts.
   build_opts: [// Use generic implementations of prim modules.
                "+define+PRIM_DEFAULT_IMPL=prim_pkg::ImplGeneric"]
diff --git a/hw/top_earlgrey/dv/env/chip_env.core b/hw/top_earlgrey/dv/env/chip_env.core
index 98506ef..dec660e 100644
--- a/hw/top_earlgrey/dv/env/chip_env.core
+++ b/hw/top_earlgrey/dv/env/chip_env.core
@@ -7,13 +7,13 @@
 filesets:
   files_dv:
     depend:
+      - lowrisc:dv:ralgen
       - lowrisc:dv:cip_lib
       - lowrisc:dv:uart_agent
       - lowrisc:dv:jtag_agent
       - lowrisc:dv:spi_agent
       - lowrisc:dv:mem_bkdr_if
       - lowrisc:dv:sw_msg_monitor_if
-      - lowrisc:dv:gen_ral_pkg
     files:
       - chip_env_pkg.sv
       - chip_tl_seq_item.sv: {is_include_file: true}
@@ -28,8 +28,16 @@
       - seq_lib/chip_common_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: chip
+      top_hjson: ../../data/top_earlgrey.hjson
 
 targets:
   default:
     filesets:
       - files_dv
+    generate:
+      - ral
diff --git a/util/dvsim/Deploy.py b/util/dvsim/Deploy.py
index 285317f..a856218 100644
--- a/util/dvsim/Deploy.py
+++ b/util/dvsim/Deploy.py
@@ -493,12 +493,6 @@
             "tool_srcs": False,
             "tool_srcs_dir": False,
 
-            # RAL gen
-            "skip_ral": False,
-            "gen_ral_pkg_cmd": False,
-            "gen_ral_pkg_dir": False,
-            "gen_ral_pkg_opts": False,
-
             # Flist gen
             "sv_flist_gen_cmd": False,
             "sv_flist_gen_dir": False,
diff --git a/util/dvsim/SimCfg.py b/util/dvsim/SimCfg.py
index e00b320..91562ba 100644
--- a/util/dvsim/SimCfg.py
+++ b/util/dvsim/SimCfg.py
@@ -51,7 +51,6 @@
         self.email = args.email
         self.verbose = args.verbose
         self.dry_run = args.dry_run
-        self.skip_ral = args.skip_ral
         self.map_full_testplan = args.map_full_testplan
 
         # Set default sim modes for unpacking
@@ -498,13 +497,14 @@
             self.results_summary = self.testplan.results_summary
 
             # Append coverage results of coverage was enabled.
-            if self.cov and self.cov_report_deploy.status == "P":
-                results_str += "\n## Coverage Results\n"
-                results_str += "\n### [Coverage Dashboard](cov_report/dashboard.html)\n\n"
-                results_str += self.cov_report_deploy.cov_results
-                self.results_summary[
-                    "Coverage"] = self.cov_report_deploy.cov_total
-            elif self.cov:
+            if self.cov:
+                if self.cov_report_deploy.status == "P":
+                    results_str += "\n## Coverage Results\n"
+                    results_str += "\n### [Coverage Dashboard]"
+                    results_str += "(cov_report/dashboard.html)\n\n"
+                    results_str += self.cov_report_deploy.cov_results
+                    self.results_summary[
+                        "Coverage"] = self.cov_report_deploy.cov_total
                 self.results_summary["Coverage"] = "--"
 
             # append link of detail result to block name
diff --git a/util/dvsim/dvsim.py b/util/dvsim/dvsim.py
index fe05393..d61d304 100755
--- a/util/dvsim/dvsim.py
+++ b/util/dvsim/dvsim.py
@@ -335,11 +335,6 @@
         """By default, failing tests will be automatically be rerun with waves;
                 this option will prevent the rerun from being triggered""")
 
-    parser.add_argument("--skip-ral",
-                        default=False,
-                        action='store_true',
-                        help="""Skip the ral generation step.""")
-
     parser.add_argument("-v",
                         "--verbosity",
                         default="l",
diff --git a/util/uvmdvgen/dv_plan.md.tpl b/util/uvmdvgen/dv_plan.md.tpl
index 43d8f6c..3cab56e 100644
--- a/util/uvmdvgen/dv_plan.md.tpl
+++ b/util/uvmdvgen/dv_plan.md.tpl
@@ -77,11 +77,9 @@
 
 % if has_ral:
 ${'###'} UVM RAL Model
-The ${name.upper()} RAL model is created with the `hw/dv/tools/gen_ral_pkg.py` wrapper script at the start of the simulation automatically and is placed in the build area, along with a corresponding `fusesoc` core file.
-The wrapper script invokes the [regtool.py]({{< relref "util/reggen/README.md" >}}) script from within to generate the RAL model.
+The ${name.upper()} RAL model is created with the [`ralgen`]({{< relref "hw/dv/tools/ralgen/README.md" >}}) FuseSoC generator script automatically when the simulation is at the build stage.
 
-It can be created manually by running `make ral` command from the `dv` area.
-% endif
+It can be created manually (separately) by running `make` in the the `hw/` area.
 
 ${'###'} Reference models
 [Describe reference models in use if applicable, example: SHA256/HMAC]
diff --git a/util/uvmdvgen/env.core.tpl b/util/uvmdvgen/env.core.tpl
index dd1ba33..5d1e3e2 100644
--- a/util/uvmdvgen/env.core.tpl
+++ b/util/uvmdvgen/env.core.tpl
@@ -7,6 +7,9 @@
 filesets:
   files_dv:
     depend:
+% if has_ral:
+      - lowrisc:dv:ralgen
+% endif
 % if is_cip:
       - lowrisc:dv:cip_lib
 % else:
@@ -15,9 +18,6 @@
 % for agent in env_agents:
       - lowrisc:dv:${agent}_agent
 % endfor
-% if has_ral:
-      - lowrisc:dv:gen_ral_pkg
-% endif
     files:
       - ${name}_env_pkg.sv
       - ${name}_env_cfg.sv: {is_include_file: true}
@@ -33,7 +33,20 @@
       - seq_lib/${name}_sanity_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
+% if has_ral:
+generate:
+  ral:
+    generator: ralgen
+    parameters:
+      name: ${name}
+      ral_spec: ../../data/${name}.hjson
+% endif
+
 targets:
   default:
     filesets:
       - files_dv
+% if has_ral:
+    generate:
+      - ral
+% endif