Update lowrisc_ibex to lowRISC/ibex@25cd6600

Update code from upstream repository
https://github.com/lowRISC/ibex.git to revision
25cd6600c64e6eec4c3f5ee20237b53e4d5a3a52

* [dv] Don't kill regression on sim error (Greg Chadwick)
* [rtl] Add dual core lockstep option (Tom Roberts)
* [rtl] Add a new top level plus wiring (Tom Roberts)
* [rtl/icache] Move various parameters into the pkg (Tom Roberts)
* [rtl] Add SVA to ensure valid_i in compressed decoder is known
  (Pirmin Vogel)
* Update google_riscv-dv to google/riscv-dv@59dcd8c (Rupert Swarbrick)
* [util] Document required VCS version (Rupert Swarbrick)
* [util] Manually "vendor" latest check_tool_requirements.py (Rupert
  Swarbrick)
* Fix initialisation in ibex_icache_env_cfg.sv (Rupert Swarbrick)
* Update lowrisc_ip to lowRISC/opentitan@f29a0f7a7 (Rupert Swarbrick)
* Avoid encumbered name in ibex_icache_testplan.hjson (Rupert
  Swarbrick)
* [dv] Remove semicolon (Philipp Wagner)
* [dv] Fix name of ELF file in report (Philipp Wagner)
* [dv] Fix riscv_nested_interrupt_test (Greg Chadwick)
* [dv] Fix riscv_irq_in_debug_mode_test (Greg Chadwick)
* [dv] Allow full IRQ randomisation (Greg Chadwick)
* [dv] Small core_ibex_test_lib refactor (Greg Chadwick)

Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
diff --git a/hw/ip/rv_core_ibex/lint/rv_core_ibex.waiver b/hw/ip/rv_core_ibex/lint/rv_core_ibex.waiver
index 6844a58..0285907 100644
--- a/hw/ip/rv_core_ibex/lint/rv_core_ibex.waiver
+++ b/hw/ip/rv_core_ibex/lint/rv_core_ibex.waiver
@@ -4,7 +4,7 @@
 #
 # waiver file for Ibex core
 
-waive -rules EXPLICIT_BITLEN      -location {ibex_core.sv} -regexp {Bit length not specified for constant .*h2} \
+waive -rules EXPLICIT_BITLEN      -location {ibex_top.sv} -regexp {Bit length not specified for constant .*h2} \
       -comment "better way to write it?"
 waive -rules HIER_BRANCH_NOT_READ -location {ibex_decoder.sv} -regexp {Net 'instr_rdata_i.*is not read from in module} \
       -comment "not all bits are used"
@@ -16,7 +16,7 @@
       -comment "testability signal used in some versions of register file"
 waive -rules INPUT_NOT_READ       -location {ibex_register_file_fpga.sv} -regexp {Input port 'test_en_i' is not read from} \
       -comment "testability signal used in some versions of register file"
-waive -rules INPUT_NOT_READ       -location {ibex_core.sv} -regexp {Input port 'clock_en_i' is not read from} \
+waive -rules INPUT_NOT_READ       -location {ibex_top.sv} -regexp {Input port 'clock_en_i' is not read from} \
       -comment "clock enable signal used in behavioral code"
 waive -rules HIER_NET_NOT_READ    -location {rv_core_ibex.sv} -regexp {Net 'instr_addr_o.1.0.' is not read from} \
       -comment "Bottom bits not needed, cleaner to keep them as inputs"
@@ -30,7 +30,7 @@
       -comment "Bottom bit is round, not needed"
 waive -rules HIER_NET_NOT_READ    -location {ibex_ex_block.sv} -regexp {Connected net 'alu_adder_ext_i.0.' .* is not read from} \
       -comment "Bottom bit is round, not needed"
-waive -rules HIER_NET_NOT_READ    -location {ibex_core.sv} -regexp {[nN]et 'boot_addr_i.7:0.' .* is not read from} \
+waive -rules HIER_NET_NOT_READ    -location {ibex_top.sv} -regexp {[nN]et 'boot_addr_i.7:0.' .* is not read from} \
       -comment "Boot address is 256B aligned, cleaner to pass all bits in"
 waive -rules {INPUT_NOT_READ HIER_BRANCH_NOT_READ} -location {ibex_if_stage.sv} -regexp {'boot_addr_i.7:0.' is not read from} \
       -comment "Boot address is 256B aligned, cleaner to pass all bits in"
@@ -77,20 +77,20 @@
 waive -rules NOT_READ             -location {ibex_alu.sv} -regexp {Signal 'shift_right_result_ext.32.' is not read from} \
       -comment "As mentioned in the RTL, MSB of shift_right_result_ext can be safely ignored"
 waive -rules NOT_READ             -location {ibex_id_stage.sv} -regexp {Signal 'operand_b_fw_id' is not read from in module 'ibex_id_stage'} \
-      -comment "This signal is actually used (not via a port but through hierarchical path) in ibex_core.sv"
+      -comment "This signal is actually used (not via a port but through hierarchical path) in ibex_top.sv"
 waive -rules INTEGER              -location {ibex_register_file_ff.sv rv_core_ibex.sv} -msg {'i' of type int used as a non-constant value} \
       -comment "This assigns int i (signed) to a multibit logic variable (unsigned), which is fine"
-waive -rules ONE_BIT_MEM_WIDTH             -location {ibex_core.sv} -regexp {Memory 'pmp_req_err' has word width which is single bit wide} \
+waive -rules ONE_BIT_MEM_WIDTH             -location {ibex_top.sv} -regexp {Memory 'pmp_req_err' has word width which is single bit wide} \
       -comment "For consistency with related signals, we use an unpacked array for this signal."
 waive -rules HIER_BRANCH_NOT_READ -location {ibex_decoder.sv ibex_compressed_decoder.sv} -regexp {Net '(clk_i|rst_ni)' is not read from in module '(ibex_decoder|ibex_compressed_decoder)'.*} \
       -comment "These signals are only used for assertions inside these two modules"
 waive -rules INPUT_NOT_READ -location {ibex_decoder.sv ibex_compressed_decoder.sv} -regexp {Input port '(clk_i|rst_ni)' is not read from in module '(ibex_decoder|ibex_compressed_decoder)'.*} \
       -comment "These signals are only used for assertions inside these two modules"
-waive -rules IFDEF_CODE -location {ibex_core.sv} -regexp {Assignment to 'unused_instr_new_id' contained within `else block} \
+waive -rules IFDEF_CODE -location {ibex_top.sv} -regexp {Assignment to 'unused_instr_new_id' contained within `else block} \
       -comment "Declaration of signal and assignment to it are in same `else block"
-waive -rules IFDEF_CODE -location {ibex_core.sv} -regexp {Assignment to 'unused_instr_id_done' contained within `else block} \
+waive -rules IFDEF_CODE -location {ibex_top.sv} -regexp {Assignment to 'unused_instr_id_done' contained within `else block} \
       -comment "Declaration of signal and assignment to it are in same `else block"
-waive -rules IFDEF_CODE -location {ibex_core.sv} -regexp {Assignment to 'unused_instr_done_wb' contained within `else block} \
+waive -rules IFDEF_CODE -location {ibex_top.sv} -regexp {Assignment to 'unused_instr_done_wb' contained within `else block} \
       -comment "Declaration of signal and assignment to it are in same `else block"
 waive -rules IFDEF_CODE -location {rv_core_ibex.sv} -regexp {Assignment to 'tl_d_o' contained within `else block} \
       -comment "DV environment will drive things when `else block isn't used so assignment only occurs in `else block"
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
index 23d13be..d676f39 100644
--- a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
@@ -173,7 +173,7 @@
     .lc_en_o(lc_cpu_en)
   );
 
-  ibex_core #(
+  ibex_top #(
     .PMPEnable                ( PMPEnable                ),
     .PMPGranularity           ( PMPGranularity           ),
     .PMPNumRegions            ( PMPNumRegions            ),
diff --git a/hw/ip/rv_core_ibex/rv_core_ibex.core b/hw/ip/rv_core_ibex/rv_core_ibex.core
index 29ab3c5..c4e40b9 100644
--- a/hw/ip/rv_core_ibex/rv_core_ibex.core
+++ b/hw/ip/rv_core_ibex/rv_core_ibex.core
@@ -7,7 +7,7 @@
 filesets:
   files_rtl:
     depend:
-      - lowrisc:ibex:ibex_core
+      - lowrisc:ibex:ibex_top
       - lowrisc:prim:all
       - lowrisc:prim:clock_gating
       - lowrisc:ip:tlul
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index cd2d429..d0e438d 100644
--- a/hw/vendor/lowrisc_ibex.lock.hjson
+++ b/hw/vendor/lowrisc_ibex.lock.hjson
@@ -9,6 +9,6 @@
   upstream:
   {
     url: https://github.com/lowRISC/ibex.git
-    rev: 4b43afa53315d00784d5c3b714583276127eddcc
+    rev: 25cd6600c64e6eec4c3f5ee20237b53e4d5a3a52
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml b/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
index 5fc32a7..5b1a853 100644
--- a/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
+++ b/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
@@ -14,19 +14,19 @@
       displayName: Test and display fusesoc config for ${{ config }}
 
     - bash: |
-        fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS
+        fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS
         if [ $? != 0 ]; then
           echo -n "##vso[task.logissue type=error]"
-          echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
+          echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
           exit 1
         fi
       displayName: Lint Verilog source files with Verilator for ${{ config }}
 
     - bash: |
-        fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS
+        fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS
         if [ $? != 0 ]; then
           echo -n "##vso[task.logissue type=error]"
-          echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
+          echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
           exit 1
         fi
       displayName: Lint Verilog source files with Verible Verilog Lint for ${{ config }}
diff --git a/hw/vendor/lowrisc_ibex/doc/02_user/integration.rst b/hw/vendor/lowrisc_ibex/doc/02_user/integration.rst
index d165fdb..f53c708 100644
--- a/hw/vendor/lowrisc_ibex/doc/02_user/integration.rst
+++ b/hw/vendor/lowrisc_ibex/doc/02_user/integration.rst
@@ -3,7 +3,10 @@
 Core Integration
 ================
 
-The main module is named ``ibex_core`` and can be found in ``ibex_core.sv``.
+The main module is named ``ibex_top`` and can be found in ``ibex_top.sv``.
+Note that the core logic is split-out from the register file and RAMs under ``ibex_top``.
+This is to facilitate a dual-core lockstep implementation (see :ref:`security`).
+
 Below, the instantiation template is given and the parameters and interfaces are described.
 
 Instantiation Template
@@ -11,7 +14,7 @@
 
 .. code-block:: verilog
 
-  ibex_core #(
+  ibex_top #(
       .PMPEnable        ( 0                   ),
       .PMPGranularity   ( 0                   ),
       .PMPNumRegions    ( 4                   ),
@@ -28,7 +31,7 @@
       .DbgTriggerEn     ( 0                   ),
       .DmHaltAddr       ( 32'h1A110800        ),
       .DmExceptionAddr  ( 32'h1A110808        )
-  ) u_core (
+  ) u_top (
       // Clock and reset
       .clk_i          (),
       .rst_ni         (),
diff --git a/hw/vendor/lowrisc_ibex/doc/02_user/system_requirements.rst b/hw/vendor/lowrisc_ibex/doc/02_user/system_requirements.rst
index 7fbd3f9..1b2ed0a 100644
--- a/hw/vendor/lowrisc_ibex/doc/02_user/system_requirements.rst
+++ b/hw/vendor/lowrisc_ibex/doc/02_user/system_requirements.rst
@@ -10,7 +10,7 @@
 - Synopsys Design Compiler
 - Xilinx Vivado
 - Verilator, version |tool_requirements.verilator| and up.
-- Synopsys VCS
+- Synopsys VCS, version at least |tool_requirements.vcs|.
 - Cadence Incisive/Xcelium
 - Mentor Questa
 - Aldec Riviera Pro
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
index c96273e..1e55de9 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
@@ -204,7 +204,7 @@
 The I$ has a single clock (``clk_i``) and asynchronous reset (``rst_ni``).
 
 Data is requested from the instruction memory with the ports prefixed by ``instr_``. These work as described in :ref:`instruction-fetch`.
-Note that there's one extra port on the I$, which doesn't appear at the ``ibex_core`` top-level.
+Note that there's one extra port on the I$, which doesn't appear at the ``ibex_top`` top-level.
 This is ``instr_pmp_err_i``.
 If the PMP block disallows a fetch for a certain address, it will squash the outgoing memory request entirely and set ``instr_pmp_err_i``.
 If that happens, the cache drops ``instr_req_o`` and stops making any further requests for that cache line.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
index b44d715..c52de53 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
@@ -77,3 +77,13 @@
 Certain critical CSRs (`mstatus`, `mtvec`, `cpuctrl`, `pmpcfg` and `pmpaddr`) have extra glitch detection enabled.
 This creates a second copy of the register which stores a complemented version of the main CSR data.
 A constant check is made that the two copies are consistent, and a major alert is signalled if not.
+
+Dual core lockstep
+------------------
+
+This configuration option instantiates a second copy of the core logic, referred to as the shadow core.
+The shadow core executes using a delayed version of all inputs supplied to the main core.
+All outputs of the shadow core are compared against a delayed version of the outputs of the main core.
+Any mismatch between the two sets of outputs will trigger a major alert.
+
+Note that the register file and icache RAMs are not duplicated since these units are covered by ECC protection.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/tracer.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/tracer.rst
index 6a1feda..3824206 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/tracer.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/tracer.rst
@@ -4,7 +4,7 @@
 ======
 
 The module ``ibex_tracer`` can be used to create a log of the executed instructions.
-It is used by ``ibex_core_tracing`` which forwards the `RVFI signals <https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md>`_ to the tracer (see also :ref:`rvfi`).
+It is used by ``ibex_top_tracing`` which forwards the `RVFI signals <https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md>`_ to the tracer (see also :ref:`rvfi`).
 
 Output file
 -----------
diff --git a/hw/vendor/lowrisc_ibex/doc/conf.py b/hw/vendor/lowrisc_ibex/doc/conf.py
index 215db10..a9b0e62 100644
--- a/hw/vendor/lowrisc_ibex/doc/conf.py
+++ b/hw/vendor/lowrisc_ibex/doc/conf.py
@@ -12,12 +12,19 @@
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 #
 import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
+import sys
 
 # Source top directory
 topsrcdir = os.path.join(os.path.dirname(__file__), '..')
 
+old_sys_path = sys.path
+try:
+    sys.path.append(os.path.join(topsrcdir, 'util'))
+    import check_tool_requirements as ctr
+finally:
+    sys.path = old_sys_path
+
+
 numfig=True
 numfig_format = {'figure': 'Figure %s', 'table': 'Table %s', 'code-block': 'Listing %s'}
 
@@ -164,7 +171,8 @@
 
 # Add minimum versions of required tools as variables for use inside the
 # documentation.
-exec(open(os.path.join(topsrcdir, 'tool_requirements.py')).read())
+tool_reqs = ctr.read_tool_requirements()
 rst_epilog = ""
-for tool_name, tool_version in __TOOL_REQUIREMENTS__.items():
-    rst_epilog += ".. |tool_requirements.{}| replace:: {}\n".format(tool_name, tool_version)
+for tool, req in tool_reqs.items():
+    rst_epilog += (".. |tool_requirements.{}| replace:: {}\n"
+                   .format(tool, req.min_version))
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
index db4e461..62c9fea 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
@@ -42,11 +42,11 @@
   logic [31:0] mem_rdata;
 
 
-  ibex_core #(
+  ibex_top #(
      .RegFile(ibex_pkg::RegFileFPGA),
      .DmHaltAddr(32'h00000000),
      .DmExceptionAddr(32'h00000000)
-  ) u_core (
+  ) u_top (
      .clk_i                 (clk_sys),
      .rst_ni                (rst_sys_n),
 
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
index 811fb93..5b7fab2 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
@@ -7,7 +7,7 @@
 filesets:
   files_rtl_artya7:
     depend:
-      - lowrisc:ibex:ibex_core
+      - lowrisc:ibex:ibex_top
       - lowrisc:ibex:fpga_xilinx_shared
     files:
       - rtl/top_artya7.sv
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
index 99b8d65..4ec4186 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
@@ -17,8 +17,10 @@
   simctrl.SetTop(&top, &top.IO_CLK, &top.IO_RST_N,
                  VerilatorSimCtrlFlags::ResetPolarityNegative);
 
-  memutil.RegisterMemoryArea(
-      "ram", "TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic");
+  MemArea ram("TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
+              1024 * 1024 / 4, 4);
+
+  memutil.RegisterMemoryArea("ram", 0x0, &ram);
   simctrl.RegisterExtension(&memutil);
 
   bool exit_app = false;
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
index a153ea2..c585a09 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
@@ -7,7 +7,7 @@
 filesets:
   files_sim:
     depend:
-      - lowrisc:ibex:ibex_core_tracing
+      - lowrisc:ibex:ibex_top_tracing
       - lowrisc:ibex:sim_shared
     files:
       - rtl/ibex_simple_system.sv
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
index 3de2c17..68c7bf7 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
@@ -161,7 +161,7 @@
     .cfg_device_addr_mask
   );
 
-  ibex_core_tracing #(
+  ibex_top_tracing #(
       .SecureIbex      ( SecureIbex      ),
       .PMPEnable       ( PMPEnable       ),
       .PMPGranularity  ( PMPGranularity  ),
@@ -178,7 +178,7 @@
       .BranchPredictor ( BranchPredictor ),
       .DmHaltAddr      ( 32'h00100000    ),
       .DmExceptionAddr ( 32'h00100000    )
-    ) u_core (
+    ) u_top (
       .clk_i                 (clk_sys),
       .rst_ni                (rst_sys_n),
 
@@ -282,7 +282,7 @@
   export "DPI-C" function mhpmcounter_get;
 
   function automatic longint unsigned mhpmcounter_get(int index);
-    return u_core.u_ibex_core.cs_registers_i.mhpmcounter[index];
+    return u_top.u_ibex_top.u_ibex_core.cs_registers_i.mhpmcounter[index];
   endfunction
 
 endmodule
diff --git a/hw/vendor/lowrisc_ibex/ibex_core.core b/hw/vendor/lowrisc_ibex/ibex_core.core
index 4a6333d..a77ba59 100644
--- a/hw/vendor/lowrisc_ibex/ibex_core.core
+++ b/hw/vendor/lowrisc_ibex/ibex_core.core
@@ -3,7 +3,7 @@
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
 name: "lowrisc:ibex:ibex_core:0.1"
-description: "Ibex, a small RV32 CPU core"
+description: "Ibex CPU Core Components"
 
 filesets:
   files_rtl:
@@ -34,9 +34,6 @@
       - rtl/ibex_pmp.sv
       - rtl/ibex_wb_stage.sv
       - rtl/ibex_dummy_instr.sv
-      - rtl/ibex_register_file_ff.sv # generic FF-based
-      - rtl/ibex_register_file_fpga.sv # FPGA
-      - rtl/ibex_register_file_latch.sv # ASIC
       - rtl/ibex_core.sv
     file_type: systemVerilogSource
 
diff --git a/hw/vendor/lowrisc_ibex/ibex_icache.core b/hw/vendor/lowrisc_ibex/ibex_icache.core
index c093ba2..5445bdc 100644
--- a/hw/vendor/lowrisc_ibex/ibex_icache.core
+++ b/hw/vendor/lowrisc_ibex/ibex_icache.core
@@ -10,6 +10,7 @@
       - lowrisc:prim:secded
       - lowrisc:prim:ram_1p
       - lowrisc:prim:assert
+      - lowrisc:ibex:ibex_pkg
     files:
       - rtl/ibex_icache.sv
     file_type: systemVerilogSource
diff --git a/hw/vendor/lowrisc_ibex/ibex_core_tracing.core b/hw/vendor/lowrisc_ibex/ibex_top.core
similarity index 75%
copy from hw/vendor/lowrisc_ibex/ibex_core_tracing.core
copy to hw/vendor/lowrisc_ibex/ibex_top.core
index 8832f0d..ef27228 100644
--- a/hw/vendor/lowrisc_ibex/ibex_core_tracing.core
+++ b/hw/vendor/lowrisc_ibex/ibex_top.core
@@ -2,28 +2,49 @@
 # Copyright lowRISC contributors.
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
-name: "lowrisc:ibex:ibex_core_tracing:0.1"
-description: "Ibex, a small RV32 CPU core with tracing enabled"
+name: "lowrisc:ibex:ibex_top:0.1"
+description: "Ibex, a small RV32 CPU core"
+
 filesets:
   files_rtl:
     depend:
+      - lowrisc:ibex:ibex_pkg
       - lowrisc:ibex:ibex_core
-      - lowrisc:ibex:ibex_tracer
     files:
-      - rtl/ibex_core_tracing.sv
+      - rtl/ibex_register_file_ff.sv # generic FF-based
+      - rtl/ibex_register_file_fpga.sv # FPGA
+      - rtl/ibex_register_file_latch.sv # ASIC
+      - rtl/ibex_lockstep.sv
+      - rtl/ibex_top.sv
     file_type: systemVerilogSource
 
+  files_lint_verilator:
+    files:
+      - lint/verilator_waiver.vlt: {file_type: vlt}
+
+  files_lint_verible:
+    files:
+      - lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
+
+  files_check_tool_requirements:
+    depend:
+     - lowrisc:tool:check_tool_requirements
+
 parameters:
-  # The tracer uses the RISC-V Formal Interface (RVFI) to collect trace signals.
   RVFI:
     datatype: bool
     paramtype: vlogdefine
-    default: true
 
   SYNTHESIS:
     datatype: bool
     paramtype: vlogdefine
 
+  FPGA_XILINX:
+    datatype: bool
+    description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters.
+    default: false
+    paramtype: vlogdefine
+
   RV32E:
     datatype: int
     default: 0
@@ -104,29 +125,18 @@
 targets:
   default: &default_target
     filesets:
+      - tool_verilator ? (files_lint_verilator)
+      - tool_veriblelint ? (files_lint_verible)
       - files_rtl
+      - files_check_tool_requirements
+    toplevel: ibex_top
     parameters:
-      - RVFI=true
-    toplevel: ibex_core_tracing
-
+      - tool_vivado ? (FPGA_XILINX=true)
   lint:
     <<: *default_target
     parameters:
-      - RVFI=true
       - SYNTHESIS=true
-      - RV32E
-      - RV32M
-      - RV32B
-      - RegFile
-      - ICache
-      - ICacheECC
-      - BranchTargetALU
-      - WritebackStage
-      - BranchPredictor
-      - SecureIbex
-      - PMPEnable
-      - PMPGranularity
-      - PMPNumRegions
+      - RVFI=true
     default_tool: verilator
     tools:
       verilator:
@@ -143,8 +153,9 @@
       - SYNTHESIS=true
       - RVFI=true
     default_tool: veribleformat
-    toplevel: ibex_core
+    toplevel: ibex_top
     tools:
       veribleformat:
         verible_format_args:
           - "--inplace"
+
diff --git a/hw/vendor/lowrisc_ibex/ibex_core_tracing.core b/hw/vendor/lowrisc_ibex/ibex_top_tracing.core
similarity index 95%
rename from hw/vendor/lowrisc_ibex/ibex_core_tracing.core
rename to hw/vendor/lowrisc_ibex/ibex_top_tracing.core
index 8832f0d..a586d9e 100644
--- a/hw/vendor/lowrisc_ibex/ibex_core_tracing.core
+++ b/hw/vendor/lowrisc_ibex/ibex_top_tracing.core
@@ -2,15 +2,15 @@
 # Copyright lowRISC contributors.
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
-name: "lowrisc:ibex:ibex_core_tracing:0.1"
+name: "lowrisc:ibex:ibex_top_tracing:0.1"
 description: "Ibex, a small RV32 CPU core with tracing enabled"
 filesets:
   files_rtl:
     depend:
-      - lowrisc:ibex:ibex_core
+      - lowrisc:ibex:ibex_top
       - lowrisc:ibex:ibex_tracer
     files:
-      - rtl/ibex_core_tracing.sv
+      - rtl/ibex_top_tracing.sv
     file_type: systemVerilogSource
 
 parameters:
@@ -107,7 +107,7 @@
       - files_rtl
     parameters:
       - RVFI=true
-    toplevel: ibex_core_tracing
+    toplevel: ibex_top_tracing
 
   lint:
     <<: *default_target
@@ -143,7 +143,7 @@
       - SYNTHESIS=true
       - RVFI=true
     default_tool: veribleformat
-    toplevel: ibex_core
+    toplevel: ibex_top_tracing
     tools:
       veribleformat:
         verible_format_args:
diff --git a/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt b/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
index 929a9c8..c1a1092 100644
--- a/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
+++ b/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
@@ -23,13 +23,13 @@
 // matches when you set a 1-bit value to a literal 1, so it won't hide
 // silly mistakes like setting it to 2.
 //
-lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv"
+lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv"
          -match "*expects 1 bits*Initial value's CONST '32'h1'*"
 
 // Operator expects 1 bit on initial value but initial value's CONST generates
 // 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all
 // waiver doesn't work.
-lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv" -match "*'RV32B'*"
+lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*"
 
 // Bits of signal are not used: be_i[3:1]
 // Bits of signal are not used: addr_i[31:10,1:0]
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
index 12a487f..ec694f5 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
@@ -282,6 +282,9 @@
   // Assertions //
   ////////////////
 
+  // The valid_i signal used to gate below assertions must be known.
+  `ASSERT_KNOWN(IbexInstrValidKnown, valid_i)
+
   // Selectors must be known/valid.
   `ASSERT(IbexInstrLSBsKnown, valid_i |->
       !$isunknown(instr_i[1:0]))
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index a74448b..92017c3 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -12,34 +12,36 @@
 /**
  * Top level module of the ibex RISC-V core
  */
-module ibex_core #(
-    parameter bit                 PMPEnable        = 1'b0,
-    parameter int unsigned        PMPGranularity   = 0,
-    parameter int unsigned        PMPNumRegions    = 4,
-    parameter int unsigned        MHPMCounterNum   = 0,
-    parameter int unsigned        MHPMCounterWidth = 40,
-    parameter bit                 RV32E            = 1'b0,
-    parameter ibex_pkg::rv32m_e   RV32M            = ibex_pkg::RV32MFast,
-    parameter ibex_pkg::rv32b_e   RV32B            = ibex_pkg::RV32BNone,
-    parameter ibex_pkg::regfile_e RegFile          = ibex_pkg::RegFileFF,
-    parameter bit                 BranchTargetALU  = 1'b0,
-    parameter bit                 WritebackStage   = 1'b0,
-    parameter bit                 ICache           = 1'b0,
-    parameter bit                 ICacheECC        = 1'b0,
-    parameter bit                 BranchPredictor  = 1'b0,
-    parameter bit                 DbgTriggerEn     = 1'b0,
-    parameter int unsigned        DbgHwBreakNum    = 1,
-    parameter bit                 SecureIbex       = 1'b0,
-    parameter int unsigned        DmHaltAddr       = 32'h1A110800,
-    parameter int unsigned        DmExceptionAddr  = 32'h1A110808
+module ibex_core import ibex_pkg::*; #(
+    parameter bit          PMPEnable         = 1'b0,
+    parameter int unsigned PMPGranularity    = 0,
+    parameter int unsigned PMPNumRegions     = 4,
+    parameter int unsigned MHPMCounterNum    = 0,
+    parameter int unsigned MHPMCounterWidth  = 40,
+    parameter bit          RV32E             = 1'b0,
+    parameter rv32m_e      RV32M             = RV32MFast,
+    parameter rv32b_e      RV32B             = RV32BNone,
+    parameter bit          BranchTargetALU   = 1'b0,
+    parameter bit          WritebackStage    = 1'b0,
+    parameter bit          ICache            = 1'b0,
+    parameter bit          ICacheECC         = 1'b0,
+    parameter int unsigned BusSizeECC        = BUS_SIZE,
+    parameter int unsigned TagSizeECC        = IC_TAG_SIZE,
+    parameter int unsigned LineSizeECC       = IC_LINE_SIZE,
+    parameter bit          BranchPredictor   = 1'b0,
+    parameter bit          DbgTriggerEn      = 1'b0,
+    parameter int unsigned DbgHwBreakNum     = 1,
+    parameter bit          SecureIbex        = 1'b0,
+    parameter bit          DummyInstructions = 1'b0,
+    parameter bit          RegFileECC        = 1'b0,
+    parameter int unsigned RegFileDataWidth  = 32,
+    parameter int unsigned DmHaltAddr        = 32'h1A110800,
+    parameter int unsigned DmExceptionAddr   = 32'h1A110808
 ) (
     // Clock and Reset
     input  logic                         clk_i,
     input  logic                         rst_ni,
 
-    input  logic                         test_en_i,     // enable all clock gates for testing
-    input  prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
-
     input  logic [31:0]                  hart_id_i,
     input  logic [31:0]                  boot_addr_i,
 
@@ -62,16 +64,39 @@
     input  logic [31:0]                  data_rdata_i,
     input  logic                         data_err_i,
 
+    // Register file interface
+    output logic                         dummy_instr_id_o,
+    output logic [4:0]                   rf_raddr_a_o,
+    output logic [4:0]                   rf_raddr_b_o,
+    output logic [4:0]                   rf_waddr_wb_o,
+    output logic                         rf_we_wb_o,
+    output logic [RegFileDataWidth-1:0]  rf_wdata_wb_ecc_o,
+    input  logic [RegFileDataWidth-1:0]  rf_rdata_a_ecc_i,
+    input  logic [RegFileDataWidth-1:0]  rf_rdata_b_ecc_i,
+
+    // RAMs interface
+    output logic [IC_NUM_WAYS-1:0]       ic_tag_req_o,
+    output logic                         ic_tag_write_o,
+    output logic [IC_INDEX_W-1:0]        ic_tag_addr_o,
+    output logic [TagSizeECC-1:0]        ic_tag_wdata_o,
+    input  logic [TagSizeECC-1:0]        ic_tag_rdata_i [IC_NUM_WAYS],
+    output logic [IC_NUM_WAYS-1:0]       ic_data_req_o,
+    output logic                         ic_data_write_o,
+    output logic [IC_INDEX_W-1:0]        ic_data_addr_o,
+    output logic [LineSizeECC-1:0]       ic_data_wdata_o,
+    input  logic [LineSizeECC-1:0]       ic_data_rdata_i [IC_NUM_WAYS],
+
     // Interrupt inputs
     input  logic                         irq_software_i,
     input  logic                         irq_timer_i,
     input  logic                         irq_external_i,
     input  logic [14:0]                  irq_fast_i,
     input  logic                         irq_nm_i,       // non-maskeable interrupt
+    output logic                         irq_pending_o,
 
     // Debug Interface
     input  logic                         debug_req_i,
-    output ibex_pkg::crash_dump_t        crash_dump_o,
+    output crash_dump_t                  crash_dump_o,
 
     // RISC-V Formal Interface
     // Does not comply with the coding standards of _i/_o suffixes, but follows
@@ -103,26 +128,20 @@
 `endif
 
     // CPU Control Signals
-    input  logic                         fetch_enable_i,
     output logic                         alert_minor_o,
     output logic                         alert_major_o,
-    output logic                         core_sleep_o
+    output logic                         core_busy_o
 );
 
-  import ibex_pkg::*;
-
   localparam int unsigned PMP_NUM_CHAN      = 2;
   localparam bit          DataIndTiming     = SecureIbex;
-  localparam bit          DummyInstructions = SecureIbex;
   localparam bit          PCIncrCheck       = SecureIbex;
-  localparam bit          ShadowCSR         = SecureIbex;
+  localparam bit          ShadowCSR         = 1'b0;
   // Speculative branch option, trades-off performance against timing.
   // Setting this to 1 eases branch target critical paths significantly but reduces performance
   // by ~3% (based on CoreMark/MHz score).
   // Set by default in the max PMP config which has the tightest budget for branch target timing.
   localparam bit          SpecBranch        = PMPEnable & (PMPNumRegions == 16);
-  localparam bit          RegFileECC        = SecureIbex;
-  localparam int unsigned RegFileDataWidth  = RegFileECC ? 32 + 7 : 32;
 
   // IF/ID signals
   logic        dummy_instr_id;
@@ -179,7 +198,6 @@
   logic        ctrl_busy;
   logic        if_busy;
   logic        lsu_busy;
-  logic        core_busy_d, core_busy_q;
 
   // Register File
   logic [4:0]  rf_raddr_a;
@@ -196,6 +214,7 @@
   logic [31:0] rf_wdata_lsu;
   logic        rf_we_wb;
   logic        rf_we_lsu;
+  logic        rf_ecc_err_comb;
 
   logic [4:0]  rf_waddr_id;
   logic [31:0] rf_wdata_id;
@@ -263,7 +282,6 @@
   logic           outstanding_store_wb;
 
   // Interrupts
-  logic        irq_pending;
   logic        nmi_mode;
   irqs_t       irqs;
   logic        csr_mstatus_mie;
@@ -358,43 +376,9 @@
   // Clock management //
   //////////////////////
 
-  logic        clk;
-
-  logic        clock_en;
-
   // Before going to sleep, wait for I- and D-side
   // interfaces to finish ongoing operations.
-  assign core_busy_d = ctrl_busy | if_busy | lsu_busy;
-
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      core_busy_q <= 1'b0;
-    end else begin
-      core_busy_q <= core_busy_d;
-    end
-  end
-  // capture fetch_enable_i in fetch_enable_q, once for ever
-  logic fetch_enable_q;
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      fetch_enable_q <= 1'b0;
-    end else if (fetch_enable_i) begin
-      fetch_enable_q <= 1'b1;
-    end
-  end
-
-  assign clock_en     = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i);
-  assign core_sleep_o = ~clock_en;
-
-  // main clock gate of the core
-  // generates all clocks except the one for the debug unit which is
-  // independent
-  prim_clock_gating core_clock_gate_i (
-      .clk_i     ( clk_i           ),
-      .en_i      ( clock_en        ),
-      .test_en_i ( test_en_i       ),
-      .clk_o     ( clk             )
-  );
+  assign core_busy_o = ctrl_busy | if_busy | lsu_busy;
 
   //////////////
   // IF stage //
@@ -406,13 +390,15 @@
       .DummyInstructions ( DummyInstructions ),
       .ICache            ( ICache            ),
       .ICacheECC         ( ICacheECC         ),
+      .BusSizeECC        ( BusSizeECC        ),
+      .TagSizeECC        ( TagSizeECC        ),
+      .LineSizeECC       ( LineSizeECC       ),
       .PCIncrCheck       ( PCIncrCheck       ),
       .BranchPredictor   ( BranchPredictor   )
   ) if_stage_i (
-      .clk_i                    ( clk                    ),
+      .clk_i                    ( clk_i                  ),
       .rst_ni                   ( rst_ni                 ),
 
-      .ram_cfg_i                ( ram_cfg_i              ),
       .boot_addr_i              ( boot_addr_i            ),
       .req_i                    ( instr_req_int          ), // instruction request control
 
@@ -425,6 +411,17 @@
       .instr_err_i              ( instr_err_i            ),
       .instr_pmp_err_i          ( pmp_req_err[PMP_I]     ),
 
+      .ic_tag_req_o             ( ic_tag_req_o           ),
+      .ic_tag_write_o           ( ic_tag_write_o         ),
+      .ic_tag_addr_o            ( ic_tag_addr_o          ),
+      .ic_tag_wdata_o           ( ic_tag_wdata_o         ),
+      .ic_tag_rdata_i           ( ic_tag_rdata_i         ),
+      .ic_data_req_o            ( ic_data_req_o          ),
+      .ic_data_write_o          ( ic_data_write_o        ),
+      .ic_data_addr_o           ( ic_data_addr_o         ),
+      .ic_data_wdata_o          ( ic_data_wdata_o        ),
+      .ic_data_rdata_i          ( ic_data_rdata_i        ),
+
       // outputs to ID stage
       .instr_valid_id_o         ( instr_valid_id         ),
       .instr_new_id_o           ( instr_new_id           ),
@@ -492,7 +489,7 @@
       .WritebackStage  ( WritebackStage  ),
       .BranchPredictor ( BranchPredictor )
   ) id_stage_i (
-      .clk_i                        ( clk                      ),
+      .clk_i                        ( clk_i                    ),
       .rst_ni                       ( rst_ni                   ),
 
       // Processor Enable
@@ -586,7 +583,7 @@
 
       // Interrupt Signals
       .csr_mstatus_mie_i            ( csr_mstatus_mie          ),
-      .irq_pending_i                ( irq_pending              ),
+      .irq_pending_i                ( irq_pending_o            ),
       .irqs_i                       ( irqs                     ),
       .irq_nm_i                     ( irq_nm_i                 ),
       .nmi_mode_o                   ( nmi_mode                 ),
@@ -646,7 +643,7 @@
       .RV32B                    ( RV32B                    ),
       .BranchTargetALU          ( BranchTargetALU          )
   ) ex_block_i (
-      .clk_i                    ( clk                      ),
+      .clk_i                    ( clk_i                    ),
       .rst_ni                   ( rst_ni                   ),
 
       // ALU signal from ID stage
@@ -694,7 +691,7 @@
   assign lsu_resp_err = lsu_load_err | lsu_store_err;
 
   ibex_load_store_unit load_store_unit_i (
-      .clk_i                 ( clk                 ),
+      .clk_i                 ( clk_i               ),
       .rst_ni                ( rst_ni              ),
 
       // data interface
@@ -742,7 +739,7 @@
   ibex_wb_stage #(
     .WritebackStage ( WritebackStage )
   ) wb_stage_i (
-    .clk_i                          ( clk                          ),
+    .clk_i                          ( clk_i                        ),
     .rst_ni                         ( rst_ni                       ),
     .en_wb_i                        ( en_wb                        ),
     .instr_type_wb_i                ( instr_type_wb                ),
@@ -777,14 +774,15 @@
     .instr_done_wb_o                ( instr_done_wb                )
   );
 
-  ///////////////////////
-  // Register file ECC //
-  ///////////////////////
+  /////////////////////////////
+  // Register file interface //
+  /////////////////////////////
 
-  logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
-  logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
-  logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
-  logic                        rf_ecc_err_comb;
+  assign dummy_instr_id_o = dummy_instr_id;
+  assign rf_raddr_a_o     = rf_raddr_a;
+  assign rf_waddr_wb_o    = rf_waddr_wb;
+  assign rf_we_wb_o       = rf_we_wb;
+  assign rf_raddr_b_o     = rf_raddr_b;
 
   if (RegFileECC) begin : gen_regfile_ecc
 
@@ -794,26 +792,26 @@
     // ECC checkbit generation for regiter file wdata
     prim_secded_39_32_enc regfile_ecc_enc (
       .in  (rf_wdata_wb),
-      .out (rf_wdata_wb_ecc)
+      .out (rf_wdata_wb_ecc_o)
     );
 
     // ECC checking on register file rdata
     prim_secded_39_32_dec regfile_ecc_dec_a (
-      .in         (rf_rdata_a_ecc),
+      .in         (rf_rdata_a_ecc_i),
       .d_o        (),
       .syndrome_o (),
       .err_o      (rf_ecc_err_a)
     );
     prim_secded_39_32_dec regfile_ecc_dec_b (
-      .in         (rf_rdata_b_ecc),
+      .in         (rf_rdata_b_ecc_i),
       .d_o        (),
       .syndrome_o (),
       .err_o      (rf_ecc_err_b)
     );
 
     // Assign read outputs - no error correction, just trigger an alert
-    assign rf_rdata_a = rf_rdata_a_ecc[31:0];
-    assign rf_rdata_b = rf_rdata_b_ecc[31:0];
+    assign rf_rdata_a = rf_rdata_a_ecc_i[31:0];
+    assign rf_rdata_b = rf_rdata_b_ecc_i[31:0];
 
     // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal
     assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match;
@@ -830,73 +828,12 @@
     assign unused_rf_ren_b         = rf_ren_b;
     assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match;
     assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match;
-    assign rf_wdata_wb_ecc         = rf_wdata_wb;
-    assign rf_rdata_a              = rf_rdata_a_ecc;
-    assign rf_rdata_b              = rf_rdata_b_ecc;
+    assign rf_wdata_wb_ecc_o       = rf_wdata_wb;
+    assign rf_rdata_a              = rf_rdata_a_ecc_i;
+    assign rf_rdata_b              = rf_rdata_b_ecc_i;
     assign rf_ecc_err_comb         = 1'b0;
   end
 
-  if (RegFile == RegFileFF) begin : gen_regfile_ff
-    ibex_register_file_ff #(
-        .RV32E             ( RV32E             ),
-        .DataWidth         ( RegFileDataWidth  ),
-        .DummyInstructions ( DummyInstructions )
-    ) register_file_i (
-        .clk_i            ( clk_i           ),
-        .rst_ni           ( rst_ni          ),
-
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
-
-        .raddr_a_i        ( rf_raddr_a      ),
-        .rdata_a_o        ( rf_rdata_a_ecc  ),
-        .raddr_b_i        ( rf_raddr_b      ),
-        .rdata_b_o        ( rf_rdata_b_ecc  ),
-        .waddr_a_i        ( rf_waddr_wb     ),
-        .wdata_a_i        ( rf_wdata_wb_ecc ),
-        .we_a_i           ( rf_we_wb        )
-    );
-  end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
-    ibex_register_file_fpga #(
-        .RV32E             ( RV32E             ),
-        .DataWidth         ( RegFileDataWidth  ),
-        .DummyInstructions ( DummyInstructions )
-    ) register_file_i (
-        .clk_i            ( clk_i           ),
-        .rst_ni           ( rst_ni          ),
-
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
-
-        .raddr_a_i        ( rf_raddr_a      ),
-        .rdata_a_o        ( rf_rdata_a_ecc  ),
-        .raddr_b_i        ( rf_raddr_b      ),
-        .rdata_b_o        ( rf_rdata_b_ecc  ),
-        .waddr_a_i        ( rf_waddr_wb     ),
-        .wdata_a_i        ( rf_wdata_wb_ecc ),
-        .we_a_i           ( rf_we_wb        )
-    );
-  end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
-    ibex_register_file_latch #(
-        .RV32E             ( RV32E             ),
-        .DataWidth         ( RegFileDataWidth  ),
-        .DummyInstructions ( DummyInstructions )
-    ) register_file_i (
-        .clk_i            ( clk_i           ),
-        .rst_ni           ( rst_ni          ),
-
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
-
-        .raddr_a_i        ( rf_raddr_a      ),
-        .rdata_a_o        ( rf_rdata_a_ecc  ),
-        .raddr_b_i        ( rf_raddr_b      ),
-        .rdata_b_o        ( rf_rdata_b_ecc  ),
-        .waddr_a_i        ( rf_waddr_wb     ),
-        .wdata_a_i        ( rf_wdata_wb_ecc ),
-        .we_a_i           ( rf_we_wb        )
-    );
-  end
 
   ///////////////////////
   // Crash dump output //
@@ -918,9 +855,6 @@
   // Major alert - core is unrecoverable
   assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err;
 
-  `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o)
-  `ASSERT_KNOWN(IbexAlertMajorX, alert_major_o)
-
   // Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included
   `ifdef INC_ASSERT
   // Signals used for assertions only
@@ -993,7 +927,7 @@
       .RV32M             ( RV32M             ),
       .RV32B             ( RV32B             )
   ) cs_registers_i (
-      .clk_i                   ( clk                          ),
+      .clk_i                   ( clk_i                        ),
       .rst_ni                  ( rst_ni                       ),
 
       // Hart ID from outside
@@ -1021,7 +955,7 @@
       .irq_external_i          ( irq_external_i               ),
       .irq_fast_i              ( irq_fast_i                   ),
       .nmi_mode_i              ( nmi_mode                     ),
-      .irq_pending_o           ( irq_pending                  ),
+      .irq_pending_o           ( irq_pending_o                ),
       .irqs_o                  ( irqs                         ),
       .csr_mstatus_mie_o       ( csr_mstatus_mie              ),
       .csr_mstatus_tw_o        ( csr_mstatus_tw               ),
@@ -1104,7 +1038,7 @@
         .PMPNumChan            ( PMP_NUM_CHAN    ),
         .PMPNumRegions         ( PMPNumRegions   )
     ) pmp_i (
-        .clk_i                 ( clk             ),
+        .clk_i                 ( clk_i           ),
         .rst_ni                ( rst_ni          ),
         // Interface to CSRs
         .csr_pmp_cfg_i         ( csr_pmp_cfg     ),
@@ -1212,7 +1146,7 @@
 
     assign rvfi_instr_new_wb = rvfi_instr_new_wb_q;
 
-    always_ff @(posedge clk or negedge rst_ni) begin
+    always_ff @(posedge clk_i or negedge rst_ni) begin
       if (~rst_ni) begin
         rvfi_instr_new_wb_q <= 0;
       end else begin
@@ -1229,7 +1163,7 @@
   end
 
   for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
-    always_ff @(posedge clk or negedge rst_ni) begin
+    always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
         rvfi_stage_halt[i]      <= '0;
         rvfi_stage_trap[i]      <= '0;
@@ -1338,7 +1272,7 @@
     end
   end
 
-  always_ff @(posedge clk or negedge rst_ni) begin
+  always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       rvfi_mem_addr_q  <= '0;
       rvfi_mem_rdata_q <= '0;
@@ -1386,7 +1320,7 @@
       rvfi_rs3_addr_d = rf_raddr_a;
     end
   end
-  always_ff @(posedge clk or negedge rst_ni) begin
+  always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       rvfi_rs1_data_q <= '0;
       rvfi_rs1_addr_q <= '0;
@@ -1425,7 +1359,7 @@
 
   // RD write register is refreshed only once per cycle and
   // then it is kept stable for the cycle.
-  always_ff @(posedge clk or negedge rst_ni) begin
+  always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       rvfi_rd_addr_q    <= '0;
       rvfi_rd_wdata_q   <= '0;
@@ -1453,7 +1387,7 @@
     end
   end
 
-  always_ff @(posedge clk or negedge rst_ni) begin
+  always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       rvfi_set_trap_pc_q <= 1'b0;
       rvfi_intr_q        <= 1'b0;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
index 591e3b0..77f1de2 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
@@ -10,194 +10,187 @@
 
 `include "prim_assert.sv"
 
-module ibex_icache #(
+module ibex_icache import ibex_pkg::*; #(
   parameter bit          BranchPredictor = 1'b0,
-  // Cache arrangement parameters
-  parameter int unsigned BusWidth        = 32,
-  parameter int unsigned CacheSizeBytes  = 4*1024,
   parameter bit          ICacheECC       = 1'b0,
-  parameter int unsigned LineSize        = 64,
-  parameter int unsigned NumWays         = 2,
+  parameter int unsigned BusSizeECC      = BUS_SIZE,
+  parameter int unsigned TagSizeECC      = IC_TAG_SIZE,
+  parameter int unsigned LineSizeECC     = IC_LINE_SIZE,
   // Only cache branch targets
   parameter bit          BranchCache     = 1'b0
 ) (
     // Clock and reset
-    input  logic                         clk_i,
-    input  logic                         rst_ni,
+    input  logic                           clk_i,
+    input  logic                           rst_ni,
 
     // Signal that the core would like instructions
-    input  logic                         req_i,
+    input  logic                           req_i,
 
     // Set the cache's address counter
-    input  logic                         branch_i,
-    input  logic                         branch_spec_i,
-    input  logic                         predicted_branch_i,
-    input  logic                         branch_mispredict_i,
-    input  logic [31:0]                  addr_i,
+    input  logic                           branch_i,
+    input  logic                           branch_spec_i,
+    input  logic                           predicted_branch_i,
+    input  logic                           branch_mispredict_i,
+    input  logic [31:0]                    addr_i,
 
     // IF stage interface: Pass fetched instructions to the core
-    input  logic                         ready_i,
-    output logic                         valid_o,
-    output logic [31:0]                  rdata_o,
-    output logic [31:0]                  addr_o,
-    output logic                         err_o,
-    output logic                         err_plus2_o,
+    input  logic                           ready_i,
+    output logic                           valid_o,
+    output logic [31:0]                    rdata_o,
+    output logic [31:0]                    addr_o,
+    output logic                           err_o,
+    output logic                           err_plus2_o,
 
     // Instruction memory / interconnect interface: Fetch instruction data from memory
-    output logic                         instr_req_o,
-    input  logic                         instr_gnt_i,
-    output logic [31:0]                  instr_addr_o,
-    input  logic [BusWidth-1:0]          instr_rdata_i,
-    input  logic                         instr_err_i,
-    input  logic                         instr_pmp_err_i,
-    input  logic                         instr_rvalid_i,
+    output logic                           instr_req_o,
+    input  logic                           instr_gnt_i,
+    output logic [31:0]                    instr_addr_o,
+    input  logic [BUS_SIZE-1:0]            instr_rdata_i,
+    input  logic                           instr_err_i,
+    input  logic                           instr_pmp_err_i,
+    input  logic                           instr_rvalid_i,
+
+    // RAM IO
+    output logic [IC_NUM_WAYS-1:0]         ic_tag_req_o,
+    output logic                           ic_tag_write_o,
+    output logic [IC_INDEX_W-1:0]          ic_tag_addr_o,
+    output logic [TagSizeECC-1:0]          ic_tag_wdata_o,
+    input  logic [TagSizeECC-1:0]          ic_tag_rdata_i [IC_NUM_WAYS],
+    output logic [IC_NUM_WAYS-1:0]         ic_data_req_o,
+    output logic                           ic_data_write_o,
+    output logic [IC_INDEX_W-1:0]          ic_data_addr_o,
+    output logic [LineSizeECC-1:0]         ic_data_wdata_o,
+    input  logic [LineSizeECC-1:0]         ic_data_rdata_i [IC_NUM_WAYS],
 
     // Cache status
-    input  prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
-    input  logic                         icache_enable_i,
-    input  logic                         icache_inval_i,
-    output logic                         busy_o
+    input  logic                           icache_enable_i,
+    input  logic                           icache_inval_i,
+    output logic                           busy_o
 );
-  // Local constants
-  localparam int unsigned ADDR_W       = 32;
+
   // Number of fill buffers (must be >= 2)
-  localparam int unsigned NUM_FB       = 4;
+  localparam int unsigned NUM_FB        = 4;
   // Request throttling threshold
-  localparam int unsigned FB_THRESHOLD = NUM_FB - 2;
-  // Derived parameters
-  localparam int unsigned LINE_SIZE_BYTES = LineSize/8;
-  localparam int unsigned LINE_W          = $clog2(LINE_SIZE_BYTES);
-  localparam int unsigned BUS_SIZE_ECC    = ICacheECC ? (BusWidth + 7) : BusWidth;
-  localparam int unsigned BUS_BYTES       = BusWidth/8;
-  localparam int unsigned BUS_W           = $clog2(BUS_BYTES);
-  localparam int unsigned LINE_BEATS      = LINE_SIZE_BYTES / BUS_BYTES;
-  localparam int unsigned LINE_BEATS_W    = $clog2(LINE_BEATS);
-  localparam int unsigned NUM_LINES       = CacheSizeBytes / NumWays / LINE_SIZE_BYTES;
-  localparam int unsigned LINE_SIZE_ECC   = BUS_SIZE_ECC * LINE_BEATS;
-  localparam int unsigned INDEX_W         = $clog2(NUM_LINES);
-  localparam int unsigned INDEX_HI        = INDEX_W + LINE_W - 1;
-  localparam int unsigned TAG_SIZE        = ADDR_W - INDEX_W - LINE_W + 1; // 1 valid bit
-  localparam int unsigned TAG_SIZE_ECC    = ICacheECC ? (TAG_SIZE + 6) : TAG_SIZE;
-  localparam int unsigned OUTPUT_BEATS    = (BUS_BYTES / 2); // number of halfwords
+  localparam int unsigned FB_THRESHOLD  = NUM_FB - 2;
 
   // Prefetch signals
-  logic [ADDR_W-1:0]                   lookup_addr_aligned;
-  logic [ADDR_W-1:0]                   branch_mispredict_addr;
-  logic [ADDR_W-1:0]                   prefetch_addr_d, prefetch_addr_q;
-  logic                                prefetch_addr_en;
-  logic                                branch_or_mispredict;
+  logic [ADDR_W-1:0]                      lookup_addr_aligned;
+  logic [ADDR_W-1:0]                      branch_mispredict_addr;
+  logic [ADDR_W-1:0]                      prefetch_addr_d, prefetch_addr_q;
+  logic                                   prefetch_addr_en;
+  logic                                   branch_or_mispredict;
   // Cache pipelipe IC0 signals
-  logic                                branch_suppress;
-  logic                                lookup_throttle;
-  logic                                lookup_req_ic0;
-  logic [ADDR_W-1:0]                   lookup_addr_ic0;
-  logic [INDEX_W-1:0]                  lookup_index_ic0;
-  logic                                fill_req_ic0;
-  logic [INDEX_W-1:0]                  fill_index_ic0;
-  logic [TAG_SIZE-1:0]                 fill_tag_ic0;
-  logic [LineSize-1:0]                 fill_wdata_ic0;
-  logic                                lookup_grant_ic0;
-  logic                                lookup_actual_ic0;
-  logic                                fill_grant_ic0;
-  logic                                tag_req_ic0;
-  logic [INDEX_W-1:0]                  tag_index_ic0;
-  logic [NumWays-1:0]                  tag_banks_ic0;
-  logic                                tag_write_ic0;
-  logic [TAG_SIZE_ECC-1:0]             tag_wdata_ic0;
-  logic                                data_req_ic0;
-  logic [INDEX_W-1:0]                  data_index_ic0;
-  logic [NumWays-1:0]                  data_banks_ic0;
-  logic                                data_write_ic0;
-  logic [LINE_SIZE_ECC-1:0]            data_wdata_ic0;
+  logic                                   branch_suppress;
+  logic                                   lookup_throttle;
+  logic                                   lookup_req_ic0;
+  logic [ADDR_W-1:0]                      lookup_addr_ic0;
+  logic [IC_INDEX_W-1:0]                  lookup_index_ic0;
+  logic                                   fill_req_ic0;
+  logic [IC_INDEX_W-1:0]                  fill_index_ic0;
+  logic [IC_TAG_SIZE-1:0]                 fill_tag_ic0;
+  logic [IC_LINE_SIZE-1:0]                fill_wdata_ic0;
+  logic                                   lookup_grant_ic0;
+  logic                                   lookup_actual_ic0;
+  logic                                   fill_grant_ic0;
+  logic                                   tag_req_ic0;
+  logic [IC_INDEX_W-1:0]                  tag_index_ic0;
+  logic [IC_NUM_WAYS-1:0]                 tag_banks_ic0;
+  logic                                   tag_write_ic0;
+  logic [TagSizeECC-1:0]                  tag_wdata_ic0;
+  logic                                   data_req_ic0;
+  logic [IC_INDEX_W-1:0]                  data_index_ic0;
+  logic [IC_NUM_WAYS-1:0]                 data_banks_ic0;
+  logic                                   data_write_ic0;
+  logic [LineSizeECC-1:0]                 data_wdata_ic0;
   // Cache pipelipe IC1 signals
-  logic [TAG_SIZE_ECC-1:0]             tag_rdata_ic1  [NumWays];
-  logic [LINE_SIZE_ECC-1:0]            data_rdata_ic1 [NumWays];
-  logic [LINE_SIZE_ECC-1:0]            hit_data_ecc_ic1;
-  logic [LineSize-1:0]                 hit_data_ic1;
-  logic                                lookup_valid_ic1;
-  logic [ADDR_W-1:INDEX_HI+1]          lookup_addr_ic1;
-  logic [NumWays-1:0]                  tag_match_ic1;
-  logic                                tag_hit_ic1;
-  logic [NumWays-1:0]                  tag_invalid_ic1;
-  logic [NumWays-1:0]                  lowest_invalid_way_ic1;
-  logic [NumWays-1:0]                  round_robin_way_ic1, round_robin_way_q;
-  logic [NumWays-1:0]                  sel_way_ic1;
-  logic                                ecc_err_ic1;
-  logic                                ecc_write_req;
-  logic [NumWays-1:0]                  ecc_write_ways;
-  logic [INDEX_W-1:0]                  ecc_write_index;
+  logic [TagSizeECC-1:0]                  tag_rdata_ic1  [IC_NUM_WAYS];
+  logic [LineSizeECC-1:0]                 data_rdata_ic1 [IC_NUM_WAYS];
+  logic [LineSizeECC-1:0]                 hit_data_ecc_ic1;
+  logic [IC_LINE_SIZE-1:0]                hit_data_ic1;
+  logic                                   lookup_valid_ic1;
+  logic [ADDR_W-1:IC_INDEX_HI+1]          lookup_addr_ic1;
+  logic [IC_NUM_WAYS-1:0]                 tag_match_ic1;
+  logic                                   tag_hit_ic1;
+  logic [IC_NUM_WAYS-1:0]                 tag_invalid_ic1;
+  logic [IC_NUM_WAYS-1:0]                 lowest_invalid_way_ic1;
+  logic [IC_NUM_WAYS-1:0]                 round_robin_way_ic1, round_robin_way_q;
+  logic [IC_NUM_WAYS-1:0]                 sel_way_ic1;
+  logic                                   ecc_err_ic1;
+  logic                                   ecc_write_req;
+  logic [IC_NUM_WAYS-1:0]                 ecc_write_ways;
+  logic [IC_INDEX_W-1:0]                  ecc_write_index;
   // Fill buffer signals
-  logic                                gnt_or_pmp_err, gnt_not_pmp_err;
-  logic [$clog2(NUM_FB)-1:0]           fb_fill_level;
-  logic                                fill_cache_new;
-  logic                                fill_new_alloc;
-  logic                                fill_spec_req, fill_spec_done, fill_spec_hold;
-  logic [NUM_FB-1:0][NUM_FB-1:0]       fill_older_d, fill_older_q;
-  logic [NUM_FB-1:0]                   fill_alloc_sel, fill_alloc;
-  logic [NUM_FB-1:0]                   fill_busy_d, fill_busy_q;
-  logic [NUM_FB-1:0]                   fill_done;
-  logic [NUM_FB-1:0]                   fill_in_ic1;
-  logic [NUM_FB-1:0]                   fill_stale_d, fill_stale_q;
-  logic [NUM_FB-1:0]                   fill_cache_d, fill_cache_q;
-  logic [NUM_FB-1:0]                   fill_hit_ic1, fill_hit_d, fill_hit_q;
-  logic [NUM_FB-1:0][LINE_BEATS_W:0]   fill_ext_cnt_d, fill_ext_cnt_q;
-  logic [NUM_FB-1:0]                   fill_ext_hold_d, fill_ext_hold_q;
-  logic [NUM_FB-1:0]                   fill_ext_done_d, fill_ext_done_q;
-  logic [NUM_FB-1:0][LINE_BEATS_W:0]   fill_rvd_cnt_d, fill_rvd_cnt_q;
-  logic [NUM_FB-1:0]                   fill_rvd_done;
-  logic [NUM_FB-1:0]                   fill_ram_done_d, fill_ram_done_q;
-  logic [NUM_FB-1:0]                   fill_out_grant;
-  logic [NUM_FB-1:0][LINE_BEATS_W:0]   fill_out_cnt_d, fill_out_cnt_q;
-  logic [NUM_FB-1:0]                   fill_out_done;
-  logic [NUM_FB-1:0]                   fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req;
-  logic [NUM_FB-1:0]                   fill_data_sel, fill_data_reg, fill_data_hit, fill_data_rvd;
-  logic [NUM_FB-1:0][LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off;
-  logic [NUM_FB-1:0][LINE_BEATS_W:0]   fill_ext_beat, fill_rvd_beat;
-  logic [NUM_FB-1:0]                   fill_ext_arb, fill_ram_arb, fill_out_arb;
-  logic [NUM_FB-1:0]                   fill_rvd_arb;
-  logic [NUM_FB-1:0]                   fill_entry_en;
-  logic [NUM_FB-1:0]                   fill_addr_en;
-  logic [NUM_FB-1:0]                   fill_way_en;
-  logic [NUM_FB-1:0][LINE_BEATS-1:0]   fill_data_en;
-  logic [NUM_FB-1:0][LINE_BEATS-1:0]   fill_err_d, fill_err_q;
-  logic [ADDR_W-1:0]                   fill_addr_q [NUM_FB];
-  logic [NumWays-1:0]                  fill_way_q  [NUM_FB];
-  logic [LineSize-1:0]                 fill_data_d [NUM_FB];
-  logic [LineSize-1:0]                 fill_data_q [NUM_FB];
-  logic [ADDR_W-1:BUS_W]               fill_ext_req_addr;
-  logic [ADDR_W-1:0]                   fill_ram_req_addr;
-  logic [NumWays-1:0]                  fill_ram_req_way;
-  logic [LineSize-1:0]                 fill_ram_req_data;
-  logic [LineSize-1:0]                 fill_out_data;
-  logic [LINE_BEATS-1:0]               fill_out_err;
+  logic                                   gnt_or_pmp_err, gnt_not_pmp_err;
+  logic [$clog2(NUM_FB)-1:0]              fb_fill_level;
+  logic                                   fill_cache_new;
+  logic                                   fill_new_alloc;
+  logic                                   fill_spec_req, fill_spec_done, fill_spec_hold;
+  logic [NUM_FB-1:0][NUM_FB-1:0]          fill_older_d, fill_older_q;
+  logic [NUM_FB-1:0]                      fill_alloc_sel, fill_alloc;
+  logic [NUM_FB-1:0]                      fill_busy_d, fill_busy_q;
+  logic [NUM_FB-1:0]                      fill_done;
+  logic [NUM_FB-1:0]                      fill_in_ic1;
+  logic [NUM_FB-1:0]                      fill_stale_d, fill_stale_q;
+  logic [NUM_FB-1:0]                      fill_cache_d, fill_cache_q;
+  logic [NUM_FB-1:0]                      fill_hit_ic1, fill_hit_d, fill_hit_q;
+  logic [NUM_FB-1:0][IC_LINE_BEATS_W:0]   fill_ext_cnt_d, fill_ext_cnt_q;
+  logic [NUM_FB-1:0]                      fill_ext_hold_d, fill_ext_hold_q;
+  logic [NUM_FB-1:0]                      fill_ext_done_d, fill_ext_done_q;
+  logic [NUM_FB-1:0][IC_LINE_BEATS_W:0]   fill_rvd_cnt_d, fill_rvd_cnt_q;
+  logic [NUM_FB-1:0]                      fill_rvd_done;
+  logic [NUM_FB-1:0]                      fill_ram_done_d, fill_ram_done_q;
+  logic [NUM_FB-1:0]                      fill_out_grant;
+  logic [NUM_FB-1:0][IC_LINE_BEATS_W:0]   fill_out_cnt_d, fill_out_cnt_q;
+  logic [NUM_FB-1:0]                      fill_out_done;
+  logic [NUM_FB-1:0]                      fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req;
+  logic [NUM_FB-1:0]                      fill_data_sel, fill_data_reg, fill_data_hit, fill_data_rvd;
+  logic [NUM_FB-1:0][IC_LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off;
+  logic [NUM_FB-1:0][IC_LINE_BEATS_W:0]   fill_ext_beat, fill_rvd_beat;
+  logic [NUM_FB-1:0]                      fill_ext_arb, fill_ram_arb, fill_out_arb;
+  logic [NUM_FB-1:0]                      fill_rvd_arb;
+  logic [NUM_FB-1:0]                      fill_entry_en;
+  logic [NUM_FB-1:0]                      fill_addr_en;
+  logic [NUM_FB-1:0]                      fill_way_en;
+  logic [NUM_FB-1:0][IC_LINE_BEATS-1:0]   fill_data_en;
+  logic [NUM_FB-1:0][IC_LINE_BEATS-1:0]   fill_err_d, fill_err_q;
+  logic [ADDR_W-1:0]                      fill_addr_q [NUM_FB];
+  logic [IC_NUM_WAYS-1:0]                 fill_way_q  [NUM_FB];
+  logic [IC_LINE_SIZE-1:0]                fill_data_d [NUM_FB];
+  logic [IC_LINE_SIZE-1:0]                fill_data_q [NUM_FB];
+  logic [ADDR_W-1:BUS_W]                  fill_ext_req_addr;
+  logic [ADDR_W-1:0]                      fill_ram_req_addr;
+  logic [IC_NUM_WAYS-1:0]                 fill_ram_req_way;
+  logic [IC_LINE_SIZE-1:0]                fill_ram_req_data;
+  logic [IC_LINE_SIZE-1:0]                fill_out_data;
+  logic [IC_LINE_BEATS-1:0]               fill_out_err;
   // External req signals
-  logic                                instr_req;
-  logic [ADDR_W-1:BUS_W]               instr_addr;
+  logic                                   instr_req;
+  logic [ADDR_W-1:BUS_W]                  instr_addr;
   // Data output signals
-  logic                                skid_complete_instr;
-  logic                                skid_ready;
-  logic                                output_compressed;
-  logic                                skid_valid_d, skid_valid_q, skid_en;
-  logic [15:0]                         skid_data_d, skid_data_q;
-  logic                                skid_err_q;
-  logic                                output_valid;
-  logic                                addr_incr_two;
-  logic                                output_addr_en;
-  logic [ADDR_W-1:1]                   output_addr_incr;
-  logic [ADDR_W-1:1]                   output_addr_d, output_addr_q;
-  logic [15:0]                         output_data_lo, output_data_hi;
-  logic                                data_valid, output_ready;
-  logic [LineSize-1:0]                 line_data;
-  logic [LINE_BEATS-1:0]               line_err;
-  logic [31:0]                         line_data_muxed;
-  logic                                line_err_muxed;
-  logic [31:0]                         output_data;
-  logic                                output_err;
+  logic                                   skid_complete_instr;
+  logic                                   skid_ready;
+  logic                                   output_compressed;
+  logic                                   skid_valid_d, skid_valid_q, skid_en;
+  logic [15:0]                            skid_data_d, skid_data_q;
+  logic                                   skid_err_q;
+  logic                                   output_valid;
+  logic                                   addr_incr_two;
+  logic                                   output_addr_en;
+  logic [ADDR_W-1:1]                      output_addr_incr;
+  logic [ADDR_W-1:1]                      output_addr_d, output_addr_q;
+  logic [15:0]                            output_data_lo, output_data_hi;
+  logic                                   data_valid, output_ready;
+  logic [IC_LINE_SIZE-1:0]                line_data;
+  logic [IC_LINE_BEATS-1:0]               line_err;
+  logic [31:0]                            line_data_muxed;
+  logic                                   line_err_muxed;
+  logic [31:0]                            output_data;
+  logic                                   output_err;
   // Invalidations
-  logic                                start_inval, inval_done;
-  logic                                reset_inval_q;
-  logic                                inval_prog_d, inval_prog_q;
-  logic [INDEX_W-1:0]                  inval_index_d, inval_index_q;
+  logic                                   start_inval, inval_done;
+  logic                                   reset_inval_q;
+  logic                                   inval_prog_d, inval_prog_q;
+  logic [IC_INDEX_W-1:0]                  inval_index_d, inval_index_q;
 
   //////////////////////////
   // Instruction prefetch //
@@ -230,7 +223,7 @@
 
   assign branch_or_mispredict = branch_i | branch_mispredict_i;
 
-  assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:LINE_W],{LINE_W{1'b0}}};
+  assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}};
 
   // The prefetch address increments by one cache line for each granted request.
   // This address is also updated if there is a branch that is not granted, since the target
@@ -239,7 +232,8 @@
   // The captured branch target address is not forced to be aligned since the offset in the cache
   // line must also be recorded for later use by the fill buffers.
   assign prefetch_addr_d     =
-      lookup_grant_ic0 ? (lookup_addr_aligned + {{ADDR_W-LINE_W-1{1'b0}},1'b1,{LINE_W{1'b0}}}) :
+      lookup_grant_ic0 ? (lookup_addr_aligned +
+                          {{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) :
       branch_i         ? addr_i :
                          branch_mispredict_addr;
 
@@ -263,12 +257,13 @@
   assign lookup_addr_ic0  = branch_spec_i       ? addr_i :
                             branch_mispredict_i ? branch_mispredict_addr :
                                                   prefetch_addr_q;
-  assign lookup_index_ic0 = lookup_addr_ic0[INDEX_HI:LINE_W];
+  assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W];
 
   // Cache write
   assign fill_req_ic0   = (|fill_ram_req);
-  assign fill_index_ic0 = fill_ram_req_addr[INDEX_HI:LINE_W];
-  assign fill_tag_ic0   = {(~inval_prog_q & ~ecc_write_req),fill_ram_req_addr[ADDR_W-1:INDEX_HI+1]};
+  assign fill_index_ic0 = fill_ram_req_addr[IC_INDEX_HI:IC_LINE_W];
+  assign fill_tag_ic0   = {(~inval_prog_q & ~ecc_write_req),
+                           fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]};
   assign fill_wdata_ic0 = fill_ram_req_data;
 
   // Suppress a new lookup on a not-taken branch (as the address will be incorrect)
@@ -289,7 +284,7 @@
                                           lookup_index_ic0;
   assign tag_banks_ic0 = ecc_write_req  ? ecc_write_ways :
                          fill_grant_ic0 ? fill_ram_req_way :
-                                          {NumWays{1'b1}};
+                                          {IC_NUM_WAYS{1'b1}};
   assign tag_write_ic0 = fill_grant_ic0 | inval_prog_q | ecc_write_req;
 
   // Dataram
@@ -303,25 +298,25 @@
 
     // Tagram ECC
     // Reuse the same ecc encoding module for larger cache sizes by padding with zeros
-    logic [21:0]          tag_ecc_input_padded;
-    logic [27:0]          tag_ecc_output_padded;
-    logic [22-TAG_SIZE:0] tag_ecc_output_unused;
+    logic [21:0]             tag_ecc_input_padded;
+    logic [27:0]             tag_ecc_output_padded;
+    logic [22-IC_TAG_SIZE:0] tag_ecc_output_unused;
 
-    assign tag_ecc_input_padded  = {{22-TAG_SIZE{1'b0}},fill_tag_ic0};
-    assign tag_ecc_output_unused = tag_ecc_output_padded[21:TAG_SIZE-1];
+    assign tag_ecc_input_padded  = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0};
+    assign tag_ecc_output_unused = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
 
     prim_secded_28_22_enc tag_ecc_enc (
       .in  (tag_ecc_input_padded),
       .out (tag_ecc_output_padded)
     );
 
-    assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[TAG_SIZE-1:0]};
+    assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]};
 
     // Dataram ECC
-    for (genvar bank = 0; bank < LINE_BEATS; bank ++) begin : gen_ecc_banks
+    for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
       prim_secded_39_32_enc data_ecc_enc (
-        .in  (fill_wdata_ic0[bank*BusWidth+:BusWidth]),
-        .out (data_wdata_ic0[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC])
+        .in  (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
+        .out (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
       );
     end
 
@@ -334,38 +329,23 @@
   // IC0 -> IC1 //
   ////////////////
 
-  for (genvar way = 0; way < NumWays; way++) begin : gen_rams
-    // Tag RAM instantiation
-    prim_ram_1p #(
-      .Width           (TAG_SIZE_ECC),
-      .Depth           (NUM_LINES),
-      .DataBitsPerMask (TAG_SIZE_ECC)
-    ) tag_bank (
-      .clk_i    (clk_i),
-      .req_i    (tag_req_ic0 & tag_banks_ic0[way]),
-      .cfg_i    (ram_cfg_i),
-      .write_i  (tag_write_ic0),
-      .wmask_i  ({TAG_SIZE_ECC{1'b1}}),
-      .addr_i   (tag_index_ic0),
-      .wdata_i  (tag_wdata_ic0),
-      .rdata_o  (tag_rdata_ic1[way])
-    );
-    // Data RAM instantiation
-    prim_ram_1p #(
-      .Width           (LINE_SIZE_ECC),
-      .Depth           (NUM_LINES),
-      .DataBitsPerMask (LINE_SIZE_ECC)
-    ) data_bank (
-      .clk_i    (clk_i),
-      .req_i    (data_req_ic0 & data_banks_ic0[way]),
-      .cfg_i    (ram_cfg_i),
-      .write_i  (data_write_ic0),
-      .wmask_i  ({LINE_SIZE_ECC{1'b1}}),
-      .addr_i   (data_index_ic0),
-      .wdata_i  (data_wdata_ic0),
-      .rdata_o  (data_rdata_ic1[way])
-    );
-  end
+  // Tag RAMs outputs
+  assign ic_tag_req_o    = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0;
+  assign ic_tag_write_o  = tag_write_ic0;
+  assign ic_tag_addr_o   = tag_index_ic0;
+  assign ic_tag_wdata_o  = tag_wdata_ic0;
+
+  // Tag RAMs inputs
+  assign tag_rdata_ic1   = ic_tag_rdata_i;
+
+  // Data RAMs outputs
+  assign ic_data_req_o   = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0;
+  assign ic_data_write_o = data_write_ic0;
+  assign ic_data_addr_o  = data_index_ic0;
+  assign ic_data_wdata_o = data_wdata_ic0;
+
+  // Data RAMs inputs
+  assign data_rdata_ic1  = ic_data_rdata_i;
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
@@ -377,7 +357,7 @@
 
   always_ff @(posedge clk_i) begin
     if (lookup_grant_ic0) begin
-      lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:INDEX_HI+1];
+      lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1];
       fill_in_ic1     <= fill_alloc_sel;
     end
   end
@@ -387,10 +367,10 @@
   ////////////////////////
 
   // Tag matching
-  for (genvar way = 0; way < NumWays; way++) begin : gen_tag_match
-    assign tag_match_ic1[way]   = (tag_rdata_ic1[way][TAG_SIZE-1:0] ==
-                                   {1'b1,lookup_addr_ic1[ADDR_W-1:INDEX_HI+1]});
-    assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][TAG_SIZE-1];
+  for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_match
+    assign tag_match_ic1[way]   = (tag_rdata_ic1[way][IC_TAG_SIZE-1:0] ==
+                                   {1'b1,lookup_addr_ic1[ADDR_W-1:IC_INDEX_HI+1]});
+    assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][IC_TAG_SIZE-1];
   end
 
   assign tag_hit_ic1 = |tag_match_ic1;
@@ -398,7 +378,7 @@
   // Hit data mux
   always_comb begin
     hit_data_ecc_ic1 = 'b0;
-    for (int way = 0; way < NumWays; way++) begin
+    for (int way = 0; way < IC_NUM_WAYS; way++) begin
       if (tag_match_ic1[way]) begin
         hit_data_ecc_ic1 |= data_rdata_ic1[way];
       end
@@ -409,15 +389,15 @@
   // 1 first invalid way
   // 2 global round-robin (pseudorandom) way
   assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0];
-  assign round_robin_way_ic1[0]    = round_robin_way_q[NumWays-1];
-  for (genvar way = 1; way < NumWays; way++) begin : gen_lowest_way
+  assign round_robin_way_ic1[0]    = round_robin_way_q[IC_NUM_WAYS-1];
+  for (genvar way = 1; way < IC_NUM_WAYS; way++) begin : gen_lowest_way
     assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way-1:0];
     assign round_robin_way_ic1[way]    = round_robin_way_q[way-1];
   end
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
-      round_robin_way_q <= {{NumWays-1{1'b0}},1'b1};
+      round_robin_way_q <= {{IC_NUM_WAYS-1{1'b0}}, 1'b1};
     end else if (lookup_valid_ic1) begin
       round_robin_way_q <= round_robin_way_ic1;
     end
@@ -428,21 +408,21 @@
 
   // ECC checking logic
   if (ICacheECC) begin : gen_data_ecc_checking
-    logic [NumWays-1:0]      tag_err_ic1;
-    logic [LINE_BEATS*2-1:0] data_err_ic1;
-    logic                    ecc_correction_write_d, ecc_correction_write_q;
-    logic [NumWays-1:0]      ecc_correction_ways_d, ecc_correction_ways_q;
-    logic [INDEX_W-1:0]      lookup_index_ic1, ecc_correction_index_q;
+    logic [IC_NUM_WAYS-1:0]     tag_err_ic1;
+    logic [IC_LINE_BEATS*2-1:0] data_err_ic1;
+    logic                       ecc_correction_write_d, ecc_correction_write_q;
+    logic [IC_NUM_WAYS-1:0]     ecc_correction_ways_d, ecc_correction_ways_q;
+    logic [IC_INDEX_W-1:0]      lookup_index_ic1, ecc_correction_index_q;
 
     // Tag ECC checking
-    for (genvar way = 0; way < NumWays; way++) begin : gen_tag_ecc
+    for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_ecc
       logic [1:0]  tag_err_bank_ic1;
       logic [27:0] tag_rdata_padded_ic1;
 
       // Expand the tag rdata with extra padding if the tag size is less than the maximum
-      assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TAG_SIZE_ECC-1-:6],
-                                     {22-TAG_SIZE{1'b0}},
-                                     tag_rdata_ic1[way][TAG_SIZE-1:0]};
+      assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6],
+                                     {22-IC_TAG_SIZE{1'b0}},
+                                     tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
 
       prim_secded_28_22_dec data_ecc_dec (
         .in         (tag_rdata_padded_ic1),
@@ -455,15 +435,16 @@
 
     // Data ECC checking
     // Note - could generate for all ways and mux after
-    for (genvar bank = 0; bank < LINE_BEATS; bank++) begin : gen_ecc_banks
+    for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
       prim_secded_39_32_dec data_ecc_dec (
-        .in         (hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC]),
+        .in         (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
         .d_o        (),
         .syndrome_o (),
         .err_o      (data_err_ic1[bank*2+:2])
       );
 
-      assign hit_data_ic1[bank*BusWidth+:BusWidth] = hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BusWidth];
+      assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] =
+          hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE];
 
     end
 
@@ -473,8 +454,8 @@
     // All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on
     // spurious hits. Also prevents the same line being allocated twice when there was a true
     // hit and a spurious hit.
-    assign ecc_correction_ways_d  = {NumWays{|tag_err_ic1}} |
-                                    (tag_match_ic1 & {NumWays{|data_err_ic1}});
+    assign ecc_correction_ways_d  = {IC_NUM_WAYS{|tag_err_ic1}} |
+                                    (tag_match_ic1 & {IC_NUM_WAYS{|data_err_ic1}});
     assign ecc_correction_write_d = ecc_err_ic1;
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -488,7 +469,7 @@
     // The index is required in IC1 only when ECC is configured so is registered here
     always_ff @(posedge clk_i) begin
       if (lookup_grant_ic0) begin
-        lookup_index_ic1 <= lookup_addr_ic0[INDEX_HI-:INDEX_W];
+        lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W];
       end
     end
 
@@ -620,17 +601,17 @@
     // Make an external request
     assign fill_ext_req[fb]    = fill_busy_q[fb] & ~fill_ext_done_d[fb];
 
-    // Count the number of completed external requests (each line requires LINE_BEATS requests)
+    // Count the number of completed external requests (each line requires IC_LINE_BEATS requests)
     // Don't count fake PMP error grants here since they will never receive an rvalid response
     assign fill_ext_cnt_d[fb]  = fill_alloc[fb] ?
-                                   {{LINE_BEATS_W{1'b0}},fill_spec_done} :
-                                   (fill_ext_cnt_q[fb] + {{LINE_BEATS_W{1'b0}},
+                                   {{IC_LINE_BEATS_W{1'b0}},fill_spec_done} :
+                                   (fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}},
                                                           fill_ext_arb[fb] & gnt_not_pmp_err});
     // External request must be held until granted
     assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) |
                                  (fill_ext_arb[fb] & ~gnt_or_pmp_err);
     // External requests are completed when the counter is filled or when the request is cancelled
-    assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][LINE_BEATS_W] |
+    assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] |
                                   // external requests are considered complete if the request hit
                                   fill_hit_ic1[fb] | fill_hit_q[fb] |
                                   // external requests will stop once any PMP error is received
@@ -638,7 +619,7 @@
                                   // cancel if the line won't be cached and, it is stale
                                   (~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] |
                                    // or we're already at the end of the line
-                                                        fill_ext_beat[fb][LINE_BEATS_W]))) &
+                                                        fill_ext_beat[fb][IC_LINE_BEATS_W]))) &
                                  // can't cancel while we are waiting for a grant on the bus
                                  ~fill_ext_hold_q[fb] & fill_busy_q[fb];
     // Track whether this fill buffer expects to receive beats of data
@@ -646,7 +627,7 @@
     // Count the number of rvalid beats received
     assign fill_rvd_cnt_d[fb]  = fill_alloc[fb] ? '0 :
                                                   (fill_rvd_cnt_q[fb] +
-                                                   {{LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]});
+                                                   {{IC_LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]});
     // External data is complete when all issued external requests have received their data
     assign fill_rvd_done[fb]   = (fill_ext_done_q[fb] & ~fill_ext_hold_q[fb]) &
                                  (fill_rvd_cnt_q[fb] == fill_ext_cnt_q[fb]);
@@ -664,25 +645,25 @@
     // - Data is available from the bus this cycle (fill_rvd_arb)
     assign fill_out_req[fb]    = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] &
                                  (fill_hit_ic1[fb] | fill_hit_q[fb] |
-                                  (fill_err_q[fb][fill_out_cnt_q[fb][LINE_BEATS_W-1:0]]) |
+                                  (fill_err_q[fb][fill_out_cnt_q[fb][IC_LINE_BEATS_W-1:0]]) |
                                   (fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]);
 
     // Calculate when a beat of data is output. Any ECC error squashes the output that cycle.
     assign fill_out_grant[fb]  = fill_out_arb[fb] & output_ready;
 
     // Count the beats of data output to the IF stage
-    assign fill_out_cnt_d[fb]  = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[LINE_W-1:BUS_W]} :
+    assign fill_out_cnt_d[fb]  = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[IC_LINE_W-1:BUS_W]} :
                                                   (fill_out_cnt_q[fb] +
-                                                   {{LINE_BEATS_W{1'b0}},fill_out_grant[fb]});
+                                                   {{IC_LINE_BEATS_W{1'b0}},fill_out_grant[fb]});
     // Data output complete when the counter fills
-    assign fill_out_done[fb]   = fill_out_cnt_q[fb][LINE_BEATS_W];
+    assign fill_out_done[fb]   = fill_out_cnt_q[fb][IC_LINE_BEATS_W];
 
     //////////////////////////////////////
     // Fill buffer ram request tracking //
     //////////////////////////////////////
 
                                  // make a fill request once all data beats received
-    assign fill_ram_req[fb]    = fill_busy_q[fb] & fill_rvd_cnt_q[fb][LINE_BEATS_W] &
+    assign fill_ram_req[fb]    = fill_busy_q[fb] & fill_rvd_cnt_q[fb][IC_LINE_BEATS_W] &
                                  // unless the request hit, was non-allocating or got an error
                                  ~fill_hit_q[fb] & fill_cache_q[fb] & ~|fill_err_q[fb] &
                                  // or the request was already completed
@@ -697,12 +678,12 @@
 
     // When we branch into the middle of a line, the output count will not start from zero. This
     // beat count is used to know which incoming rdata beats are relevant.
-    assign fill_ext_beat[fb]   = {1'b0,fill_addr_q[fb][LINE_W-1:BUS_W]} +
-                                 fill_ext_cnt_q[fb][LINE_BEATS_W:0];
-    assign fill_ext_off[fb]    = fill_ext_beat[fb][LINE_BEATS_W-1:0];
-    assign fill_rvd_beat[fb]   = {1'b0,fill_addr_q[fb][LINE_W-1:BUS_W]} +
-                                 fill_rvd_cnt_q[fb][LINE_BEATS_W:0];
-    assign fill_rvd_off[fb]    = fill_rvd_beat[fb][LINE_BEATS_W-1:0];
+    assign fill_ext_beat[fb]   = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} +
+                                 fill_ext_cnt_q[fb][IC_LINE_BEATS_W:0];
+    assign fill_ext_off[fb]    = fill_ext_beat[fb][IC_LINE_BEATS_W-1:0];
+    assign fill_rvd_beat[fb]   = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} +
+                                 fill_rvd_cnt_q[fb][IC_LINE_BEATS_W:0];
+    assign fill_rvd_off[fb]    = fill_rvd_beat[fb][IC_LINE_BEATS_W-1:0];
 
     /////////////////////////////
     // Fill buffer arbitration //
@@ -796,19 +777,20 @@
     // Data either comes from the cache or the bus. If there was an ECC error, we must take
     // the incoming bus data since the cache hit data is corrupted.
     assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1 :
-                                                {LINE_BEATS{instr_rdata_i}};
+                                                {IC_LINE_BEATS{instr_rdata_i}};
 
-    for (genvar b = 0; b < LINE_BEATS; b++) begin : gen_data_buf
+    for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf
       // Error tracking (per beat)
       //                           Either a PMP error on a speculative request,
       assign fill_err_d[fb][b]   = (instr_pmp_err_i & fill_alloc[fb] & fill_spec_req &
-                                    (lookup_addr_ic0[LINE_W-1:BUS_W] == b[LINE_BEATS_W-1:0])) |
+                                    (lookup_addr_ic0[IC_LINE_W-1:BUS_W] ==
+                                     b[IC_LINE_BEATS_W-1:0])) |
       //                           a PMP error on a fill buffer ext req
                                    (instr_pmp_err_i & fill_ext_arb[fb] &
-                                    (fill_ext_off[fb] == b[LINE_BEATS_W-1:0])) |
+                                    (fill_ext_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
       //                           Or a data error with instr_rvalid_i
                                    (fill_rvd_arb[fb] & instr_err_i &
-                                    (fill_rvd_off[fb] == b[LINE_BEATS_W-1:0])) |
+                                    (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
       //                           Hold the error once recorded
                                    (fill_busy_q[fb] & fill_err_q[fb][b]);
 
@@ -824,11 +806,11 @@
       // Ignore incoming rvalid data when we already have cache hit data
       assign fill_data_en[fb][b] = fill_hit_ic1[fb] |
                                    (fill_rvd_arb[fb] & ~fill_hit_q[fb] &
-                                    (fill_rvd_off[fb] == b[LINE_BEATS_W-1:0]));
+                                    (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0]));
 
       always_ff @(posedge clk_i) begin
         if (fill_data_en[fb][b]) begin
-          fill_data_q[fb][b*BusWidth+:BusWidth] <= fill_data_d[fb][b*BusWidth+:BusWidth];
+          fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE];
         end
       end
 
@@ -844,7 +826,7 @@
     fill_ext_req_addr = '0;
     for (int i = 0; i < NUM_FB; i++) begin
       if (fill_ext_arb[i]) begin
-        fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:LINE_W], fill_ext_off[i]};
+        fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:IC_LINE_W], fill_ext_off[i]};
       end
     end
   end
@@ -871,7 +853,7 @@
       if (fill_data_reg[i]) begin
         fill_out_data |= fill_data_q[i];
         // Ignore any speculative errors accumulated on cache hits
-        fill_out_err  |= (fill_err_q[i] & ~{LINE_BEATS{fill_hit_q[i]}});
+        fill_out_err  |= (fill_err_q[i] & ~{IC_LINE_BEATS{fill_hit_q[i]}});
       end
     end
   end
@@ -895,16 +877,16 @@
 
   // Mux between line-width data sources
   assign line_data = |fill_data_hit ? hit_data_ic1 : fill_out_data;
-  assign line_err  = |fill_data_hit ? {LINE_BEATS{1'b0}} : fill_out_err;
+  assign line_err  = |fill_data_hit ? {IC_LINE_BEATS{1'b0}} : fill_out_err;
 
   // Mux the relevant beat of line data, based on the output address
   always_comb begin
     line_data_muxed = '0;
     line_err_muxed  = 1'b0;
-    for (int i = 0; i < LINE_BEATS; i++) begin
+    for (int i = 0; i < IC_LINE_BEATS; i++) begin
       // When data has been skidded, the output address is behind by one
-      if ((output_addr_q[LINE_W-1:BUS_W] + {{LINE_BEATS_W-1{1'b0}},skid_valid_q}) ==
-          i[LINE_BEATS_W-1:0]) begin
+      if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) ==
+          i[IC_LINE_BEATS_W-1:0]) begin
         line_data_muxed |= line_data[i*32+:32];
         line_err_muxed  |= line_err[i];
       end
@@ -994,14 +976,14 @@
     end
   end
 
-  // Mux the data from BusWidth to halfword
+  // Mux the data from BUS_SIZE to halfword
   // This muxing realigns data when instruction words are split across BUS_W e.g.
   // word 1 |----|*h1*|
   // word 0 |*h0*|----| --> |*h1*|*h0*|
   //        31   15   0     31   15   0
   always_comb begin
     output_data_lo = '0;
-    for (int i = 0; i < OUTPUT_BEATS; i++) begin
+    for (int i = 0; i < IC_OUTPUT_BEATS; i++) begin
       if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
         output_data_lo |= output_data[i*16+:16];
       end
@@ -1010,7 +992,7 @@
 
   always_comb begin
     output_data_hi = '0;
-    for (int i = 0; i < OUTPUT_BEATS-1; i++) begin
+    for (int i = 0; i < IC_OUTPUT_BEATS-1; i++) begin
       if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
         output_data_hi |= output_data[(i+1)*16+:16];
       end
@@ -1038,7 +1020,7 @@
   assign inval_prog_d  = start_inval | (inval_prog_q & ~inval_done);
   assign inval_done    = &inval_index_q;
   assign inval_index_d = start_inval ? '0 :
-                                       (inval_index_q + {{INDEX_W-1{1'b0}},1'b1});
+                                       (inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1});
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
@@ -1068,11 +1050,11 @@
   // Assertions //
   ////////////////
 
-  `ASSERT_INIT(size_param_legal, (LineSize > 32))
+  `ASSERT_INIT(size_param_legal, (IC_LINE_SIZE > 32))
 
   // ECC primitives will need to be changed for different sizes
-  `ASSERT_INIT(ecc_tag_param_legal, (TAG_SIZE <= 27))
-  `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BusWidth == 32))
+  `ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27))
+  `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32))
 
   // Lookups in the tag ram should always give a known result
   `ASSERT_KNOWN(TagHitKnown,     lookup_valid_ic1 & tag_hit_ic1)
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index 2c49175..8bd0efe 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -12,19 +12,21 @@
 
 `include "prim_assert.sv"
 
-module ibex_if_stage #(
+module ibex_if_stage import ibex_pkg::*; #(
     parameter int unsigned DmHaltAddr        = 32'h1A110800,
     parameter int unsigned DmExceptionAddr   = 32'h1A110808,
     parameter bit          DummyInstructions = 1'b0,
     parameter bit          ICache            = 1'b0,
     parameter bit          ICacheECC         = 1'b0,
+    parameter int unsigned BusSizeECC        = BUS_SIZE,
+    parameter int unsigned TagSizeECC        = IC_TAG_SIZE,
+    parameter int unsigned LineSizeECC       = IC_LINE_SIZE,
     parameter bit          PCIncrCheck       = 1'b0,
     parameter bit          BranchPredictor   = 1'b0
 ) (
     input  logic                         clk_i,
     input  logic                         rst_ni,
 
-    input  prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
     input  logic [31:0]                  boot_addr_i,              // also used for mtvec
     input  logic                         req_i,                    // instruction request control
 
@@ -37,6 +39,18 @@
     input  logic                        instr_err_i,
     input  logic                        instr_pmp_err_i,
 
+    // ICache RAM IO
+    output logic [IC_NUM_WAYS-1:0]      ic_tag_req_o,
+    output logic                        ic_tag_write_o,
+    output logic [IC_INDEX_W-1:0]       ic_tag_addr_o,
+    output logic [TagSizeECC-1:0]       ic_tag_wdata_o,
+    input  logic [TagSizeECC-1:0]       ic_tag_rdata_i [IC_NUM_WAYS],
+    output logic [IC_NUM_WAYS-1:0]      ic_data_req_o,
+    output logic                        ic_data_write_o,
+    output logic [IC_INDEX_W-1:0]       ic_data_addr_o,
+    output logic [LineSizeECC-1:0]      ic_data_wdata_o,
+    input  logic [LineSizeECC-1:0]      ic_data_rdata_i [IC_NUM_WAYS],
+
     // output of ID stage
     output logic                        instr_valid_id_o,         // instr in IF-ID is valid
     output logic                        instr_new_id_o,           // instr in IF-ID is new
@@ -45,7 +59,7 @@
                                                                   // to reduce fan-out
     output logic [15:0]                 instr_rdata_c_id_o,       // compressed instr for ID stage
                                                                   // (mtval), meaningful only if
-                                                                 // instr_is_compressed_id_o = 1'b1
+                                                                  // instr_is_compressed_id_o = 1'b1
     output logic                        instr_is_compressed_id_o, // compressed decoder thinks this
                                                                   // is a compressed instr
     output logic                        instr_bp_taken_o,         // instruction was predicted to be
@@ -62,11 +76,11 @@
     input  logic                        instr_valid_clear_i,      // clear instr valid bit in IF-ID
     input  logic                        pc_set_i,                 // set the PC to a new value
     input  logic                        pc_set_spec_i,
-    input  ibex_pkg::pc_sel_e           pc_mux_i,                 // selector for PC multiplexer
+    input  pc_sel_e                     pc_mux_i,                 // selector for PC multiplexer
     input  logic                        nt_branch_mispredict_i,   // Not-taken branch in ID/EX was
                                                                   // mispredicted (predicted taken)
-    input  ibex_pkg::exc_pc_sel_e       exc_pc_mux_i,             // selects ISR address
-    input  ibex_pkg::exc_cause_e        exc_cause,                // selects ISR address for
+    input  exc_pc_sel_e                 exc_pc_mux_i,             // selects ISR address
+    input  exc_cause_e                  exc_cause,                // selects ISR address for
                                                                   // vectorized interrupt lines
     input logic                         dummy_instr_en_i,
     input logic [2:0]                   dummy_instr_mask_i,
@@ -94,8 +108,6 @@
     output logic                        if_busy_o                 // IF stage is busy fetching instr
 );
 
-  import ibex_pkg::*;
-
   logic              instr_valid_id_d, instr_valid_id_q;
   logic              instr_new_id_d, instr_new_id_q;
 
@@ -186,7 +198,10 @@
     // Full I-Cache option
     ibex_icache #(
       .BranchPredictor (BranchPredictor),
-      .ICacheECC       (ICacheECC)
+      .ICacheECC       (ICacheECC),
+      .BusSizeECC      (BusSizeECC),
+      .TagSizeECC      (TagSizeECC),
+      .LineSizeECC     (LineSizeECC)
     ) icache_i (
         .clk_i               ( clk_i                      ),
         .rst_ni              ( rst_ni                     ),
@@ -214,7 +229,17 @@
         .instr_err_i         ( instr_err_i                ),
         .instr_pmp_err_i     ( instr_pmp_err_i            ),
 
-        .ram_cfg_i           ( ram_cfg_i                  ),
+        .ic_tag_req_o        ( ic_tag_req_o               ),
+        .ic_tag_write_o      ( ic_tag_write_o             ),
+        .ic_tag_addr_o       ( ic_tag_addr_o              ),
+        .ic_tag_wdata_o      ( ic_tag_wdata_o             ),
+        .ic_tag_rdata_i      ( ic_tag_rdata_i             ),
+        .ic_data_req_o       ( ic_data_req_o              ),
+        .ic_data_write_o     ( ic_data_write_o            ),
+        .ic_data_addr_o      ( ic_data_addr_o             ),
+        .ic_data_wdata_o     ( ic_data_wdata_o            ),
+        .ic_data_rdata_i     ( ic_data_rdata_i            ),
+
         .icache_enable_i     ( icache_enable_i            ),
         .icache_inval_i      ( icache_inval_i             ),
         .busy_o              ( prefetch_busy              )
@@ -253,11 +278,21 @@
         .busy_o              ( prefetch_busy              )
     );
     // ICache tieoffs
-    logic unused_icen, unused_icinv;
-    prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg;
-    assign unused_icen    = icache_enable_i;
-    assign unused_icinv   = icache_inval_i;
-    assign unused_ram_cfg = ram_cfg_i;
+    logic                   unused_icen, unused_icinv;
+    logic [TagSizeECC-1:0]  unused_tag_ram_input [IC_NUM_WAYS];
+    logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS];
+    assign unused_icen           = icache_enable_i;
+    assign unused_icinv          = icache_inval_i;
+    assign unused_tag_ram_input  = ic_tag_rdata_i;
+    assign unused_data_ram_input = ic_data_rdata_i;
+    assign ic_tag_req_o          = 'b0;
+    assign ic_tag_write_o        = 'b0;
+    assign ic_tag_addr_o         = 'b0;
+    assign ic_tag_wdata_o        = 'b0;
+    assign ic_data_req_o         = 'b0;
+    assign ic_data_write_o       = 'b0;
+    assign ic_data_addr_o        = 'b0;
+    assign ic_data_wdata_o       = 'b0;
   end
 
   assign unused_fetch_addr_n0 = fetch_addr_n[0];
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
new file mode 100644
index 0000000..0d56ade
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
@@ -0,0 +1,377 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Ibex lockstep module
+// This module instantiates a second copy of the core logic, and compares it's outputs against
+// those from the main core. The second core runs synchronously with the main core, delayed by
+// LockstepOffset cycles.
+module ibex_lockstep import ibex_pkg::*; #(
+    parameter int unsigned LockstepOffset    = 2,
+    parameter bit          PMPEnable         = 1'b0,
+    parameter int unsigned PMPGranularity    = 0,
+    parameter int unsigned PMPNumRegions     = 4,
+    parameter int unsigned MHPMCounterNum    = 0,
+    parameter int unsigned MHPMCounterWidth  = 40,
+    parameter bit          RV32E             = 1'b0,
+    parameter rv32m_e      RV32M             = RV32MFast,
+    parameter rv32b_e      RV32B             = RV32BNone,
+    parameter bit          BranchTargetALU   = 1'b0,
+    parameter bit          WritebackStage    = 1'b0,
+    parameter bit          ICache            = 1'b0,
+    parameter bit          ICacheECC         = 1'b0,
+    parameter int unsigned BusSizeECC        = BUS_SIZE,
+    parameter int unsigned TagSizeECC        = IC_TAG_SIZE,
+    parameter int unsigned LineSizeECC       = IC_LINE_SIZE,
+    parameter bit          BranchPredictor   = 1'b0,
+    parameter bit          DbgTriggerEn      = 1'b0,
+    parameter int unsigned DbgHwBreakNum     = 1,
+    parameter bit          SecureIbex        = 1'b0,
+    parameter bit          DummyInstructions = 1'b0,
+    parameter bit          RegFileECC        = 1'b0,
+    parameter int unsigned RegFileDataWidth  = 32,
+    parameter int unsigned DmHaltAddr        = 32'h1A110800,
+    parameter int unsigned DmExceptionAddr   = 32'h1A110808
+) (
+    input  logic                         clk_i,
+    input  logic                         rst_ni,
+
+    input  logic [31:0]                  hart_id_i,
+    input  logic [31:0]                  boot_addr_i,
+
+    input  logic                         instr_req_i,
+    input  logic                         instr_gnt_i,
+    input  logic                         instr_rvalid_i,
+    input  logic [31:0]                  instr_addr_i,
+    input  logic [31:0]                  instr_rdata_i,
+    input  logic                         instr_err_i,
+
+    input  logic                         data_req_i,
+    input  logic                         data_gnt_i,
+    input  logic                         data_rvalid_i,
+    input  logic                         data_we_i,
+    input  logic [3:0]                   data_be_i,
+    input  logic [31:0]                  data_addr_i,
+    input  logic [31:0]                  data_wdata_i,
+    input  logic [31:0]                  data_rdata_i,
+    input  logic                         data_err_i,
+
+    input  logic                         dummy_instr_id_i,
+    input  logic [4:0]                   rf_raddr_a_i,
+    input  logic [4:0]                   rf_raddr_b_i,
+    input  logic [4:0]                   rf_waddr_wb_i,
+    input  logic                         rf_we_wb_i,
+    input  logic [RegFileDataWidth-1:0]  rf_wdata_wb_ecc_i,
+    input  logic [RegFileDataWidth-1:0]  rf_rdata_a_ecc_i,
+    input  logic [RegFileDataWidth-1:0]  rf_rdata_b_ecc_i,
+
+    input  logic [IC_NUM_WAYS-1:0]       ic_tag_req_i,
+    input  logic                         ic_tag_write_i,
+    input  logic [IC_INDEX_W-1:0]        ic_tag_addr_i,
+    input  logic [TagSizeECC-1:0]        ic_tag_wdata_i,
+    input  logic [TagSizeECC-1:0]        ic_tag_rdata_i [IC_NUM_WAYS],
+    input  logic [IC_NUM_WAYS-1:0]       ic_data_req_i,
+    input  logic                         ic_data_write_i,
+    input  logic [IC_INDEX_W-1:0]        ic_data_addr_i,
+    input  logic [LineSizeECC-1:0]       ic_data_wdata_i,
+    input  logic [LineSizeECC-1:0]       ic_data_rdata_i [IC_NUM_WAYS],
+
+    input  logic                         irq_software_i,
+    input  logic                         irq_timer_i,
+    input  logic                         irq_external_i,
+    input  logic [14:0]                  irq_fast_i,
+    input  logic                         irq_nm_i,
+    input  logic                         irq_pending_i,
+
+    input  logic                         debug_req_i,
+    input  crash_dump_t                  crash_dump_i,
+
+    output logic                         alert_minor_o,
+    output logic                         alert_major_o,
+    input  logic                         core_busy_i
+);
+
+  localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset);
+
+  //////////////////////
+  // Reset generation //
+  //////////////////////
+
+  logic [LockstepOffsetW-1:0] rst_shadow_cnt_d, rst_shadow_cnt_q;
+  logic                       rst_shadow_set_d, rst_shadow_set_q;
+  // Internally generated resets cause IMPERFECTSCH warnings
+  /* verilator lint_off IMPERFECTSCH */
+  logic                       rst_shadow_n;
+  /* verilator lint_on IMPERFECTSCH */
+
+  assign rst_shadow_set_d = (rst_shadow_cnt_q == LockstepOffsetW'(LockstepOffset - 1));
+  assign rst_shadow_cnt_d = rst_shadow_set_d ? rst_shadow_cnt_q :
+                                               (rst_shadow_cnt_q + LockstepOffsetW'(1));
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      rst_shadow_cnt_q <= '0;
+      rst_shadow_set_q <= '0;
+    end else begin
+      rst_shadow_cnt_q <= rst_shadow_cnt_d;
+      rst_shadow_set_q <= rst_shadow_set_d;
+    end
+  end
+
+  assign rst_shadow_n = rst_shadow_set_q;
+
+  //////////////////
+  // Input delays //
+  //////////////////
+
+  typedef struct packed {
+    logic                        instr_gnt;
+    logic                        instr_rvalid;
+    logic [31:0]                 instr_rdata;
+    logic                        instr_err;
+    logic                        data_gnt;
+    logic                        data_rvalid;
+    logic [31:0]                 data_rdata;
+    logic                        data_err;
+    logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
+    logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
+    logic                        irq_software;
+    logic                        irq_timer;
+    logic                        irq_external;
+    logic [14:0]                 irq_fast;
+    logic                        irq_nm;
+    logic                        debug_req;
+  } delayed_inputs_t;
+
+  delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q;
+  delayed_inputs_t                      shadow_inputs_in;
+  // Packed arrays must be dealt with separately
+  logic [TagSizeECC-1:0]                shadow_tag_rdata_q [IC_NUM_WAYS][LockstepOffset];
+  logic [LineSizeECC-1:0]               shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset];
+
+  // Assign the inputs to the delay structure
+  assign shadow_inputs_in.instr_gnt      = instr_gnt_i;
+  assign shadow_inputs_in.instr_rvalid   = instr_rvalid_i;
+  assign shadow_inputs_in.instr_rdata    = instr_rdata_i;
+  assign shadow_inputs_in.instr_err      = instr_err_i;
+  assign shadow_inputs_in.data_gnt       = data_gnt_i;
+  assign shadow_inputs_in.data_rvalid    = data_rvalid_i;
+  assign shadow_inputs_in.data_rdata     = data_rdata_i;
+  assign shadow_inputs_in.data_err       = data_err_i;
+  assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i;
+  assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i;
+  assign shadow_inputs_in.irq_software   = irq_software_i;
+  assign shadow_inputs_in.irq_timer      = irq_timer_i;
+  assign shadow_inputs_in.irq_external   = irq_external_i;
+  assign shadow_inputs_in.irq_fast       = irq_fast_i;
+  assign shadow_inputs_in.irq_nm         = irq_nm_i;
+  assign shadow_inputs_in.debug_req      = debug_req_i;
+
+  // Delay the inputs
+  always_ff @(posedge clk_i) begin
+    for (int unsigned i = 0; i < LockstepOffset-1; i++) begin
+      shadow_inputs_q[i]     <= shadow_inputs_q[i+1];
+      shadow_tag_rdata_q[i]  <= shadow_tag_rdata_q[i+1];
+      shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1];
+    end
+    shadow_inputs_q[LockstepOffset-1]     <= shadow_inputs_in;
+    shadow_tag_rdata_q[LockstepOffset-1]  <= ic_tag_rdata_i;
+    shadow_data_rdata_q[LockstepOffset-1] <= ic_data_rdata_i;
+  end
+
+  ///////////////////
+  // Output delays //
+  ///////////////////
+
+  typedef struct packed {
+    logic                        instr_req;
+    logic [31:0]                 instr_addr;
+    logic                        data_req;
+    logic                        data_we;
+    logic [3:0]                  data_be;
+    logic [31:0]                 data_addr;
+    logic [31:0]                 data_wdata;
+    logic                        dummy_instr_id;
+    logic [4:0]                  rf_raddr_a;
+    logic [4:0]                  rf_raddr_b;
+    logic [4:0]                  rf_waddr_wb;
+    logic                        rf_we_wb;
+    logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
+    logic [IC_NUM_WAYS-1:0]      ic_tag_req;
+    logic                        ic_tag_write;
+    logic [IC_INDEX_W-1:0]       ic_tag_addr;
+    logic [TagSizeECC-1:0]       ic_tag_wdata;
+    logic [IC_NUM_WAYS-1:0]      ic_data_req;
+    logic                        ic_data_write;
+    logic [IC_INDEX_W-1:0]       ic_data_addr;
+    logic [LineSizeECC-1:0]      ic_data_wdata;
+    logic                        irq_pending;
+    crash_dump_t                 crash_dump;
+    logic                        core_busy;
+  } delayed_outputs_t;
+
+  delayed_outputs_t [LockstepOffset-1:0] core_outputs_q;
+  delayed_outputs_t                      core_outputs_in, shadow_outputs;
+
+  // Assign core outputs to the structure
+  assign core_outputs_in.instr_req       = instr_req_i;
+  assign core_outputs_in.instr_addr      = instr_addr_i;
+  assign core_outputs_in.data_req        = data_req_i;
+  assign core_outputs_in.data_we         = data_we_i;
+  assign core_outputs_in.data_be         = data_be_i;
+  assign core_outputs_in.data_addr       = data_addr_i;
+  assign core_outputs_in.data_wdata      = data_wdata_i;
+  assign core_outputs_in.dummy_instr_id  = dummy_instr_id_i;
+  assign core_outputs_in.rf_raddr_a      = rf_raddr_a_i;
+  assign core_outputs_in.rf_raddr_b      = rf_raddr_b_i;
+  assign core_outputs_in.rf_waddr_wb     = rf_waddr_wb_i;
+  assign core_outputs_in.rf_we_wb        = rf_we_wb_i;
+  assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i;
+  assign core_outputs_in.ic_tag_req      = ic_tag_req_i;
+  assign core_outputs_in.ic_tag_write    = ic_tag_write_i;
+  assign core_outputs_in.ic_tag_addr     = ic_tag_addr_i;
+  assign core_outputs_in.ic_tag_wdata    = ic_tag_wdata_i;
+  assign core_outputs_in.ic_data_req     = ic_data_req_i;
+  assign core_outputs_in.ic_data_write   = ic_data_write_i;
+  assign core_outputs_in.ic_data_addr    = ic_data_addr_i;
+  assign core_outputs_in.ic_data_wdata   = ic_data_wdata_i;
+  assign core_outputs_in.irq_pending     = irq_pending_i;
+  assign core_outputs_in.crash_dump      = crash_dump_i;
+  assign core_outputs_in.core_busy       = core_busy_i;
+
+  // Delay the outputs
+  always_ff @(posedge clk_i) begin
+    for (int unsigned i = 0; i < LockstepOffset-1; i++) begin
+      core_outputs_q[i] <= core_outputs_q[i+1];
+    end
+    core_outputs_q[LockstepOffset-1] <= core_outputs_in;
+  end
+
+  ///////////////////////////////
+  // Shadow core instantiation //
+  ///////////////////////////////
+
+  logic shadow_alert_minor, shadow_alert_major;
+
+  ibex_core #(
+    .PMPEnable         ( PMPEnable         ),
+    .PMPGranularity    ( PMPGranularity    ),
+    .PMPNumRegions     ( PMPNumRegions     ),
+    .MHPMCounterNum    ( MHPMCounterNum    ),
+    .MHPMCounterWidth  ( MHPMCounterWidth  ),
+    .RV32E             ( RV32E             ),
+    .RV32M             ( RV32M             ),
+    .RV32B             ( RV32B             ),
+    .BranchTargetALU   ( BranchTargetALU   ),
+    .ICache            ( ICache            ),
+    .ICacheECC         ( ICacheECC         ),
+    .BusSizeECC        ( BusSizeECC        ),
+    .TagSizeECC        ( TagSizeECC        ),
+    .LineSizeECC       ( LineSizeECC       ),
+    .BranchPredictor   ( BranchPredictor   ),
+    .DbgTriggerEn      ( DbgTriggerEn      ),
+    .DbgHwBreakNum     ( DbgHwBreakNum     ),
+    .WritebackStage    ( WritebackStage    ),
+    .SecureIbex        ( SecureIbex        ),
+    .DummyInstructions ( DummyInstructions ),
+    .RegFileECC        ( RegFileECC        ),
+    .RegFileDataWidth  ( RegFileDataWidth  ),
+    .DmHaltAddr        ( DmHaltAddr        ),
+    .DmExceptionAddr   ( DmExceptionAddr   )
+  ) u_shadow_core (
+    .clk_i             (clk_i),
+    .rst_ni            (rst_shadow_n),
+
+    .hart_id_i         (hart_id_i),
+    .boot_addr_i       (boot_addr_i),
+
+    .instr_req_o       (shadow_outputs.instr_req),
+    .instr_gnt_i       (shadow_inputs_q[0].instr_gnt),
+    .instr_rvalid_i    (shadow_inputs_q[0].instr_rvalid),
+    .instr_addr_o      (shadow_outputs.instr_addr),
+    .instr_rdata_i     (shadow_inputs_q[0].instr_rdata),
+    .instr_err_i       (shadow_inputs_q[0].instr_err),
+
+    .data_req_o        (shadow_outputs.data_req),
+    .data_gnt_i        (shadow_inputs_q[0].data_gnt),
+    .data_rvalid_i     (shadow_inputs_q[0].data_rvalid),
+    .data_we_o         (shadow_outputs.data_we),
+    .data_be_o         (shadow_outputs.data_be),
+    .data_addr_o       (shadow_outputs.data_addr),
+    .data_wdata_o      (shadow_outputs.data_wdata),
+    .data_rdata_i      (shadow_inputs_q[0].data_rdata),
+    .data_err_i        (shadow_inputs_q[0].data_err),
+
+    .dummy_instr_id_o  (shadow_outputs.dummy_instr_id),
+    .rf_raddr_a_o      (shadow_outputs.rf_raddr_a),
+    .rf_raddr_b_o      (shadow_outputs.rf_raddr_b),
+    .rf_waddr_wb_o     (shadow_outputs.rf_waddr_wb),
+    .rf_we_wb_o        (shadow_outputs.rf_we_wb),
+    .rf_wdata_wb_ecc_o (shadow_outputs.rf_wdata_wb_ecc),
+    .rf_rdata_a_ecc_i  (shadow_inputs_q[0].rf_rdata_a_ecc),
+    .rf_rdata_b_ecc_i  (shadow_inputs_q[0].rf_rdata_b_ecc),
+
+    .ic_tag_req_o      (shadow_outputs.ic_tag_req),
+    .ic_tag_write_o    (shadow_outputs.ic_tag_write),
+    .ic_tag_addr_o     (shadow_outputs.ic_tag_addr),
+    .ic_tag_wdata_o    (shadow_outputs.ic_tag_wdata),
+    .ic_tag_rdata_i    (shadow_tag_rdata_q[0]),
+    .ic_data_req_o     (shadow_outputs.ic_data_req),
+    .ic_data_write_o   (shadow_outputs.ic_data_write),
+    .ic_data_addr_o    (shadow_outputs.ic_data_addr),
+    .ic_data_wdata_o   (shadow_outputs.ic_data_wdata),
+    .ic_data_rdata_i   (shadow_data_rdata_q[0]),
+
+    .irq_software_i    (shadow_inputs_q[0].irq_software),
+    .irq_timer_i       (shadow_inputs_q[0].irq_timer),
+    .irq_external_i    (shadow_inputs_q[0].irq_external),
+    .irq_fast_i        (shadow_inputs_q[0].irq_fast),
+    .irq_nm_i          (shadow_inputs_q[0].irq_nm),
+    .irq_pending_o     (shadow_outputs.irq_pending),
+
+    .debug_req_i       (shadow_inputs_q[0].debug_req),
+    .crash_dump_o      (shadow_outputs.crash_dump),
+
+`ifdef RVFI
+    .rvfi_valid        (),
+    .rvfi_order        (),
+    .rvfi_insn         (),
+    .rvfi_trap         (),
+    .rvfi_halt         (),
+    .rvfi_intr         (),
+    .rvfi_mode         (),
+    .rvfi_ixl          (),
+    .rvfi_rs1_addr     (),
+    .rvfi_rs2_addr     (),
+    .rvfi_rs3_addr     (),
+    .rvfi_rs1_rdata    (),
+    .rvfi_rs2_rdata    (),
+    .rvfi_rs3_rdata    (),
+    .rvfi_rd_addr      (),
+    .rvfi_rd_wdata     (),
+    .rvfi_pc_rdata     (),
+    .rvfi_pc_wdata     (),
+    .rvfi_mem_addr     (),
+    .rvfi_mem_rmask    (),
+    .rvfi_mem_wmask    (),
+    .rvfi_mem_rdata    (),
+    .rvfi_mem_wdata    (),
+`endif
+
+    .alert_minor_o     (shadow_alert_minor),
+    .alert_major_o     (shadow_alert_major),
+    .core_busy_o       (shadow_outputs.core_busy)
+  );
+
+  /////////////////////////
+  // Compare the outputs //
+  /////////////////////////
+
+  logic outputs_mismatch;
+
+  // TODO evaluate the timing here - might need to register shadow_outputs
+  assign outputs_mismatch = rst_shadow_n & (shadow_outputs != core_outputs_q[0]);
+  assign alert_major_o    = outputs_mismatch | shadow_alert_major;
+  assign alert_minor_o    = shadow_alert_minor;
+
+endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
index dcff9df..bc4a851 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
@@ -19,6 +19,14 @@
   logic [31:0] exception_addr;
 } crash_dump_t;
 
+typedef struct packed {
+  logic        dummy_instr_id;
+  logic [4:0]  raddr_a;
+  logic [4:0]  waddr_a;
+  logic        we_a;
+  logic [4:0]  raddr_b;
+} core2rf_t;
+
 /////////////////////
 // Parameter Enums //
 /////////////////////
@@ -311,6 +319,24 @@
   DBG_CAUSE_STEP    = 3'h4
 } dbg_cause_e;
 
+// ICache constants
+parameter int unsigned ADDR_W          = 32;
+parameter int unsigned BUS_SIZE        = 32;
+parameter int unsigned BUS_BYTES       = BUS_SIZE/8;
+parameter int unsigned BUS_W           = $clog2(BUS_BYTES);
+parameter int unsigned IC_SIZE_BYTES   = 4096;
+parameter int unsigned IC_NUM_WAYS     = 2;
+parameter int unsigned IC_LINE_SIZE    = 64;
+parameter int unsigned IC_LINE_BYTES   = IC_LINE_SIZE/8;
+parameter int unsigned IC_LINE_W       = $clog2(IC_LINE_BYTES);
+parameter int unsigned IC_NUM_LINES    = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
+parameter int unsigned IC_LINE_BEATS   = IC_LINE_BYTES / BUS_BYTES;
+parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
+parameter int unsigned IC_INDEX_W      = $clog2(IC_NUM_LINES);
+parameter int unsigned IC_INDEX_HI     = IC_INDEX_W + IC_LINE_W - 1;
+parameter int unsigned IC_TAG_SIZE     = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
+parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
+
 // PMP constants
 parameter int unsigned PMP_MAX_REGIONS      = 16;
 parameter int unsigned PMP_CFG_W            = 8;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
new file mode 100644
index 0000000..1d89eb6
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
@@ -0,0 +1,515 @@
+// Copyright lowRISC contributors.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`ifdef RISCV_FORMAL
+  `define RVFI
+`endif
+
+/**
+ * Top level module of the ibex RISC-V core
+ */
+module ibex_top #(
+    parameter bit                 PMPEnable        = 1'b0,
+    parameter int unsigned        PMPGranularity   = 0,
+    parameter int unsigned        PMPNumRegions    = 4,
+    parameter int unsigned        MHPMCounterNum   = 0,
+    parameter int unsigned        MHPMCounterWidth = 40,
+    parameter bit                 RV32E            = 1'b0,
+    parameter ibex_pkg::rv32m_e   RV32M            = ibex_pkg::RV32MFast,
+    parameter ibex_pkg::rv32b_e   RV32B            = ibex_pkg::RV32BNone,
+    parameter ibex_pkg::regfile_e RegFile          = ibex_pkg::RegFileFF,
+    parameter bit                 BranchTargetALU  = 1'b0,
+    parameter bit                 WritebackStage   = 1'b0,
+    parameter bit                 ICache           = 1'b0,
+    parameter bit                 ICacheECC        = 1'b0,
+    parameter bit                 BranchPredictor  = 1'b0,
+    parameter bit                 DbgTriggerEn     = 1'b0,
+    parameter int unsigned        DbgHwBreakNum    = 1,
+    parameter bit                 SecureIbex       = 1'b0,
+    parameter int unsigned        DmHaltAddr       = 32'h1A110800,
+    parameter int unsigned        DmExceptionAddr  = 32'h1A110808
+) (
+    // Clock and Reset
+    input  logic                         clk_i,
+    input  logic                         rst_ni,
+
+    input  logic                         test_en_i,     // enable all clock gates for testing
+    input  prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
+
+    input  logic [31:0]                  hart_id_i,
+    input  logic [31:0]                  boot_addr_i,
+
+    // Instruction memory interface
+    output logic                         instr_req_o,
+    input  logic                         instr_gnt_i,
+    input  logic                         instr_rvalid_i,
+    output logic [31:0]                  instr_addr_o,
+    input  logic [31:0]                  instr_rdata_i,
+    input  logic                         instr_err_i,
+
+    // Data memory interface
+    output logic                         data_req_o,
+    input  logic                         data_gnt_i,
+    input  logic                         data_rvalid_i,
+    output logic                         data_we_o,
+    output logic [3:0]                   data_be_o,
+    output logic [31:0]                  data_addr_o,
+    output logic [31:0]                  data_wdata_o,
+    input  logic [31:0]                  data_rdata_i,
+    input  logic                         data_err_i,
+
+    // Interrupt inputs
+    input  logic                         irq_software_i,
+    input  logic                         irq_timer_i,
+    input  logic                         irq_external_i,
+    input  logic [14:0]                  irq_fast_i,
+    input  logic                         irq_nm_i,       // non-maskeable interrupt
+
+    // Debug Interface
+    input  logic                         debug_req_i,
+    output ibex_pkg::crash_dump_t        crash_dump_o,
+
+    // RISC-V Formal Interface
+    // Does not comply with the coding standards of _i/_o suffixes, but follows
+    // the convention of RISC-V Formal Interface Specification.
+`ifdef RVFI
+    output logic                         rvfi_valid,
+    output logic [63:0]                  rvfi_order,
+    output logic [31:0]                  rvfi_insn,
+    output logic                         rvfi_trap,
+    output logic                         rvfi_halt,
+    output logic                         rvfi_intr,
+    output logic [ 1:0]                  rvfi_mode,
+    output logic [ 1:0]                  rvfi_ixl,
+    output logic [ 4:0]                  rvfi_rs1_addr,
+    output logic [ 4:0]                  rvfi_rs2_addr,
+    output logic [ 4:0]                  rvfi_rs3_addr,
+    output logic [31:0]                  rvfi_rs1_rdata,
+    output logic [31:0]                  rvfi_rs2_rdata,
+    output logic [31:0]                  rvfi_rs3_rdata,
+    output logic [ 4:0]                  rvfi_rd_addr,
+    output logic [31:0]                  rvfi_rd_wdata,
+    output logic [31:0]                  rvfi_pc_rdata,
+    output logic [31:0]                  rvfi_pc_wdata,
+    output logic [31:0]                  rvfi_mem_addr,
+    output logic [ 3:0]                  rvfi_mem_rmask,
+    output logic [ 3:0]                  rvfi_mem_wmask,
+    output logic [31:0]                  rvfi_mem_rdata,
+    output logic [31:0]                  rvfi_mem_wdata,
+`endif
+
+    // CPU Control Signals
+    input  logic                         fetch_enable_i,
+    output logic                         alert_minor_o,
+    output logic                         alert_major_o,
+    output logic                         core_sleep_o
+);
+
+  import ibex_pkg::*;
+
+  localparam bit          Lockstep          = SecureIbex;
+  localparam bit          DummyInstructions = SecureIbex;
+  localparam bit          RegFileECC        = SecureIbex;
+  localparam int unsigned RegFileDataWidth  = RegFileECC ? 32 + 7 : 32;
+  // Icache parameters
+  localparam int unsigned BusSizeECC        = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE;
+  localparam int unsigned LineSizeECC       = BusSizeECC * IC_LINE_BEATS;
+  localparam int unsigned TagSizeECC        = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
+
+  // Clock signals
+  logic                        clk;
+  logic                        core_busy_d, core_busy_q;
+  logic                        fetch_enable_q;
+  logic                        clock_en;
+  logic                        irq_pending;
+  // Core <-> Register file signals
+  logic                        dummy_instr_id;
+  logic [4:0]                  rf_raddr_a;
+  logic [4:0]                  rf_raddr_b;
+  logic [4:0]                  rf_waddr_wb;
+  logic                        rf_we_wb;
+  logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
+  logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
+  logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
+  // Core <-> RAMs signals
+  logic [IC_NUM_WAYS-1:0]      ic_tag_req;
+  logic                        ic_tag_write;
+  logic [IC_INDEX_W-1:0]       ic_tag_addr;
+  logic [TagSizeECC-1:0]       ic_tag_wdata;
+  logic [TagSizeECC-1:0]       ic_tag_rdata [IC_NUM_WAYS];
+  logic [IC_NUM_WAYS-1:0]      ic_data_req;
+  logic                        ic_data_write;
+  logic [IC_INDEX_W-1:0]       ic_data_addr;
+  logic [LineSizeECC-1:0]      ic_data_wdata;
+  logic [LineSizeECC-1:0]      ic_data_rdata [IC_NUM_WAYS];
+  // Alert signals
+  logic                        core_alert_major, core_alert_minor;
+  logic                        lockstep_alert_major, lockstep_alert_minor;
+
+  /////////////////////
+  // Main clock gate //
+  /////////////////////
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      core_busy_q <= 1'b0;
+    end else begin
+      core_busy_q <= core_busy_d;
+    end
+  end
+
+  // capture fetch_enable_i in fetch_enable_q, once for ever
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      fetch_enable_q <= 1'b0;
+    end else if (fetch_enable_i) begin
+      fetch_enable_q <= 1'b1;
+    end
+  end
+
+  assign clock_en     = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i);
+  assign core_sleep_o = ~clock_en;
+
+  prim_clock_gating core_clock_gate_i (
+      .clk_i     ( clk_i           ),
+      .en_i      ( clock_en        ),
+      .test_en_i ( test_en_i       ),
+      .clk_o     ( clk             )
+  );
+
+  ////////////////////////
+  // Core instantiation //
+  ////////////////////////
+
+  ibex_core #(
+    .PMPEnable         ( PMPEnable         ),
+    .PMPGranularity    ( PMPGranularity    ),
+    .PMPNumRegions     ( PMPNumRegions     ),
+    .MHPMCounterNum    ( MHPMCounterNum    ),
+    .MHPMCounterWidth  ( MHPMCounterWidth  ),
+    .RV32E             ( RV32E             ),
+    .RV32M             ( RV32M             ),
+    .RV32B             ( RV32B             ),
+    .BranchTargetALU   ( BranchTargetALU   ),
+    .ICache            ( ICache            ),
+    .ICacheECC         ( ICacheECC         ),
+    .BusSizeECC        ( BusSizeECC        ),
+    .TagSizeECC        ( TagSizeECC        ),
+    .LineSizeECC       ( LineSizeECC       ),
+    .BranchPredictor   ( BranchPredictor   ),
+    .DbgTriggerEn      ( DbgTriggerEn      ),
+    .DbgHwBreakNum     ( DbgHwBreakNum     ),
+    .WritebackStage    ( WritebackStage    ),
+    .SecureIbex        ( SecureIbex        ),
+    .DummyInstructions ( DummyInstructions ),
+    .RegFileECC        ( RegFileECC        ),
+    .RegFileDataWidth  ( RegFileDataWidth  ),
+    .DmHaltAddr        ( DmHaltAddr        ),
+    .DmExceptionAddr   ( DmExceptionAddr   )
+  ) u_ibex_core (
+    .clk_i (clk),
+    .rst_ni,
+
+    .hart_id_i,
+    .boot_addr_i,
+
+    .instr_req_o,
+    .instr_gnt_i,
+    .instr_rvalid_i,
+    .instr_addr_o,
+    .instr_rdata_i,
+    .instr_err_i,
+
+    .data_req_o,
+    .data_gnt_i,
+    .data_rvalid_i,
+    .data_we_o,
+    .data_be_o,
+    .data_addr_o,
+    .data_wdata_o,
+    .data_rdata_i,
+    .data_err_i,
+
+    .dummy_instr_id_o  (dummy_instr_id),
+    .rf_raddr_a_o      (rf_raddr_a),
+    .rf_raddr_b_o      (rf_raddr_b),
+    .rf_waddr_wb_o     (rf_waddr_wb),
+    .rf_we_wb_o        (rf_we_wb),
+    .rf_wdata_wb_ecc_o (rf_wdata_wb_ecc),
+    .rf_rdata_a_ecc_i  (rf_rdata_a_ecc),
+    .rf_rdata_b_ecc_i  (rf_rdata_b_ecc),
+
+    .ic_tag_req_o      (ic_tag_req),
+    .ic_tag_write_o    (ic_tag_write),
+    .ic_tag_addr_o     (ic_tag_addr),
+    .ic_tag_wdata_o    (ic_tag_wdata),
+    .ic_tag_rdata_i    (ic_tag_rdata),
+    .ic_data_req_o     (ic_data_req),
+    .ic_data_write_o   (ic_data_write),
+    .ic_data_addr_o    (ic_data_addr),
+    .ic_data_wdata_o   (ic_data_wdata),
+    .ic_data_rdata_i   (ic_data_rdata),
+
+    .irq_software_i,
+    .irq_timer_i,
+    .irq_external_i,
+    .irq_fast_i,
+    .irq_nm_i,
+    .irq_pending_o (irq_pending),
+
+    .debug_req_i,
+    .crash_dump_o,
+
+`ifdef RVFI
+    .rvfi_valid,
+    .rvfi_order,
+    .rvfi_insn,
+    .rvfi_trap,
+    .rvfi_halt,
+    .rvfi_intr,
+    .rvfi_mode,
+    .rvfi_ixl,
+    .rvfi_rs1_addr,
+    .rvfi_rs2_addr,
+    .rvfi_rs3_addr,
+    .rvfi_rs1_rdata,
+    .rvfi_rs2_rdata,
+    .rvfi_rs3_rdata,
+    .rvfi_rd_addr,
+    .rvfi_rd_wdata,
+    .rvfi_pc_rdata,
+    .rvfi_pc_wdata,
+    .rvfi_mem_addr,
+    .rvfi_mem_rmask,
+    .rvfi_mem_wmask,
+    .rvfi_mem_rdata,
+    .rvfi_mem_wdata,
+`endif
+
+    .alert_minor_o (core_alert_minor),
+    .alert_major_o (core_alert_major),
+    .core_busy_o (core_busy_d)
+  );
+
+  /////////////////////////////////
+  // Register file Instantiation //
+  /////////////////////////////////
+
+  if (RegFile == RegFileFF) begin : gen_regfile_ff
+    ibex_register_file_ff #(
+        .RV32E             ( RV32E             ),
+        .DataWidth         ( RegFileDataWidth  ),
+        .DummyInstructions ( DummyInstructions )
+    ) register_file_i (
+        .clk_i            ( clk             ),
+        .rst_ni           ( rst_ni          ),
+
+        .test_en_i        ( test_en_i       ),
+        .dummy_instr_id_i ( dummy_instr_id  ),
+
+        .raddr_a_i        ( rf_raddr_a      ),
+        .rdata_a_o        ( rf_rdata_a_ecc  ),
+        .raddr_b_i        ( rf_raddr_b      ),
+        .rdata_b_o        ( rf_rdata_b_ecc  ),
+        .waddr_a_i        ( rf_waddr_wb     ),
+        .wdata_a_i        ( rf_wdata_wb_ecc ),
+        .we_a_i           ( rf_we_wb        )
+    );
+  end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
+    ibex_register_file_fpga #(
+        .RV32E             ( RV32E             ),
+        .DataWidth         ( RegFileDataWidth  ),
+        .DummyInstructions ( DummyInstructions )
+    ) register_file_i (
+        .clk_i            ( clk             ),
+        .rst_ni           ( rst_ni          ),
+
+        .test_en_i        ( test_en_i       ),
+        .dummy_instr_id_i ( dummy_instr_id  ),
+
+        .raddr_a_i        ( rf_raddr_a      ),
+        .rdata_a_o        ( rf_rdata_a_ecc  ),
+        .raddr_b_i        ( rf_raddr_b      ),
+        .rdata_b_o        ( rf_rdata_b_ecc  ),
+        .waddr_a_i        ( rf_waddr_wb     ),
+        .wdata_a_i        ( rf_wdata_wb_ecc ),
+        .we_a_i           ( rf_we_wb        )
+    );
+  end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
+    ibex_register_file_latch #(
+        .RV32E             ( RV32E             ),
+        .DataWidth         ( RegFileDataWidth  ),
+        .DummyInstructions ( DummyInstructions )
+    ) register_file_i (
+        .clk_i            ( clk             ),
+        .rst_ni           ( rst_ni          ),
+
+        .test_en_i        ( test_en_i       ),
+        .dummy_instr_id_i ( dummy_instr_id  ),
+
+        .raddr_a_i        ( rf_raddr_a      ),
+        .rdata_a_o        ( rf_rdata_a_ecc  ),
+        .raddr_b_i        ( rf_raddr_b      ),
+        .rdata_b_o        ( rf_rdata_b_ecc  ),
+        .waddr_a_i        ( rf_waddr_wb     ),
+        .wdata_a_i        ( rf_wdata_wb_ecc ),
+        .we_a_i           ( rf_we_wb        )
+    );
+  end
+
+  ////////////////////////
+  // Rams Instantiation //
+  ////////////////////////
+
+  if (ICache) begin : gen_rams
+
+    for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
+      // Tag RAM instantiation
+      prim_ram_1p #(
+        .Width           (TagSizeECC),
+        .Depth           (IC_NUM_LINES),
+        .DataBitsPerMask (TagSizeECC)
+      ) tag_bank (
+        .clk_i    (clk_i),
+        .req_i    (ic_tag_req[way]),
+        .cfg_i    (ram_cfg_i),
+        .write_i  (ic_tag_write),
+        .wmask_i  ({TagSizeECC{1'b1}}),
+        .addr_i   (ic_tag_addr),
+        .wdata_i  (ic_tag_wdata),
+        .rdata_o  (ic_tag_rdata[way])
+      );
+      // Data RAM instantiation
+      prim_ram_1p #(
+        .Width           (LineSizeECC),
+        .Depth           (IC_NUM_LINES),
+        .DataBitsPerMask (LineSizeECC)
+      ) data_bank (
+        .clk_i    (clk_i),
+        .req_i    (ic_data_req[way]),
+        .cfg_i    (ram_cfg_i),
+        .write_i  (ic_data_write),
+        .wmask_i  ({LineSizeECC{1'b1}}),
+        .addr_i   (ic_data_addr),
+        .wdata_i  (ic_data_wdata),
+        .rdata_o  (ic_data_rdata[way])
+      );
+    end
+
+  end else begin : gen_norams
+
+    prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg;
+    logic unused_ram_inputs;
+
+    assign unused_ram_cfg    = ram_cfg_i;
+    assign unused_ram_inputs = 1'b0 & (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) &
+                               (|ic_tag_wdata) & (|ic_data_req) & ic_data_write & (|ic_data_addr) &
+                               (|ic_data_wdata);
+    assign ic_tag_rdata      = '{default:'b0};
+    assign ic_data_rdata     = '{default:'b0};
+
+  end
+
+  // Redundant lockstep core implementation
+  if (Lockstep) begin : gen_lockstep
+    ibex_lockstep #(
+      .PMPEnable         ( PMPEnable         ),
+      .PMPGranularity    ( PMPGranularity    ),
+      .PMPNumRegions     ( PMPNumRegions     ),
+      .MHPMCounterNum    ( MHPMCounterNum    ),
+      .MHPMCounterWidth  ( MHPMCounterWidth  ),
+      .RV32E             ( RV32E             ),
+      .RV32M             ( RV32M             ),
+      .RV32B             ( RV32B             ),
+      .BranchTargetALU   ( BranchTargetALU   ),
+      .ICache            ( ICache            ),
+      .ICacheECC         ( ICacheECC         ),
+      .BusSizeECC        ( BusSizeECC        ),
+      .TagSizeECC        ( TagSizeECC        ),
+      .LineSizeECC       ( LineSizeECC       ),
+      .BranchPredictor   ( BranchPredictor   ),
+      .DbgTriggerEn      ( DbgTriggerEn      ),
+      .DbgHwBreakNum     ( DbgHwBreakNum     ),
+      .WritebackStage    ( WritebackStage    ),
+      .SecureIbex        ( SecureIbex        ),
+      .DummyInstructions ( DummyInstructions ),
+      .RegFileECC        ( RegFileECC        ),
+      .RegFileDataWidth  ( RegFileDataWidth  ),
+      .DmHaltAddr        ( DmHaltAddr        ),
+      .DmExceptionAddr   ( DmExceptionAddr   )
+    ) u_ibex_lockstep (
+      .clk_i             (clk),
+      .rst_ni            (rst_ni),
+
+      .hart_id_i         (hart_id_i),
+      .boot_addr_i       (boot_addr_i),
+
+      .instr_req_i       (instr_req_o),
+      .instr_gnt_i       (instr_gnt_i),
+      .instr_rvalid_i    (instr_rvalid_i),
+      .instr_addr_i      (instr_addr_o),
+      .instr_rdata_i     (instr_rdata_i),
+      .instr_err_i       (instr_err_i),
+
+      .data_req_i        (data_req_o),
+      .data_gnt_i        (data_gnt_i),
+      .data_rvalid_i     (data_rvalid_i),
+      .data_we_i         (data_we_o),
+      .data_be_i         (data_be_o),
+      .data_addr_i       (data_addr_o),
+      .data_wdata_i      (data_wdata_o),
+      .data_rdata_i      (data_rdata_i),
+      .data_err_i        (data_err_i),
+
+      .dummy_instr_id_i  (dummy_instr_id),
+      .rf_raddr_a_i      (rf_raddr_a),
+      .rf_raddr_b_i      (rf_raddr_b),
+      .rf_waddr_wb_i     (rf_waddr_wb),
+      .rf_we_wb_i        (rf_we_wb),
+      .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc),
+      .rf_rdata_a_ecc_i  (rf_rdata_a_ecc),
+      .rf_rdata_b_ecc_i  (rf_rdata_b_ecc),
+
+      .ic_tag_req_i      (ic_tag_req),
+      .ic_tag_write_i    (ic_tag_write),
+      .ic_tag_addr_i     (ic_tag_addr),
+      .ic_tag_wdata_i    (ic_tag_wdata),
+      .ic_tag_rdata_i    (ic_tag_rdata),
+      .ic_data_req_i     (ic_data_req),
+      .ic_data_write_i   (ic_data_write),
+      .ic_data_addr_i    (ic_data_addr),
+      .ic_data_wdata_i   (ic_data_wdata),
+      .ic_data_rdata_i   (ic_data_rdata),
+
+      .irq_software_i    (irq_software_i),
+      .irq_timer_i       (irq_timer_i),
+      .irq_external_i    (irq_external_i),
+      .irq_fast_i        (irq_fast_i),
+      .irq_nm_i          (irq_nm_i),
+      .irq_pending_i     (irq_pending),
+
+      .debug_req_i       (debug_req_i),
+      .crash_dump_i      (crash_dump_o),
+
+      .alert_minor_o     (lockstep_alert_minor),
+      .alert_major_o     (lockstep_alert_major),
+      .core_busy_i       (core_busy_d)
+    );
+  end else begin : gen_no_lockstep
+    assign lockstep_alert_major = 1'b0;
+    assign lockstep_alert_minor = 1'b0;
+  end
+
+  // TODO - need a config to reset all registers before the lockstep alert can be used
+  logic unused_lockstep_alert_major;
+  assign unused_lockstep_alert_major = lockstep_alert_major;
+
+  assign alert_major_o = core_alert_major;// | lockstep_alert_major;
+  assign alert_minor_o = core_alert_minor | lockstep_alert_minor;
+
+  `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o)
+  `ASSERT_KNOWN(IbexAlertMajorX, alert_major_o)
+
+endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
similarity index 98%
rename from hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
rename to hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
index d921ef7..b777ea9 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
@@ -6,7 +6,7 @@
  * Top level module of the ibex RISC-V core with tracing enabled
  */
 
-module ibex_core_tracing #(
+module ibex_top_tracing #(
     parameter bit                 PMPEnable        = 1'b0,
     parameter int unsigned        PMPGranularity   = 0,
     parameter int unsigned        PMPNumRegions    = 4,
@@ -107,7 +107,7 @@
   logic [31:0] rvfi_mem_rdata;
   logic [31:0] rvfi_mem_wdata;
 
-  ibex_core #(
+  ibex_top #(
     .PMPEnable        ( PMPEnable        ),
     .PMPGranularity   ( PMPGranularity   ),
     .PMPNumRegions    ( PMPNumRegions    ),
@@ -127,7 +127,7 @@
     .SecureIbex       ( SecureIbex       ),
     .DmHaltAddr       ( DmHaltAddr       ),
     .DmExceptionAddr  ( DmExceptionAddr  )
-  ) u_ibex_core (
+  ) u_ibex_top (
     .clk_i,
     .rst_ni,
 
diff --git a/hw/vendor/lowrisc_ibex/syn/README.md b/hw/vendor/lowrisc_ibex/syn/README.md
index cfb248c..4f2a37b 100644
--- a/hw/vendor/lowrisc_ibex/syn/README.md
+++ b/hw/vendor/lowrisc_ibex/syn/README.md
@@ -72,10 +72,10 @@
       - sta.log - Log of the OpenSTA run
     - `generated`
       - *.v - Ibex RTL after sv2v processing
-      - ibex_core.pre_map.v - Pre-mapping synthesis netlists
-      - ibex_core_netlist.v - Post-synthesis netlist
-      - ibex_core_netlist.sta.v - Post-synthesis netlist usable by OpenSTA
-      - ibex_core.[library-name].out.sdc - Generated .sdc timing constraints
+      - ibex_top.pre_map.v - Pre-mapping synthesis netlists
+      - ibex_top_netlist.v - Post-synthesis netlist
+      - ibex_top_netlist.sta.v - Post-synthesis netlist usable by OpenSTA
+      - ibex_top.[library-name].out.sdc - Generated .sdc timing constraints
         file
 
 If you wish to change the results directory naming or location edit
@@ -86,7 +86,7 @@
 Two files specify the timing constraints and timing related settings for the
 flow. These are used to generate a single .sdc file
 
-* `ibex_core_lr_synth_core.tcl` - This specifies the constraints on all inputs
+* `ibex_top_lr_synth_core.tcl` - This specifies the constraints on all inputs
   and outputs as a fraction of a clock cycle, the names of the clock and reset
   inputs and the desired clock period in ps
 * `ibex.[library-name].sdc` - Header to include in generated .sdc file. Settings
diff --git a/hw/vendor/lowrisc_ibex/syn/ibex_core.nangate.sdc b/hw/vendor/lowrisc_ibex/syn/ibex_top.nangate.sdc
similarity index 100%
rename from hw/vendor/lowrisc_ibex/syn/ibex_core.nangate.sdc
rename to hw/vendor/lowrisc_ibex/syn/ibex_top.nangate.sdc
diff --git a/hw/vendor/lowrisc_ibex/syn/ibex_core_abc.nangate.sdc b/hw/vendor/lowrisc_ibex/syn/ibex_top_abc.nangate.sdc
similarity index 100%
rename from hw/vendor/lowrisc_ibex/syn/ibex_core_abc.nangate.sdc
rename to hw/vendor/lowrisc_ibex/syn/ibex_top_abc.nangate.sdc
diff --git a/hw/vendor/lowrisc_ibex/syn/ibex_core_lr_synth_conf.tcl b/hw/vendor/lowrisc_ibex/syn/ibex_top_lr_synth_conf.tcl
similarity index 100%
rename from hw/vendor/lowrisc_ibex/syn/ibex_core_lr_synth_conf.tcl
rename to hw/vendor/lowrisc_ibex/syn/ibex_top_lr_synth_conf.tcl
diff --git a/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh
index ba89dc3..df73b68 100755
--- a/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh
+++ b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh
@@ -23,7 +23,7 @@
 #-------------------------------------------------------------------------
 rm -Rf build lec_out
 fusesoc --cores-root .. run --tool=icarus --target=lint \
-  --setup "lowrisc:ibex:ibex_core" > /dev/null 2>&1
+  --setup "lowrisc:ibex:ibex_top" > /dev/null 2>&1
 
 # copy all files to lec_out
 mkdir lec_out
diff --git a/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh b/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
index 9156a48..bbfd24c 100755
--- a/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
+++ b/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
@@ -47,8 +47,9 @@
   sv2v \
     --define=SYNTHESIS \
     ../rtl/*_pkg.sv \
+    ../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv \
     -I../vendor/lowrisc_ip/ip/prim/rtl \
-    -I../dv/fcov \
+    -I../vendor/lowrisc_ip/dv/sv/dv_utils \
     $file \
     > $LR_SYNTH_OUT_DIR/generated/${module}.v
 done
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
index 8e2dd10..303852f 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
@@ -5,7 +5,7 @@
 puts "=================== Flow Vars ==================="
 
 set_flow_var cell_library_path "cmos_cells.lib" "Path to cell library"
-set_flow_var top_module "ibex_core" "top module"
+set_flow_var top_module "ibex_top" "top module"
 set_flow_var out_dir "syn_out" "Output directory for synthesis"
 set_flow_var pre_map_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}.pre_map.v" "Pre-mapping netlist out"
 set_flow_var netlist_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}_netlist.v" "netlist out"
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
index 7986f32..898d624 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
@@ -17,18 +17,18 @@
 yosys "read_verilog -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
 
 if { $lr_synth_ibex_branch_target_alu } {
-  yosys "chparam -set BranchTargetALU 1 ibex_core"
+  yosys "chparam -set BranchTargetALU 1 $lr_synth_top_module"
 }
 
 if { $lr_synth_ibex_writeback_stage } {
-  yosys "chparam -set WritebackStage 1 ibex_core"
+  yosys "chparam -set WritebackStage 1 $lr_synth_top_module"
 }
 
-yosys "chparam -set RV32B $lr_synth_ibex_bitmanip ibex_core"
+yosys "chparam -set RV32B $lr_synth_ibex_bitmanip $lr_synth_top_module"
 
-yosys "chparam -set RV32M $lr_synth_ibex_multiplier ibex_core"
+yosys "chparam -set RV32M $lr_synth_ibex_multiplier $lr_synth_top_module"
 
-yosys "chparam -set RegFile $lr_synth_ibex_regfile ibex_core"
+yosys "chparam -set RegFile $lr_synth_ibex_regfile $lr_synth_top_module"
 
 yosys "synth $flatten_opt -top $lr_synth_top_module"
 yosys "opt -purge"
diff --git a/hw/vendor/lowrisc_ibex/syn/translate_timing_rpts.sh b/hw/vendor/lowrisc_ibex/syn/translate_timing_rpts.sh
index 3396a41..10ffe80 100755
--- a/hw/vendor/lowrisc_ibex/syn/translate_timing_rpts.sh
+++ b/hw/vendor/lowrisc_ibex/syn/translate_timing_rpts.sh
@@ -4,7 +4,7 @@
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
 
-./python/build_translated_names.py ibex_core ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt
+./python/build_translated_names.py ibex_top ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt
 
 for file in ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt; do
   ./python/translate_timing_csv.py $file ./$LR_SYNTH_OUT_DIR/generated
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
index c51538e..66c7185 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
@@ -9,6 +9,6 @@
   upstream:
   {
     url: https://github.com/google/riscv-dv
-    rev: 0b625258549e733082c12e5dc749f05aefb07d5a
+    rev: 59dcd8c813484eb6dcca67e7e36089fe772b9cc8
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml
index 2efccf9..de92648 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml
@@ -7,8 +7,8 @@
 on:
   push:
     branches: [ master ]
-  pull_request:
-    branches: [ master ]
+#  pull_request_target:
+#    branches: [ master ]
 
 # If you fork this repository, you must create a new Metrics project for your fork
 # and set the environment variable $METRICS_PROJECT_ID accordingly
@@ -22,5 +22,6 @@
           METRICS_CI_TOKEN: ${{ secrets.METRICS_CI_TOKEN }}
           METRICS_REGRESSION_NAME: riscv-dv_regression
           METRICS_PROJECT_ID: ${{ secrets.METRICS_PROJECT_ID }}
+          PR_NUMBER: ${{ github.event.pull_request.number }}
         shell: bash
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.metrics.json b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.metrics.json
index 7b688cb..1ecbb0f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.metrics.json
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.metrics.json
@@ -1,15 +1,8 @@
 {
-    "variables": {
-        "DSIM" : "${DSIM_HOME}/bin/dsim",
-        "DSIM_LIB_PATH" : "${DSIM_HOME}/uvm-1.2/src/dpi",
-        "RISCV_GCC" : "${RISCV_TOOLCHAIN}/bin/riscv-none-embed-gcc",
-        "RISCV_OBJCOPY" : "${RISCV_TOOLCHAIN}/bin/riscv-none-embed-objcopy",
-        "OVPSIM_PATH" : "/customer-tools/riscv-ovpsim/bin/Linux64"
-    },
     "builds": {
       "list": [{
         "name": "rv32imc",
-        "image": "ibex-dsim-toolchain:latest",
+        "image": "ibex-toolchain:v2",
         "memory" : "1",  
         "cmd": "python3 run.py --test riscv_arithmetic_basic_test --simulator dsim --output out --verbose --co",
         "wavesCmd": "python3 run.py --test riscv_arithmetic_basic_test --simulator dsim --output out --verbose --co"
@@ -27,8 +20,8 @@
                   "name": "riscv_arithmetic_basic_test",
                   "build": "rv32imc",
                   "iterations": 2,
-                  "cmd": "cd /mux-flow/results; python3 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss ovpsim --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim",
-                  "wavesCmd": "python3 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss ovpsim --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -rf out/dsim",
+                  "cmd": "cd /mux-flow/results; python3 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss spike --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim",
+                  "wavesCmd": "python3 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss spike --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -rf out/dsim",
                   "logFile": "simulation.log",
                   "metricsFile": "metrics.db",
                   "isPass": "Test passed",
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
index 1692652..9ed8f85 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
@@ -30,55 +30,55 @@
 
     @vsc.constraint
     def rvc_csr_c(self):
-        # Registers specified by the three-bit rs1’, rs2’, and rd’
-        with vsc.implies(self.format.inside(vsc.rangelist(riscv_instr_format_t.CIW_FORMAT,
+        # Registers specified by the three-bit rs1, rs2, and rd
+        with vsc.if_then(self.format.inside(vsc.rangelist(riscv_instr_format_t.CIW_FORMAT,
                                                           riscv_instr_format_t.CL_FORMAT,
                                                           riscv_instr_format_t.CS_FORMAT,
                                                           riscv_instr_format_t.CB_FORMAT,
                                                           riscv_instr_format_t.CA_FORMAT))):
-            with vsc.implies(self.has_rs1 == 1):
+            with vsc.if_then(self.has_rs1 == 1):
                 self.rs1.inside(vsc.rangelist(riscv_reg_t.S0, riscv_reg_t.S1, riscv_reg_t.A0,
                                               riscv_reg_t.A1, riscv_reg_t.A2, riscv_reg_t.A3,
                                               riscv_reg_t.A4, riscv_reg_t.A5))
-            with vsc.implies(self.has_rs2 == 1):
+            with vsc.if_then(self.has_rs2 == 1):
                 self.rs2.inside(vsc.rangelist(riscv_reg_t.S0, riscv_reg_t.S1, riscv_reg_t.A0,
                                               riscv_reg_t.A1, riscv_reg_t.A2, riscv_reg_t.A3,
                                               riscv_reg_t.A4, riscv_reg_t.A5))
-            with vsc.implies(self.has_rd == 1):
+            with vsc.if_then(self.has_rd == 1):
                 self.rd.inside(vsc.rangelist(riscv_reg_t.S0, riscv_reg_t.S1, riscv_reg_t.A0,
                                              riscv_reg_t.A1, riscv_reg_t.A2, riscv_reg_t.A3,
                                              riscv_reg_t.A4, riscv_reg_t.A5))
         # _ADDI16SP is only valid when rd == SP
-        with vsc.implies(self.instr_name == riscv_instr_name_t.C_ADDI16SP):
+        with vsc.if_then(self.instr_name == riscv_instr_name_t.C_ADDI16SP):
             self.rd == riscv_reg_t.SP
-        with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_JR,
+        with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_JR,
                                                               riscv_instr_name_t.C_JALR))):
             self.rs1 != riscv_reg_t.ZERO
             self.rs2 == riscv_reg_t.ZERO
 
     @vsc.constraint
     def imm_val_c(self):
-        with vsc.implies(self.imm_type.inside(vsc.rangelist(imm_t.NZIMM, imm_t.NZUIMM))):
+        with vsc.if_then(self.imm_type.inside(vsc.rangelist(imm_t.NZIMM, imm_t.NZUIMM))):
             self.imm[5:0] != 0
-            with vsc.implies(self.instr_name == riscv_instr_name_t.C_LUI):
+            with vsc.if_then(self.instr_name == riscv_instr_name_t.C_LUI):
                 self.imm[31:5] == 0
-            with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_SRAI,
+            with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_SRAI,
                                                                   riscv_instr_name_t.C_SRLI,
                                                                   riscv_instr_name_t.C_SLLI))):
                 self.imm[31:5] == 0
-            with vsc.implies(self.instr_name == riscv_instr_name_t.C_ADDI4SPN):
+            with vsc.if_then(self.instr_name == riscv_instr_name_t.C_ADDI4SPN):
                 self.imm[1:0] == 0
 
     # C_JAL is RV32C only instruction
     @vsc.constraint
     def jal_c(self):
-        with vsc.implies(self.XLEN != 32):
+        with vsc.if_then(self.XLEN != 32):
             self.instr_name != riscv_instr_name_t.C_JAL
 
     # Avoid generating HINT or illegal instruction by default as it's not supported by the compiler
     @vsc.constraint
     def no_hint_illegal_instr_c(self):
-        with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_ADDI,
+        with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_ADDI,
                                                               riscv_instr_name_t.C_ADDIW,
                                                               riscv_instr_name_t.C_LI,
                                                               riscv_instr_name_t.C_LUI,
@@ -90,12 +90,12 @@
                                                               riscv_instr_name_t.C_ADD,
                                                               riscv_instr_name_t.C_LWSP))):
             self.rd != riscv_reg_t.ZERO
-        with vsc.implies(self.instr_name == riscv_instr_name_t.C_JR):
+        with vsc.if_then(self.instr_name == riscv_instr_name_t.C_JR):
             self.rs1 != riscv_reg_t.ZERO
-        with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_ADD,
+        with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.C_ADD,
                                                               riscv_instr_name_t.C_MV))):
             self.rs2 != riscv_reg_t.ZERO
-        with vsc.implies(self.instr_name == riscv_instr_name_t.C_LUI):
+        with vsc.if_then(self.instr_name == riscv_instr_name_t.C_LUI):
             self.rd != riscv_reg_t.SP
 
     def set_imm_len(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
index ff1639a..74d922c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
@@ -98,16 +98,16 @@
 
     @vsc.constraint
     def imm_c(self):
-        with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.SLLIW,
+        with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.SLLIW,
                                                               riscv_instr_name_t.SRLIW,
                                                               riscv_instr_name_t.SRAIW))):
             self.imm[11:5] == 0
-        with vsc.implies(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.SLLI,
+        with vsc.if_then(self.instr_name.inside(vsc.rangelist(riscv_instr_name_t.SLLI,
                                                               riscv_instr_name_t.SRLI,
                                                               riscv_instr_name_t.SRAI))):
-            with vsc.implies(self.XLEN == 32):
+            with vsc.if_then(self.XLEN == 32):
                 self.imm[11:5] == 0
-            with vsc.implies(self.XLEN != 32):
+            with vsc.if_then(self.XLEN != 32):
                 self.imm[11:6] == 0
 
     @classmethod
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
index abf8cd7..cf751b3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
@@ -22,7 +22,9 @@
 from pygen_src.riscv_instr_pkg import (pkg_ins, privileged_reg_t,
                                        privileged_mode_t, mtvec_mode_t,
                                        misa_ext_t, riscv_instr_group_t,
-                                       satp_mode_t)
+                                       satp_mode_t, exception_cause_t)
+from pygen_src.riscv_signature_pkg import (signature_type_t, core_status_t,
+                                           test_result_t)
 from pygen_src.riscv_instr_gen_config import cfg
 from pygen_src.riscv_data_page_gen import riscv_data_page_gen
 from pygen_src.riscv_privileged_common_seq import riscv_privileged_common_seq
@@ -83,7 +85,8 @@
                 self.gen_load_fault_handler(hart)
                 # Store fault handler
                 self.gen_store_fault_handler(hart)
-                self.gen_test_done()
+                if hart == 0:
+                    self.gen_test_done()
 
             # Generate main program
             gt_lbl_str = pkg_ins.get_label("main", hart)
@@ -96,7 +99,7 @@
             self.generate_directed_instr_stream(hart=hart,
                                                 label=self.main_program[hart].label_name,
                                                 original_instr_cnt=
-                                                    self.main_program[hart].instr_cnt,
+                                                self.main_program[hart].instr_cnt,
                                                 min_insert_cnt=1,
                                                 instr_stream=self.main_program[hart].directed_instr)
             self.main_program[hart].gen_instr(is_main_program=1, no_branch=cfg.no_branch_jump)
@@ -121,17 +124,26 @@
             logging.info("Main/sub program generation...done")
             # program end
             self.gen_program_end(hart)
-            for hart in range(cfg.num_of_harts):
-                self.gen_data_page_begin(hart)
-                if not cfg.no_data_page:
-                    self.gen_data_page(hart)
-                    if(hart == 0 and riscv_instr_group_t.RV32A
-                                         in rcs.supported_isa):
-                        self.gen_data_page(hart, amo = 1)
-
+            if not cfg.bare_program_mode:
+                # Generate debug rom section
+                if rcs.support_debug_mode:
+                    self.gen_debug_rom(hart)
+                self.gen_section(pkg_ins.hart_prefix(hart) + "instr_end", ["nop"])
+        for hart in range(cfg.num_of_harts):
+            # Starting point of data section
+            self.gen_data_page_begin(hart)
+            if not cfg.no_data_page:
+                # User data section
+                self.gen_data_page(hart)
+                # AMO memory region
+                if(hart == 0 and riscv_instr_group_t.RV32A in rcs.supported_isa):
+                    self.gen_data_page(hart, amo = 1)
             self.gen_stack_section(hart)
             if not cfg.bare_program_mode:
+                # Generate kernel program/data/stack section
                 self.gen_kernel_sections(hart)
+                # Page table
+                self.gen_page_table_section(hart)
 
     def gen_kernel_sections(self, hart):
         if rcs.SATP_MODE != satp_mode_t.BARE:
@@ -241,14 +253,14 @@
             self.instr_stream.push_back(".popsection;")
 
     def gen_init_section(self, hart):
-        string = pkg_ins.format_string("init:", pkg_ins.LABEL_STR_LEN)
+        string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
         self.instr_stream.append(string)
         if cfg.enable_floating_point:
             self.init_floating_point_gpr()
         self.init_gpr()
         # Init stack pointer to point to the end of the user stack
         string = "{}la x{}, {}user_stack_end".format(
-            pkg_ins.indent, cfg.sp.value, pkg_ins.hart_prefix(hart))
+            pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart))
         self.instr_stream.append(string)
         if cfg.enable_vector_extension:
             self.init_vector_engine()
@@ -306,10 +318,10 @@
                 sys.exit(1)
         if privileged_mode_t.SUPERVISOR_MODE.name in rcs.supported_privileged_mode:
             misa[misa_ext_t.MISA_EXT_S] = 1
-        self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value,
+        self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0],
                                                        hex(misa.get_val())))
         self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, hex(privileged_reg_t.MISA),
-                                                         cfg.gpr[0].value))
+                                                         cfg.gpr[0]))
 
     def core_is_initialized(self):
         pass
@@ -346,9 +358,9 @@
 
     def init_floating_point_gpr_with_spf(self, int_floating_gpr):
         imm = self.get_rand_spf_value()
-        li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value, hex(imm))
+        li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0], hex(imm))
         fmv_instr = "{}fmv.w.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr,
-                                                cfg.gpr[0].value)
+                                                cfg.gpr[0])
         self.instr_stream.extend((li_instr, fmv_instr))
 
     def init_floating_point_gpr_with_dpf(self, int_floating_gpr):
@@ -394,24 +406,24 @@
     def gen_register_dump(self):
         string = ""
         # load base address
-        string = "{}la x{}, _start".format(pkg_ins.indent, cfg.gpr[0].value)
+        string = "{}la x{}, _start".format(pkg_ins.indent, cfg.gpr[0])
         self.instr_stream.append(string)
 
         # Generate sw/sd instructions
         for i in range(32):
             if rcs.XLEN == 64:
                 string = "{}sd x{}, {}(x{})".format(
-                    pkg_ins.indent, i, i * (rcs.XLEN / 8), cfg.gpr[0].value)
+                    pkg_ins.indent, i, i * (rcs.XLEN / 8), cfg.gpr[0])
             else:
                 string = "{}sw x{}, {}(x{})".format(
-                    pkg_ins.indent, i, int(i * (rcs.XLEN / 8)), cfg.gpr[0].value)
+                    pkg_ins.indent, i, int(i * (rcs.XLEN / 8)), cfg.gpr[0])
             self.instr_stream.append(string)
 
     def pre_enter_privileged_mode(self, hart):
         instr = []
         string = []
 
-        string.append("la x{}, {}kernel_stack_end".format(cfg.tp.value, pkg_ins.hart_prefix(hart)))
+        string.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart)))
         self.gen_section(pkg_ins.get_label("kernel_sp", hart), string)
 
         if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE):
@@ -429,7 +441,7 @@
         privil_seq = riscv_privileged_common_seq()
         for i in range(len(rcs.supported_privileged_mode)):
             instr = []
-            csr_handshake = []
+            # csr_handshake = []
             if rcs.supported_privileged_mode[i] != cfg.init_privileged_mode:
                 continue
             logging.info("Generating privileged mode routing for {}"
@@ -445,17 +457,15 @@
 
     def setup_epc(self, hart):
         instr = []
-        instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart)))
+        instr.append("la x{}, {}init".format(cfg.gpr[0], pkg_ins.hart_prefix(hart)))
         if cfg.virtual_addr_translation_on:
             # For supervisor and user mode, use virtual address instead of physical address.
             # Virtual address starts from address 0x0, here only the lower 12 bits are kept
             # as virtual address offset.
-            instr.append("slli x{}, x{}, {}".format(cfg.gpr[0].value,
-                                                    cfg.gpr[0].value, rcs.XLEN - 12) +
-                         "srli x{}, x{}, {}".format(cfg.gpr[0].value,
-                                                    cfg.gpr[0].value, rcs.XLEN - 12))
+            instr.append("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12) +
+                         "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12))
         mode_name = cfg.init_privileged_mode.name
-        instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0].value))
+        instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0]))
         if not rcs.support_pmp:
             instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower()))
         self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
@@ -498,17 +508,14 @@
             tvec_name = trap_vec_reg.name
             tvec_name = tvec_name.lower()
             instr.append("la x{}, {}{}_handler".format(
-                cfg.gpr[0].value, pkg_ins.hart_prefix(hart), tvec_name))
+                cfg.gpr[0], pkg_ins.hart_prefix(hart), tvec_name))
             if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE):
-                instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0].value,
-                                                          cfg.gpr[0].value, rcs.XLEN - 20) +
-                             "srli x{}, x{}, {}".format(cfg.gpr[0].value,
-                                                        cfg.gpr[0].value, rcs.XLEN - 20))
+                instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20) +
+                             "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20))
 
-            instr.append("ori x{}, x{}, {}".format(
-                cfg.gpr[0].value, cfg.gpr[0].value, cfg.mtvec_mode.value))
+            instr.append("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode))
             instr.append("csrw {}, x{} # {}".format(
-                hex(trap_vec_reg.value), cfg.gpr[0].value, trap_vec_reg.name))
+                hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name))
 
         self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
 
@@ -519,6 +526,7 @@
             self.gen_instr_fault_handler(hart)
             self.gen_load_fault_handler(hart)
             self.gen_store_fault_handler(hart)
+        self.gen_illegal_instr_handler(hart)
 
     def gen_trap_handlers(self, hart):
         self.gen_trap_handler_section(hart, "m", privileged_reg_t.MCAUSE,
@@ -529,7 +537,7 @@
 
     def gen_trap_handler_section(self, hart, mode, cause, tvec,
                                  tval, epc, scratch, status, ie, ip):
-        is_interrupt = 1
+        # is_interrupt = 1
         tvec_name = ""
         instr = []
         if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
@@ -545,15 +553,15 @@
             # certain fields compared with the RTL processor.
             if cfg.check_xstatus:
                 instr.append("csrr x{}, {} # {}".format(
-                    cfg.gpr[0].value, hex(status.value), status.name))
-            instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0].value, hex(cause.value),
+                    cfg.gpr[0], hex(status), status.name))
+            instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(cause),
                                                       cause.name) +
-                         "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0].value,
-                                                        cfg.gpr[0].value, rcs.XLEN - 1) +
-                         "{}bne x{}, x0, {}{}mode_instr_handler".format(pkg_ins.indent,
-                                                                        cfg.gpr[0].value,
-                                                                        pkg_ins.hart_prefix(hart),
-                                                                        mode))
+                         "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0],
+                                                        cfg.gpr[0], rcs.XLEN - 1) +
+                         "{}bne x{}, x0, {}{}mode_intr_handler".format(pkg_ins.indent,
+                                                                       cfg.gpr[0],
+                                                                       pkg_ins.hart_prefix(hart),
+                                                                       mode))
         # The trap handler will occupy one 4KB page, it will be allocated one entry in
         # the page table with a specific privileged mode.
 
@@ -564,16 +572,68 @@
 
         tvec_name = tvec.name
         self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr)
-
-        # TODO Exception handler
+        # TODO Exception handlers
         instr = []
         if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
-            pkg_ins.push_gpr_to_kernel_stack(
-                status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
+            pkg_ins.push_gpr_to_kernel_stack(status, scratch,
+                                             cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
+        self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+                                     core_status_t.HANDLING_EXCEPTION)
+        # The trap is caused by an exception, read back xCAUSE, xEPC to see if these
+        # CSR values are set properly. The checking is done by comparing against the log
+        # generated by ISA simulator (spike).
+        instr.extend(("csrr x{}, 0x{} # {}".format(cfg.gpr[0], epc, epc.name),
+                      "csrr x{}, 0x{} # {}".format(cfg.gpr[0], cause, cause.name),
+                      # Illegal instruction exception
+                      "li x{}, {} # ILLEGAL_INSTRUCTION".format(
+                      cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)),
+                      "beq x{}, x{}, {}illegal_instr_handler".format(
+                      cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)),
+                      # Skip checking tval for illegal instruction as it's implementation specific
+                      "csrr x{}, {} # {}".format(cfg.gpr[1], hex(tval), tval.name),
+                      # use JALR to jump to test_done.
+                      "1: la x{}, test_done".format(cfg.scratch_reg),
+                      "jalr x1, x{}, 0".format(cfg.scratch_reg)))
+        self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
 
     def gen_interrupt_vector_table(self, hart, mode, status, cause, ie,
                                    ip, scratch, instr):
-        pass
+        '''In vector mode, the BASE address is shared between interrupt 0 and exception handling.
+           When vectored interrupts are enabled, interrupt cause 0, which corresponds to user-mode
+           software interrupts, are vectored to the same location as synchronous exceptions. This
+           ambiguity does not arise in practice, since user-mode software interrupts are either
+           disabled or delegated'''
+        instr.extend((".option norvc;", "j {}{}mode_exception_handler".format(
+            pkg_ins.hart_prefix(hart), mode)))
+        # Redirect the interrupt to the corresponding interrupt handler
+        for i in range(1, rcs.max_interrupt_vector_num):
+            instr.append("j {}{}mode_intr_vector_{}".format(pkg_ins.hart_prefix(hart), mode, i))
+        if not cfg.disable_compressed_instr:
+            instr.append(".option rvc;")
+        for i in range(1, rcs.max_interrupt_vector_num):
+            intr_handler = []
+            pkg_ins.push_gpr_to_kernel_stack(
+                status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, intr_handler)
+            self.gen_signature_handshake(instr=intr_handler,
+                                         signature_type=signature_type_t.CORE_STATUS,
+                                         core_status=core_status_t.HANDLING_IRQ)
+            intr_handler.extend(("csrr x{}, {} # {}".format(
+                                 cfg.gpr[0], hex(cause), cause.name),
+                                 # Terminate the test if xCause[31] != 0 (indicating exception)
+                                 "srli x{}, x{}, {}".format(
+                                 cfg.gpr[0], cfg.gpr[0], hex(rcs.XLEN - 1)),
+                                 "beqz x{}, 1f".format(cfg.gpr[0])))
+            csr_list = [status, cause, ie, ip]
+            for csr_t in csr_list:
+                self.gen_signature_handshake(
+                    instr=intr_handler, signature_type=signature_type_t.WRITE_CSR, csr=csr_t)
+
+            # Jump to commmon interrupt handling routine
+            intr_handler.extend(("j {}{}mode_intr_handler".format(pkg_ins.hart_prefix(hart), mode),
+                                 "1: la x{}, test_done".format(cfg.scratch_reg),
+                                 "jalr x0, x{}, 0".format(cfg.scratch_reg)))
+            self.gen_section(pkg_ins.get_label(
+                "{}mode_intr_vector_{}".format(mode, i), hart), intr_handler)
 
     def gen_ecall_handler(self, hart):
         string = ""
@@ -590,7 +650,17 @@
         pass
 
     def gen_illegal_instr_handler(self, hart):
-        pass
+        instr = []
+        self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+                                     core_status_t.ILLEGAL_INSTR_EXCEPTION)
+        self.gen_signature_handshake(instr, signature_type_t.WRITE_CSR, privileged_reg_t.MCAUSE)
+        instr.extend(("csrr  x{}, {}".format(cfg.gpr[0], hex(privileged_reg_t.MEPC)),
+                      "addi  x{}, x{}, 4".format(cfg.gpr[0], cfg.gpr[0]),
+                      "csrw  {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0])))
+        pkg_ins.pop_gpr_from_kernel_stack(privileged_reg_t.MSTATUS, privileged_reg_t.MSCRATCH,
+                                          cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
+        instr.append("mret")
+        self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart), instr)
 
     def gen_instr_fault_handler(self, hart):
         pass
@@ -612,7 +682,7 @@
 
     def gen_interrupt_handler_section(self, mode, hart):
         interrupt_handler_instr = []
-        ls_unit = "w" if rcs.XLEN == 32 else "d"
+        # ls_unit = "w" if rcs.XLEN == 32 else "d"
         if mode < cfg.init_privileged_mode:
             return
         if(mode is privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)):
@@ -640,45 +710,45 @@
             sys.exit(1)
 
         if cfg.enable_nested_interrupt:
-            interrupt_handler_instr.append("csrr x%0d, 0x%0x" % (cfg.gpr[0].value, scratch.value))
-            interrupt_handler_instr.append("bgtz x%0d, 1f" % (cfg.gpr[0].value))
-            interrupt_handler_instr.append("csrwi 0x%0x, 0x1" % (scratch.value))
+            interrupt_handler_instr.append("csrr x{}, {}".format(cfg.gpr[0], hex(scratch)))
+            interrupt_handler_instr.append("bgtz x{}, 1f".format(cfg.gpr[0]))
+            interrupt_handler_instr.append("csrwi {}, 0x1".format(hex(scratch)))
 
             if status == privileged_reg_t.MSTATUS:
-                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 8))
+                interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(8)))
             elif status == privileged_reg_t.SSTATUS:
-                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 2))
+                interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(2)))
             elif status == privileged_reg_t.USTATUS:
-                interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 1))
+                interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(1)))
             else:
                 logging.critical("Unsupported status {}".format(status.name))
                 sys.exit(1)
 
-            interrupt_handler_instr.append("1: csrwi 0x%0x,0" % (scratch.value))
+            interrupt_handler_instr.append("1: csrwi {},0".format(hex(scratch)))
 
-        to_extend_interrupt_hanlder_instr = ["csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
-                                                                           status.value,
-                                                                           status.name),
-                                             "csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
-                                                                           ie.value, ie.name),
-                                             "csrr  x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
-                                                                           ip.value, ip.name),
-                                             "csrrc x%0d, 0x%0x, x%0d # %0s;" % (cfg.gpr[0].value,
-                                                                                 ip.value,
-                                                                                 cfg.gpr[0].value,
-                                                                                 ip.name)]
+        to_extend_interrupt_hanlder_instr = ["csrr  x{}, {} # {};".format(cfg.gpr[0],
+                                                                          hex(status),
+                                                                          status.name),
+                                             "csrr  x{}, {} # {};".format(cfg.gpr[0],
+                                                                          hex(ie), ie.name),
+                                             "csrr  x{}, {} # {};".format(cfg.gpr[0],
+                                                                          hex(ip), ip.name),
+                                             "csrrc x{}, {}, x{} # {};".format(cfg.gpr[0],
+                                                                               hex(ip),
+                                                                               cfg.gpr[0],
+                                                                               ip.name)]
         interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
         self.gen_plic_section(interrupt_handler_instr)
         pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                           cfg.sp, cfg.tp, interrupt_handler_instr)
-        interrupt_handler_instr.append("%0sret;" % (mode_prefix))
+        interrupt_handler_instr.append("{}ret;".format(mode_prefix))
 
         if rcs.SATP_MODE != satp_mode_t.BARE:
             self.instr_stream.append(".align 12")
         else:
             self.instr_stream.append(".align 2")
 
-        self.gen_section(pkg_ins.get_label("%0smode_instr_handler" %
+        self.gen_section(pkg_ins.get_label("%0smode_intr_handler" %
                                            (mode_prefix), hart), interrupt_handler_instr)
 
     def format_section(self, instr):
@@ -702,11 +772,61 @@
             file.write("{}\n".format(items))
 
         file.close()
-        logging.info("%0s is generated", test_name)
+        logging.info("{} is generated".format(test_name))
 
-    def gen_signature_handshake(self, instr, signature_type, core_status = "INITIALIZED",
-                                test_result = "TEST_FAIL", csr = "MSCRATCH", addr_label = ""):
-        pass
+    def gen_signature_handshake(self, instr, signature_type,
+                                core_status=core_status_t.INITIALIZED,
+                                test_result=test_result_t.TEST_FAIL,
+                                csr=privileged_reg_t.MSCRATCH,
+                                addr_label = ""):
+        if cfg.require_signature_addr:
+            instr.extend(("li x{}, {}".format(cfg.gpr[1], hex(cfg.signature_addr))))
+            # A single data word is written to the signature address.
+            # Bits [7:0] contain the signature_type of CORE_STATUS, and the upper
+            # XLEN-8 bits contain the core_status_t data.
+            if signature_type == signature_type_t.CORE_STATUS:
+                instr.extend(("li x{}, {}".format(cfg.gpr[0], hex(core_status)),
+                              "slli x{}, x{}, 8".format(cfg.gpr[0], cfg.gpr[0]),
+                              "addi x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0],
+                                                         hex(signature_type)),
+                              "sw x{}, 0(x{})".format(cfg.gpr[0], cfg.gpr[1])))
+            # A single data word is written to the signature address.
+            # Bits [7:0] contain the signature_type of TEST_RESULT, and the upper
+            # XLEN-8 bits contain the test_result_t data.
+            elif signature_type == test_result_t.TEST_RESULT:
+                instr.extend(("li x{}, {}".format(cfg.gpr[0], hex(test_result)),
+                              "slli x{}, x{}, 8".format(cfg.gpr[0], cfg.gpr[0]),
+                              "addi x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0],
+                                                         hex(signature_type)),
+                              "sw x{}, 0(x{})".format(cfg.gpr[0], cfg.gpr[1])))
+            # The first write to the signature address contains just the
+            # signature_type of WRITE_GPR.
+            # It is followed by 32 consecutive writes to the signature address,
+            # each writing the data contained in one GPR, starting from x0 as the
+            # first write, and ending with x31 as the 32nd write.
+            elif signature_type == signature_type_t.WRITE_GPR:
+                instr.extend(("li x{}, {}".format(cfg.gpr[0], hex(signature_type)),
+                              "sw x{}, 0(x{})".format(cfg.gpr[0], cfg.gpr[1])))
+                for i in range(32):
+                    instr.append("sw x{},0(x{})".format(i, cfg.gpr[1]))
+            # The first write to the signature address contains the
+            # signature_type of WRITE_CSR in bits [7:0], and the CSR address in
+            # the upper XLEN-8 bits.
+            # It is followed by a second write to the signature address,
+            # containing the data stored in the specified CSR.
+            elif signature_type == signature_type_t.WRITE_CSR:
+                if csr not in rcs.implemented_csr:
+                    return
+                instr.extend(("li x{}, {}".format(cfg.gpr[0], hex(csr)),
+                              "slli x{}, x{}, 8".format(cfg.gpr[0], cfg.gpr[0]),
+                              "addi x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0],
+                                                         hex(signature_type)),
+                              "sw x{}, 0(x{})".format(cfg.gpr[0], cfg.gpr[1]),
+                              "csrr x{}, {}".format(cfg.gpr[0], hex(csr)),
+                              "sw x{}, 0(x{})".format(cfg.gpr[0], cfg.gpr[1])))
+            else:
+                logging.critical("signature_type is not defined")
+                sys.exit(1)
 
     def add_directed_instr_stream(self, name, ratio):
         self.directed_instr_stream_ratio[name] = ratio
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
index dcd2c62..03a4499 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
@@ -23,6 +23,7 @@
     def __init__(self):
         self.data_page_str = []
         self.mem_region_setting = defaultdict(list)
+
     @staticmethod
     def gen_data(idx, pattern, num_of_bytes, data):
         temp_data = 0
@@ -38,8 +39,6 @@
     def gen_data_page(self, hart_id, pattern, is_kernel=0, amo=0):
         tmp_str = ""
         temp_data = []
-        tmp_data = []
-        page_cnt = 0
         page_size = 0
         self.data_page_str.clear()
         if is_kernel:
@@ -49,30 +48,32 @@
         else:
             self.mem_region_setting = cfg.mem_region
         for i in range(len(self.mem_region_setting)):
+            logging.info("mem_region_setting {}".format(self.mem_region_setting[i]))
+        for i in range(len(self.mem_region_setting)):
             logging.info("Generate data section: {} size:0x{} xwr:0x{}".format(
-                         self.mem_region_setting[i]["name"],
-                         self.mem_region_setting[i]["size_in_bytes"],
-                         self.mem_region_setting[i]["xwr"]))
+                         self.mem_region_setting[i].name,
+                         self.mem_region_setting[i].size_in_bytes,
+                         self.mem_region_setting[i].xwr))
             if amo:
                 if cfg.use_push_data_section:
                     self.data_page_str.append(".pushsection .{},\"aw\",@progbits;"
-                                              .format(self.mem_region_setting[i]["name"]))
+                                              .format(self.mem_region_setting[i].name))
                 else:
                     self.data_page_str.append(".section .{},\"aw\",@progbits;"
-                                              .format(self.mem_region_setting[i]["name"]))
-                self.data_page_str.append("{}:".format(self.mem_region_setting[i]["name"]))
+                                              .format(self.mem_region_setting[i].name))
+                self.data_page_str.append("{}:".format(self.mem_region_setting[i].name))
             else:
                 if cfg.use_push_data_section:
                     self.data_page_str.append(".pushsection .{},\"aw\",@progbits;"
                                               .format(pkg_ins.hart_prefix(hart_id) +
-                                                      self.mem_region_setting[i]["name"]))
+                                                      self.mem_region_setting[i].name))
                 else:
                     self.data_page_str.append(".section .{},\"aw\",@progbits;"
                                               .format(pkg_ins.hart_prefix(hart_id) +
-                                                      self.mem_region_setting[i]["name"]))
+                                                      self.mem_region_setting[i].name))
                 self.data_page_str.append("{}:".format(pkg_ins.hart_prefix(hart_id) +
-                                                       self.mem_region_setting[i]["name"]))
-            page_size = self.mem_region_setting[i]["size_in_bytes"]
+                                                       self.mem_region_setting[i].name))
+            page_size = self.mem_region_setting[i].size_in_bytes
             for i in range(0, page_size, 32):
                 if page_size - 1 >= 32:
                     temp_data = self.gen_data(idx=i, pattern=pattern,
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
index 6029d91..0d6784b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
@@ -21,7 +21,9 @@
 from pygen_src.isa.riscv_instr import riscv_instr
 from pygen_src.riscv_instr_gen_config import cfg
 from pygen_src.riscv_instr_pkg import (riscv_reg_t,
-                                       riscv_pseudo_instr_name_t, riscv_instr_name_t, pkg_ins)
+                                       riscv_pseudo_instr_name_t,
+                                       riscv_instr_name_t, pkg_ins,
+                                       mem_region_t)
 from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
@@ -51,15 +53,16 @@
         super().__init__()
         self.max_data_page_id = vsc.int32_t()
         self.load_store_shared_memory = 0
-        self.data_page = {}
+        self.data_page = vsc.list_t(mem_region_t())
 
     def pre_randomize(self):
+        self.data_page.clear()
         if self.load_store_shared_memory:
-            self.data_page = cfg.amo_region
+            self.data_page.extend(cfg.amo_region)
         elif self.kernel_mode:
-            self.data_page = cfg.s_mem_region
+            self.data_page.extend(cfg.s_mem_region)
         else:
-            self.data_page = cfg.mem_region
+            self.data_page.extend(cfg.mem_region)
         self.max_data_page_id = len(self.data_page)
 
     def add_rs1_init_la_instr(self, gpr, idx, base = 0):
@@ -67,13 +70,13 @@
         la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA
         la_instr.rd = gpr
         if self.load_store_shared_memory:
-            la_instr.imm_str = "{}+{}".format(cfg.amo_region[idx]['name'], base)
+            la_instr.imm_str = "{}+{}".format(cfg.amo_region[idx].name, base)
         elif self.kernel_mode:
             la_instr.imm_str = "{}{}+{}".format(pkg_ins.hart_prefix(self.hart),
-                                                cfg.s_mem_region[idx]['name'], base)
+                                                cfg.s_mem_region[idx].name, base)
         else:
             la_instr.imm_str = "{}{}+{}".format(pkg_ins.hart_prefix(self.hart),
-                                                cfg.mem_region[idx]['name'], base)
+                                                cfg.mem_region[idx].name, base)
         self.instr_list.insert(0, la_instr)
 
     def add_mixed_instr(self, instr_cnt):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py
new file mode 100644
index 0000000..3f534a4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py
@@ -0,0 +1,368 @@
+
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+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.
+"""
+
+import vsc
+import logging
+from enum import IntEnum, auto
+from importlib import import_module
+from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.riscv_instr_pkg import riscv_instr_group_t
+rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+
+
+# ---------------------------------------------------------------------------------------------
+# This class is used to generate illegal or HINT instructions.
+# The illegal instruction will be generated in binary format and mixed with other valid instr.
+# The mixed instruction stream will be stored in data section and loaded to instruction pages
+# at run time.
+# ---------------------------------------------------------------------------------------------
+
+
+class illegal_instr_type_e(IntEnum):
+    kIllegalOpcode = 0
+    kIllegalCompressedOpcode = auto()
+    kIllegalFunc3 = auto()
+    kIllegalFunc7 = auto()
+    kReservedCompressedInstr = auto()
+    kHintInstr = auto()
+    kIllegalSystemInstr = auto()
+
+
+class reserved_c_instr_e(IntEnum):
+    kIllegalCompressed = 0
+    kReservedAddispn = auto()
+    kReservedAddiw = auto()
+    kReservedAddi16sp = auto()
+    kReservedLui = auto()
+    kReservedLwsp = auto()
+    kReservedLdsp = auto()
+    kReservedLqsp = auto()
+    kReservedJr = auto()
+    kReservedC0 = auto()
+    kReservedC1 = auto()
+    kReservedC2 = auto()
+
+
+@vsc.randobj
+class riscv_illegal_instr:
+    def __init__(self):
+        self.comment = ""
+        self.exception = vsc.rand_enum_t(illegal_instr_type_e)
+        self.reserved_c = vsc.rand_enum_t(reserved_c_instr_e)
+        self.instr_bin = vsc.rand_bit_t(32)
+        self.opcode = vsc.rand_bit_t(7)
+        self.compressed = vsc.rand_bit_t(1)
+        self.func3 = vsc.rand_bit_t(3)
+        self.func7 = vsc.rand_bit_t(7)
+        self.has_func3 = vsc.rand_bit_t(1)
+        self.has_func7 = vsc.rand_bit_t(1)
+        self.c_op = vsc.rand_bit_t(2)
+        self.c_msb = vsc.rand_bit_t(3)
+        self.csrs = []
+        # Default legal self.opcode for RV32I instructions
+        self.legal_opcode = vsc.list_t(vsc.bit_t(7))
+        self.legal_opcode = [3, 15, 19, 23, 35, 55, 99, 51, 103, 115, 111]
+        # Default legal self.opcode for RV32C instructions
+        self.legal_c00_opcode = vsc.list_t(vsc.bit_t(3))
+        self.legal_c00_opcode = [0, 2, 6]
+        self.legal_c10_opcode = vsc.list_t(vsc.bit_t(3))
+        self.legal_c10_opcode = [0, 2, 4, 6]
+        self.xlen = vsc.uint8_t(0)
+        self.xlen = rcs.XLEN
+        self.temp_1 = vsc.bit_t(6)
+
+    @vsc.constraint
+    def exception_dist_c(self):
+        vsc.dist(self.exception,
+                 [vsc.weight(illegal_instr_type_e.kIllegalOpcode, 3),
+                  vsc.weight(illegal_instr_type_e.kIllegalCompressedOpcode, 1),
+                  vsc.weight(illegal_instr_type_e.kIllegalFunc3, 1),
+                  vsc.weight(illegal_instr_type_e.kIllegalFunc7, 1),
+                  vsc.weight(illegal_instr_type_e.kReservedCompressedInstr, 1),
+                  vsc.weight(illegal_instr_type_e.kHintInstr, 3),
+                  vsc.weight(illegal_instr_type_e.kIllegalSystemInstr, 3)
+                  ])
+
+    @vsc.constraint
+    def instr_bit_assignment_c(self):
+        vsc.solve_order(self.opcode, self.instr_bin)
+        vsc.solve_order(self.func3, self.instr_bin)
+        vsc.solve_order(self.func7, self.instr_bin)
+        vsc.solve_order(self.c_msb, self.instr_bin)
+        # vsc.solve_order(self.c_op, self.instr_bin)
+        with vsc.if_then(self.compressed == 1):
+            self.instr_bin[1:0] == self.c_op
+            self.instr_bin[15:13] == self.c_msb
+        with vsc.else_then():
+            self.instr_bin[6:0] == self.opcode
+            with vsc.if_then(self.has_func7 == 1):
+                self.instr_bin[31:25] == self.func7
+            with vsc.if_then(self.has_func3 == 1):
+                self.instr_bin[14:12] == self.func3
+
+    # Invalid SYSTEM instructions
+    @vsc.constraint
+    def system_instr_c(self):
+        with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalSystemInstr):
+            self.opcode == 115
+            # ECALL/EBREAK/xRET/WFI
+            with vsc.if_then(self.func3 == 0):
+                # Constrain RS1 and RD to be non-zero
+                self.instr_bin[19:15] != 0
+                self.instr_bin[11:7] != 0
+                # Valid SYSTEM instructions considered by this
+                # Constrain the upper 12 bits to be invalid
+                self.instr_bin[31:20].not_inside(vsc.rangelist(0, 1, 2, 258, 770, 1970, 261))
+            with vsc.else_then():
+                # Invalid CSR instructions
+                self.instr_bin[31:20].not_inside(vsc.rangelist(self.csrs))
+                # self.instr_bin[20:31].not_inside(vsc.rangelist(self.custom_csr))
+
+    @vsc.constraint
+    def legal_rv32_c_slli(self):
+        with vsc.if_then((self.c_msb == 0) and (self.c_op == 2) and (self.xlen == 32)):
+            with vsc.if_then(self.exception == illegal_instr_type_e.kReservedCompressedInstr):
+                self.instr_bin[12] == 1
+            with vsc.else_then():
+                self.instr_bin[12] == 0
+
+    @vsc.constraint
+    def exception_type_c(self):
+        with vsc.if_then(self.compressed == 1):
+            self.exception.inside(vsc.rangelist(illegal_instr_type_e.kReservedCompressedInstr,
+                                                illegal_instr_type_e.kIllegalCompressedOpcode,
+                                                illegal_instr_type_e.kHintInstr))
+        with vsc.else_then():
+            self.exception.inside(vsc.rangelist(illegal_instr_type_e.kIllegalOpcode,
+                                                illegal_instr_type_e.kIllegalFunc3,
+                                                illegal_instr_type_e.kIllegalFunc7,
+                                                illegal_instr_type_e.kIllegalSystemInstr))
+        with vsc.if_then(self.has_func7 == 0):
+            self.exception != illegal_instr_type_e.kIllegalFunc7
+        with vsc.if_then(self.has_func3 == 0):
+            self.exception != illegal_instr_type_e.kIllegalFunc3
+
+    @vsc.constraint
+    def compressed_instr_op_c(self):
+        self.c_op != 3
+
+    # Avoid generating illegal func3/func7 errors for self.opcode used by B-extension for now
+    # TODO: add support for generating illegal B-extension instructions
+    @vsc.constraint
+    def b_extension_c(self):
+        if riscv_instr_group_t.RV32B in rcs.supported_isa:
+            with vsc.if_then(self.exception in [illegal_instr_type_e.kIllegalFunc3,
+                                                illegal_instr_type_e.kIllegalFunc7]):
+                self.opcode.inside(vsc.rangelist([51, 19, 59]))
+
+    @vsc.constraint
+    def illegal_compressed_op_c(self):
+        with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalCompressedOpcode):
+            self.c_op != 1
+            with vsc.if_then(self.legal_c00_opcode.size == 8):
+                self.c_op != 0
+            with vsc.else_then():
+                self.c_msb.not_inside(vsc.rangelist(self.legal_c00_opcode))
+            with vsc.if_then(self.legal_c10_opcode.size == 8):
+                self.c_op != 2
+            with vsc.else_then():
+                self.c_msb.not_inside(vsc.rangelist(self.legal_c10_opcode))
+
+    @vsc.constraint
+    def reserved_compressed_instr_c(self):
+        vsc.solve_order(self.exception, self.reserved_c)
+        vsc.solve_order(self.exception, self.opcode)
+        vsc.solve_order(self.reserved_c, self.instr_bin)
+        vsc.solve_order(self.reserved_c, self.c_msb)
+        vsc.solve_order(self.reserved_c, self.c_op)
+        with vsc.if_then(self.xlen == 32):
+            # c.addiw is RV64/RV128 only instruction, the encoding is used for C.JAL for RV32C
+            self.reserved_c != reserved_c_instr_e.kReservedAddiw
+        with vsc.if_then(self.exception == illegal_instr_type_e.kReservedCompressedInstr):
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kIllegalCompressed):
+                self.instr_bin[15:0] == 0
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedAddispn):
+                ((self.instr_bin[15:0] == 0) and (self.c_op == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedAddiw):
+                ((self.c_msb == 1) and (self.c_op == 1) and
+                 (self.instr_bin[11:7] == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedC0):
+                ((self.instr_bin[15:10] == 39) and
+                 (self.instr_bin[6:5] == 2) and (self.c_op == 1))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedC1):
+                ((self.instr_bin[15:10] == 39) and
+                 (self.instr_bin[6:5] == 3) and (self.c_op == 1))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedC2):
+                ((self.c_msb == 4) and (self.c_op == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedAddi16sp):
+                ((self.c_msb == 3) and (self.c_op == 1) and
+                 (self.instr_bin[11:7] == 2) and
+                 (not self.instr_bin[12]) and (self.instr_bin[6:2] == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedLui):
+                ((self.c_msb == 3) and (self.c_op == 1) and
+                 (not self.instr_bin[12]) and (self.instr_bin[6:2] == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedJr):
+                self.instr_bin == 32770
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedLqsp):
+                ((self.c_msb == 1) and (self.c_op == 2) and
+                 (self.instr_bin[11:7] == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedLwsp):
+                ((self.c_msb == 2) and (self.c_op == 2) and
+                 (self.instr_bin[11:7] == 0))
+            with vsc.if_then(self.reserved_c == reserved_c_instr_e.kReservedLdsp):
+                ((self.c_msb == 3) and (self.c_op == 2) and (self.instr_bin[11:7] == 0))
+
+    @vsc.constraint
+    def hint_instr_c(self):
+        with vsc.if_then(self.exception == illegal_instr_type_e.kHintInstr):
+            ((self.c_msb == 0) and (self.c_op == 1) and (self.instr_bin[12] +
+                                                         self.instr_bin[6:2] == 0)) or \
+                ((self.c_msb == 2) and (self.c_op == 1) and (self.instr_bin[11:7] == 0)) or \
+                ((self.c_msb == 4) and (self.c_op == 1) and (self.instr_bin[12:11] == 0) and
+                 (self.instr_bin[6:2] == 0)) or \
+                ((self.c_msb == 4) and (self.c_op == 2) and (self.instr_bin[11:7] == 0) and
+                 (self.instr_bin[6:2] != 0)) or \
+                ((self.c_msb == 3) and (self.c_op == 1) and (self.instr_bin[11:7] == 0) and
+                 (self.instr_bin[12] + self.instr_bin[6:2]) != 0) or \
+                ((self.c_msb == 0) and (self.c_op == 2) and (self.instr_bin[11:7] == 0)) or \
+                ((self.c_msb == 0) and (self.c_op == 2) and (self.instr_bin[11:7] != 0) and
+                 not(self.instr_bin[12]) and (self.instr_bin[6:2] == 0)) or \
+                ((self.c_msb == 4) and (self.c_op == 2) and (self.instr_bin[11:7] == 0) and
+                 self.instr_bin[12] and (self.instr_bin[6:2] != 0))
+
+    @vsc.constraint
+    def illegal_opcode_c(self):
+        vsc.solve_order(self.opcode, self.instr_bin)
+        with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalOpcode):
+            self.opcode.not_inside(vsc.rangelist(self.legal_opcode))
+            self.opcode[1:0] == 3
+        with vsc.else_then():
+            self.opcode.inside(vsc.rangelist(self.legal_opcode))
+
+    # TODO: Enable atomic instruction
+    @vsc.constraint
+    def no_atomic_c(self):
+        with vsc.if_then(self.exception != illegal_instr_type_e.kIllegalOpcode):
+            self.opcode != 47
+
+    @vsc.constraint
+    def illegal_func3_c(self):
+        vsc.solve_order(self.opcode, self.func3)
+        with vsc.if_then(self.compressed == 0):
+            with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalFunc3):
+                with vsc.if_then(self.opcode == 103):
+                    self.func3 != 0
+                with vsc.if_then(self.opcode == 99):
+                    self.func3.inside(vsc.rangelist(2, 3))
+                with vsc.if_then(self.xlen == 32):
+                    with vsc.if_then(self.opcode == 35):
+                        self.func3 >= 3
+                    with vsc.if_then(self.opcode == 3):
+                        self.func3.inside(vsc.rangelist(3, 7))
+                with vsc.else_then():
+                    with vsc.if_then(self.opcode == 35):
+                        self.func3 > 3
+                    with vsc.if_then(self.opcode == 3):
+                        self.func3 == 7
+                with vsc.if_then(self.opcode == 15):
+                    self.func3.not_inside(vsc.rangelist(0, 1))
+                with vsc.if_then(self.opcode == 115):
+                    self.func3 == 4
+                with vsc.if_then(self.opcode == 27):
+                    self.func3.not_inside(vsc.rangelist(0, 1, 5))
+                with vsc.if_then(self.opcode == 59):
+                    self.func3.inside(vsc.rangelist(2, 3))
+                self.opcode.inside(vsc.rangelist(103, 99, 3, 35, 15, 115, 27, 59))
+            with vsc.else_then():
+                with vsc.if_then(self.opcode == 103):
+                    self.func3 == 0
+                with vsc.if_then(self.opcode == 99):
+                    self.func3.inside(vsc.rangelist(2, 3))
+                with vsc.if_then(self.xlen == 32):
+                    with vsc.if_then(self.opcode == 35):
+                        self.func3 < 3
+                    with vsc.if_then(self.opcode == 3):
+                        self.func3.inside(vsc.rangelist(3, 7))
+                with vsc.else_then():
+                    with vsc.if_then(self.opcode == 35):
+                        self.func3 <= 3
+                    with vsc.if_then(self.opcode == 3):
+                        self.func3 != 7
+                with vsc.if_then(self.opcode == 15):
+                    self.func3.inside(vsc.rangelist(0, 1))
+                with vsc.if_then(self.opcode == 115):
+                    self.func3 != 4
+                with vsc.if_then(self.opcode == 27):
+                    self.func3.inside(vsc.rangelist(0, 1, 5))
+                with vsc.if_then(self.opcode == 59):
+                    self.func3.not_inside(vsc.rangelist(2, 3))
+
+    @vsc.constraint
+    def has_func7_c(self):
+        vsc.solve_order(self.opcode, self.func7)
+        with vsc.if_then((self.opcode == 19) and (self.func3 == 1 or self.func3 == 5) or
+                         (self.opcode == 51 or self.opcode == 59)):
+            self.has_func7 == 1
+        with vsc.else_then():
+            self.has_func7 == 0
+
+    @vsc.constraint
+    def has_func3_c(self):
+        vsc.solve_order(self.opcode, self.func7)
+        with vsc.if_then(self.opcode == 55 or self.opcode == 111 or self.opcode == 23):
+            self.has_func3 == 0
+        with vsc.else_then():
+            self.has_func3 == 1
+
+    @vsc.constraint
+    def illegal_func7_c(self):
+        with vsc.if_then(self.compressed == 0):
+            with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalFunc7):
+                self.func7.not_inside(vsc.rangelist(0, 32, 1))
+                with vsc.if_then(self.opcode == 9):  # SLLI, SRLI, SRAI
+                    self.func7[6:1].not_inside(vsc.rangelist(0, 16))
+            with vsc.else_then():
+                self.func7.inside(vsc.rangelist(0, 32, 1))
+
+    def initialize(self):
+        if (riscv_instr_group_t.RV32F in rcs.supported_isa) or \
+                (riscv_instr_group_t.RV32D in rcs.supported_isa):
+            self.legal_opcode.extend(7, 39, 67, 71, 75, 79, 83)
+        if riscv_instr_group_t.RV64I in rcs.supported_isa:
+            self.legal_opcode.append(27)
+        if riscv_instr_group_t.RV32A in rcs.supported_isa:
+            self.legal_opcode.append(47)
+        if (riscv_instr_group_t.RV64I in rcs.supported_isa) or \
+                (riscv_instr_group_t.RV64M in rcs.supported_isa):
+            self.legal_opcode.append(59)
+        if riscv_instr_group_t.RV64I in rcs.supported_isa:
+            self.legal_c00_opcode.extend(3, 7)
+            self.legal_c10_opcode.extend(3, 7)
+        # TODO csr
+
+    def get_bin_str(self):
+        if self.compressed == 1:
+            local_instr_bin = self.instr_bin & 0xffff
+        else:
+            local_instr_bin = hex(self.instr_bin)
+        logging.info("Illegal instruction type: {}, illegal instruction: {}".format(
+            self.exception.name, local_instr_bin))
+        return ("{}".format(local_instr_bin))
+
+    def post_randomize(self):
+        self.comment = self.exception.name
+        if self.exception == illegal_instr_type_e.kReservedCompressedInstr:
+            self.comment += " {}".format(self.reserved_c.name)
+        elif self.exception == illegal_instr_type_e.kIllegalOpcode:
+            self.comment += " {}".format(self.opcode)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
index a273179..0de86af 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
@@ -12,15 +12,17 @@
 
 """
 
-import argparse
-import logging
 import sys
+import math
+import logging
+import argparse
 import vsc
 from importlib import import_module
 from pygen_src.riscv_instr_pkg import (mtvec_mode_t, f_rounding_mode_t,
                                        riscv_reg_t, privileged_mode_t,
                                        riscv_instr_group_t, data_pattern_t,
-                                       riscv_instr_category_t, satp_mode_t)
+                                       riscv_instr_category_t, satp_mode_t,
+                                       mem_region_t)
 
 
 @vsc.randobj
@@ -81,19 +83,17 @@
         # Commenting out for now
         # vector_cfg = riscv_vector_cfg # TODO
         # pmp_cfg = riscv_pmp_cfg  # TODO
-        self.mem_region = {
-            0: {'name': "region_0", 'size_in_bytes': 4096, 'xwr': 8},
-            1: {'name': "region_1", 'size_in_bytes': 4096 * 16, 'xwr': 8}
-        }
-        self.amo_region = {
-            0: {'name': "amo_0", 'size_in_bytes': 64, 'xwr': 8}
-        }
-        self.stack_len = 5000
-        self.s_mem_region = {
-            0: {'name': "s_region_0", 'size_in_bytes': 4096, 'xwr': 8},
-            1: {'name': "s_region_1", 'size_in_bytes': 4096, 'xwr': 8}
-        }
 
+        self.mem_region = vsc.list_t(mem_region_t())
+        self.amo_region = vsc.list_t(mem_region_t())
+        self.s_mem_region = vsc.list_t(mem_region_t())
+        self.mem_region.extend([mem_region_t(name = "region_0", size_in_bytes = 4096, xwr = 8),
+                                mem_region_t(name = "region_1", size_in_bytes = 4096, xwr = 8)])
+        self.amo_region.extend([mem_region_t(name = "amo_0", size_in_bytes = 64, xwr = 8)])
+        self.s_mem_region.extend([mem_region_t(name = "s_region_0", size_in_bytes = 4096, xwr = 8),
+                                  mem_region_t(name = "s_region_1", size_in_bytes = 4096, xwr = 8)])
+
+        self.stack_len = 5000
         self.kernel_stack_len = 4000
         self.kernel_program_instr_cnt = 400
         # list of main implemented CSRs
@@ -112,7 +112,10 @@
         self.enable_unaligned_load_store = self.argv.enable_unaligned_load_store
         self.illegal_instr_ratio = self.argv.illegal_instr_ratio
         self.hint_instr_ratio = self.argv.hint_instr_ratio
-        self.num_of_harts = self.argv.num_of_harts
+        if self.argv.num_of_harts is None:
+            self.num_of_harts = rcs.NUM_HARTS
+        else:
+            self.num_of_harts = self.argv.num_of_harts
         self.fix_sp = self.argv.fix_sp
         self.use_push_data_section = self.argv.use_push_data_section
         self.boot_mode_opts = self.argv.boot_mode
@@ -161,6 +164,7 @@
         self.enable_debug_single_step = self.argv.enable_debug_single_step
         self.single_step_iterations = 0
         self.set_mstatus_tw = self.argv.set_mstatus_tw
+        self.set_mstatus_mprv = vsc.bit_t(1)
         self.set_mstatus_mprv = self.argv.set_mstatus_mprv
         self.min_stack_len_per_program = 10 * (rcs.XLEN / 8)
         self.max_stack_len_per_program = 16 * (rcs.XLEN / 8)
@@ -180,6 +184,17 @@
             self.disable_compressed_instr = 1
         self.setup_instr_distribution()
         self.get_invalid_priv_lvl_csr()
+        # Helpers fields to build the vsc constraints
+        self.supported_interrupt_mode = vsc.list_t(vsc.enum_t(mtvec_mode_t))
+        self.XLEN = vsc.uint32_t()
+        self.SATP_MODE = vsc.enum_t(satp_mode_t)
+        self.init_privil_mode = vsc.enum_t(privileged_mode_t)
+        self.init_privil_mode = self.init_privileged_mode
+        self.supported_interrupt_mode = rcs.supported_interrupt_mode
+        self.XLEN = rcs.XLEN
+        self.SATP_MODE = rcs.SATP_MODE
+        self.tvec_ceil = vsc.uint32_t()
+        self.tvec_ceil = math.ceil(math.log2((self.XLEN * 4) / 8))
 
     @vsc.constraint
     def default_c(self):
@@ -215,11 +230,11 @@
 
     @vsc.constraint
     def mtvec_c(self):
-        self.mtvec_mode.inside(vsc.rangelist(mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED))
+        self.mtvec_mode.inside(vsc.rangelist(self.supported_interrupt_mode))
         with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT):
             vsc.soft(self.tvec_alignment == 2)
         with vsc.else_then():
-            vsc.soft(self.tvec_alignment == (rcs.XLEN * 4) // 8)
+            vsc.soft(self.tvec_alignment == self.tvec_ceil)
 
     @vsc.constraint
     def floating_point_c(self):
@@ -230,11 +245,11 @@
 
     @vsc.constraint
     def mstatus_c(self):
-        if self.set_mstatus_mprv:
+        with vsc.if_then(self.set_mstatus_mprv == 1):
             self.mstatus_mprv == 1
-        else:
+        with vsc.else_then():
             self.mstatus_mprv == 0
-        if rcs.SATP_MODE == satp_mode_t.BARE:
+        with vsc.if_then(self.SATP_MODE == satp_mode_t.BARE):
             self.mstatus_mxr == 0
             self.mstatus_sum == 0
             self.mstatus_tvm == 0
@@ -400,8 +415,6 @@
         parse.add_argument('--illegal_instr_ratio',
                            help = 'illegal_instr_ratio', type = int, default = 0)
         parse.add_argument('--hint_instr_ratio', help = 'hint_instr_ratio', type = int, default = 0)
-        # TODO map it with rcs NUM_HARTS. After solving the cyclic issue for core setting.
-        # rcs is out of scope while using in the default value of num_of_harts
         parse.add_argument('--num_of_harts', help = 'num_of_harts',
                            type = int, default = 1)
         parse.add_argument('--enable_unaligned_load_store',
@@ -463,6 +476,7 @@
         parse.add_argument('--log_file_name', help='log file name',
                            default="")
         parse.add_argument('--target', help='target', default="rv32imc")
+        parse.add_argument('--gen_test', help='gen_test', default="riscv_instr_base_test")
         parse.add_argument("--enable_visualization", action="store_true", default=False,
                            help="Enabling coverage report visualization for pyflow")
         parse.add_argument('--trace_csv', help='List of csv traces', default="")
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
index 1649355..41f4ba3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
@@ -13,15 +13,18 @@
 """
 
 import logging
+import vsc
 from enum import Enum, IntEnum, auto
 from bitstring import BitArray
 from importlib import import_module
 
 
+@vsc.randobj
 class mem_region_t:
-    name = 0
-    size_in_bytes = auto()
-    xwr = auto()
+    def __init__(self, name = "", size_in_bytes=0, xwr=0):
+        self.name = name
+        self.size_in_bytes = vsc.uint32_t(i=size_in_bytes)
+        self.xwr = vsc.uint8_t(i=xwr)
 
 
 class satp_mode_t(IntEnum):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
index 109d269..5c1a1f0 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
@@ -19,6 +19,7 @@
 from importlib import import_module
 from collections import defaultdict
 from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
+from pygen_src.riscv_illegal_instr import riscv_illegal_instr, illegal_instr_type_e
 from pygen_src.riscv_instr_gen_config import cfg
 from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_name_t, riscv_reg_t,
                                        riscv_instr_category_t)
@@ -42,6 +43,7 @@
         self.branch_idx = [None] * 30
         self.instr_stack_enter = riscv_push_stack_instr()
         self.instr_stack_exit = riscv_pop_stack_instr()
+        self.illegal_instr = riscv_illegal_instr()
 
     def gen_instr(self, is_main_program, no_branch = 1):
         self.is_main_program = is_main_program
@@ -151,7 +153,7 @@
                 reserved loop registers
                 '''
                 branch_target_label = 0
-                branch_byte_offset = 0
+                # branch_byte_offset = 0
                 branch_target_label = self.instr_stream.instr_list[j].idx + \
                     self.branch_idx[branch_cnt]
                 if(branch_target_label >= label_idx):
@@ -204,7 +206,6 @@
                 else:
                     prefix = pkg_ins.format_string(string = '{}:'.format(
                         self.label_name), length = pkg_ins.LABEL_STR_LEN)
-
                 self.instr_stream.instr_list[i].has_label = 1
             else:
                 if(self.instr_stream.instr_list[i].has_label):
@@ -214,15 +215,15 @@
                     prefix = pkg_ins.format_string(string = " ", length = pkg_ins.LABEL_STR_LEN)
             string = prefix + self.instr_stream.instr_list[i].convert2asm()
             self.instr_string_list.append(string)
-            if(rcs.support_pmp and not re.search("main", self.label_name)):
-                self.instr_string_list.insert(0, ".align 2")
-            self.insert_illegal_hint_instr()
-            prefix = pkg_ins.format_string(str(i), pkg_ins.LABEL_STR_LEN)
-            if not self.is_main_program:
-                self.generate_return_routine(prefix)
+        if(rcs.support_pmp and not re.search("main", self.label_name)):
+            self.instr_string_list.insert(0, ".align 2")
+        self.insert_illegal_hint_instr()
+        prefix = pkg_ins.format_string(str(i), pkg_ins.LABEL_STR_LEN)
+        if not self.is_main_program:
+            self.generate_return_routine(prefix)
 
     def generate_return_routine(self, prefix):
-        string = ''
+        routine_str = ''
         jump_instr = [riscv_instr_name_t.JALR]
         rand_lsb = random.randrange(0, 1)
         ra = vsc.rand_enum_t(riscv_reg_t)
@@ -233,25 +234,49 @@
         except Exception:
             logging.critical("Cannot randomize ra")
             sys.exit(1)
-        string = (prefix + pkg_ins.format_string("{}addi x{} x{} {}".format(ra.name,
-                                                                            cfg.ra.name, rand_lsb)))
-        self.instr_string_list.append(string)
-        if(not cfg.disable_compressed_instr):
+        routine_str = prefix + "addi x{} x{} {}".format(ra.name, cfg.ra.name, rand_lsb)
+        self.instr_string_list.append(routine_str)
+        if not cfg.disable_compressed_instr:
             jump_instr.append(riscv_instr_name_t.C_JR)
-            if(not (riscv_reg_t.RA in {cfg.reserved_regs})):
+            if not (riscv_reg_t.RA in cfg.reserved_regs):
                 jump_instr.append(riscv_instr_name_t.C_JALR)
         i = random.randrange(0, len(jump_instr) - 1)
-        if (jump_instr[i] == riscv_instr_name_t.C_JAL):
-            string = prefix + pkg_ins.format_string("{}c.jalr x{}".format(ra.name))
-        elif(jump_instr[i] == riscv_instr_name_t.C_JR):
-            string = prefix + pkg_ins.format_string("{}c.jr x{}".format(ra.name))
-        elif(jump_instr[i] == riscv_instr_name_t.JALR):
-            string = prefix + pkg_ins.format_string("{}c.jalr x{} x{} 0".format(ra.name, ra.name))
+        if jump_instr[i] == riscv_instr_name_t.C_JAL:
+            routine_str = prefix + "c.jalr x{}".format(ra.name)
+        elif jump_instr[i] == riscv_instr_name_t.C_JR:
+            routine_str = prefix + "c.jr x{}".format(ra.name)
+        elif jump_instr[i] == riscv_instr_name_t.JALR:
+            routine_str = prefix + "jalr x{} x{} 0".format(ra.name, ra.name)
         else:
-            logging.critical("Unsupported jump_instr: %0s" % (jump_instr[i]))
+            logging.critical("Unsupported jump_instr: {}".format(jump_instr[i]))
             sys.exit(1)
-            self.instr_string_list.append(string)
+        self.instr_string_list.append(routine_str)
 
-    # TODO
     def insert_illegal_hint_instr(self):
-        pass
+        idx = 0
+        insert_str = ""
+        self.illegal_instr.initialize()
+        bin_instr_cnt = int(self.instr_cnt * cfg.illegal_instr_ratio / 1000)
+        if bin_instr_cnt >= 0:
+            logging.info("Injecting {} illegal instructions, ratio {}/100".
+                         format(bin_instr_cnt, cfg.illegal_instr_ratio))
+            for _ in range(bin_instr_cnt):
+                with vsc.randomize_with(self.illegal_instr):
+                    self.illegal_instr.exception != illegal_instr_type_e.kHintInstr
+                insert_str = "{}.4byte {} # {}".format(pkg_ins.indent,
+                                                       self.illegal_instr.get_bin_str(),
+                                                       self.illegal_instr.comment)
+                idx = random.randrange(0, len(self.instr_string_list))
+                self.instr_string_list.insert(idx, insert_str)
+        bin_instr_cnt = int(self.instr_cnt * cfg.hint_instr_ratio / 1000)
+        if bin_instr_cnt >= 0:
+            logging.info("Injecting {} HINT instructions, ratio {}/100".format(
+                bin_instr_cnt, cfg.hint_instr_ratio))
+            for _ in range(int(bin_instr_cnt)):
+                with vsc.randomize_with(self.illegal_instr):
+                    self.illegal_instr.exception == illegal_instr_type_e.kHintInstr
+                insert_str = "{}.2byte {} # {}".format(pkg_ins.indent,
+                                                       self.illegal_instr.get_bin_str(),
+                                                       self.illegal_instr.comment)
+                idx = random.randrange(0, len(self.instr_string_list))
+                self.instr_string_list.insert(idx, insert_str)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
index c0bf8a8..5b957d1 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
@@ -186,7 +186,9 @@
         self.setup_instruction_dist(no_branch, no_load_store)

 

     def randomize_avail_regs(self):

-        if self.avail_regs.size > 0:

+        pass

+        # TODO

+        '''if self.avail_regs.size > 0:

             try:

                 with vsc.randomize_with(self.avail_regs):

                     vsc.unique(self.avail_regs)

@@ -197,7 +199,7 @@
                                                       self.reserved_rd))

             except Exception:

                 logging.critical("Cannot randomize avail_regs")

-                sys.exit(1)

+                sys.exit(1)'''

 

     def setup_instruction_dist(self, no_branch = 0, no_load_store = 1):

         if cfg.dist_control_mode:

diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py
new file mode 100644
index 0000000..7df1cb7
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py
@@ -0,0 +1,293 @@
+
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+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.
+"""
+
+import sys
+import random
+import logging
+import vsc
+from enum import IntEnum, auto
+from importlib import import_module
+from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.isa.riscv_instr import riscv_instr
+from pygen_src.riscv_directed_instr_lib import riscv_mem_access_stream
+from pygen_src.riscv_instr_pkg import riscv_reg_t, riscv_instr_name_t, riscv_instr_group_t
+rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+
+
+class locality_e(IntEnum):
+    NARROW = 0
+    HIGH = auto()
+    MEDIUM = auto()
+    SPARSE = auto()
+
+
+@vsc.randobj
+class riscv_load_store_base_instr_stream(riscv_mem_access_stream):
+    def __init__(self):
+        super().__init__()
+        self.num_load_store = vsc.rand_uint32_t()
+        self.num_mixed_instr = vsc.rand_uint32_t()
+        self.base = vsc.rand_int32_t()
+        self.offset = []
+        self.addr = []
+        self.load_store_instr = []
+        self.data_page_id = vsc.rand_uint32_t()
+        self.rs1_reg = vsc.rand_enum_t(riscv_reg_t)
+        self.locality = vsc.rand_enum_t(locality_e)
+        self.max_load_store_offset = vsc.rand_int32_t()
+        self.use_sp_as_rs1 = vsc.rand_bit_t()
+
+    @vsc.constraint
+    def sp_rnd_order_c(self):
+        vsc.solve_order(self.use_sp_as_rs1, self.rs1_reg)
+
+    @vsc.constraint
+    def sp_c(self):
+        vsc.dist(self.use_sp_as_rs1, [vsc.weight(1, 1), vsc.weight(0, 2)])
+        with vsc.if_then(self.use_sp_as_rs1 == 1):
+            self.rs1_reg == riscv_reg_t.SP
+
+    # TODO Getting pyvsc error -- > rs1 has not been build yet
+    '''@vsc.constraint
+    def rs1_c(self):
+        self.rs1_reg.not_inside(vsc.rangelist(cfg.reserved_regs,
+                                              self.reserved_rd, riscv_reg_t.ZERO))'''
+
+    @vsc.constraint
+    def addr_c(self):
+        # TODO solve_order
+        # vsc.solve_order(self.data_page_id, self.max_load_store_offset)
+        # vsc.solve_order(self.max_load_store_offset, self.base)
+        self.data_page_id < self.max_data_page_id
+        with vsc.foreach(self.data_page, idx = True) as i:
+            with vsc.if_then(i == self.data_page_id):
+                self.max_load_store_offset == self.data_page[i].size_in_bytes
+        self.base in vsc.rangelist(vsc.rng(0, self.max_load_store_offset - 1))
+
+    def randomize_offset(self):
+        addr_ = vsc.rand_int32_t()
+        offset_ = vsc.rand_int32_t()
+        self.offset = [0] * self.num_load_store
+        self.addr = [0] * self.num_load_store
+        for i in range(self.num_load_store):
+            try:
+                if self.locality == locality_e.NARROW:
+                    offset_ = random.randrange(-16, 16)
+                elif self.locality == locality_e.HIGH:
+                    offset_ = random.randrange(-64, 64)
+                elif self.locality == locality_e.MEDIUM:
+                    offset_ = random.randrange(-256, 256)
+                elif self.locality == locality_e.SPARSE:
+                    offset_ = random.randrange(-2048, 2047)
+                var1 = self.base + offset_ - 1
+                var2 = self.base + offset_ + 1
+                addr_ = random.randrange(var1, var2)
+            except Exception:
+                logging.critical("Cannot randomize load/store offset")
+                sys.exit(1)
+            self.offset[i] = offset_
+            self.addr[i] = addr_
+
+    def pre_randomize(self):
+        super().pre_randomize()
+        if(riscv_reg_t.SP in [cfg.reserved_regs, self.reserved_rd]):
+            self.use_sp_as_rs1 = 0
+            with vsc.raw_mode():
+                self.use_sp_as_rs1.rand_mode = False
+            self.sp_rnd_order_c.constraint_mode(False)
+
+    def post_randomize(self):
+        self.randomize_offset()
+        # rs1 cannot be modified by other instructions
+        if not(self.rs1_reg in self.reserved_rd):
+            self.reserved_rd.append(self.rs1_reg)
+        self.gen_load_store_instr()
+        self.add_mixed_instr(self.num_mixed_instr)
+        self.add_rs1_init_la_instr(self.rs1_reg, self.data_page_id, self.base)
+        super().post_randomize()
+
+    # Generate each load/store instruction
+    def gen_load_store_instr(self):
+        allowed_instr = []
+        enable_compressed_load_store = 0
+        self.randomize_avail_regs()
+        if ((self.rs1_reg in [riscv_reg_t.S0, riscv_reg_t.S1, riscv_reg_t.A0, riscv_reg_t.A1,
+                              riscv_reg_t.A2, riscv_reg_t.A3, riscv_reg_t.A4, riscv_reg_t.A5,
+                              riscv_reg_t.SP]) and not(cfg.disable_compressed_instr)):
+            enable_compressed_load_store = 1
+        for i in range(len(self.addr)):
+            # Assign the allowed load/store instructions based on address alignment
+            # This is done separately rather than a constraint to improve the randomization
+            # performance
+            allowed_instr.extend(
+                [riscv_instr_name_t.LB, riscv_instr_name_t.LBU, riscv_instr_name_t.SB])
+            if not cfg.enable_unaligned_load_store:
+                if (self.addr[i] & 1) == 0:
+                    allowed_instr.extend(
+                        [riscv_instr_name_t.LH, riscv_instr_name_t.LHU, riscv_instr_name_t.SH])
+                if self.addr[i] % 4 == 0:
+                    allowed_instr.extend([riscv_instr_name_t.LW, riscv_instr_name_t.SW])
+                    if cfg.enable_floating_point:
+                        allowed_instr.extend([riscv_instr_name_t.FLW,
+                                              riscv_instr_name_t.FSW])
+                    if ((self.offset[i] in range(128)) and (self.offset[i] % 4 == 0) and
+                        (riscv_instr_group_t.RV32C in rcs.supported_isa) and
+                            (enable_compressed_load_store)):
+                        if self.rs1_reg == riscv_reg_t.SP:
+                            logging.info("Add LWSP/SWSP to allowed instr")
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LWSP, riscv_instr_name_t.C_SWSP])
+                        else:
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LW, riscv_instr_name_t.C_SW])
+                            if (cfg.enable_floating_point and
+                                    riscv_instr_group_t.RV32FC in rcs.supported_isa):
+                                allowed_instr.extend(
+                                    [riscv_instr_name_t.C_FLW, riscv_instr_name_t.C_FSW])
+                if (rcs.XLEN >= 64) and (self.addr[i] % 8 == 0):
+                    allowed_instr.extend([riscv_instr_name_t.LWU,
+                                          riscv_instr_name_t.LD,
+                                          riscv_instr_name_t.SD])
+                    if (cfg.enable_floating_point and
+                            (riscv_instr_group_t.RV32D in rcs.supported_isa)):
+                        allowed_instr.extend([riscv_instr_name_t.FLD,
+                                              riscv_instr_name_t.FSD])
+                    if (self.offset[i] in range(256) and (self.offset[i] % 8 == 0) and
+                        (riscv_instr_group_t.RV64C in rcs.supported_isa) and
+                            enable_compressed_load_store):
+                        if self.rs1_reg == riscv_reg_t.SP:
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LDSP, riscv_instr_name_t.C_SDSP])
+                        else:
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LD, riscv_instr_name_t.C_SD])
+                            if (cfg.enable_floating_point and
+                                    (riscv_instr_group_t.RV32DC in rcs.supported_isa)):
+                                allowed_instr.extend(
+                                    [riscv_instr_name_t.C_FLD, riscv_instr_name_t.C_FSD])
+                else:  # unalligned load/store
+                    allowed_instr.extend([riscv_instr_name_t.LW, riscv_instr_name_t.SW,
+                                          riscv_instr_name_t.LH, riscv_instr_name_t.LHU,
+                                          riscv_instr_name_t.SH])
+                    # Compressed load/store still needs to be alligned
+                    if (self.offset[i] in range(128) and (self.offset[i] % 4 == 0) and
+                        (riscv_instr_group_t.RV32C in rcs.supported_isa) and
+                            enable_compressed_load_store):
+                        if self.rs1_reg == riscv_reg_t.SP:
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LWSP, riscv_instr_name_t.C_SWSP])
+                        else:
+                            allowed_instr.extend(
+                                [riscv_instr_name_t.C_LW, riscv_instr_name_t.C_SW])
+                    if rcs.XLEN >= 64:
+                        allowed_instr.extend(
+                            [riscv_instr_name_t.LWU, riscv_instr_name_t.LD, riscv_instr_name_t.SD])
+                        if (self.offset[i] in range(256) and (self.offset[i] % 8 == 0) and
+                            (riscv_instr_group_t.RV64C in rcs.supported_isa) and
+                                enable_compressed_load_store):
+                            if self.rs1_reg == riscv_reg_t.SP:
+                                allowed_instr.extend(
+                                    [riscv_instr_name_t.C_LWSP, riscv_instr_name_t.C_SWSP])
+                            else:
+                                allowed_instr.extend(
+                                    [riscv_instr_name_t.C_LD, riscv_instr_name_t.C_SD])
+            instr = riscv_instr.get_load_store_instr(allowed_instr)
+            instr.has_rs1 = 0
+            instr.has_imm = 0
+            self.randomize_gpr(instr)
+            instr.rs1 = self.rs1_reg
+            instr.imm_str = str(instr.uintToInt(self.offset[i]))
+            instr.process_load_store = 0
+            self.instr_list.append(instr)
+            self.load_store_instr.append(instr)
+
+
+@vsc.randobj
+class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream):
+    def __init__(self):
+        super().__init__()
+
+    @vsc.constraint
+    def legal_c(self):
+        self.num_load_store == 1
+        self.num_mixed_instr < 5
+
+
+@vsc.randobj
+class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream):
+    def __init__(self):
+        super().__init__()
+        self.max_instr_cnt = 30
+        self.min_instr_cnt = 10
+
+    @vsc.constraint
+    def legal_c(self):
+        self.num_load_store.inside(vsc.rangelist(vsc.rng(self.min_instr_cnt, self.max_instr_cnt)))
+        self.num_mixed_instr == 0
+
+
+@vsc.randobj
+class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream):
+    def __init__(self):
+        super().__init__()
+
+    @vsc.constraint
+    def legal_c(self):
+        self.num_load_store.inside(vsc.rangelist(vsc.rng(10, 30)))
+        self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(10, 30)))
+
+
+@vsc.randobj
+class riscv_load_store_hazard_instr_stream(riscv_load_store_base_instr_stream):
+    def __init__(self):
+        super().__init__()
+        self.hazard_ratio = vsc.rand_int32_t()
+
+    @vsc.constraint
+    def hazard_ratio_c(self):
+        self.hazard_ratio.inside(vsc.rangelist(vsc.rng(20, 100)))
+
+    @vsc.constraint
+    def legal_c(self):
+        self.num_load_store.inside(vsc.rangelist(vsc.rng(10, 20)))
+        self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(1, 7)))
+
+    def randomize_offset(self):
+        addr_ = vsc.rand_int32_t()
+        offset_ = vsc.rand_int32_t()
+        self.offset = [0] * self.num_load_store
+        self.addr = [0] * self.num_load_store
+        rand_num = random.randrange(0, 100)
+        for i in range(self.num_load_store):
+            if (i > 0) and (rand_num < self.hazard_ratio):
+                self.offset[i] = self.offset[i - 1]
+                self.addr[i] = self.addr[i - 1]
+            else:
+                try:
+                    if self.locality == locality_e.NARROW:
+                        offset_ = random.randrange(-16, 16)
+                    elif self.locality == locality_e.HIGH:
+                        offset_ = random.randrange(-64, 64)
+                    elif self.locality == locality_e.MEDIUM:
+                        offset_ = random.randrange(-256, 256)
+                    elif self.locality == locality_e.SPARSE:
+                        offset_ = random.randrange(-2048, 2047)
+                    var1 = self.base + offset_ - 1
+                    var2 = self.base + offset_ + 1
+                    addr_ = random.randrange(var1, var2)
+                except Exception:
+                    logging.critical("Cannot randomize load/store offset")
+                    sys.exit(1)
+                self.offset[i] = offset_
+                self.addr[i] = addr_
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py
new file mode 100644
index 0000000..1f67bcb
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py
@@ -0,0 +1,62 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+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.
+"""
+
+from enum import IntEnum, auto
+
+# Will be the lowest 8 bits of the data word
+
+
+class signature_type_t(IntEnum):
+    '''
+    Information sent to the core relating its current status.
+    Bits [12:8] of the data word will be the core_status_t value
+    corresponding to the current core status.
+    '''
+    CORE_STATUS = 0
+    '''
+    Information sent to the core conveying the uvm simulation result.
+    Bit [8] of the data word will be the test_result_t value.
+    '''
+    TEST_RESULT = auto()
+    '''
+    Sent to the core to indicate a dump of GPRs to testbench.
+    Will be followed by 32 writes of registers x0-x32.
+    '''
+    WRITE_GPR = auto()
+    '''
+    Sent to the core to indicate a write of a CSR's data.
+    Bits [19:8] of the data word will be the CSR address.
+    Will be followed by a second write of the actual data from the CSR.
+    '''
+    WRITE_CSR = auto()
+
+
+class core_status_t(IntEnum):
+    INITIALIZED = 0
+    IN_DEBUG_MODE = auto()
+    IN_MACHINE_MODE = auto()
+    IN_HYPERVISOR_MODE = auto()
+    IN_SUPERVISOR_MODE = auto()
+    IN_USER_MODE = auto()
+    HANDLING_IRQ = auto()
+    FINISHED_IRQ = auto()
+    HANDLING_EXCEPTION = auto()
+    INSTR_FAULT_EXCEPTION = auto()
+    ILLEGAL_INSTR_EXCEPTION = auto()
+    LOAD_FAULT_EXCEPTION = auto()
+    STORE_FAULT_EXCEPTION = auto()
+    EBREAK_EXCEPTION = auto()
+
+
+class test_result_t(IntEnum):
+    TEST_PASS = 0
+    TEST_FAIL = auto()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
index e38109b..127b085 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
@@ -20,6 +20,10 @@
                                                 riscv_int_numeric_corner_stream,
                                                 riscv_jal_instr, riscv_mem_access_stream)
 from pygen_src.riscv_amo_instr_lib import (riscv_lr_sc_instr_stream, riscv_amo_instr_stream)
+from pygen_src.riscv_load_store_instr_lib import (riscv_load_store_rand_instr_stream,
+                                                  riscv_load_store_hazard_instr_stream,
+                                                  riscv_load_store_stress_instr_stream,
+                                                  riscv_single_load_store_instr_stream)
 
 
 def factory(obj_of):
@@ -29,7 +33,11 @@
         "riscv_jal_instr": riscv_jal_instr,
         "riscv_mem_access_stream": riscv_mem_access_stream,
         "riscv_lr_sc_instr_stream": riscv_lr_sc_instr_stream,
-        "riscv_amo_instr_stream": riscv_amo_instr_stream
+        "riscv_amo_instr_stream": riscv_amo_instr_stream,
+        "riscv_load_store_rand_instr_stream": riscv_load_store_rand_instr_stream,
+        "riscv_load_store_hazard_instr_stream": riscv_load_store_hazard_instr_stream,
+        "riscv_load_store_stress_instr_stream": riscv_load_store_stress_instr_stream,
+        "riscv_single_load_store_instr_stream": riscv_single_load_store_instr_stream
     }
 
     try:
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscvOVPsim.ic b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscvOVPsim.ic
new file mode 100644
index 0000000..36e0eea
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscvOVPsim.ic
@@ -0,0 +1,22 @@
+# riscOVPsim configuration file converted from YAML
+--variant RV32I
+--override riscvOVPsim/cpu/add_Extensions=MCA
+--override riscvOVPsim/cpu/misa_MXL=1
+--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0
+--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0
+--override riscvOVPsim/cpu/unaligned=T
+--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0
+--override riscvOVPsim/cpu/user_version=2.3
+--override riscvOVPsim/cpu/priv_version=1.11
+--override riscvOVPsim/cpu/mvendorid=0
+--override riscvOVPsim/cpu/marchid=0
+--override riscvOVPsim/cpu/mimpid=0
+--override riscvOVPsim/cpu/mhartid=0
+--override riscvOVPsim/cpu/cycle_undefined=F
+--override riscvOVPsim/cpu/instret_undefined=F
+--override riscvOVPsim/cpu/time_undefined=T
+--override riscvOVPsim/cpu/reset_address=0x80000000
+--override riscvOVPsim/cpu/simulateexceptions=T
+--override riscvOVPsim/cpu/defaultsemihost=F
+--override riscvOVPsim/cpu/wfi_is_nop=T
+--exitonsymbol _exit
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py
new file mode 100644
index 0000000..d984036
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py
@@ -0,0 +1,83 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+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.
+"""
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
+                                       exception_cause_t, satp_mode_t,
+                                       riscv_instr_group_t, privileged_mode_t,
+                                       mtvec_mode_t)
+
+
+
+
+
+XLEN = 32
+
+implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID,
+                   privileged_reg_t.MIMPID, privileged_reg_t.MHARTID,
+                   privileged_reg_t.MSTATUS, privileged_reg_t.MISA, privileged_reg_t.MIE,
+                   privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
+                   privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
+                   privileged_reg_t.MTVAL, privileged_reg_t.MIP]
+
+SATP_MODE = satp_mode_t.BARE
+
+supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
+                 riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32A]
+
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+
+max_interrupt_vector_num = 16
+
+support_debug_mode = 0
+
+NUM_HARTS = 2
+
+support_pmp = 0
+
+unsupported_instr = []
+
+support_umode_trap = 0
+
+support_sfence = 0
+
+support_unaligned_load_store = 1
+
+NUM_FLOAT_GPR = 32
+
+NUM_GPR = 32
+
+NUM_VEC_GPR = 32
+
+VECTOR_EXTENSION_ENABLE = 0
+
+VLEN = 512
+
+ELEN = 32
+
+SELEN = 8
+
+#VELEN = 
+
+MAX_MUL = 8
+
+implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
+                         interrupt_cause_t.M_TIMER_INTR,
+                         interrupt_cause_t.M_EXTERNAL_INTR]
+
+implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT,
+                         exception_cause_t.ILLEGAL_INSTRUCTION,
+                         exception_cause_t.BREAKPOINT,
+                         exception_cause_t.LOAD_ADDRESS_MISALIGNED,
+                         exception_cause_t.LOAD_ACCESS_FAULT,
+                         exception_cause_t.ECALL_MMODE]
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
index 6563ec6..fbcc451 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
@@ -32,6 +32,8 @@
 
 support_pmp = 0
 
+support_debug_mode = 0
+
 unsupported_instr = []
 
 support_umode_trap = 0
@@ -40,3 +42,5 @@
 NUM_FLOAT_GPR = 32
 NUM_GPR = 32
 NUM_VEC_GPR = 32
+
+max_interrupt_vector_num = 16
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
index bc6a107..75e29d5 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
@@ -12,6 +12,8 @@
 
 import sys
 import logging
+import time
+import multiprocessing
 sys.path.append("pygen/")
 from pygen_src.riscv_instr_pkg import *
 from pygen_src.riscv_instr_gen_config import cfg  # NOQA
@@ -28,19 +30,22 @@
         self.asm_file_name = cfg.argv.asm_file_name
         self.asm = ""
 
-    def run_phase(self):
-        for _ in range(cfg.num_of_tests):
-            self.randomize_cfg()
-            self.asm = riscv_asm_program_gen()
-            riscv_instr.create_instr_list(cfg)
-            if cfg.asm_test_suffix != "":
-                self.asm_file_name = "{}.{}".format(self.asm_file_name,
-                                                    cfg.asm_test_suffix)
-            test_name = "{}_{}.S".format(self.asm_file_name,
-                                         _ + self.start_idx)
-            self.asm.get_directed_instr_stream()
-            self.asm.gen_program()
-            self.asm.gen_test_file(test_name)
+    def run(self):
+        with multiprocessing.Pool(processes = cfg.num_of_tests) as pool:
+            pool.map(self.run_phase, list(range(cfg.num_of_tests)))
+
+    def run_phase(self, num):
+        self.randomize_cfg()
+        self.asm = riscv_asm_program_gen()
+        riscv_instr.create_instr_list(cfg)
+        if cfg.asm_test_suffix != "":
+            self.asm_file_name = "{}.{}".format(self.asm_file_name,
+                                                cfg.asm_test_suffix)
+        test_name = "{}_{}.S".format(self.asm_file_name,
+                                     num + self.start_idx)
+        self.asm.get_directed_instr_stream()
+        self.asm.gen_program()
+        self.asm.gen_test_file(test_name)
 
     def randomize_cfg(self):
         cfg.randomize()
@@ -48,5 +53,9 @@
         gen_config_table()
 
 
+start_time = time.time()
 riscv_base_test_ins = riscv_instr_base_test()
-riscv_base_test_ins.run_phase()
+if cfg.argv.gen_test == "riscv_instr_base_test":
+    riscv_base_test_ins.run()
+    end_time = time.time()
+    logging.info("Total execution time: {}s".format(round(end_time - start_time)))
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
index 6fc084b..352c520 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
@@ -11,6 +11,7 @@
 """
 
 import sys
+import time
 import logging
 sys.path.append("pygen/")
 from pygen_src.test.riscv_instr_base_test import riscv_instr_base_test
@@ -39,4 +40,8 @@
         self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4)
 
 
+start_time = time.time()
 riscv_rand_test_ins = riscv_rand_instr_test()
+riscv_rand_test_ins.run()
+end_time = time.time()
+logging.info("Total execution time: {}s".format(round(end_time - start_time)))
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
index a389526..0458b01 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
@@ -302,7 +302,8 @@
                               (" --log_file_name={}/sim_{}_{}{}.log ".format(
                                   output_dir,
                                   test['test'], i, log_suffix)) + \
-                              (" --target=%s " % (target))
+                              (" --target=%s " % (target)) + \
+                              (" --gen_test=%s " % (test['gen_test']))
                     else:
                         cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
                               (" +UVM_TESTNAME={} ".format(test['gen_test'])) + \
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/genMetricsList.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/genMetricsList.py
index 58f4794..2e14f6c 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/genMetricsList.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/genMetricsList.py
@@ -20,7 +20,7 @@
 
 import json
 
-runCmdBase = "cd /mux-flow/results; python3 <rootDir>/run.py --test TESTNAME --simulator dsim --iss ovpsim --seed <seed> --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim"
+runCmdBase = "cd /mux-flow/results; python3 <rootDir>/run.py --test TESTNAME --simulator dsim --iss spike --seed <seed> --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim"
 
 ## Based on testlist located in <rootDir>/yaml/base_testlist.yaml
 base_testList = ["riscv_arithmetic_basic_test",
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/metrics-regress.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/metrics-regress.py
index 303fa9e..ffac640 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/metrics-regress.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/metrics-regress.py
@@ -39,15 +39,21 @@
 ## Start regression
 reqParams = {}
 reqParams['regressionName'] = args.regressionName
-reqParams['branch'] = str(os.environ['GITHUB_REF'])
+
+# Determine the git reference to pass to Metrics. For PRs, the reference
+# is of the format refs/pull/<PR-number>/merge
+if str(os.environ['GITHUB_EVENT_NAME']) == 'pull_request_target':
+    reqParams['branch'] = 'refs/pull/' + str(os.environ['PR_NUMBER']) + '/merge'
+else:
+    reqParams['branch'] = str(os.environ['GITHUB_REF'])
 params = json.dumps(reqParams)
 
 response, regressionData = make_http_request('POST', postRegression, params) 
 
 ## Check response
-if response.status is not 201:
+if response.status != 201:
     print('Error, regression was not started. Response: ' + str(response.status) + ':' \
-          + str(response.reason))
+          + str(response.reason) + ' ' + str(regressionData))
     print('Exit with code 1')
     exit(1)
 else:
@@ -59,7 +65,7 @@
 while True:
     time.sleep(10)
     response, regressionData = make_http_request('GET', getRegressionRunInfo+regressionRunId)
-    if response.status is 200:
+    if response.status == 200:
         if 'complete' in regressionData['status']:
             print('Regression complete')
             break
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
index a8dbbe6..91ced68 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
@@ -96,6 +96,10 @@
       kHintInstr               := 3,
       kIllegalSystemInstr      := 3
     };
+    if (!(RV32C inside {supported_isa})) {
+      exception != kHintInstr;
+      compressed == 1'b0;
+    }
   }
 
   constraint instr_bit_assignment_c {
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
index 009e756..f2cff1e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
@@ -130,9 +130,9 @@
       if (riscv_instr::instr_template.exists(instr_name)) begin
         riscv_instr instr;
         instr = riscv_instr::get_instr(instr_name);
-        if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
-                                RV32F, RV64F, RV32D, RV64D,
-                                RV32B, RV64B}) begin
+        if ((instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
+                                 RV32F, RV64F, RV32D, RV64D, RV32B, RV64B}) &&
+            (instr.group inside {supported_isa})) begin
           assign_trace_info_to_instr(instr);
           instr.pre_sample();
           instr_cg.sample(instr);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
index 344ef79..63cbb2a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
@@ -20,7 +20,7 @@
 - iss: ovpsim
   path_var: OVPSIM_PATH
   cmd: >
-    <path_var>/riscvOVPsim.exe
+    <path_var>/riscvOVPsimPlus.exe
     --controlfile <cfg_path>/riscvOVPsim.ic
     --objfilenoentry <elf>
     --override riscvOVPsim/cpu/simulateexceptions=T
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
index be02543..fe389cf 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
@@ -57,7 +57,6 @@
       - "vlog -64
         +incdir+<setting>
         +incdir+<user_extension>
-        -access=rwc
         -f <cwd>/files.f
         -sv
         -mfcu -cuname design_cuname