Update lowrisc_ibex to lowRISC/ibex@a33a91b2

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

* [lint] Fix some AscentLint errors (Pirmin Vogel)
* [dv] Set UVM_VERBOSITY to UVM_LOW (Greg Chadwick)
* [dv] Fix bad reference to instr_req_out (Greg Chadwick)
* [rtl] Move PMP checking to IF stage output (Tom Roberts)
* [rtl] Replace always_ff with always @(posedge .. in FPGA regfile
  (Pirmin Vogel)
* [dv] Fix PMP error handling for icache (Greg Chadwick)
* [dv] Add missing copyright header (Greg Chadwick)
* [dv] Add recoverable NMI handling to cosim (Greg Chadwick)
* [dv] Fix dside memory checking (Greg Chadwick)
* [dv] Fix cosim memory size (Greg Chadwick)
* Update google_riscv-dv to google/riscv-dv@6053014 (Michael
  Schaffner)
* [ibex_top] Use correct ECC codeword for '0 reset in regfile (Michael
  Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@be1359d27 (Michael Schaffner)
* [rtl, bitmanip] Add xperm.[nbh] instruction (Zbp, draft v.0.93)
  (Pirmin Vogel)
* [rtl, bitmanip] Clarify situation around zext.[bh] pseudo-
  instructions (Pirmin Vogel)
* [rtl] Fix typo in comment (Pirmin Vogel)
* [rtl, bitmanip] Align Zbb implementation with draft v.0.93 and
  v.1.0.0 (Pirmin Vogel)
* [rtl, bitmanip] Align Zbs implementation with draft v.0.93 and
  v.1.0.0 (Pirmin Vogel)
* [rtl, bitmanip] Rename bext/bdep to bcompress/bdecompress (Pirmin
  Vogel)
* Update google_riscv-dv to google/riscv-dv@ea8dd25 (Pirmin Vogel)
* [secded] Switch to inverted ECC codes (Michael Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@34ba5e45f (Michael Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@3a672eb36 (Canberk Topal)
* [dv/icache] Add missing window reset call (Tom Roberts)
* Move NT branch addr calculation to ID stage (Sam Shahrestani)
* Update lowrisc_ip to lowRISC/opentitan@ad629e3e6 (Rupert Swarbrick)
* [ci] Add co-simulation testing of CoreMark (Greg Chadwick)
* [coremark] Add option to coremark build to suppress pcount dump
  (Greg Chadwick)
* [cosim] Update documentation for cosim (Greg Chadwick)
* [cosim] Add Simple System with cosim (Greg Chadwick)
* [simple_system] Refactor Simple System (Greg Chadwick)
* [dv] Add matched instruction count to cosim (Greg Chadwick)
* [dv] Adjust cosim include paths (Greg Chadwick)
* [bitmanip][zba] Add support for Zba (address calculation) extension
  (Michael Munday)
* [dv] get ibex dv co-sim to run w questa (Miguel Escobar)
* [doc] Update DIT documentation for unaligned ld/st (Tom Roberts)
* Change use of blocking assignment to non-blocking inside always_ff
  (Henner Zeller)
* [dv] Add co-simulation environment support to UVM testbench (Greg
  Chadwick)
* [rtl] RVFI changes and extensions for co-simulation (Greg Chadwick)
* [dv] Add co-simulation framework (Greg Chadwick)
* [rtl,dv,doc] Flip priority of fast interrupts (Greg Chadwick)
* [ibex/ml] add CSR/mem_error tests to ml_testlist (Udi)
* [syn] Use read_verilog -defer in yosys_run_synth.tcl (Zachary Snow)
* remove unused RD in branch insn from tracer (zeeshanrafique23)
* Add missing parameters to ibex_top_tracing (Rupert Swarbrick)
* set verible action version to 'main' (Wojciech Sipak)
* bump verible action version (Wojciech Sipak)
* [rtl] Fix retired instruction counters (Greg Chadwick)
* [rtl] Factor ID exceptions into instruction kill (Greg Chadwick)
* [ci] Add GHA workflows to review PRs using Verible (Wojciech Sipak)
* [dv] Fix transaction ordering in ibex_mem_intf_monitor (Greg
  Chadwick)
* [rtl] Implement mvendorid/marchid/mimpid CSRs (Greg Chadwick)
* [style] Indent package bodies (Philipp Wagner)
* [style] Indent module header with two spaces (Philipp Wagner)
* [style] Use logical operators for reset (Philipp Wagner)
* [style] Fix whitespace issues around operators (Philipp Wagner)
* [style] Format module instantiations in tabular format (Philipp
  Wagner)

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index e9dd890..f14402b 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: 48f11c673348908c37d3eaa9bd1cd0a5b5c69253
+    rev: a33a91b2326b560c76b780d12cae200a1302fb7d
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml b/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml
new file mode 100644
index 0000000..bff5d75
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml
@@ -0,0 +1,49 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: pr-lint-review
+
+on:
+  workflow_run:
+    workflows: ["pr-trigger"]
+    types:
+      - completed
+
+jobs:
+  review_triggered:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      # this workflow does not run in a PR context
+      # download 'event.json' file from a PR-tiggered workflow
+      # to mock the PR context and make a review
+      - name: 'Download artifact'
+        id: get-artifacts
+        uses: actions/github-script@v3.1.0
+        with:
+          script: |
+            var artifacts = await github.actions.listWorkflowRunArtifacts({
+               owner: context.repo.owner,
+               repo: context.repo.repo,
+               run_id: ${{github.event.workflow_run.id }},
+            });
+            var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
+              return artifact.name == "event.json"
+            })[0];
+            var download = await github.actions.downloadArtifact({
+               owner: context.repo.owner,
+               repo: context.repo.repo,
+               artifact_id: matchArtifact.id,
+               archive_format: 'zip',
+            });
+            var fs = require('fs');
+            fs.writeFileSync('${{github.workspace}}/event.json.zip', Buffer.from(download.data));
+      - run: |
+          unzip event.json.zip
+      - name: Run Verible linter action
+        uses: chipsalliance/verible-linter-action@main
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          suggest_fixes: 'false'
+          config_file: 'vendor/lowrisc_ip/lint/tools/veriblelint/rules.vbl'
diff --git a/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml b/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml
new file mode 100644
index 0000000..b969698
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml
@@ -0,0 +1,25 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: pr-trigger
+
+on:
+  pull_request:
+
+jobs:
+  upload:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Copy event file
+        run: cp "$GITHUB_EVENT_PATH" ./event.json
+
+      # If this workflow is triggered by a PR from a fork
+      # it won't have sufficient access rights to make a review
+      # so we just save the file needed to do the review
+      # in a context with proper access rights
+      - name: Upload event file as artifact
+        uses: actions/upload-artifact@v2
+        with:
+          name: event.json
+          path: event.json
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index ace6903..ae618fa 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -28,7 +28,7 @@
 | Config | "micro" | "small" | "maxperf" | "maxperf-pmp-bmfull" |
 | ------ | ------- | --------| ----------| -------------------- |
 | Features | RV32EC | RV32IMC, 3 cycle mult | RV32IMC, 1 cycle mult, Branch target ALU, Writeback stage | RV32IMCB, 1 cycle mult, Branch target ALU, Writeback stage, 16 PMP regions |
-| Performance (CoreMark/MHz) | 0.904 | 2.47 | 3.13 | 3.05 |
+| Performance (CoreMark/MHz) | 0.904 | 2.47 | 3.13 | 3.13 |
 | Area - Yosys (kGE) | 17.44 | 26.06 | 35.64 | 58.74 |
 | Area - Commercial (estimated kGE) | ~16 | ~24 | ~33 | ~54 |
 | Verification status | Red | Green | Amber | Amber |
@@ -38,7 +38,6 @@
 * Performance numbers are based on CoreMark running on the Ibex Simple System [platform](examples/simple_system/README.md).
   Note that different ISAs (use of B and C extensions) give the best results for different configurations.
   See the [Benchmarks README](examples/sw/benchmarks/README.md) for more information.
-  The "maxperf-pmp-bmfull" configuration sets a `SpecBranch` parameter in `ibex_core.sv`; this helps timing but has a small negative performance impact.
 * Yosys synthesis area numbers are based on the Ibex basic synthesis [flow](syn/README.md) using the latch-based register file.
 * Commercial synthesis area numbers are a rough estimate of what might be achievable with a commercial synthesis flow and technology library.
 * For comparison, the original "Zero-riscy" core yields an area of 23.14kGE using our Yosys synthesis flow.
diff --git a/hw/vendor/lowrisc_ibex/azure-pipelines.yml b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
index 4306e0b..78aca02 100644
--- a/hw/vendor/lowrisc_ibex/azure-pipelines.yml
+++ b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
@@ -88,6 +88,11 @@
       git checkout "$RISCV_COMPLIANCE_GIT_VERSION"
     displayName: Get RISC-V Compliance test suite
 
+  - bash: |
+      # Build CoreMark without performance counter dump for co-simulation testing
+      make -C ./examples/sw/benchmarks/coremark SUPPRESS_PCOUNT_DUMP=1
+    displayName: Build CoreMark
+
   # Run Ibex RTL CI per supported configuration
   - template : ci/ibex-rtl-ci-steps.yml
     parameters:
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 5b1a853..907b17a 100644
--- a/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
+++ b/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
@@ -65,3 +65,23 @@
         done
         exit $fail
       displayName: Run RISC-V Compliance test for Ibex RV32IMC for ${{ config }}
+
+    - bash: |
+        # Setup environment to use cosim with Simple System
+        export IBEX_COSIM_ISS_ROOT=/opt/spike-cosim
+        export LD_LIBRARY_PATH=/opt/spike-cosim/lib:$LD_LIBRARY_PATH
+
+        # Build simple system with co-simulation
+        fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim $IBEX_CONFIG_OPTS
+
+        if [ $? != 0 ]; then
+          echo -n "##vso[task.logissue type=error]"
+          echo "Build Simple System with co-simulation failed. Run fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim $IBEX_CONFIG_OPTS to check and fix all errors."
+        fi
+
+        build/lowrisc_ibex_ibex_simple_system_cosim_0/sim-verilator/Vibex_simple_system --meminit=ram,examples/sw/benchmarks/coremark/coremark.elf
+        if [ $? != 0 ]; then
+          echo -n "##vso[task.logissue type=error]"
+          echo "Running CoreMark failed co-simulation testing"
+        fi
+      displayName: Run CoreMark for ${{ config }}
diff --git a/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh b/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
index 5fef79f..7c64102 100755
--- a/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
+++ b/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
@@ -32,6 +32,11 @@
     $SUDO_CMD sh -c "echo 'deb http://download.opensuse.org/repositories/home:/phiwag:/edatools/xUbuntu_$VERSION_ID/ /' > /etc/apt/sources.list.d/edatools.list"
     $SUDO_CMD apt-get update
 
+    # Make spike-cosim repository available
+    curl -Ls https://download.opensuse.org/repositories/home:gac_lowrisc/xUbuntu_18.04/Release.key | $SUDO_CMD apt-key add -
+    $SUDO_CMD sh -c "echo 'deb http://download.opensuse.org/repositories/home:/gac_lowrisc/xUbuntu_18.04/ /' > /etc/apt/sources.list.d/spike-cosim.list" sudo apt update
+    $SUDO_CMD apt-get update
+
     # Packaged dependencies
     # Install python3-yaml through apt to get a version with libyaml bindings,
     # which is significantly faster than the pure Python version.
@@ -53,6 +58,7 @@
         libelf-dev \
         clang-format \
         "verilator-$VERILATOR_VERSION" \
+        spike-cosim \
         xz-utils
 
       # Python dependencies
diff --git a/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst b/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
index c58407a..a113815 100644
--- a/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
+++ b/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
@@ -11,3 +11,17 @@
 Ibex comes with three different register file implementations that can be selected using the enumerated parameter ``RegFile`` defined in :file:`rtl/ibex_pkg.sv`.
 Depending on the target technology, either the flip-flop-based ("ibex_pkg::RegFileFF", default), the latch-based ("ibex_pkg::RegFileLatch") or an FPGA-targeted ("ibex_pkg::RegFileFPGA") implementation should be selected.
 For more information about the three register file implementations and their trade-offs, check out :ref:`register-file`.
+
+Identification CSRs
+-------------------
+
+The RISC-V Privileged Architecture specifies several read-only CSRs that identify the vendor and micro-architecture of a CPU.
+These are ``mvendorid``, ``marchid`` and ``mimpid``.
+The fixed, read-only values for these CSRs are defined in :file:`rtl/ibex_pkg.sv`.
+Implementers should carefully consider appropriate values for these registers.
+Ibex, as an open source implementation, has an assigned architecture ID (``marchid``) of 22.
+(Allocations are specified in `marchid.md of the riscv-isa-manual repository <https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md>`_.)
+If significant changes are made to the micro-architecture a different architecture ID should be used.
+The vendor ID and implementation ID (``mvendorid`` and ``mimpid``) both read as 0 by default, meaning non-implemented.
+Implementers may wish to use other values here.
+Please see the RISC-V Privileged Architecture specification for more details on what these IDs represent and how they should be chosen.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst
new file mode 100644
index 0000000..f2e99ac
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst
@@ -0,0 +1,178 @@
+.. _cosim:
+
+Co-simulation System
+====================
+
+Overview
+--------
+
+A co-simulation system is provided that can run in either the Ibex UVM DV environment or with Simple System.
+This system runs a RISC-V ISS (currently only Spike is supported) in lockstep with an Ibex core.
+All instructions executed by Ibex and memory transactions generated are checked against the behaviour of the ISS.
+This system supports memory errors, interrupt and debug requests which are observed in the RTL simulation and forwarded to the ISS so the ISS and RTL remain in sync.
+The system uses a generic interface to allow support of multiple ISSes.
+Only VCS is supported as a simulator, though no VCS specific functionality is required so adding support for another simulator should be straight-forward.
+
+To run the co-simulation system the `ibex-cosim branch from the lowRISC fork of Spike <https://github.com/lowRISC/riscv-isa-sim/tree/ibex>`_ is required.
+
+The RISC-V Formal Interface (RVFI) is used to provide information about retired instructions and instructions that produce synchronous traps for checking.
+The RVFI has been extended to provide interrupt and debug information and the value of the ``mcycle`` CSR.
+These extended signals have the prefix ``rvfi_ext``
+
+The co-simulation system is EXPERIMENTAL.
+It is disabled by default in the UVM DV environment currently, however it is intended to become the primary checking method for the UVM testbench.
+
+Setup and Usage
+---------------
+
+Clone the `lowRISC fork of Spike <https://github.com/lowRISC/riscv-isa-sim>`_ and checkout the ``ibex_cosim`` branch.
+Follow the Spike build instructions to build and install Spike.
+The build will install multiple header files and libraries, it is recommended a custom install location (using ``--prefix=<path>`` with ``configure``) is used to avoid cluttering system directories.
+The ``--enable-commitlog`` and ``--enable-misaligned`` options must be passed to ``configure``.
+
+Once built, the ``IBEX_COSIM_ISS_ROOT`` environment variable must be set to the Spike root install directory (as given by ``--prefix=<path>`` to ``configure``) in order to build either the UVM DV environment or Simple System with co-simulation support.
+
+To build/run the UVM DV environment with the co-simulator add the ``COSIM=1`` argument to the make command.
+To build Simple System with the co-simulator build the ``lowrisc:ibex:ibex_simple_system_cosim`` core.
+
+Quick Build and Run Instructions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Build and install the co-simulator
+
+.. code-block:: bash
+
+  # Get the Ibex co-simulation spike branch
+  git clone -b ibex_cosim https://github.com/lowRISC/riscv-isa-sim.git riscv-isa-sim-cosim
+
+  # Setup build directory
+  cd riscv-isa-sim-cosim
+  mkdir build
+  cd build
+
+  # Configure and build spike
+  ../configure --enable-commitlog --enable-misaligned --prefix=/opt/spike-cosim
+  sudo make -j8 install
+
+  # Setup IBEX_COSIM_ISS_ROOT so build flow can find the co-simulator
+  export IBEX_COSIM_ISS_ROOT=/opt/spike-cosim
+
+Run the UVM DV regression with co-simulation enabled
+
+.. code-block:: bash
+
+  # Run regression with co-simulation enabled
+  cd <ibex_area>/dv/uvm/core_ibex
+  make COSIM=1
+
+Build and run Simple System with the co-simulation enabled
+
+.. code-block:: bash
+
+  # Build simulator
+  fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim --RV32E=0 --RV32M=ibex_pkg::RV32MFast
+
+  # Build coremark test binary, with performance counter dump disabled. The
+  # co-simulator system doesn't produce matching performance counters in spike so
+  # any read of those CSRs results in a mismatch and a failure.
+  make -C ./examples/sw/benchmarks/coremark SUPPRESS_PCOUNT_DUMP=1
+
+  # Spike's libsoftfloat.so needs to be accessible so add it to LD_LIBRARY_PATH
+  export LD_LIBRARY_PATH=/opt/spike-cosim/lib:$LD_LIBRARY_PATH
+
+  # Run coremark binary with co-simulation checking
+  build/lowrisc_ibex_ibex_simple_system_cosim_0/sim-verilator/Vibex_simple_system --meminit=ram,examples/sw/benchmarks/coremark/coremark.elf
+
+Co-simulation details
+----------------------
+
+The co-simulation system uses DPI calls to link the DV and ISS sides together.
+A C++ interface is defined in ``dv/cosim/cosim.h`` with a DPI wrapper provided by ``dv/cosim/cosim_dpi.cc`` and ``dv/cosim/cosim_dpi.h``.
+A ``chandle``, which points to some class instance that implements the interface, must be provided by the DV environment.
+All the co-simulation DPI calls take this ``chandle`` as a first argument.
+
+The details below discuss the C++ interface.
+The DPI version of the interface is almost identical, with all functions prefaced with ``riscv_cosim`` and taking a ``chandle`` of the co-simulation instance to use.
+
+The core function of the co-simulation interface is the ``step`` function:
+
+.. code-block:: c++
+
+  virtual bool step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc, bool sync_trap);
+
+``step`` takes arguments giving the PC of the most recently retired or synchronously trapping instruction in the DUT along with details of any register write that occurred.
+
+Where ``step`` is provided with a retired (successfully executed) instruction it steps the ISS by one instruction and checks it executed the same instruction, with the same register write result, as the DUT.
+
+When ``step`` is provided with an instruction that produces a synchronous trap, it checks the ISS also traps on the same instruction but does not step to the next executed instruction.
+That instruction will be the first instruction of the trap handler and will be checked/stepped by the next call to ``step`` when it retires from the DUT.
+
+Any data memory accesses that the ISS produces during the ``step`` are checked against observed DUT memory accesses.
+
+``step`` returns false if any checks have failed.
+If any errors occur during the step they can be accessed via ``get_errors`` which returns a vector of error messages.
+For the DPI interface errors are accessed using ``riscv_cosim_get_num_errors`` and ``riscv_cosim_get_error``.
+When errors have been checked they can be cleared with ``clear_errors``.
+
+Trap Handling
+^^^^^^^^^^^^^
+
+Traps are separated into two categories, synchronous and asynchronous.
+Synchronous traps are caused by a particular instruction's execution (e.g. an illegal instruction).
+Asynchronous traps are caused by external interrupts.
+Note that in Ibex error responses to both loads and store produce a synchronous trap so the co-simulation system has the same behaviour.
+
+A synchronous trap is associated with a particular instruction and prevents that instruction from completing its execution.
+That instruction doesn't retire, but is still made visible on the RVFI.
+The ``rvfi_trap`` signal is asserted for an instruction that causes a synchronous trap.
+As described above ``step`` should be called for any instruction that causes a synchronous trap to check the trap is also seen by the ISS.
+
+An asynchronous trap can be seen as occurring between instructions and as such doesn't have an associated instruction, nothing will be seen on RVFI with ``rvfi_trap`` set.
+The co-simulation system will immediately take any pending asynchronous trap when ``step`` is called, expecting the instruction checked with ``step`` to be the first instruction of the trap handler.
+
+While a debug request is not strictly an asynchronous trap (it doesn't use the same exception handling mechanism), they work identically to asynchronous traps for the co-simulation system.
+When a debug request is pending when ``step`` is called the co-simulation will expect the instruction checked by ``step`` to be the first instruction of the debug handler.
+
+Interrupts and Debug Requests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The DV environment must observe any incoming interrupts and debug requests generated by the testbench and notify the co-simulation system of them using ``set_mip``, ``set_debug_req`` and ``set_nmi``.
+An interrupt or debug request will take immediate effect at the next ``step`` (if architecturally required to do so).
+The DV environment is responsible for determining when to call ``set_mip``, ``set_debug_req`` and ``set_nmi`` to ensure a RTL and co-simulation match.
+
+The state of the incoming interrupts and debug request is sampled when an instruction moves from IF to ID/EX.
+The sampled state is tracked with the rest of the RVFI pipeline and used to call ``set_mip``, ``set_debug_req`` and ``set_nmi`` when the instruction is output by the RVFI.
+See the comments in :file:`rtl/ibex_core.sv`, around the ``new_debug_req``, ``new_nmi`` and ``new_irq`` signals for further details.
+
+Memory Access Checking and Bus Errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The co-simulation system must be informed of all Dside accesses performed by the RTL using ``notify_dside_access``.
+See :file:`dv/cosim/cosim.h` for further details.
+As Ibex doesn't perform speculative Dside memory accesses, all notified accesses are expected to match with accesses performed by the ISS in the same order they are notified.
+
+Accesses notified via ``notify_dside_access`` can specify they saw an error response, the co-simulation system will produce the appropriate trap when the ISS attempts to access the address that saw the error.
+
+Accesses must be notified before they occur in the ISS for the access matching and trapping on errors to work.
+
+Iside accesses from Ibex can be speculative, so there is no simple link between accesses produced by the RTL and the accesses performed by the ISS for the Iside.
+This means no direct checking of Iside accesses is done, however errors on the Iside accesses that result in an instruction fault trap need to be notified to the co-simulation system.
+``set_iside_error`` does this, it is provided with the address that saw the bus error and it should be called immediately before the ``step`` that will process the trap.
+The co-simulation system will produce an instruction fault trap if it attempts to access the provided error address in the ``step`` call following the ``set_iside_error`` call.
+
+Two methods are available for dealing with bus errors on the Iside, they differ in where they probe.
+One probes on the external instr_X memory interface, the other probes internally within the IF stage.
+The probe used is selected by the ``probe_imem_for_err`` field of the ``core_ibex_cosim_cfg`` structure.
+When set external probing is used, otherwise internal probing is used.
+
+Both probe points look for addresses that have seen bus errors.
+If an instruction entering ID/EX fetches from an address that has seen a bus error (as recorded by one of the probing methods) its ``rvfi_order_id`` is recorded.
+When a faulting instruction is reported on the RVFI and its ``rvfi_order_id`` matches a recorded faulting one ``set_iside_error`` is called with the faulting address before the next ``step``.
+
+The external interface probe should be used when it is guaranteed that a bus error to address A on the external interface results in a fetch error the next time an instruction with address A is observed entering the ID/EX stage (providing no successful access to A has occurred in the mean time).
+Otherwise the internal probe should be used.
+When Ibex is used with the prefetch buffer this guarantee holds and the external probe can be used.
+When Ibex is used with the instruction cache this guarantee does not hold and the internal probe must be used.
+
+Care should be taken when using the internal probe as it will miss any bug that causes instruction faults to be ignored by the prefetch buffer or ICache (or whatever else has been used in place of these by a custom implementation).
+In the case of the Ibex ICache a separate testbench ensures instruction faults are dealt with appropriately within the ICache.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
index 24b5ece..c73894a 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
@@ -94,6 +94,12 @@
 +---------+--------------------+--------+-----------------------------------------------+
 |  0xB9F  | ``mhpmcounter31h`` | WARL   | Upper 32 bits of ``mhmpcounter31``            |
 +---------+--------------------+--------+-----------------------------------------------+
+|  0xF11  | ``mvendorid``      | R      | Machine Vendor ID                             |
++---------+--------------------+--------+-----------------------------------------------+
+|  0xF12  | ``marchid``        | R      | Machine Architecture ID                       |
++---------+--------------------+--------+-----------------------------------------------+
+|  0xF13  | ``mimpid``         | R      | Machine Implementation ID                     |
++---------+--------------------+--------+-----------------------------------------------+
 |  0xF14  | ``mhartid``        | R      | Hardware Thread ID                            |
 +---------+--------------------+--------+-----------------------------------------------+
 
@@ -576,6 +582,38 @@
 Any access to these registers will trap.
 It is recommended that trap handler software provides a means of accessing platform-defined ``mtime(h)`` timers where available.
 
+Machine Vendor ID (mvendorid)
+-----------------------------
+
+CSR Address: ``0xF11``
+
+Reset Value: ``0x0000_0000``
+
+Use the ``CSR_MVENDORID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
+Machine Architecture ID (marchid)
+---------------------------------
+
+CSR Address: ``0xF12``
+
+Reset Value: ``0x0000_0016``
+
+Use the ``CSR_MARCHID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+The value used is allocated specifically to Ibex.
+If significant changes are made a different ID should be used.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
+Machine Implementation ID (mimpid)
+----------------------------------
+
+CSR Address: ``0xF13``
+
+Reset Value: ``0x0000_0000``
+
+Use the ``CSR_MIMPID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
 .. _csr-mhartid:
 
 Hardware Thread ID (mhartid)
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
index 567c149..a80dd47 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
@@ -50,7 +50,8 @@
 For more information, see the :ref:`cs-registers` documentation.
 
 If multiple interrupts are pending, they are handled in the priority order defined by the RISC-V Privileged Specification, version 1.11 (see Machine Interrupt Registers, Section 3.1.9).
-The highest priority is given to the interrupt with the highest ID, except for timer interrupts, which have the lowest priority.
+The fast interrupts have a platform defined priority.
+In Ibex they take priority over all other interrupts and between fast interrupts the highest priority is given to the interrupt with the lowest ID.
 
 The NMI is enabled independent of the values in the ``mstatus`` and ``mie`` CSRs, and it is not visible through the ``mip`` CSR.
 It has interrupt ID 31, i.e., it has the highest priority of all interrupts and the core jumps to the trap-handler base address (in ``mtvec``) plus 0x7C to handle the NMI.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
index 6c96aaf..6ab1dd5 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
@@ -22,5 +22,6 @@
    debug
    tracer
    verification
+   cosim
    rvfi
    history
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
index b79d5e4..3a57e49 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
@@ -87,7 +87,7 @@
   +---------------------------------+---------------+--------------------------+
   | Zbp (Permutation)               | Full          | None                     |
   +---------------------------------+---------------+--------------------------+
-  | Zbe (Bit extract/deposit)       | Full          | All                      |
+  | Zbe (Bit compress/decompress)   | Full          | All                      |
   +---------------------------------+---------------+--------------------------+
   | Zbf (Bit-field place)           | Balanced/Full | All                      |
   +---------------------------------+---------------+--------------------------+
@@ -97,8 +97,6 @@
   +---------------------------------+---------------+--------------------------+
   | Zbt (Ternary)                   | Balanced/Full | All                      |
   +---------------------------------+---------------+--------------------------+
-  | Zb_tmp (Temporary) [#B_zb_tmp]_ | Balanced/Full | None                     |
-  +---------------------------------+---------------+--------------------------+
 
   The implementation of the B-extension comes with an area overhead of 1.8 to 3.0 kGE for the balanced version and 6.0 to 8.7 kGE for the full version.
   That corresponds to an approximate percentage increase in area of 9 to 14 % and 25 to 30 % for the balanced and full versions respectively.
@@ -178,6 +176,3 @@
    Ibex will be updated to match future versions of the specification.
    Prior to ratification this may involve backwards incompatible changes.
    Additionally, neither GCC or Clang have committed to maintaining support upstream for unratified versions of the specification.
-
-.. [#B_zb_tmp] The sign-extend instructions `sext.b/sext.h` are defined but not unambiguously categorized in draft version 0.92 of the extension.
-   Temporarily, they have been assigned a separate Z-extension (Zb_tmp) both in Ibex and the RISCV-DV random instruction generator used to verify the bit manipulation instructions in Ibex.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
index a169298..0898fc1 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
@@ -58,7 +58,7 @@
 ----------------------
 
 The core can optionally generate and verify check bits sent alongside the data for memory accesses.
-Checkbits are generated and checked using a 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv`).
+Checkbits are generated and checked using an inverted 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv`).
 When this feature is used, any mismatch in checkbits will generate a major alert.
 
 This feature is only used if the core is configured with the SecureIbex parameter set.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
index 5f41df1..167ec48 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
@@ -26,6 +26,10 @@
 * Early completion of multiplication by zero/one is removed
 * Early completion of divide by zero is removed
 
+Note that data memory operations to unaligned addresses might result in multiple bus accesses being made.
+This in turn could expose information about the address as a timing side-channel.
+It is therefore recommended to stick to aligned memory accesses when using this feature for critical code regions.
+
 Dummy Instruction Insertion
 ---------------------------
 
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 4ec4186..e1a00ce 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
@@ -6,37 +6,59 @@
 #include <iostream>
 
 #include "ibex_pcounts.h"
+#include "ibex_simple_system.h"
 #include "verilated_toplevel.h"
 #include "verilator_memutil.h"
 #include "verilator_sim_ctrl.h"
 
-int main(int argc, char **argv) {
-  ibex_simple_system top;
-  VerilatorMemUtil memutil;
-  VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
-  simctrl.SetTop(&top, &top.IO_CLK, &top.IO_RST_N,
-                 VerilatorSimCtrlFlags::ResetPolarityNegative);
+SimpleSystem::SimpleSystem(const char *ram_hier_path, int ram_size_words)
+    : _ram(ram_hier_path, ram_size_words, 4) {}
 
-  MemArea ram("TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
-              1024 * 1024 / 4, 4);
+int SimpleSystem::Main(int argc, char **argv) {
+  bool exit_app;
+  int ret_code = Setup(argc, argv, exit_app);
 
-  memutil.RegisterMemoryArea("ram", 0x0, &ram);
-  simctrl.RegisterExtension(&memutil);
-
-  bool exit_app = false;
-  int ret_code = simctrl.ParseCommandArgs(argc, argv, exit_app);
   if (exit_app) {
     return ret_code;
   }
 
+  Run();
+
+  if (!Finish()) {
+    return 1;
+  }
+
+  return 0;
+}
+
+int SimpleSystem::Setup(int argc, char **argv, bool &exit_app) {
+  VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+
+  simctrl.SetTop(&_top, &_top.IO_CLK, &_top.IO_RST_N,
+                 VerilatorSimCtrlFlags::ResetPolarityNegative);
+
+  _memutil.RegisterMemoryArea("ram", 0x0, &_ram);
+  simctrl.RegisterExtension(&_memutil);
+
+  exit_app = false;
+  return simctrl.ParseCommandArgs(argc, argv, exit_app);
+}
+
+void SimpleSystem::Run() {
+  VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+
   std::cout << "Simulation of Ibex" << std::endl
             << "==================" << std::endl
             << std::endl;
 
   simctrl.RunSimulation();
+}
+
+bool SimpleSystem::Finish() {
+  VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
 
   if (!simctrl.WasSimulationSuccessful()) {
-    return 1;
+    return false;
   }
 
   // Set the scope to the root scope, the ibex_pcount_string function otherwise
@@ -51,5 +73,5 @@
   std::ofstream pcount_csv("ibex_simple_system_pcount.csv");
   pcount_csv << ibex_pcount_string(true);
 
-  return 0;
+  return true;
 }
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 c585a09..1813bab 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
@@ -5,26 +5,12 @@
 name: "lowrisc:ibex:ibex_simple_system"
 description: "Generic simple system for running binaries on ibex using verilator"
 filesets:
-  files_sim:
+  files_simple_system:
     depend:
-      - lowrisc:ibex:ibex_top_tracing
-      - lowrisc:ibex:sim_shared
+      - lowrisc:ibex:ibex_simple_system_core
     files:
-      - rtl/ibex_simple_system.sv
-    file_type: systemVerilogSource
-
-  files_verilator:
-    depend:
-      - lowrisc:dv_verilator:memutil_verilator
-      - lowrisc:dv_verilator:simutil_verilator
-      - lowrisc:dv_verilator:ibex_pcounts
-    files:
-      - ibex_simple_system.cc: { file_type: cppSource }
-      - lint/verilator_waiver.vlt: {file_type: vlt}
-
-  files_lint_verible:
-    files:
-      - lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
+      - ibex_simple_system_main.cc
+    file_type: cppSource
 
 parameters:
   RV32E:
@@ -113,9 +99,7 @@
 targets:
   default: &default_target
     filesets:
-      - tool_verilator ? (files_verilator)
-      - tool_veriblelint ? (files_lint_verible)
-      - files_sim
+      - files_simple_system
     toplevel: ibex_simple_system
     parameters:
       - RV32E
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h
new file mode 100644
index 0000000..e8d0919
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "verilated_toplevel.h"
+#include "verilator_memutil.h"
+
+class SimpleSystem {
+ public:
+  SimpleSystem(const char *ram_hier_path, int ram_size_words);
+  virtual ~SimpleSystem() {}
+  virtual int Main(int argc, char **argv);
+
+ protected:
+  ibex_simple_system _top;
+  VerilatorMemUtil _memutil;
+  MemArea _ram;
+
+  virtual int Setup(int argc, char **argv, bool &exit_app);
+  virtual void Run();
+  virtual bool Finish();
+};
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core
new file mode 100644
index 0000000..84c298a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core
@@ -0,0 +1,36 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:ibex:ibex_simple_system_core"
+description: "Generic simple system for running binaries on ibex using verilator"
+filesets:
+  files_sim:
+    depend:
+      - lowrisc:ibex:ibex_top_tracing
+      - lowrisc:ibex:sim_shared
+    files:
+      - rtl/ibex_simple_system.sv
+    file_type: systemVerilogSource
+
+  files_verilator:
+    depend:
+      - lowrisc:dv_verilator:memutil_verilator
+      - lowrisc:dv_verilator:simutil_verilator
+      - lowrisc:dv_verilator:ibex_pcounts
+    files:
+      - ibex_simple_system.cc: { file_type: cppSource }
+      - ibex_simple_system.h:  { file_type: cppSource, is_include_file: true}
+      - lint/verilator_waiver.vlt: {file_type: vlt}
+
+  files_lint_verible:
+    files:
+      - lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
+
+targets:
+  default:
+    filesets:
+      - tool_verilator ? (files_verilator)
+      - tool_veriblelint ? (files_lint_verible)
+      - files_sim
+      - files_verilator
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc
new file mode 100644
index 0000000..25dbbed
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc
@@ -0,0 +1,13 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "ibex_simple_system.h"
+
+int main(int argc, char **argv) {
+  SimpleSystem simple_system(
+      "TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
+      1024 * 1024);
+
+  return simple_system.Main(argc, argv);
+}
diff --git a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
index e32431d..d394515 100644
--- a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
+++ b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
@@ -174,7 +174,9 @@
         Target specific final code
 */
 void portable_fini(core_portable *p) {
+#ifndef SUPPRESS_PCOUNT_DUMP
   dump_pcounts();
+#endif
 
   CORE_TICKS elapsed = get_time();
   float coremark_mhz;
diff --git a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
index 9ef33bb..c9ae957 100755
--- a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
+++ b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
@@ -5,6 +5,7 @@
 # SPDX-License-Identifier: Apache-2.0
 
 RV_ISA = rv32im
+SUPPRESS_PCOUNT_DUMP = 0
 
 OUTFILES = $(OPATH)coremark.dis $(OPATH)coremark.map $(OPATH)coremark.vmem
 
@@ -36,6 +37,10 @@
 	-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
 	-DPERFORMANCE_RUN=1
 
+ifeq ($(SUPPRESS_PCOUNT_DUMP),1)
+	PORT_CFLAGS += -DSUPPRESS_PCOUNT_DUMP
+endif
+
 FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
 CFLAGS += $(PORT_CFLAGS) $(XCFLAGS) -I$(SIMPLE_SYSTEM_COMMON) -I$(PORT_DIR) -I.
 #Flag : LFLAGS_END
diff --git a/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv b/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
index 0095e2f..73849f2 100644
--- a/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
+++ b/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
@@ -111,9 +111,9 @@
       f_addr_valid <= 1'b0;
     end else begin
       if (branch_i) begin
-        f_addr_valid = 1'b1;
+        f_addr_valid <= 1'b1;
       end else if (valid_o & ready_i & err_o) begin
-        f_addr_valid = 1'b0;
+        f_addr_valid <= 1'b0;
       end
     end
   end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
index 695eb82..ad796e2 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
@@ -9,27 +9,27 @@
 module ibex_alu #(
   parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone
 ) (
-    input  ibex_pkg::alu_op_e operator_i,
-    input  logic [31:0]       operand_a_i,
-    input  logic [31:0]       operand_b_i,
+  input  ibex_pkg::alu_op_e operator_i,
+  input  logic [31:0]       operand_a_i,
+  input  logic [31:0]       operand_b_i,
 
-    input  logic              instr_first_cycle_i,
+  input  logic              instr_first_cycle_i,
 
-    input  logic [32:0]       multdiv_operand_a_i,
-    input  logic [32:0]       multdiv_operand_b_i,
+  input  logic [32:0]       multdiv_operand_a_i,
+  input  logic [32:0]       multdiv_operand_b_i,
 
-    input  logic              multdiv_sel_i,
+  input  logic              multdiv_sel_i,
 
-    input  logic [31:0]       imd_val_q_i[2],
-    output logic [31:0]       imd_val_d_o[2],
-    output logic [1:0]        imd_val_we_o,
+  input  logic [31:0]       imd_val_q_i[2],
+  output logic [31:0]       imd_val_d_o[2],
+  output logic [1:0]        imd_val_we_o,
 
-    output logic [31:0]       adder_result_o,
-    output logic [33:0]       adder_result_ext_o,
+  output logic [31:0]       adder_result_o,
+  output logic [33:0]       adder_result_ext_o,
 
-    output logic [31:0]       result_o,
-    output logic              comparison_result_o,
-    output logic              is_equal_result_o
+  output logic [31:0]       result_o,
+  output logic              comparison_result_o,
+  output logic              is_equal_result_o
 );
   import ibex_pkg::*;
 
@@ -45,11 +45,17 @@
   // Adder //
   ///////////
 
+  logic        adder_op_a_shift1;
+  logic        adder_op_a_shift2;
+  logic        adder_op_a_shift3;
   logic        adder_op_b_negate;
   logic [32:0] adder_in_a, adder_in_b;
   logic [31:0] adder_result;
 
   always_comb begin
+    adder_op_a_shift1 = 1'b0;
+    adder_op_a_shift2 = 1'b0;
+    adder_op_a_shift3 = 1'b0;
     adder_op_b_negate = 1'b0;
     unique case (operator_i)
       // Adder OPs
@@ -65,20 +71,33 @@
       ALU_MIN,  ALU_MINU,
       ALU_MAX,  ALU_MAXU: adder_op_b_negate = 1'b1;
 
+      // Address Calculation OPs (RV32B Ops)
+      ALU_SH1ADD: if (RV32B != RV32BNone) adder_op_a_shift1 = 1'b1;
+      ALU_SH2ADD: if (RV32B != RV32BNone) adder_op_a_shift2 = 1'b1;
+      ALU_SH3ADD: if (RV32B != RV32BNone) adder_op_a_shift3 = 1'b1;
+
       default:;
     endcase
   end
 
   // prepare operand a
-  assign adder_in_a    = multdiv_sel_i ? multdiv_operand_a_i : {operand_a_i,1'b1};
+  always_comb begin
+    unique case(1'b1)
+      multdiv_sel_i:     adder_in_a = multdiv_operand_a_i;
+      adder_op_a_shift1: adder_in_a = {operand_a_i[30:0],2'b01};
+      adder_op_a_shift2: adder_in_a = {operand_a_i[29:0],3'b001};
+      adder_op_a_shift3: adder_in_a = {operand_a_i[28:0],4'b0001};
+      default:           adder_in_a = {operand_a_i,1'b1};
+    endcase
+  end
 
   // prepare operand b
   assign operand_b_neg = {operand_b_i,1'b0} ^ {33{1'b1}};
   always_comb begin
-    unique case(1'b1)
+    unique case (1'b1)
       multdiv_sel_i:     adder_in_b = multdiv_operand_b_i;
       adder_op_b_negate: adder_in_b = operand_b_neg;
-      default :          adder_in_b = {operand_b_i, 1'b0};
+      default:           adder_in_b = {operand_b_i, 1'b0};
     endcase
   end
 
@@ -208,12 +227,12 @@
   // =======================
   // Single bit instructions operate on bit operand_b_i[4:0] of operand_a_i.
 
-  // The operations sbset, sbclr and sbinv are implemented by generation of a bit-mask using the
+  // The operations bset, bclr and binv are implemented by generation of a bit-mask using the
   // shifter structure. This is done by left-shifting the operand 32'h1 by the required amount.
   // The signal shift_sbmode multiplexes the shifter input and sets the signal shift_left.
   // Further processing is taken care of by a separate structure.
   //
-  // For sbext, the bit defined by operand_b_i[4:0] is to be returned. This is done by simply
+  // For bext, the bit defined by operand_b_i[4:0] is to be returned. This is done by simply
   // shifting operand_a_i to the right by the required amount and returning bit [0] of the result.
   //
   // Bit-Field Place
@@ -248,7 +267,7 @@
   assign bfp_len = {~(|operand_b_i[27:24]), operand_b_i[27:24]}; // len = 0 encodes for len = 16
   assign bfp_off = operand_b_i[20:16];
   assign bfp_mask = (RV32B != RV32BNone) ? ~(32'hffff_ffff << bfp_len) : '0;
-  for (genvar i=0; i<32; i++) begin : gen_rev_bfp_mask
+  for (genvar i = 0; i < 32; i++) begin : gen_rev_bfp_mask
     assign bfp_mask_rev[i] = bfp_mask[31-i];
   end
 
@@ -262,7 +281,7 @@
 
   always_comb begin
     if (bfp_op) begin
-      shift_amt[4:0] = bfp_off ; // length field of bfp control word
+      shift_amt[4:0] = bfp_off;  // length field of bfp control word
     end else begin
       shift_amt[4:0] = instr_first_cycle_i ?
           (operand_b_i[5] && shift_funnel ? shift_amt_compl[4:0] : operand_b_i[4:0]) :
@@ -272,7 +291,7 @@
 
   // single-bit mode: shift
   assign shift_sbmode = (RV32B != RV32BNone) ?
-      (operator_i == ALU_SBSET) | (operator_i == ALU_SBCLR) | (operator_i == ALU_SBINV) : 1'b0;
+      (operator_i == ALU_BSET) | (operator_i == ALU_BCLR) | (operator_i == ALU_BINV) : 1'b0;
 
   // left shift if this is:
   // * a standard left shift (slo, sll)
@@ -280,12 +299,12 @@
   // * a ror in the second cycle
   // * fsl: without word-swap bit: first cycle, else: second cycle
   // * fsr: without word-swap bit: second cycle, else: first cycle
-  // * a single-bit instruction: sbclr, sbset, sbinv (excluding sbext)
+  // * a single-bit instruction: bclr, bset, binv (excluding bext)
   // * bfp: bfp_mask << bfp_off
   always_comb begin
     unique case (operator_i)
       ALU_SLL: shift_left = 1'b1;
-      ALU_SLO,
+      ALU_SLO: shift_left = (RV32B == RV32BFull) ? 1'b1 : 1'b0;
       ALU_BFP: shift_left = (RV32B != RV32BNone) ? 1'b1 : 1'b0;
       ALU_ROL: shift_left = (RV32B != RV32BNone) ? instr_first_cycle_i : 0;
       ALU_ROR: shift_left = (RV32B != RV32BNone) ? ~instr_first_cycle_i : 0;
@@ -302,7 +321,7 @@
 
   assign shift_arith  = (operator_i == ALU_SRA);
   assign shift_ones   =
-      (RV32B != RV32BNone) ? (operator_i == ALU_SLO) | (operator_i == ALU_SRO) : 1'b0;
+      (RV32B == RV32BFull) ? (operator_i == ALU_SLO) | (operator_i == ALU_SRO) : 1'b0;
   assign shift_funnel =
       (RV32B != RV32BNone) ? (operator_i == ALU_FSL) | (operator_i == ALU_FSR) : 1'b0;
 
@@ -327,7 +346,7 @@
     shift_result            = shift_result_ext[31:0];
     unused_shift_result_ext = shift_result_ext[32];
 
-    for (int unsigned i=0; i<32; i++) begin
+    for (int unsigned i = 0; i < 32; i++) begin
       shift_result_rev[i] = shift_result[31-i];
     end
 
@@ -384,6 +403,7 @@
   logic [31:0] singlebit_result;
   logic [31:0] rev_result;
   logic [31:0] shuffle_result;
+  logic [31:0] xperm_result;
   logic [31:0] butterfly_result;
   logic [31:0] invbutterfly_result;
   logic [31:0] clmul_result;
@@ -396,9 +416,9 @@
     /////////////////
 
     // The bit-counter structure computes the number of set bits in its operand. Partial results
-    // (from left to right) are needed to compute the control masks for computation of bext/bdep
-    // by the butterfly network, if implemented.
-    // For pcnt, clz and ctz, only the end result is used.
+    // (from left to right) are needed to compute the control masks for computation of
+    // bcompress/bdecompress by the butterfly network, if implemented.
+    // For cpop, clz and ctz, only the end result is used.
 
     logic        zbe_op;
     logic        bitcnt_ctz;
@@ -433,13 +453,13 @@
       bitcnt_bit_mask = ~bitcnt_bit_mask;
     end
 
-    assign zbe_op = (operator_i == ALU_BEXT) | (operator_i == ALU_BDEP);
+    assign zbe_op = (operator_i == ALU_BCOMPRESS) | (operator_i == ALU_BDECOMPRESS);
 
     always_comb begin
-      case(1'b1)
+      case (1'b1)
         zbe_op:      bitcnt_bits = operand_b_i;
         bitcnt_cz:   bitcnt_bits = bitcnt_bit_mask & ~bitcnt_mask_op; // clz / ctz
-        default:     bitcnt_bits = operand_a_i; // pcnt
+        default:     bitcnt_bits = operand_a_i; // cpop
       endcase
     end
 
@@ -487,19 +507,19 @@
     always_comb begin
       bitcnt_partial = '{default: '0};
       // stage 1
-      for (int unsigned i=1; i<32; i+=2) begin
+      for (int unsigned i = 1; i < 32; i += 2) begin
         bitcnt_partial[i] = {5'h0, bitcnt_bits[i]} + {5'h0, bitcnt_bits[i-1]};
       end
       // stage 2
-      for (int unsigned i=3; i<32; i+=4) begin
+      for (int unsigned i = 3; i < 32; i += 4) begin
         bitcnt_partial[i] = bitcnt_partial[i-2] + bitcnt_partial[i];
       end
       // stage 3
-      for (int unsigned i=7; i<32; i+=8) begin
+      for (int unsigned i = 7; i < 32; i += 8) begin
         bitcnt_partial[i] = bitcnt_partial[i-4] + bitcnt_partial[i];
       end
       // stage 4
-      for (int unsigned i=15; i <32; i+=16) begin
+      for (int unsigned i = 15; i < 32; i += 16) begin
         bitcnt_partial[i] = bitcnt_partial[i-8] + bitcnt_partial[i];
       end
       // stage 5
@@ -510,17 +530,17 @@
       bitcnt_partial[23] = bitcnt_partial[15] + bitcnt_partial[23];
 
       // stage 6
-      for (int unsigned i=11; i<32; i+=8) begin
+      for (int unsigned i = 11; i < 32; i += 8) begin
         bitcnt_partial[i] = bitcnt_partial[i-4] + bitcnt_partial[i];
       end
 
       // stage 7
-      for (int unsigned i=5; i<32; i+=4) begin
+      for (int unsigned i = 5; i < 32; i += 4) begin
         bitcnt_partial[i] = bitcnt_partial[i-2] + bitcnt_partial[i];
       end
       // stage 8
       bitcnt_partial[0] = {5'h0, bitcnt_bits[0]};
-      for (int unsigned i=2; i<32; i+=2) begin
+      for (int unsigned i = 2; i < 32; i += 2) begin
         bitcnt_partial[i] = bitcnt_partial[i-1] + {5'h0, bitcnt_bits[i]};
       end
     end
@@ -561,10 +581,10 @@
 
     always_comb begin
       unique case (operator_i)
-        ALU_SBSET: singlebit_result = operand_a_i | shift_result;
-        ALU_SBCLR: singlebit_result = operand_a_i & ~shift_result;
-        ALU_SBINV: singlebit_result = operand_a_i ^ shift_result;
-        default:   singlebit_result = {31'h0, shift_result[0]}; // ALU_SBEXT
+        ALU_BSET: singlebit_result = operand_a_i | shift_result;
+        ALU_BCLR: singlebit_result = operand_a_i & ~shift_result;
+        ALU_BINV: singlebit_result = operand_a_i ^ shift_result;
+        default:  singlebit_result = {31'h0, shift_result[0]}; // ALU_BEXT
       endcase
     end
 
@@ -572,16 +592,16 @@
     // General Reverse and Or-combine //
     ////////////////////////////////////
 
-    // Only a subset of the General reverse and or-combine instructions are implemented in the
-    // balanced version of the B extension. Currently rev, rev8 and orc.b are supported in the
-    // base extension.
+    // Only a subset of the general reverse and or-combine instructions are implemented in the
+    // balanced version of the B extension. Currently rev8 (shift_amt = 5'b11000) and orc.b
+    // (shift_amt = 5'b00111) are supported in the base extension.
 
     logic [4:0] zbp_shift_amt;
     logic gorc_op;
 
     assign gorc_op = (operator_i == ALU_GORC);
-    assign zbp_shift_amt[2:0] = (RV32B == RV32BFull) ? shift_amt[2:0] : {3{&shift_amt[2:0]}};
-    assign zbp_shift_amt[4:3] = (RV32B == RV32BFull) ? shift_amt[4:3] : {2{&shift_amt[4:3]}};
+    assign zbp_shift_amt[2:0] = (RV32B == RV32BFull) ? shift_amt[2:0] : {3{shift_amt[0]}};
+    assign zbp_shift_amt[4:3] = (RV32B == RV32BFull) ? shift_amt[4:3] : {2{shift_amt[3]}};
 
     always_comb begin
       rev_result = operand_a_i;
@@ -705,25 +725,115 @@
         end
       end
 
+      //////////////
+      // Crossbar //
+      //////////////
+      // The crossbar permutation instructions xperm.[nbh] (Zbp) can be implemented using 8
+      // parallel 4-bit-wide, 8-input crossbars. Basically, we permute the 8 nibbles of operand_a_i
+      // based on operand_b_i.
+
+      // Generate selector indices and valid signals.
+      // - sel_n[x] indicates which nibble of operand_a_i is selected for output nibble x.
+      // - vld_n[x] indicates if the selection is valid.
+      logic  [7:0][2:0] sel_n; // nibbles
+      logic  [7:0]      vld_n; // nibbles
+      logic  [3:0][1:0] sel_b; // bytes
+      logic  [3:0]      vld_b; // bytes
+      logic  [1:0][0:0] sel_h; // half words
+      logic  [1:0]      vld_h; // half words
+
+      // Per nibble, 3 bits are needed for the selection. Other bits must be zero.
+      // sel_n bit mask: 32'b0111_0111_0111_0111_0111_0111_0111_0111
+      // vld_n bit mask: 32'b1000_1000_1000_1000_1000_1000_1000_1000
+      for (genvar i = 0; i < 8; i++) begin : gen_sel_vld_n
+        assign sel_n[i] =   operand_b_i[i*4     +: 3];
+        assign vld_n[i] = ~|operand_b_i[i*4 + 3 +: 1];
+      end
+
+      // Per byte, 2 bits are needed for the selection. Other bits must be zero.
+      // sel_b bit mask: 32'b0000_0011_0000_0011_0000_0011_0000_0011
+      // vld_b bit mask: 32'b1111_1100_1111_1100_1111_1100_1111_1100
+      for (genvar i = 0; i < 4; i++) begin : gen_sel_vld_b
+        assign sel_b[i] =   operand_b_i[i*8     +: 2];
+        assign vld_b[i] = ~|operand_b_i[i*8 + 2 +: 6];
+      end
+
+      // Per half word, 1 bit is needed for the selection only. All other bits must be zero.
+      // sel_h bit mask: 32'b0000_0000_0000_0001_0000_0000_0000_0001
+      // vld_h bit mask: 32'b1111_1111_1111_1110_1111_1111_1111_1110
+      for (genvar i = 0; i < 2; i++) begin : gen_sel_vld_h
+        assign sel_h[i] =   operand_b_i[i*16     +: 1];
+        assign vld_h[i] = ~|operand_b_i[i*16 + 1 +: 15];
+      end
+
+      // Convert selector indices and valid signals to control the nibble-based
+      // crossbar logic.
+      logic [7:0][2:0] sel;
+      logic [7:0]      vld;
+      always_comb begin
+        unique case (operator_i)
+          ALU_XPERM_N: begin
+            // No conversion needed.
+            sel = sel_n;
+            vld = vld_n;
+          end
+
+          ALU_XPERM_B: begin
+            // Convert byte to nibble indicies.
+            for (int b = 0; b < 4; b++) begin
+              sel[b*2 +  0] =   {sel_b[b], 1'b0};
+              sel[b*2 +  1] =   {sel_b[b], 1'b1};
+              vld[b*2 +: 2] = {2{vld_b[b]}};
+            end
+          end
+
+          ALU_XPERM_H: begin
+            // Convert half-word to nibble indices.
+            for (int h = 0; h < 2; h++) begin
+              sel[h*4 +  0] =   {sel_h[h], 2'b00};
+              sel[h*4 +  1] =   {sel_h[h], 2'b01};
+              sel[h*4 +  2] =   {sel_h[h], 2'b10};
+              sel[h*4 +  3] =   {sel_h[h], 2'b11};
+              vld[h*4 +: 4] = {4{vld_h[h]}};
+            end
+          end
+
+          default: begin
+            // Tie valid to zero to disable the crossbar unless we need it.
+            sel = sel_n;
+            vld = '0;
+          end
+        endcase
+      end
+
+      // The actual nibble-based crossbar logic.
+      logic [7:0][3:0] val_n;
+      logic [7:0][3:0] xperm_n;
+      assign val_n = operand_a_i;
+      for (genvar i = 0; i < 8; i++) begin : gen_xperm_n
+        assign xperm_n[i] = vld[i] ? val_n[sel[i]] : '0;
+      end
+      assign xperm_result = xperm_n;
+
       ///////////////
       // Butterfly //
       ///////////////
 
-      // The butterfly / inverse butterfly network executing bext/bdep (zbe) instructions.
-      // For bdep, the control bits mask of a local left region is generated by
-      // the inverse of a n-bit left rotate and complement upon wrap (LROTC) operation by the number
-      // of ones in the deposit bitmask to the right of the segment. n hereby denotes the width
-      // of the according segment. The bitmask for a pertaining local right region is equal to the
-      // corresponding local left region. Bext uses an analogue inverse process.
+      // The butterfly / inverse butterfly network executing bcompress/bdecompress (zbe)
+      // instructions. For bdecompress, the control bits mask of a local left region is generated
+      // by the inverse of a n-bit left rotate and complement upon wrap (LROTC) operation by the
+      // number of ones in the deposit bitmask to the right of the segment. n hereby denotes the
+      // width of the according segment. The bitmask for a pertaining local right region is equal
+      // to the corresponding local left region. Bcompress uses an analogue inverse process.
       // Consider the following 8-bit example.  For details, see Hilewitz et al. "Fast Bit Gather,
       // Bit Scatter and Bit Permuation Instructions for Commodity Microprocessors", (2008).
       //
-      // The bext/bdep instructions are completed in 2 cycles. In the first cycle, the control
-      // bitmask is prepared by executing the parallel prefix bit count. In the second cycle,
-      // the bit swapping is executed according to the control masks.
+      // The bcompress/bdecompress instructions are completed in 2 cycles. In the first cycle, the
+      // control bitmask is prepared by executing the parallel prefix bit count. In the second
+      // cycle, the bit swapping is executed according to the control masks.
 
       // 8-bit example:  (Hilewitz et al.)
-      // Consider the instruction bdep operand_a_i deposit_mask
+      // Consider the instruction bdecompress operand_a_i deposit_mask
       // Let operand_a_i = 8'babcd_efgh
       //    deposit_mask = 8'b1010_1101
       //
@@ -761,23 +871,23 @@
 
       // first cycle
       // Store partial bitcnts
-      for (genvar i=0; i<32; i++) begin : gen_bitcnt_reg_in_lsb
+      for (genvar i = 0; i < 32; i++) begin : gen_bitcnt_reg_in_lsb
         assign bitcnt_partial_lsb_d[i] = bitcnt_partial[i][0];
       end
 
-      for (genvar i=0; i<16; i++) begin : gen_bitcnt_reg_in_b1
+      for (genvar i = 0; i < 16; i++) begin : gen_bitcnt_reg_in_b1
         assign bitcnt_partial_msb_d[i] = bitcnt_partial[2*i+1][1];
       end
 
-      for (genvar i=0; i<8; i++) begin : gen_bitcnt_reg_in_b2
+      for (genvar i = 0; i < 8; i++) begin : gen_bitcnt_reg_in_b2
         assign bitcnt_partial_msb_d[16+i] = bitcnt_partial[4*i+3][2];
       end
 
-      for (genvar i=0; i<4; i++) begin : gen_bitcnt_reg_in_b3
+      for (genvar i = 0; i < 4; i++) begin : gen_bitcnt_reg_in_b3
         assign bitcnt_partial_msb_d[24+i] = bitcnt_partial[8*i+7][3];
       end
 
-      for (genvar i=0; i<2; i++) begin : gen_bitcnt_reg_in_b4
+      for (genvar i = 0; i < 2; i++) begin : gen_bitcnt_reg_in_b4
         assign bitcnt_partial_msb_d[28+i] = bitcnt_partial[16*i+15][4];
       end
 
@@ -789,23 +899,23 @@
       always_comb begin
         bitcnt_partial_q = '{default: '0};
 
-        for (int unsigned i=0; i<32; i++) begin : gen_bitcnt_reg_out_lsb
+        for (int unsigned i = 0; i < 32; i++) begin : gen_bitcnt_reg_out_lsb
           bitcnt_partial_q[i][0] = imd_val_q_i[0][i];
         end
 
-        for (int unsigned i=0; i<16; i++) begin : gen_bitcnt_reg_out_b1
+        for (int unsigned i = 0; i < 16; i++) begin : gen_bitcnt_reg_out_b1
           bitcnt_partial_q[2*i+1][1] = imd_val_q_i[1][i];
         end
 
-        for (int unsigned i=0; i<8; i++) begin : gen_bitcnt_reg_out_b2
+        for (int unsigned i = 0; i < 8; i++) begin : gen_bitcnt_reg_out_b2
           bitcnt_partial_q[4*i+3][2] = imd_val_q_i[1][16+i];
         end
 
-        for (int unsigned i=0; i<4; i++) begin : gen_bitcnt_reg_out_b3
+        for (int unsigned i = 0; i < 4; i++) begin : gen_bitcnt_reg_out_b3
           bitcnt_partial_q[8*i+7][3] = imd_val_q_i[1][24+i];
         end
 
-        for (int unsigned i=0; i<2; i++) begin : gen_bitcnt_reg_out_b4
+        for (int unsigned i = 0; i < 2; i++) begin : gen_bitcnt_reg_out_b4
           bitcnt_partial_q[16*i+15][4] = imd_val_q_i[1][28+i];
         end
 
@@ -820,8 +930,8 @@
       // number of bits in local r = 32 / 2**(stage + 1) = 16/2**stage
       `define _N(stg) (16 >> stg)
 
-      // bext / bdep control bit generation
-      for (genvar stg=0; stg<5; stg++) begin : gen_butterfly_ctrl_stage
+      // bcompress / bdecompress control bit generation
+      for (genvar stg = 0; stg < 5; stg++) begin : gen_butterfly_ctrl_stage
         // number of segs: 2** stg
         for (genvar seg=0; seg<2**stg; seg++) begin : gen_butterfly_ctrl
 
@@ -841,7 +951,7 @@
       end
       `undef _N
 
-      for (genvar stg=0; stg<5; stg++) begin : gen_butterfly_not
+      for (genvar stg = 0; stg < 5; stg++) begin : gen_butterfly_not
         assign butterfly_mask_not[stg] =
             ~(butterfly_mask_l[stg] | butterfly_mask_r[stg]);
       end
@@ -970,7 +1080,7 @@
 
       logic [31:0] clmul_result_raw;
 
-      for (genvar i=0; i<32; i++) begin: gen_rev_operand_b
+      for (genvar i = 0; i < 32; i++) begin : gen_rev_operand_b
         assign operand_b_rev[i] = operand_b_i[31-i];
       end
 
@@ -1007,7 +1117,7 @@
       assign crc_mu_rev = crc_cpoly ? CRC32C_MU_REV : CRC32_MU_REV;
 
       always_comb begin
-        unique case(1'b1)
+        unique case (1'b1)
           crc_bmode: crc_operand = {operand_a_i[7:0], 24'h0};
           crc_hmode: crc_operand = {operand_a_i[15:0], 16'h0};
           default:   crc_operand = operand_a_i;
@@ -1025,36 +1135,36 @@
         end
       end
 
-      for (genvar i=0; i<32; i++) begin : gen_clmul_and_op
+      for (genvar i = 0; i < 32; i++) begin : gen_clmul_and_op
         assign clmul_and_stage[i] = clmul_op_b[i] ? clmul_op_a << i : '0;
       end
 
-      for (genvar i=0; i<16; i++) begin : gen_clmul_xor_op_l1
+      for (genvar i = 0; i < 16; i++) begin : gen_clmul_xor_op_l1
         assign clmul_xor_stage1[i] = clmul_and_stage[2*i] ^ clmul_and_stage[2*i+1];
       end
 
-      for (genvar i=0; i<8; i++) begin : gen_clmul_xor_op_l2
+      for (genvar i = 0; i < 8; i++) begin : gen_clmul_xor_op_l2
         assign clmul_xor_stage2[i] = clmul_xor_stage1[2*i] ^ clmul_xor_stage1[2*i+1];
       end
 
-      for (genvar i=0; i<4; i++) begin : gen_clmul_xor_op_l3
+      for (genvar i = 0; i < 4; i++) begin : gen_clmul_xor_op_l3
         assign clmul_xor_stage3[i] = clmul_xor_stage2[2*i] ^ clmul_xor_stage2[2*i+1];
       end
 
-      for (genvar i=0; i<2; i++) begin : gen_clmul_xor_op_l4
+      for (genvar i = 0; i < 2; i++) begin : gen_clmul_xor_op_l4
         assign clmul_xor_stage4[i] = clmul_xor_stage3[2*i] ^ clmul_xor_stage3[2*i+1];
       end
 
       assign clmul_result_raw = clmul_xor_stage4[0] ^ clmul_xor_stage4[1];
 
-      for (genvar i=0; i<32; i++) begin : gen_rev_clmul_result
+      for (genvar i = 0; i < 32; i++) begin : gen_rev_clmul_result
         assign clmul_result_rev[i] = clmul_result_raw[31-i];
       end
 
       // clmulr_result = rev(clmul(rev(a), rev(b)))
       // clmulh_result = clmulr_result >> 1
       always_comb begin
-        case(1'b1)
+        case (1'b1)
           clmul_rmode: clmul_result = clmul_result_rev;
           clmul_hmode: clmul_result = {1'b0, clmul_result_rev[31:1]};
           default:     clmul_result = clmul_result_raw;
@@ -1064,6 +1174,7 @@
       logic [31:0] unused_imd_val_q_1;
       assign unused_imd_val_q_1   = imd_val_q_i[1];
       assign shuffle_result       = '0;
+      assign xperm_result         = '0;
       assign butterfly_result     = '0;
       assign invbutterfly_result  = '0;
       assign clmul_result         = '0;
@@ -1078,7 +1189,7 @@
     //////////////////////////////////////
     // Multicycle Bitmanip Instructions //
     //////////////////////////////////////
-    // Ternary instructions + Shift Rotations + Bit extract/deposit + CRC
+    // Ternary instructions + Shift Rotations + Bit Compress/Decompress + CRC
     // For ternary instructions (zbt), operand_a_i is tied to rs1 in the first cycle and rs3 in the
     // second cycle. operand_b_i is always tied to rs2.
 
@@ -1123,7 +1234,7 @@
         ALU_CRC32_H, ALU_CRC32C_H,
         ALU_CRC32_B, ALU_CRC32C_B: begin
           if (RV32B == RV32BFull) begin
-            unique case(1'b1)
+            unique case (1'b1)
               crc_bmode: multicycle_result = clmul_result_rev ^ (operand_a_i >> 8);
               crc_hmode: multicycle_result = clmul_result_rev ^ (operand_a_i >> 16);
               default:   multicycle_result = clmul_result_rev;
@@ -1141,9 +1252,10 @@
           end
         end
 
-        ALU_BEXT, ALU_BDEP: begin
+        ALU_BCOMPRESS, ALU_BDECOMPRESS: begin
           if (RV32B == RV32BFull) begin
-            multicycle_result = (operator_i == ALU_BDEP) ? butterfly_result : invbutterfly_result;
+            multicycle_result = (operator_i == ALU_BDECOMPRESS) ? butterfly_result :
+                                                                  invbutterfly_result;
             imd_val_d_o = '{bitcnt_partial_lsb_d, bitcnt_partial_msb_d};
             if (instr_first_cycle_i) begin
               imd_val_we_o = 2'b11;
@@ -1181,6 +1293,7 @@
     assign singlebit_result    = '0;
     assign rev_result          = '0;
     assign shuffle_result      = '0;
+    assign xperm_result        = '0;
     assign butterfly_result    = '0;
     assign invbutterfly_result = '0;
     assign clmul_result        = '0;
@@ -1204,7 +1317,10 @@
       ALU_AND,  ALU_ANDN: result_o = bwlogic_result;
 
       // Adder Operations
-      ALU_ADD,  ALU_SUB: result_o = adder_result;
+      ALU_ADD,  ALU_SUB,
+      // RV32B
+      ALU_SH1ADD, ALU_SH2ADD,
+      ALU_SH3ADD: result_o = adder_result;
 
       // Shift Operations
       ALU_SLL,  ALU_SRL,
@@ -1215,6 +1331,9 @@
       // Shuffle Operations (RV32B)
       ALU_SHFL, ALU_UNSHFL: result_o = shuffle_result;
 
+      // Crossbar Permutation Operations (RV32B)
+      ALU_XPERM_N, ALU_XPERM_B, ALU_XPERM_H: result_o = xperm_result;
+
       // Comparison Operations
       ALU_EQ,   ALU_NE,
       ALU_GE,   ALU_GEU,
@@ -1227,7 +1346,7 @@
 
       // Bitcount Operations (RV32B)
       ALU_CLZ, ALU_CTZ,
-      ALU_PCNT: result_o = {26'h0, bitcnt_result};
+      ALU_CPOP: result_o = {26'h0, bitcnt_result};
 
       // Pack Operations (RV32B)
       ALU_PACK, ALU_PACKH,
@@ -1245,12 +1364,12 @@
       ALU_CRC32_W, ALU_CRC32C_W,
       ALU_CRC32_H, ALU_CRC32C_H,
       ALU_CRC32_B, ALU_CRC32C_B,
-      // Bit Extract / Deposit (RV32B)
-      ALU_BEXT, ALU_BDEP: result_o = multicycle_result;
+      // Bit Compress / Decompress (RV32B)
+      ALU_BCOMPRESS, ALU_BDECOMPRESS: result_o = multicycle_result;
 
       // Single-Bit Bitmanip Operations (RV32B)
-      ALU_SBSET, ALU_SBCLR,
-      ALU_SBINV, ALU_SBEXT: result_o = singlebit_result;
+      ALU_BSET, ALU_BCLR,
+      ALU_BINV, ALU_BEXT: result_o = singlebit_result;
 
       // General Reverse / Or-combine (RV32B)
       ALU_GREV, ALU_GORC: result_o = rev_result;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
index ec694f5..e3c6aa5 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
@@ -14,13 +14,13 @@
 `include "prim_assert.sv"
 
 module ibex_compressed_decoder (
-    input  logic        clk_i,
-    input  logic        rst_ni,
-    input  logic        valid_i,
-    input  logic [31:0] instr_i,
-    output logic [31:0] instr_o,
-    output logic        is_compressed_o,
-    output logic        illegal_instr_o
+  input  logic        clk_i,
+  input  logic        rst_ni,
+  input  logic        valid_i,
+  input  logic [31:0] instr_i,
+  output logic [31:0] instr_o,
+  output logic        is_compressed_o,
+  output logic        illegal_instr_o
 );
   import ibex_pkg::*;
 
@@ -229,7 +229,7 @@
               end else begin
                 // c.jr -> jalr x0, rd/rs1, 0
                 instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, {OPCODE_JALR}};
-                if (instr_i[11:7] == 5'b0)  illegal_instr_o = 1'b1;
+                if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
               end
             end else begin
               if (instr_i[6:2] != 5'b0) begin
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index 1a6523c..8641253 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -11,103 +11,101 @@
 `include "dv_fcov_macros.svh"
 
 module ibex_controller #(
-    parameter bit WritebackStage  = 0,
-    parameter bit BranchPredictor = 0
+  parameter bit WritebackStage  = 0,
+  parameter bit BranchPredictor = 0
  ) (
-    input  logic                  clk_i,
-    input  logic                  rst_ni,
+  input  logic                  clk_i,
+  input  logic                  rst_ni,
 
-    output logic                  ctrl_busy_o,           // core is busy processing instrs
+  output logic                  ctrl_busy_o,             // core is busy processing instrs
 
-    // decoder related signals
-    input  logic                  illegal_insn_i,          // decoder has an invalid instr
-    input  logic                  ecall_insn_i,            // decoder has ECALL instr
-    input  logic                  mret_insn_i,             // decoder has MRET instr
-    input  logic                  dret_insn_i,             // decoder has DRET instr
-    input  logic                  wfi_insn_i,              // decoder has WFI instr
-    input  logic                  ebrk_insn_i,             // decoder has EBREAK instr
-    input  logic                  csr_pipe_flush_i,        // do CSR-related pipeline flush
+  // decoder related signals
+  input  logic                  illegal_insn_i,          // decoder has an invalid instr
+  input  logic                  ecall_insn_i,            // decoder has ECALL instr
+  input  logic                  mret_insn_i,             // decoder has MRET instr
+  input  logic                  dret_insn_i,             // decoder has DRET instr
+  input  logic                  wfi_insn_i,              // decoder has WFI instr
+  input  logic                  ebrk_insn_i,             // decoder has EBREAK instr
+  input  logic                  csr_pipe_flush_i,        // do CSR-related pipeline flush
 
-    // instr from IF-ID pipeline stage
-    input  logic                  instr_valid_i,           // instr is valid
-    input  logic [31:0]           instr_i,                 // uncompressed instr data for mtval
-    input  logic [15:0]           instr_compressed_i,      // instr compressed data for mtval
-    input  logic                  instr_is_compressed_i,   // instr is compressed
-    input  logic                  instr_bp_taken_i,        // instr was predicted taken branch
-    input  logic                  instr_fetch_err_i,       // instr has error
-    input  logic                  instr_fetch_err_plus2_i, // instr error is x32
-    input  logic [31:0]           pc_id_i,                 // instr address
+  // instr from IF-ID pipeline stage
+  input  logic                  instr_valid_i,           // instr is valid
+  input  logic [31:0]           instr_i,                 // uncompressed instr data for mtval
+  input  logic [15:0]           instr_compressed_i,      // instr compressed data for mtval
+  input  logic                  instr_is_compressed_i,   // instr is compressed
+  input  logic                  instr_bp_taken_i,        // instr was predicted taken branch
+  input  logic                  instr_fetch_err_i,       // instr has error
+  input  logic                  instr_fetch_err_plus2_i, // instr error is x32
+  input  logic [31:0]           pc_id_i,                 // instr address
 
-    // to IF-ID pipeline stage
-    output logic                  instr_valid_clear_o,     // kill instr in IF-ID reg
-    output logic                  id_in_ready_o,           // ID stage is ready for new instr
-    output logic                  controller_run_o,        // Controller is in standard instruction
-                                                           // run mode
+  // to IF-ID pipeline stage
+  output logic                  instr_valid_clear_o,     // kill instr in IF-ID reg
+  output logic                  id_in_ready_o,           // ID stage is ready for new instr
+  output logic                  controller_run_o,        // Controller is in standard instruction
+                                                         // run mode
 
-    // to prefetcher
-    output logic                  instr_req_o,             // start fetching instructions
-    output logic                  pc_set_o,                // jump to address set by pc_mux
-    output logic                  pc_set_spec_o,           // speculative branch
-    output ibex_pkg::pc_sel_e     pc_mux_o,                // IF stage fetch address selector
-                                                           // (boot, normal, exception...)
-    output logic                  nt_branch_mispredict_o,  // Not-taken branch in ID/EX was
-                                                           // mispredicted (predicted taken)
-    output ibex_pkg::exc_pc_sel_e exc_pc_mux_o,            // IF stage selector for exception PC
-    output ibex_pkg::exc_cause_e  exc_cause_o,             // for IF stage, CSRs
+  // to prefetcher
+  output logic                  instr_req_o,             // start fetching instructions
+  output logic                  pc_set_o,                // jump to address set by pc_mux
+  output ibex_pkg::pc_sel_e     pc_mux_o,                // IF stage fetch address selector
+                                                         // (boot, normal, exception...)
+  output logic                  nt_branch_mispredict_o,  // Not-taken branch in ID/EX was
+                                                         // mispredicted (predicted taken)
+  output ibex_pkg::exc_pc_sel_e exc_pc_mux_o,            // IF stage selector for exception PC
+  output ibex_pkg::exc_cause_e  exc_cause_o,             // for IF stage, CSRs
 
-    // LSU
-    input  logic [31:0]           lsu_addr_last_i,         // for mtval
-    input  logic                  load_err_i,
-    input  logic                  store_err_i,
-    output logic                  wb_exception_o,          // Instruction in WB taking an exception
+  // LSU
+  input  logic [31:0]           lsu_addr_last_i,         // for mtval
+  input  logic                  load_err_i,
+  input  logic                  store_err_i,
+  output logic                  wb_exception_o,          // Instruction in WB taking an exception
+  output logic                  id_exception_o,          // Instruction in ID taking an exception
 
-    // jump/branch signals
-    input  logic                  branch_set_i,            // branch set signal (branch definitely
-                                                           // taken)
-    input  logic                  branch_set_spec_i,       // speculative branch signal (branch
-                                                           // may be taken)
-    input  logic                  branch_not_set_i,        // branch is definitely not taken
-    input  logic                  jump_set_i,              // jump taken set signal
+  // jump/branch signals
+  input  logic                  branch_set_i,            // branch set signal (branch definitely
+                                                         // taken)
+  input  logic                  branch_not_set_i,        // branch is definitely not taken
+  input  logic                  jump_set_i,              // jump taken set signal
 
-    // interrupt signals
-    input  logic                  csr_mstatus_mie_i,       // M-mode interrupt enable bit
-    input  logic                  irq_pending_i,           // interrupt request pending
-    input  ibex_pkg::irqs_t       irqs_i,                  // interrupt requests qualified with
-                                                           // mie CSR
-    input  logic                  irq_nm_i,                // non-maskeable interrupt
-    output logic                  nmi_mode_o,              // core executing NMI handler
+  // interrupt signals
+  input  logic                  csr_mstatus_mie_i,       // M-mode interrupt enable bit
+  input  logic                  irq_pending_i,           // interrupt request pending
+  input  ibex_pkg::irqs_t       irqs_i,                  // interrupt requests qualified with
+                                                         // mie CSR
+  input  logic                  irq_nm_i,                // non-maskeable interrupt
+  output logic                  nmi_mode_o,              // core executing NMI handler
 
-    // debug signals
-    input  logic                  debug_req_i,
-    output ibex_pkg::dbg_cause_e  debug_cause_o,
-    output logic                  debug_csr_save_o,
-    output logic                  debug_mode_o,
-    input  logic                  debug_single_step_i,
-    input  logic                  debug_ebreakm_i,
-    input  logic                  debug_ebreaku_i,
-    input  logic                  trigger_match_i,
+  // debug signals
+  input  logic                  debug_req_i,
+  output ibex_pkg::dbg_cause_e  debug_cause_o,
+  output logic                  debug_csr_save_o,
+  output logic                  debug_mode_o,
+  input  logic                  debug_single_step_i,
+  input  logic                  debug_ebreakm_i,
+  input  logic                  debug_ebreaku_i,
+  input  logic                  trigger_match_i,
 
-    output logic                  csr_save_if_o,
-    output logic                  csr_save_id_o,
-    output logic                  csr_save_wb_o,
-    output logic                  csr_restore_mret_id_o,
-    output logic                  csr_restore_dret_id_o,
-    output logic                  csr_save_cause_o,
-    output logic [31:0]           csr_mtval_o,
-    input  ibex_pkg::priv_lvl_e   priv_mode_i,
-    input  logic                  csr_mstatus_tw_i,
+  output logic                  csr_save_if_o,
+  output logic                  csr_save_id_o,
+  output logic                  csr_save_wb_o,
+  output logic                  csr_restore_mret_id_o,
+  output logic                  csr_restore_dret_id_o,
+  output logic                  csr_save_cause_o,
+  output logic [31:0]           csr_mtval_o,
+  input  ibex_pkg::priv_lvl_e   priv_mode_i,
+  input  logic                  csr_mstatus_tw_i,
 
-    // stall & flush signals
-    input  logic                  stall_id_i,
-    input  logic                  stall_wb_i,
-    output logic                  flush_id_o,
-    input  logic                  ready_wb_i,
+  // stall & flush signals
+  input  logic                  stall_id_i,
+  input  logic                  stall_wb_i,
+  output logic                  flush_id_o,
+  input  logic                  ready_wb_i,
 
-    // performance monitors
-    output logic                  perf_jump_o,             // we are executing a jump
-                                                           // instruction (j, jr, jal, jalr)
-    output logic                  perf_tbranch_o           // we are executing a taken branch
-                                                           // instruction
+  // performance monitors
+  output logic                  perf_jump_o,             // we are executing a jump
+                                                         // instruction (j, jr, jal, jalr)
+  output logic                  perf_tbranch_o           // we are executing a taken branch
+                                                         // instruction
 );
   import ibex_pkg::*;
 
@@ -222,6 +220,7 @@
   // LSU exception requests
   assign exc_req_lsu = store_err_i | load_err_i;
 
+  assign id_exception_o = exc_req_d;
 
   // special requests: special instructions, pipeline flushes, exceptions...
   // All terms in these expressions are qualified by instr_valid_i except exc_req_lsu which can come
@@ -347,23 +346,15 @@
   assign handle_irq = ~debug_mode_q & ~nmi_mode_q &
       (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i));
 
-  // generate ID of fast interrupts, highest priority to highest ID
+  // generate ID of fast interrupts, highest priority to lowest ID
   always_comb begin : gen_mfip_id
-    if      (irqs_i.irq_fast[14]) mfip_id = 4'd14;
-    else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
-    else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
-    else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
-    else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
-    else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
-    else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
-    else if (irqs_i.irq_fast[ 7]) mfip_id = 4'd7;
-    else if (irqs_i.irq_fast[ 6]) mfip_id = 4'd6;
-    else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
-    else if (irqs_i.irq_fast[ 4]) mfip_id = 4'd4;
-    else if (irqs_i.irq_fast[ 3]) mfip_id = 4'd3;
-    else if (irqs_i.irq_fast[ 2]) mfip_id = 4'd2;
-    else if (irqs_i.irq_fast[ 1]) mfip_id = 4'd1;
-    else                          mfip_id = 4'd0;
+    mfip_id = 4'd0;
+
+    for (int i = 14; i >= 0; i--) begin
+      if (irqs_i.irq_fast[i]) begin
+        mfip_id = i[3:0];
+      end
+    end
   end
 
   assign unused_irq_timer = irqs_i.irq_timer;
@@ -390,7 +381,6 @@
     // helping timing.
     pc_mux_o               = PC_BOOT;
     pc_set_o               = 1'b0;
-    pc_set_spec_o          = 1'b0;
     nt_branch_mispredict_o = 1'b0;
 
     exc_pc_mux_o           = EXC_PC_IRQ;
@@ -419,7 +409,6 @@
         instr_req_o   = 1'b0;
         pc_mux_o      = PC_BOOT;
         pc_set_o      = 1'b1;
-        pc_set_spec_o = 1'b1;
         ctrl_fsm_ns   = BOOT_SET;
       end
 
@@ -428,7 +417,6 @@
         instr_req_o   = 1'b1;
         pc_mux_o      = PC_BOOT;
         pc_set_o      = 1'b1;
-        pc_set_spec_o = 1'b1;
 
         ctrl_fsm_ns = FIRST_FETCH;
       end
@@ -532,13 +520,6 @@
           end
         end
 
-        // pc_set signal excluding branch taken condition
-        if (branch_set_spec_i || jump_set_i) begin
-          // Only speculatively set the PC if the branch predictor hasn't already done the branch
-          // for us
-          pc_set_spec_o = BranchPredictor ? ~instr_bp_taken_i : 1'b1;
-        end
-
         // If entering debug mode or handling an IRQ the core needs to wait until any instruction in
         // ID or WB has finished executing. Stall IF during that time.
         if ((enter_debug_mode || handle_irq) && (stall || id_wb_pending)) begin
@@ -572,7 +553,6 @@
 
         if (handle_irq) begin
           pc_set_o         = 1'b1;
-          pc_set_spec_o    = 1'b1;
 
           csr_save_if_o    = 1'b1;
           csr_save_cause_o = 1'b1;
@@ -607,7 +587,6 @@
         // jump to debug exception handler in debug memory
         flush_id         = 1'b1;
         pc_set_o         = 1'b1;
-        pc_set_spec_o    = 1'b1;
 
         csr_save_if_o    = 1'b1;
         debug_csr_save_o = 1'b1;
@@ -638,7 +617,6 @@
         flush_id      = 1'b1;
         pc_mux_o      = PC_EXC;
         pc_set_o      = 1'b1;
-        pc_set_spec_o = 1'b1;
         exc_pc_mux_o  = EXC_PC_DBD;
 
         // update dcsr and dpc
@@ -672,7 +650,6 @@
         // exc_req_lsu is high for one clock cycle only (in DECODE)
         if (exc_req_q || store_err_q || load_err_q) begin
           pc_set_o         = 1'b1;
-          pc_set_spec_o    = 1'b1;
           pc_mux_o         = PC_EXC;
           exc_pc_mux_o     = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC;
 
@@ -691,8 +668,8 @@
           // Exception/fault prioritisation logic will have set exactly 1 X_prio signal
           unique case (1'b1)
             instr_fetch_err_prio: begin
-                exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
-                csr_mtval_o = instr_fetch_err_plus2_i ? (pc_id_i + 32'd2) : pc_id_i;
+              exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
+              csr_mtval_o = instr_fetch_err_plus2_i ? (pc_id_i + 32'd2) : pc_id_i;
             end
             illegal_insn_prio: begin
               exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
@@ -718,7 +695,6 @@
                  * [Debug Spec v0.13.2, p.42]
                  */
                 pc_set_o         = 1'b0;
-                pc_set_spec_o    = 1'b0;
                 csr_save_id_o    = 1'b0;
                 csr_save_cause_o = 1'b0;
                 ctrl_fsm_ns      = DBG_TAKEN_ID;
@@ -751,7 +727,6 @@
           if (mret_insn) begin
             pc_mux_o              = PC_ERET;
             pc_set_o              = 1'b1;
-            pc_set_spec_o         = 1'b1;
             csr_restore_mret_id_o = 1'b1;
             if (nmi_mode_q) begin
               nmi_mode_d          = 1'b0; // exit NMI mode
@@ -759,7 +734,6 @@
           end else if (dret_insn) begin
             pc_mux_o              = PC_DRET;
             pc_set_o              = 1'b1;
-            pc_set_spec_o         = 1'b1;
             debug_mode_d          = 1'b0;
             csr_restore_dret_id_o = 1'b1;
           end else if (wfi_insn) begin
@@ -866,9 +840,6 @@
       RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH,
       IRQ_TAKEN, DBG_TAKEN_IF, DBG_TAKEN_ID})
 
-  // The speculative branch signal should be set whenever the actual branch signal is set
-  `ASSERT(IbexSpecImpliesSetPC, pc_set_o |-> pc_set_spec_o)
-
   `ifdef INC_ASSERT
     // If something that causes a jump into an exception handler is seen that jump must occur before
     // the next instruction executes. The logic tracks whether a jump into an exception handler is
@@ -942,4 +913,12 @@
     `ASSERT(IbexNoPCSetOnSpecialReqIfNotExpected,
       exception_req_pending && !expect_exception_pc_set |-> ~pc_set_o)
   `endif
+
+  `ifdef RVFI
+    // Workaround for internal verilator error when using hierarchical refers to calcuate this
+    // directly in ibex_core
+    logic rvfi_flush_next;
+
+    assign rvfi_flush_next = ctrl_fsm_ns == FLUSH;
+  `endif
 endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 9cf1a0c..136648d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -13,139 +13,138 @@
  * Top level module of the ibex RISC-V core
  */
 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          ResetAll          = 1'b0,
-    parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
-    parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
-    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
+  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          ResetAll          = 1'b0,
+  parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
+  parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
+  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,
+  // Clock and Reset
+  input  logic                         clk_i,
+  input  logic                         rst_ni,
 
-    input  logic [31:0]                  hart_id_i,
-    input  logic [31:0]                  boot_addr_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,
+  // 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,
+  // 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,
 
-    // 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,
+  // 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],
+  // 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,
+  // 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 crash_dump_t                  crash_dump_o,
+  // Debug Interface
+  input  logic                         debug_req_i,
+  output 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.
+  // 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,
+  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,
+  output logic [31:0]                  rvfi_ext_mip,
+  output logic                         rvfi_ext_nmi,
+  output logic                         rvfi_ext_debug_req,
+  output logic [63:0]                  rvfi_ext_mcycle,
 `endif
 
-    // CPU Control Signals
-    input  logic                         fetch_enable_i,
-    output logic                         alert_minor_o,
-    output logic                         alert_major_o,
-    output logic                         core_busy_o
+  // CPU Control Signals
+  input  logic                         fetch_enable_i,
+  output logic                         alert_minor_o,
+  output logic                         alert_major_o,
+  output logic                         core_busy_o
 );
 
-  localparam int unsigned PMP_NUM_CHAN      = 2;
+  localparam int unsigned PMP_NUM_CHAN      = 3;
   localparam bit          DataIndTiming     = SecureIbex;
   localparam bit          PCIncrCheck       = 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);
 
   // IF/ID signals
   logic        dummy_instr_id;
@@ -181,8 +180,8 @@
   logic        instr_first_cycle_id;
   logic        instr_valid_clear;
   logic        pc_set;
-  logic        pc_set_spec;
   logic        nt_branch_mispredict;
+  logic [31:0] nt_branch_addr;
   pc_sel_e     pc_mux_id;                      // Mux selector for next PC
   exc_pc_sel_e exc_pc_mux_id;                  // Mux selector for exception PC
   exc_cause_e  exc_cause;                      // Exception cause
@@ -297,7 +296,6 @@
   pmp_cfg_t     csr_pmp_cfg  [PMPNumRegions];
   pmp_mseccfg_t csr_pmp_mseccfg;
   logic         pmp_req_err  [PMP_NUM_CHAN];
-  logic         instr_req_out;
   logic         data_req_out;
 
   logic        csr_save_if;
@@ -311,7 +309,6 @@
   logic [31:0] csr_mtval;
   logic        csr_mstatus_tw;
   priv_lvl_e   priv_mode_id;
-  priv_lvl_e   priv_mode_if;
   priv_lvl_e   priv_mode_lsu;
 
   // debug mode and dcsr configuration
@@ -330,6 +327,8 @@
 
   logic        perf_instr_ret_wb;
   logic        perf_instr_ret_compressed_wb;
+  logic        perf_instr_ret_wb_spec;
+  logic        perf_instr_ret_compressed_wb_spec;
   logic        perf_iside_wait;
   logic        perf_dside_wait;
   logic        perf_mul_wait;
@@ -343,40 +342,6 @@
   // for RVFI
   logic        illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction
 
-  // RISC-V Formal Interface signals
-`ifdef RVFI
-  logic        rvfi_instr_new_wb;
-  logic        rvfi_intr_d;
-  logic        rvfi_intr_q;
-  logic        rvfi_set_trap_pc_d;
-  logic        rvfi_set_trap_pc_q;
-  logic [31:0] rvfi_insn_id;
-  logic [4:0]  rvfi_rs1_addr_d;
-  logic [4:0]  rvfi_rs1_addr_q;
-  logic [4:0]  rvfi_rs2_addr_d;
-  logic [4:0]  rvfi_rs2_addr_q;
-  logic [4:0]  rvfi_rs3_addr_d;
-  logic [31:0] rvfi_rs1_data_d;
-  logic [31:0] rvfi_rs1_data_q;
-  logic [31:0] rvfi_rs2_data_d;
-  logic [31:0] rvfi_rs2_data_q;
-  logic [31:0] rvfi_rs3_data_d;
-  logic [4:0]  rvfi_rd_addr_wb;
-  logic [4:0]  rvfi_rd_addr_q;
-  logic [4:0]  rvfi_rd_addr_d;
-  logic [31:0] rvfi_rd_wdata_wb;
-  logic [31:0] rvfi_rd_wdata_d;
-  logic [31:0] rvfi_rd_wdata_q;
-  logic        rvfi_rd_we_wb;
-  logic [3:0]  rvfi_mem_mask_int;
-  logic [31:0] rvfi_mem_rdata_d;
-  logic [31:0] rvfi_mem_rdata_q;
-  logic [31:0] rvfi_mem_wdata_d;
-  logic [31:0] rvfi_mem_wdata_q;
-  logic [31:0] rvfi_mem_addr_d;
-  logic [31:0] rvfi_mem_addr_q;
-`endif
-
   //////////////////////
   // Clock management //
   //////////////////////
@@ -390,99 +355,97 @@
   //////////////
 
   ibex_if_stage #(
-      .DmHaltAddr        ( DmHaltAddr        ),
-      .DmExceptionAddr   ( DmExceptionAddr   ),
-      .DummyInstructions ( DummyInstructions ),
-      .ICache            ( ICache            ),
-      .ICacheECC         ( ICacheECC         ),
-      .BusSizeECC        ( BusSizeECC        ),
-      .TagSizeECC        ( TagSizeECC        ),
-      .LineSizeECC       ( LineSizeECC       ),
-      .PCIncrCheck       ( PCIncrCheck       ),
-      .ResetAll          ( ResetAll          ),
-      .RndCnstLfsrSeed   ( RndCnstLfsrSeed   ),
-      .RndCnstLfsrPerm   ( RndCnstLfsrPerm   ),
-      .BranchPredictor   ( BranchPredictor   )
+    .DmHaltAddr       (DmHaltAddr),
+    .DmExceptionAddr  (DmExceptionAddr),
+    .DummyInstructions(DummyInstructions),
+    .ICache           (ICache),
+    .ICacheECC        (ICacheECC),
+    .BusSizeECC       (BusSizeECC),
+    .TagSizeECC       (TagSizeECC),
+    .LineSizeECC      (LineSizeECC),
+    .PCIncrCheck      (PCIncrCheck),
+    .ResetAll          ( ResetAll          ),
+    .RndCnstLfsrSeed   ( RndCnstLfsrSeed   ),
+    .RndCnstLfsrPerm   ( RndCnstLfsrPerm   ),
+    .BranchPredictor  (BranchPredictor)
   ) if_stage_i (
-      .clk_i                    ( clk_i                  ),
-      .rst_ni                   ( rst_ni                 ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      .boot_addr_i              ( boot_addr_i            ),
-      .req_i                    ( instr_req_gated        ), // instruction request control
+    .boot_addr_i(boot_addr_i),
+    .req_i      (instr_req_gated),  // instruction request control
 
-      // instruction cache interface
-      .instr_req_o              ( instr_req_out          ),
-      .instr_addr_o             ( instr_addr_o           ),
-      .instr_gnt_i              ( instr_gnt_i            ),
-      .instr_rvalid_i           ( instr_rvalid_i         ),
-      .instr_rdata_i            ( instr_rdata_i          ),
-      .instr_err_i              ( instr_err_i            ),
-      .instr_pmp_err_i          ( pmp_req_err[PMP_I]     ),
+    // instruction cache interface
+    .instr_req_o    (instr_req_o),
+    .instr_addr_o   (instr_addr_o),
+    .instr_gnt_i    (instr_gnt_i),
+    .instr_rvalid_i (instr_rvalid_i),
+    .instr_rdata_i  (instr_rdata_i),
+    .instr_err_i    (instr_err_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        ),
+    .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           ),
-      .instr_rdata_id_o         ( instr_rdata_id         ),
-      .instr_rdata_alu_id_o     ( instr_rdata_alu_id     ),
-      .instr_rdata_c_id_o       ( instr_rdata_c_id       ),
-      .instr_is_compressed_id_o ( instr_is_compressed_id ),
-      .instr_bp_taken_o         ( instr_bp_taken_id      ),
-      .instr_fetch_err_o        ( instr_fetch_err        ),
-      .instr_fetch_err_plus2_o  ( instr_fetch_err_plus2  ),
-      .illegal_c_insn_id_o      ( illegal_c_insn_id      ),
-      .dummy_instr_id_o         ( dummy_instr_id         ),
-      .pc_if_o                  ( pc_if                  ),
-      .pc_id_o                  ( pc_id                  ),
+    // outputs to ID stage
+    .instr_valid_id_o        (instr_valid_id),
+    .instr_new_id_o          (instr_new_id),
+    .instr_rdata_id_o        (instr_rdata_id),
+    .instr_rdata_alu_id_o    (instr_rdata_alu_id),
+    .instr_rdata_c_id_o      (instr_rdata_c_id),
+    .instr_is_compressed_id_o(instr_is_compressed_id),
+    .instr_bp_taken_o        (instr_bp_taken_id),
+    .instr_fetch_err_o       (instr_fetch_err),
+    .instr_fetch_err_plus2_o (instr_fetch_err_plus2),
+    .illegal_c_insn_id_o     (illegal_c_insn_id),
+    .dummy_instr_id_o        (dummy_instr_id),
+    .pc_if_o                 (pc_if),
+    .pc_id_o                 (pc_id),
+    .pmp_err_if_i            (pmp_req_err[PMP_I]),
+    .pmp_err_if_plus2_i      (pmp_req_err[PMP_I2]),
 
-      // control signals
-      .instr_valid_clear_i      ( instr_valid_clear      ),
-      .pc_set_i                 ( pc_set                 ),
-      .pc_set_spec_i            ( pc_set_spec            ),
-      .pc_mux_i                 ( pc_mux_id              ),
-      .nt_branch_mispredict_i   ( nt_branch_mispredict   ),
-      .exc_pc_mux_i             ( exc_pc_mux_id          ),
-      .exc_cause                ( exc_cause              ),
-      .dummy_instr_en_i         ( dummy_instr_en         ),
-      .dummy_instr_mask_i       ( dummy_instr_mask       ),
-      .dummy_instr_seed_en_i    ( dummy_instr_seed_en    ),
-      .dummy_instr_seed_i       ( dummy_instr_seed       ),
-      .icache_enable_i          ( icache_enable          ),
-      .icache_inval_i           ( icache_inval           ),
+    // control signals
+    .instr_valid_clear_i   (instr_valid_clear),
+    .pc_set_i              (pc_set),
+    .pc_mux_i              (pc_mux_id),
+    .nt_branch_mispredict_i(nt_branch_mispredict),
+    .exc_pc_mux_i          (exc_pc_mux_id),
+    .exc_cause             (exc_cause),
+    .dummy_instr_en_i      (dummy_instr_en),
+    .dummy_instr_mask_i    (dummy_instr_mask),
+    .dummy_instr_seed_en_i (dummy_instr_seed_en),
+    .dummy_instr_seed_i    (dummy_instr_seed),
+    .icache_enable_i       (icache_enable),
+    .icache_inval_i        (icache_inval),
 
-      // branch targets
-      .branch_target_ex_i       ( branch_target_ex       ),
+    // branch targets
+    .branch_target_ex_i(branch_target_ex),
+    .nt_branch_addr_i  (nt_branch_addr),
 
-      // CSRs
-      .csr_mepc_i               ( csr_mepc               ), // exception return address
-      .csr_depc_i               ( csr_depc               ), // debug return address
-      .csr_mtvec_i              ( csr_mtvec              ), // trap-vector base address
-      .csr_mtvec_init_o         ( csr_mtvec_init         ),
+    // CSRs
+    .csr_mepc_i      (csr_mepc),  // exception return address
+    .csr_depc_i      (csr_depc),  // debug return address
+    .csr_mtvec_i     (csr_mtvec),  // trap-vector base address
+    .csr_mtvec_init_o(csr_mtvec_init),
 
-      // pipeline stalls
-      .id_in_ready_i            ( id_in_ready            ),
+    // pipeline stalls
+    .id_in_ready_i(id_in_ready),
 
-      .pc_mismatch_alert_o      ( pc_mismatch_alert      ),
-      .if_busy_o                ( if_busy                )
+    .pc_mismatch_alert_o(pc_mismatch_alert),
+    .if_busy_o          (if_busy)
   );
 
   // Core is waiting for the ISide when ID/EX stage is ready for a new instruction but none are
   // available
   assign perf_iside_wait = id_in_ready & ~instr_valid_id;
 
-  // Qualify the instruction request with PMP error
-  assign instr_req_o = instr_req_out & ~pmp_req_err[PMP_I];
-
   // fetch_enable_i can be used to stop the core fetching new instructions
   assign instr_req_gated = instr_req_int & fetch_enable_i;
 
@@ -491,207 +454,206 @@
   //////////////
 
   ibex_id_stage #(
-      .RV32E           ( RV32E           ),
-      .RV32M           ( RV32M           ),
-      .RV32B           ( RV32B           ),
-      .BranchTargetALU ( BranchTargetALU ),
-      .DataIndTiming   ( DataIndTiming   ),
-      .SpecBranch      ( SpecBranch      ),
-      .WritebackStage  ( WritebackStage  ),
-      .BranchPredictor ( BranchPredictor )
+    .RV32E          (RV32E),
+    .RV32M          (RV32M),
+    .RV32B          (RV32B),
+    .BranchTargetALU(BranchTargetALU),
+    .DataIndTiming  (DataIndTiming),
+    .WritebackStage (WritebackStage),
+    .BranchPredictor(BranchPredictor)
   ) id_stage_i (
-      .clk_i                        ( clk_i                    ),
-      .rst_ni                       ( rst_ni                   ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      // Processor Enable
-      .ctrl_busy_o                  ( ctrl_busy                ),
-      .illegal_insn_o               ( illegal_insn_id          ),
+    // Processor Enable
+    .ctrl_busy_o   (ctrl_busy),
+    .illegal_insn_o(illegal_insn_id),
 
-      // from/to IF-ID pipeline register
-      .instr_valid_i                ( instr_valid_id           ),
-      .instr_rdata_i                ( instr_rdata_id           ),
-      .instr_rdata_alu_i            ( instr_rdata_alu_id       ),
-      .instr_rdata_c_i              ( instr_rdata_c_id         ),
-      .instr_is_compressed_i        ( instr_is_compressed_id   ),
-      .instr_bp_taken_i             ( instr_bp_taken_id        ),
+    // from/to IF-ID pipeline register
+    .instr_valid_i        (instr_valid_id),
+    .instr_rdata_i        (instr_rdata_id),
+    .instr_rdata_alu_i    (instr_rdata_alu_id),
+    .instr_rdata_c_i      (instr_rdata_c_id),
+    .instr_is_compressed_i(instr_is_compressed_id),
+    .instr_bp_taken_i     (instr_bp_taken_id),
 
-      // Jumps and branches
-      .branch_decision_i            ( branch_decision          ),
+    // Jumps and branches
+    .branch_decision_i(branch_decision),
 
-      // IF and ID control signals
-      .instr_first_cycle_id_o       ( instr_first_cycle_id     ),
-      .instr_valid_clear_o          ( instr_valid_clear        ),
-      .id_in_ready_o                ( id_in_ready              ),
-      .instr_req_o                  ( instr_req_int            ),
-      .pc_set_o                     ( pc_set                   ),
-      .pc_set_spec_o                ( pc_set_spec              ),
-      .pc_mux_o                     ( pc_mux_id                ),
-      .nt_branch_mispredict_o       ( nt_branch_mispredict     ),
-      .exc_pc_mux_o                 ( exc_pc_mux_id            ),
-      .exc_cause_o                  ( exc_cause                ),
-      .icache_inval_o               ( icache_inval             ),
+    // IF and ID control signals
+    .instr_first_cycle_id_o(instr_first_cycle_id),
+    .instr_valid_clear_o   (instr_valid_clear),
+    .id_in_ready_o         (id_in_ready),
+    .instr_req_o           (instr_req_int),
+    .pc_set_o              (pc_set),
+    .pc_mux_o              (pc_mux_id),
+    .nt_branch_mispredict_o(nt_branch_mispredict),
+    .nt_branch_addr_o      (nt_branch_addr),
+    .exc_pc_mux_o          (exc_pc_mux_id),
+    .exc_cause_o           (exc_cause),
+    .icache_inval_o        (icache_inval),
 
-      .instr_fetch_err_i            ( instr_fetch_err          ),
-      .instr_fetch_err_plus2_i      ( instr_fetch_err_plus2    ),
-      .illegal_c_insn_i             ( illegal_c_insn_id        ),
+    .instr_fetch_err_i      (instr_fetch_err),
+    .instr_fetch_err_plus2_i(instr_fetch_err_plus2),
+    .illegal_c_insn_i       (illegal_c_insn_id),
 
-      .pc_id_i                      ( pc_id                    ),
+    .pc_id_i(pc_id),
 
-      // Stalls
-      .ex_valid_i                   ( ex_valid                 ),
-      .lsu_resp_valid_i             ( lsu_resp_valid           ),
+    // Stalls
+    .ex_valid_i      (ex_valid),
+    .lsu_resp_valid_i(lsu_resp_valid),
 
-      .alu_operator_ex_o            ( alu_operator_ex          ),
-      .alu_operand_a_ex_o           ( alu_operand_a_ex         ),
-      .alu_operand_b_ex_o           ( alu_operand_b_ex         ),
+    .alu_operator_ex_o (alu_operator_ex),
+    .alu_operand_a_ex_o(alu_operand_a_ex),
+    .alu_operand_b_ex_o(alu_operand_b_ex),
 
-      .imd_val_q_ex_o               ( imd_val_q_ex             ),
-      .imd_val_d_ex_i               ( imd_val_d_ex             ),
-      .imd_val_we_ex_i              ( imd_val_we_ex            ),
+    .imd_val_q_ex_o (imd_val_q_ex),
+    .imd_val_d_ex_i (imd_val_d_ex),
+    .imd_val_we_ex_i(imd_val_we_ex),
 
-      .bt_a_operand_o               ( bt_a_operand             ),
-      .bt_b_operand_o               ( bt_b_operand             ),
+    .bt_a_operand_o(bt_a_operand),
+    .bt_b_operand_o(bt_b_operand),
 
-      .mult_en_ex_o                 ( mult_en_ex               ),
-      .div_en_ex_o                  ( div_en_ex                ),
-      .mult_sel_ex_o                ( mult_sel_ex              ),
-      .div_sel_ex_o                 ( div_sel_ex               ),
-      .multdiv_operator_ex_o        ( multdiv_operator_ex      ),
-      .multdiv_signed_mode_ex_o     ( multdiv_signed_mode_ex   ),
-      .multdiv_operand_a_ex_o       ( multdiv_operand_a_ex     ),
-      .multdiv_operand_b_ex_o       ( multdiv_operand_b_ex     ),
-      .multdiv_ready_id_o           ( multdiv_ready_id         ),
+    .mult_en_ex_o            (mult_en_ex),
+    .div_en_ex_o             (div_en_ex),
+    .mult_sel_ex_o           (mult_sel_ex),
+    .div_sel_ex_o            (div_sel_ex),
+    .multdiv_operator_ex_o   (multdiv_operator_ex),
+    .multdiv_signed_mode_ex_o(multdiv_signed_mode_ex),
+    .multdiv_operand_a_ex_o  (multdiv_operand_a_ex),
+    .multdiv_operand_b_ex_o  (multdiv_operand_b_ex),
+    .multdiv_ready_id_o      (multdiv_ready_id),
 
-      // CSR ID/EX
-      .csr_access_o                 ( csr_access               ),
-      .csr_op_o                     ( csr_op                   ),
-      .csr_op_en_o                  ( csr_op_en                ),
-      .csr_save_if_o                ( csr_save_if              ), // control signal to save PC
-      .csr_save_id_o                ( csr_save_id              ), // control signal to save PC
-      .csr_save_wb_o                ( csr_save_wb              ), // control signal to save PC
-      .csr_restore_mret_id_o        ( csr_restore_mret_id      ), // restore mstatus upon MRET
-      .csr_restore_dret_id_o        ( csr_restore_dret_id      ), // restore mstatus upon MRET
-      .csr_save_cause_o             ( csr_save_cause           ),
-      .csr_mtval_o                  ( csr_mtval                ),
-      .priv_mode_i                  ( priv_mode_id             ),
-      .csr_mstatus_tw_i             ( csr_mstatus_tw           ),
-      .illegal_csr_insn_i           ( illegal_csr_insn_id      ),
-      .data_ind_timing_i            ( data_ind_timing          ),
+    // CSR ID/EX
+    .csr_access_o         (csr_access),
+    .csr_op_o             (csr_op),
+    .csr_op_en_o          (csr_op_en),
+    .csr_save_if_o        (csr_save_if),  // control signal to save PC
+    .csr_save_id_o        (csr_save_id),  // control signal to save PC
+    .csr_save_wb_o        (csr_save_wb),  // control signal to save PC
+    .csr_restore_mret_id_o(csr_restore_mret_id),  // restore mstatus upon MRET
+    .csr_restore_dret_id_o(csr_restore_dret_id),  // restore mstatus upon MRET
+    .csr_save_cause_o     (csr_save_cause),
+    .csr_mtval_o          (csr_mtval),
+    .priv_mode_i          (priv_mode_id),
+    .csr_mstatus_tw_i     (csr_mstatus_tw),
+    .illegal_csr_insn_i   (illegal_csr_insn_id),
+    .data_ind_timing_i    (data_ind_timing),
 
-      // LSU
-      .lsu_req_o                    ( lsu_req                  ), // to load store unit
-      .lsu_we_o                     ( lsu_we                   ), // to load store unit
-      .lsu_type_o                   ( lsu_type                 ), // to load store unit
-      .lsu_sign_ext_o               ( lsu_sign_ext             ), // to load store unit
-      .lsu_wdata_o                  ( lsu_wdata                ), // to load store unit
-      .lsu_req_done_i               ( lsu_req_done             ), // from load store unit
+    // LSU
+    .lsu_req_o     (lsu_req),  // to load store unit
+    .lsu_we_o      (lsu_we),  // to load store unit
+    .lsu_type_o    (lsu_type),  // to load store unit
+    .lsu_sign_ext_o(lsu_sign_ext),  // to load store unit
+    .lsu_wdata_o   (lsu_wdata),  // to load store unit
+    .lsu_req_done_i(lsu_req_done),  // from load store unit
 
-      .lsu_addr_incr_req_i          ( lsu_addr_incr_req        ),
-      .lsu_addr_last_i              ( lsu_addr_last            ),
+    .lsu_addr_incr_req_i(lsu_addr_incr_req),
+    .lsu_addr_last_i    (lsu_addr_last),
 
-      .lsu_load_err_i               ( lsu_load_err             ),
-      .lsu_store_err_i              ( lsu_store_err            ),
+    .lsu_load_err_i (lsu_load_err),
+    .lsu_store_err_i(lsu_store_err),
 
-      // Interrupt Signals
-      .csr_mstatus_mie_i            ( csr_mstatus_mie          ),
-      .irq_pending_i                ( irq_pending_o            ),
-      .irqs_i                       ( irqs                     ),
-      .irq_nm_i                     ( irq_nm_i                 ),
-      .nmi_mode_o                   ( nmi_mode                 ),
+    // Interrupt Signals
+    .csr_mstatus_mie_i(csr_mstatus_mie),
+    .irq_pending_i    (irq_pending_o),
+    .irqs_i           (irqs),
+    .irq_nm_i         (irq_nm_i),
+    .nmi_mode_o       (nmi_mode),
 
-      // Debug Signal
-      .debug_mode_o                 ( debug_mode               ),
-      .debug_cause_o                ( debug_cause              ),
-      .debug_csr_save_o             ( debug_csr_save           ),
-      .debug_req_i                  ( debug_req_i              ),
-      .debug_single_step_i          ( debug_single_step        ),
-      .debug_ebreakm_i              ( debug_ebreakm            ),
-      .debug_ebreaku_i              ( debug_ebreaku            ),
-      .trigger_match_i              ( trigger_match            ),
+    // Debug Signal
+    .debug_mode_o       (debug_mode),
+    .debug_cause_o      (debug_cause),
+    .debug_csr_save_o   (debug_csr_save),
+    .debug_req_i        (debug_req_i),
+    .debug_single_step_i(debug_single_step),
+    .debug_ebreakm_i    (debug_ebreakm),
+    .debug_ebreaku_i    (debug_ebreaku),
+    .trigger_match_i    (trigger_match),
 
-      // write data to commit in the register file
-      .result_ex_i                  ( result_ex                ),
-      .csr_rdata_i                  ( csr_rdata                ),
+    // write data to commit in the register file
+    .result_ex_i(result_ex),
+    .csr_rdata_i(csr_rdata),
 
-      .rf_raddr_a_o                 ( rf_raddr_a               ),
-      .rf_rdata_a_i                 ( rf_rdata_a               ),
-      .rf_raddr_b_o                 ( rf_raddr_b               ),
-      .rf_rdata_b_i                 ( rf_rdata_b               ),
-      .rf_ren_a_o                   ( rf_ren_a                 ),
-      .rf_ren_b_o                   ( rf_ren_b                 ),
-      .rf_waddr_id_o                ( rf_waddr_id              ),
-      .rf_wdata_id_o                ( rf_wdata_id              ),
-      .rf_we_id_o                   ( rf_we_id                 ),
-      .rf_rd_a_wb_match_o           ( rf_rd_a_wb_match         ),
-      .rf_rd_b_wb_match_o           ( rf_rd_b_wb_match         ),
+    .rf_raddr_a_o      (rf_raddr_a),
+    .rf_rdata_a_i      (rf_rdata_a),
+    .rf_raddr_b_o      (rf_raddr_b),
+    .rf_rdata_b_i      (rf_rdata_b),
+    .rf_ren_a_o        (rf_ren_a),
+    .rf_ren_b_o        (rf_ren_b),
+    .rf_waddr_id_o     (rf_waddr_id),
+    .rf_wdata_id_o     (rf_wdata_id),
+    .rf_we_id_o        (rf_we_id),
+    .rf_rd_a_wb_match_o(rf_rd_a_wb_match),
+    .rf_rd_b_wb_match_o(rf_rd_b_wb_match),
 
-      .rf_waddr_wb_i                ( rf_waddr_wb              ),
-      .rf_wdata_fwd_wb_i            ( rf_wdata_fwd_wb          ),
-      .rf_write_wb_i                ( rf_write_wb              ),
+    .rf_waddr_wb_i    (rf_waddr_wb),
+    .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb),
+    .rf_write_wb_i    (rf_write_wb),
 
-      .en_wb_o                      ( en_wb                    ),
-      .instr_type_wb_o              ( instr_type_wb            ),
-      .instr_perf_count_id_o        ( instr_perf_count_id      ),
-      .ready_wb_i                   ( ready_wb                 ),
-      .outstanding_load_wb_i        ( outstanding_load_wb      ),
-      .outstanding_store_wb_i       ( outstanding_store_wb     ),
+    .en_wb_o               (en_wb),
+    .instr_type_wb_o       (instr_type_wb),
+    .instr_perf_count_id_o (instr_perf_count_id),
+    .ready_wb_i            (ready_wb),
+    .outstanding_load_wb_i (outstanding_load_wb),
+    .outstanding_store_wb_i(outstanding_store_wb),
 
-      // Performance Counters
-      .perf_jump_o                  ( perf_jump                ),
-      .perf_branch_o                ( perf_branch              ),
-      .perf_tbranch_o               ( perf_tbranch             ),
-      .perf_dside_wait_o            ( perf_dside_wait          ),
-      .perf_mul_wait_o              ( perf_mul_wait            ),
-      .perf_div_wait_o              ( perf_div_wait            ),
-      .instr_id_done_o              ( instr_id_done            )
+    // Performance Counters
+    .perf_jump_o      (perf_jump),
+    .perf_branch_o    (perf_branch),
+    .perf_tbranch_o   (perf_tbranch),
+    .perf_dside_wait_o(perf_dside_wait),
+    .perf_mul_wait_o  (perf_mul_wait),
+    .perf_div_wait_o  (perf_div_wait),
+    .instr_id_done_o  (instr_id_done)
   );
 
   // for RVFI only
   assign unused_illegal_insn_id = illegal_insn_id;
 
   ibex_ex_block #(
-      .RV32M                    ( RV32M                    ),
-      .RV32B                    ( RV32B                    ),
-      .BranchTargetALU          ( BranchTargetALU          )
+    .RV32M          (RV32M),
+    .RV32B          (RV32B),
+    .BranchTargetALU(BranchTargetALU)
   ) ex_block_i (
-      .clk_i                    ( clk_i                    ),
-      .rst_ni                   ( rst_ni                   ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      // ALU signal from ID stage
-      .alu_operator_i           ( alu_operator_ex          ),
-      .alu_operand_a_i          ( alu_operand_a_ex         ),
-      .alu_operand_b_i          ( alu_operand_b_ex         ),
-      .alu_instr_first_cycle_i  ( instr_first_cycle_id     ),
+    // ALU signal from ID stage
+    .alu_operator_i         (alu_operator_ex),
+    .alu_operand_a_i        (alu_operand_a_ex),
+    .alu_operand_b_i        (alu_operand_b_ex),
+    .alu_instr_first_cycle_i(instr_first_cycle_id),
 
-      // Branch target ALU signal from ID stage
-      .bt_a_operand_i           ( bt_a_operand             ),
-      .bt_b_operand_i           ( bt_b_operand             ),
+    // Branch target ALU signal from ID stage
+    .bt_a_operand_i(bt_a_operand),
+    .bt_b_operand_i(bt_b_operand),
 
-      // Multipler/Divider signal from ID stage
-      .multdiv_operator_i       ( multdiv_operator_ex      ),
-      .mult_en_i                ( mult_en_ex               ),
-      .div_en_i                 ( div_en_ex                ),
-      .mult_sel_i               ( mult_sel_ex              ),
-      .div_sel_i                ( div_sel_ex               ),
-      .multdiv_signed_mode_i    ( multdiv_signed_mode_ex   ),
-      .multdiv_operand_a_i      ( multdiv_operand_a_ex     ),
-      .multdiv_operand_b_i      ( multdiv_operand_b_ex     ),
-      .multdiv_ready_id_i       ( multdiv_ready_id         ),
-      .data_ind_timing_i        ( data_ind_timing          ),
+    // Multipler/Divider signal from ID stage
+    .multdiv_operator_i   (multdiv_operator_ex),
+    .mult_en_i            (mult_en_ex),
+    .div_en_i             (div_en_ex),
+    .mult_sel_i           (mult_sel_ex),
+    .div_sel_i            (div_sel_ex),
+    .multdiv_signed_mode_i(multdiv_signed_mode_ex),
+    .multdiv_operand_a_i  (multdiv_operand_a_ex),
+    .multdiv_operand_b_i  (multdiv_operand_b_ex),
+    .multdiv_ready_id_i   (multdiv_ready_id),
+    .data_ind_timing_i    (data_ind_timing),
 
-      // Intermediate value register
-      .imd_val_we_o             ( imd_val_we_ex            ),
-      .imd_val_d_o              ( imd_val_d_ex             ),
-      .imd_val_q_i              ( imd_val_q_ex             ),
+    // Intermediate value register
+    .imd_val_we_o(imd_val_we_ex),
+    .imd_val_d_o (imd_val_d_ex),
+    .imd_val_q_i (imd_val_q_ex),
 
-      // Outputs
-      .alu_adder_result_ex_o    ( alu_adder_result_ex      ), // to LSU
-      .result_ex_o              ( result_ex                ), // to ID
+    // Outputs
+    .alu_adder_result_ex_o(alu_adder_result_ex),  // to LSU
+    .result_ex_o          (result_ex),  // to ID
 
-      .branch_target_o          ( branch_target_ex         ), // to IF
-      .branch_decision_o        ( branch_decision          ), // to ID
+    .branch_target_o  (branch_target_ex),  // to IF
+    .branch_decision_o(branch_decision),  // to ID
 
-      .ex_valid_o               ( ex_valid                 )
+    .ex_valid_o(ex_valid)
   );
 
   /////////////////////
@@ -702,88 +664,90 @@
   assign lsu_resp_err = lsu_load_err | lsu_store_err;
 
   ibex_load_store_unit load_store_unit_i (
-      .clk_i                 ( clk_i               ),
-      .rst_ni                ( rst_ni              ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      // data interface
-      .data_req_o            ( data_req_out        ),
-      .data_gnt_i            ( data_gnt_i          ),
-      .data_rvalid_i         ( data_rvalid_i       ),
-      .data_err_i            ( data_err_i          ),
-      .data_pmp_err_i        ( pmp_req_err[PMP_D]  ),
+    // data interface
+    .data_req_o    (data_req_out),
+    .data_gnt_i    (data_gnt_i),
+    .data_rvalid_i (data_rvalid_i),
+    .data_err_i    (data_err_i),
+    .data_pmp_err_i(pmp_req_err[PMP_D]),
 
-      .data_addr_o           ( data_addr_o         ),
-      .data_we_o             ( data_we_o           ),
-      .data_be_o             ( data_be_o           ),
-      .data_wdata_o          ( data_wdata_o        ),
-      .data_rdata_i          ( data_rdata_i        ),
+    .data_addr_o (data_addr_o),
+    .data_we_o   (data_we_o),
+    .data_be_o   (data_be_o),
+    .data_wdata_o(data_wdata_o),
+    .data_rdata_i(data_rdata_i),
 
-      // signals to/from ID/EX stage
-      .lsu_we_i              ( lsu_we              ),
-      .lsu_type_i            ( lsu_type            ),
-      .lsu_wdata_i           ( lsu_wdata           ),
-      .lsu_sign_ext_i        ( lsu_sign_ext        ),
+    // signals to/from ID/EX stage
+    .lsu_we_i      (lsu_we),
+    .lsu_type_i    (lsu_type),
+    .lsu_wdata_i   (lsu_wdata),
+    .lsu_sign_ext_i(lsu_sign_ext),
 
-      .lsu_rdata_o           ( rf_wdata_lsu        ),
-      .lsu_rdata_valid_o     ( rf_we_lsu           ),
-      .lsu_req_i             ( lsu_req             ),
-      .lsu_req_done_o        ( lsu_req_done        ),
+    .lsu_rdata_o      (rf_wdata_lsu),
+    .lsu_rdata_valid_o(rf_we_lsu),
+    .lsu_req_i        (lsu_req),
+    .lsu_req_done_o   (lsu_req_done),
 
-      .adder_result_ex_i     ( alu_adder_result_ex ),
+    .adder_result_ex_i(alu_adder_result_ex),
 
-      .addr_incr_req_o       ( lsu_addr_incr_req   ),
-      .addr_last_o           ( lsu_addr_last       ),
+    .addr_incr_req_o(lsu_addr_incr_req),
+    .addr_last_o    (lsu_addr_last),
 
 
-      .lsu_resp_valid_o      ( lsu_resp_valid      ),
+    .lsu_resp_valid_o(lsu_resp_valid),
 
-      // exception signals
-      .load_err_o            ( lsu_load_err        ),
-      .store_err_o           ( lsu_store_err       ),
+    // exception signals
+    .load_err_o (lsu_load_err),
+    .store_err_o(lsu_store_err),
 
-      .busy_o                ( lsu_busy            ),
+    .busy_o(lsu_busy),
 
-      .perf_load_o           ( perf_load           ),
-      .perf_store_o          ( perf_store          )
+    .perf_load_o (perf_load),
+    .perf_store_o(perf_store)
   );
 
   ibex_wb_stage #(
     .ResetAll       ( ResetAll       ),
-    .WritebackStage ( WritebackStage )
+    .WritebackStage(WritebackStage)
   ) wb_stage_i (
-    .clk_i                          ( clk_i                        ),
-    .rst_ni                         ( rst_ni                       ),
-    .en_wb_i                        ( en_wb                        ),
-    .instr_type_wb_i                ( instr_type_wb                ),
-    .pc_id_i                        ( pc_id                        ),
-    .instr_is_compressed_id_i       ( instr_is_compressed_id       ),
-    .instr_perf_count_id_i          ( instr_perf_count_id          ),
+    .clk_i                   (clk_i),
+    .rst_ni                  (rst_ni),
+    .en_wb_i                 (en_wb),
+    .instr_type_wb_i         (instr_type_wb),
+    .pc_id_i                 (pc_id),
+    .instr_is_compressed_id_i(instr_is_compressed_id),
+    .instr_perf_count_id_i   (instr_perf_count_id),
 
-    .ready_wb_o                     ( ready_wb                     ),
-    .rf_write_wb_o                  ( rf_write_wb                  ),
-    .outstanding_load_wb_o          ( outstanding_load_wb          ),
-    .outstanding_store_wb_o         ( outstanding_store_wb         ),
-    .pc_wb_o                        ( pc_wb                        ),
-    .perf_instr_ret_wb_o            ( perf_instr_ret_wb            ),
-    .perf_instr_ret_compressed_wb_o ( perf_instr_ret_compressed_wb ),
+    .ready_wb_o                         (ready_wb),
+    .rf_write_wb_o                      (rf_write_wb),
+    .outstanding_load_wb_o              (outstanding_load_wb),
+    .outstanding_store_wb_o             (outstanding_store_wb),
+    .pc_wb_o                            (pc_wb),
+    .perf_instr_ret_wb_o                (perf_instr_ret_wb),
+    .perf_instr_ret_compressed_wb_o     (perf_instr_ret_compressed_wb),
+    .perf_instr_ret_wb_spec_o           (perf_instr_ret_wb_spec),
+    .perf_instr_ret_compressed_wb_spec_o(perf_instr_ret_compressed_wb_spec),
 
-    .rf_waddr_id_i                  ( rf_waddr_id                  ),
-    .rf_wdata_id_i                  ( rf_wdata_id                  ),
-    .rf_we_id_i                     ( rf_we_id                     ),
+    .rf_waddr_id_i(rf_waddr_id),
+    .rf_wdata_id_i(rf_wdata_id),
+    .rf_we_id_i   (rf_we_id),
 
-    .rf_wdata_lsu_i                 ( rf_wdata_lsu                 ),
-    .rf_we_lsu_i                    ( rf_we_lsu                    ),
+    .rf_wdata_lsu_i(rf_wdata_lsu),
+    .rf_we_lsu_i   (rf_we_lsu),
 
-    .rf_wdata_fwd_wb_o              ( rf_wdata_fwd_wb              ),
+    .rf_wdata_fwd_wb_o(rf_wdata_fwd_wb),
 
-    .rf_waddr_wb_o                  ( rf_waddr_wb                  ),
-    .rf_wdata_wb_o                  ( rf_wdata_wb                  ),
-    .rf_we_wb_o                     ( rf_we_wb                     ),
+    .rf_waddr_wb_o(rf_waddr_wb),
+    .rf_wdata_wb_o(rf_wdata_wb),
+    .rf_we_wb_o   (rf_we_wb),
 
-    .lsu_resp_valid_i               ( lsu_resp_valid               ),
-    .lsu_resp_err_i                 ( lsu_resp_err                 ),
+    .lsu_resp_valid_i(lsu_resp_valid),
+    .lsu_resp_err_i  (lsu_resp_err),
 
-    .instr_done_wb_o                ( instr_done_wb                )
+    .instr_done_wb_o(instr_done_wb)
   );
 
   /////////////////////////////
@@ -802,23 +766,23 @@
     logic       rf_ecc_err_a_id, rf_ecc_err_b_id;
 
     // ECC checkbit generation for regiter file wdata
-    prim_secded_39_32_enc regfile_ecc_enc (
-      .data_i (rf_wdata_wb),
-      .data_o (rf_wdata_wb_ecc_o)
+    prim_secded_inv_39_32_enc regfile_ecc_enc (
+      .data_i(rf_wdata_wb),
+      .data_o(rf_wdata_wb_ecc_o)
     );
 
     // ECC checking on register file rdata
-    prim_secded_39_32_dec regfile_ecc_dec_a (
-      .data_i     (rf_rdata_a_ecc_i),
-      .data_o     (),
-      .syndrome_o (),
-      .err_o      (rf_ecc_err_a)
+    prim_secded_inv_39_32_dec regfile_ecc_dec_a (
+      .data_i    (rf_rdata_a_ecc_i),
+      .data_o    (),
+      .syndrome_o(),
+      .err_o     (rf_ecc_err_a)
     );
-    prim_secded_39_32_dec regfile_ecc_dec_b (
-      .data_i     (rf_rdata_b_ecc_i),
-      .data_o     (),
-      .syndrome_o (),
-      .err_o      (rf_ecc_err_b)
+    prim_secded_inv_39_32_dec regfile_ecc_dec_b (
+      .data_i    (rf_rdata_b_ecc_i),
+      .data_o    (),
+      .syndrome_o(),
+      .err_o     (rf_ecc_err_b)
     );
 
     // Assign read outputs - no error correction, just trigger an alert
@@ -909,9 +873,6 @@
   // RF (Register File) //
   ////////////////////////
 `ifdef RVFI
-  assign rvfi_rd_addr_wb  = rf_waddr_wb;
-  assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
-  assign rvfi_rd_we_wb    = rf_we_wb | rf_we_lsu;
 `endif
 
 
@@ -923,104 +884,105 @@
   assign csr_addr   = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0);
 
   ibex_cs_registers #(
-      .DbgTriggerEn      ( DbgTriggerEn      ),
-      .DbgHwBreakNum     ( DbgHwBreakNum     ),
-      .DataIndTiming     ( DataIndTiming     ),
-      .DummyInstructions ( DummyInstructions ),
-      .ShadowCSR         ( ShadowCSR         ),
-      .ICache            ( ICache            ),
-      .MHPMCounterNum    ( MHPMCounterNum    ),
-      .MHPMCounterWidth  ( MHPMCounterWidth  ),
-      .PMPEnable         ( PMPEnable         ),
-      .PMPGranularity    ( PMPGranularity    ),
-      .PMPNumRegions     ( PMPNumRegions     ),
-      .RV32E             ( RV32E             ),
-      .RV32M             ( RV32M             ),
-      .RV32B             ( RV32B             )
+    .DbgTriggerEn     (DbgTriggerEn),
+    .DbgHwBreakNum    (DbgHwBreakNum),
+    .DataIndTiming    (DataIndTiming),
+    .DummyInstructions(DummyInstructions),
+    .ShadowCSR        (ShadowCSR),
+    .ICache           (ICache),
+    .MHPMCounterNum   (MHPMCounterNum),
+    .MHPMCounterWidth (MHPMCounterWidth),
+    .PMPEnable        (PMPEnable),
+    .PMPGranularity   (PMPGranularity),
+    .PMPNumRegions    (PMPNumRegions),
+    .RV32E            (RV32E),
+    .RV32M            (RV32M),
+    .RV32B            (RV32B)
   ) cs_registers_i (
-      .clk_i                   ( clk_i                        ),
-      .rst_ni                  ( rst_ni                       ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      // Hart ID from outside
-      .hart_id_i               ( hart_id_i                    ),
-      .priv_mode_id_o          ( priv_mode_id                 ),
-      .priv_mode_if_o          ( priv_mode_if                 ),
-      .priv_mode_lsu_o         ( priv_mode_lsu                ),
+    // Hart ID from outside
+    .hart_id_i      (hart_id_i),
+    .priv_mode_id_o (priv_mode_id),
+    .priv_mode_lsu_o(priv_mode_lsu),
 
-      // mtvec
-      .csr_mtvec_o             ( csr_mtvec                    ),
-      .csr_mtvec_init_i        ( csr_mtvec_init               ),
-      .boot_addr_i             ( boot_addr_i                  ),
+    // mtvec
+    .csr_mtvec_o     (csr_mtvec),
+    .csr_mtvec_init_i(csr_mtvec_init),
+    .boot_addr_i     (boot_addr_i),
 
-      // Interface to CSRs     ( SRAM like                    )
-      .csr_access_i            ( csr_access                   ),
-      .csr_addr_i              ( csr_addr                     ),
-      .csr_wdata_i             ( csr_wdata                    ),
-      .csr_op_i                ( csr_op                       ),
-      .csr_op_en_i             ( csr_op_en                    ),
-      .csr_rdata_o             ( csr_rdata                    ),
+    // Interface to CSRs     ( SRAM like                    )
+    .csr_access_i(csr_access),
+    .csr_addr_i  (csr_addr),
+    .csr_wdata_i (csr_wdata),
+    .csr_op_i    (csr_op),
+    .csr_op_en_i (csr_op_en),
+    .csr_rdata_o (csr_rdata),
 
-      // Interrupt related control signals
-      .irq_software_i          ( irq_software_i               ),
-      .irq_timer_i             ( irq_timer_i                  ),
-      .irq_external_i          ( irq_external_i               ),
-      .irq_fast_i              ( irq_fast_i                   ),
-      .nmi_mode_i              ( nmi_mode                     ),
-      .irq_pending_o           ( irq_pending_o                ),
-      .irqs_o                  ( irqs                         ),
-      .csr_mstatus_mie_o       ( csr_mstatus_mie              ),
-      .csr_mstatus_tw_o        ( csr_mstatus_tw               ),
-      .csr_mepc_o              ( csr_mepc                     ),
+    // Interrupt related control signals
+    .irq_software_i   (irq_software_i),
+    .irq_timer_i      (irq_timer_i),
+    .irq_external_i   (irq_external_i),
+    .irq_fast_i       (irq_fast_i),
+    .nmi_mode_i       (nmi_mode),
+    .irq_pending_o    (irq_pending_o),
+    .irqs_o           (irqs),
+    .csr_mstatus_mie_o(csr_mstatus_mie),
+    .csr_mstatus_tw_o (csr_mstatus_tw),
+    .csr_mepc_o       (csr_mepc),
 
-      // PMP
-      .csr_pmp_cfg_o           ( csr_pmp_cfg                  ),
-      .csr_pmp_addr_o          ( csr_pmp_addr                 ),
-      .csr_pmp_mseccfg_o       ( csr_pmp_mseccfg              ),
+    // PMP
+    .csr_pmp_cfg_o    (csr_pmp_cfg),
+    .csr_pmp_addr_o   (csr_pmp_addr),
+    .csr_pmp_mseccfg_o(csr_pmp_mseccfg),
 
-      // debug
-      .csr_depc_o              ( csr_depc                     ),
-      .debug_mode_i            ( debug_mode                   ),
-      .debug_cause_i           ( debug_cause                  ),
-      .debug_csr_save_i        ( debug_csr_save               ),
-      .debug_single_step_o     ( debug_single_step            ),
-      .debug_ebreakm_o         ( debug_ebreakm                ),
-      .debug_ebreaku_o         ( debug_ebreaku                ),
-      .trigger_match_o         ( trigger_match                ),
+    // debug
+    .csr_depc_o         (csr_depc),
+    .debug_mode_i       (debug_mode),
+    .debug_cause_i      (debug_cause),
+    .debug_csr_save_i   (debug_csr_save),
+    .debug_single_step_o(debug_single_step),
+    .debug_ebreakm_o    (debug_ebreakm),
+    .debug_ebreaku_o    (debug_ebreaku),
+    .trigger_match_o    (trigger_match),
 
-      .pc_if_i                 ( pc_if                        ),
-      .pc_id_i                 ( pc_id                        ),
-      .pc_wb_i                 ( pc_wb                        ),
+    .pc_if_i(pc_if),
+    .pc_id_i(pc_id),
+    .pc_wb_i(pc_wb),
 
-      .data_ind_timing_o       ( data_ind_timing              ),
-      .dummy_instr_en_o        ( dummy_instr_en               ),
-      .dummy_instr_mask_o      ( dummy_instr_mask             ),
-      .dummy_instr_seed_en_o   ( dummy_instr_seed_en          ),
-      .dummy_instr_seed_o      ( dummy_instr_seed             ),
-      .icache_enable_o         ( icache_enable                ),
-      .csr_shadow_err_o        ( csr_shadow_err               ),
+    .data_ind_timing_o    (data_ind_timing),
+    .dummy_instr_en_o     (dummy_instr_en),
+    .dummy_instr_mask_o   (dummy_instr_mask),
+    .dummy_instr_seed_en_o(dummy_instr_seed_en),
+    .dummy_instr_seed_o   (dummy_instr_seed),
+    .icache_enable_o      (icache_enable),
+    .csr_shadow_err_o     (csr_shadow_err),
 
-      .csr_save_if_i           ( csr_save_if                  ),
-      .csr_save_id_i           ( csr_save_id                  ),
-      .csr_save_wb_i           ( csr_save_wb                  ),
-      .csr_restore_mret_i      ( csr_restore_mret_id          ),
-      .csr_restore_dret_i      ( csr_restore_dret_id          ),
-      .csr_save_cause_i        ( csr_save_cause               ),
-      .csr_mcause_i            ( exc_cause                    ),
-      .csr_mtval_i             ( csr_mtval                    ),
-      .illegal_csr_insn_o      ( illegal_csr_insn_id          ),
+    .csr_save_if_i     (csr_save_if),
+    .csr_save_id_i     (csr_save_id),
+    .csr_save_wb_i     (csr_save_wb),
+    .csr_restore_mret_i(csr_restore_mret_id),
+    .csr_restore_dret_i(csr_restore_dret_id),
+    .csr_save_cause_i  (csr_save_cause),
+    .csr_mcause_i      (exc_cause),
+    .csr_mtval_i       (csr_mtval),
+    .illegal_csr_insn_o(illegal_csr_insn_id),
 
-      // performance counter related signals
-      .instr_ret_i             ( perf_instr_ret_wb            ),
-      .instr_ret_compressed_i  ( perf_instr_ret_compressed_wb ),
-      .iside_wait_i            ( perf_iside_wait              ),
-      .jump_i                  ( perf_jump                    ),
-      .branch_i                ( perf_branch                  ),
-      .branch_taken_i          ( perf_tbranch                 ),
-      .mem_load_i              ( perf_load                    ),
-      .mem_store_i             ( perf_store                   ),
-      .dside_wait_i            ( perf_dside_wait              ),
-      .mul_wait_i              ( perf_mul_wait                ),
-      .div_wait_i              ( perf_div_wait                )
+    // performance counter related signals
+    .instr_ret_i                (perf_instr_ret_wb),
+    .instr_ret_compressed_i     (perf_instr_ret_compressed_wb),
+    .instr_ret_spec_i           (perf_instr_ret_wb_spec),
+    .instr_ret_compressed_spec_i(perf_instr_ret_compressed_wb_spec),
+    .iside_wait_i               (perf_iside_wait),
+    .jump_i                     (perf_jump),
+    .branch_i                   (perf_branch),
+    .branch_taken_i             (perf_tbranch),
+    .mem_load_i                 (perf_load),
+    .mem_store_i                (perf_store),
+    .dside_wait_i               (perf_dside_wait),
+    .mul_wait_i                 (perf_mul_wait),
+    .div_wait_i                 (perf_div_wait)
   );
 
   // These assertions are in top-level as instr_valid_id required as the enable term
@@ -1037,45 +999,48 @@
     pmp_req_e    pmp_req_type [PMP_NUM_CHAN];
     priv_lvl_e   pmp_priv_lvl [PMP_NUM_CHAN];
 
-    assign pmp_req_addr[PMP_I] = {2'b00,instr_addr_o[31:0]};
-    assign pmp_req_type[PMP_I] = PMP_ACC_EXEC;
-    assign pmp_priv_lvl[PMP_I] = priv_mode_if;
-    assign pmp_req_addr[PMP_D] = {2'b00,data_addr_o[31:0]};
-    assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ;
-    assign pmp_priv_lvl[PMP_D] = priv_mode_lsu;
+    assign pmp_req_addr[PMP_I]  = {2'b00, pc_if};
+    assign pmp_req_type[PMP_I]  = PMP_ACC_EXEC;
+    assign pmp_priv_lvl[PMP_I]  = priv_mode_id;
+    assign pmp_req_addr[PMP_I2] = {2'b00, (pc_if + 32'd2)};
+    assign pmp_req_type[PMP_I2] = PMP_ACC_EXEC;
+    assign pmp_priv_lvl[PMP_I2] = priv_mode_id;
+    assign pmp_req_addr[PMP_D]  = {2'b00, data_addr_o[31:0]};
+    assign pmp_req_type[PMP_D]  = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ;
+    assign pmp_priv_lvl[PMP_D]  = priv_mode_lsu;
 
     ibex_pmp #(
-        .PMPGranularity        ( PMPGranularity  ),
-        .PMPNumChan            ( PMP_NUM_CHAN    ),
-        .PMPNumRegions         ( PMPNumRegions   )
+      .PMPGranularity(PMPGranularity),
+      .PMPNumChan    (PMP_NUM_CHAN),
+      .PMPNumRegions (PMPNumRegions)
     ) pmp_i (
-        .clk_i                 ( clk_i           ),
-        .rst_ni                ( rst_ni          ),
-        // Interface to CSRs
-        .csr_pmp_cfg_i         ( csr_pmp_cfg     ),
-        .csr_pmp_addr_i        ( csr_pmp_addr    ),
-        .csr_pmp_mseccfg_i     ( csr_pmp_mseccfg ),
-        .priv_mode_i           ( pmp_priv_lvl    ),
-        // Access checking channels
-        .pmp_req_addr_i        ( pmp_req_addr    ),
-        .pmp_req_type_i        ( pmp_req_type    ),
-        .pmp_req_err_o         ( pmp_req_err     )
+      .clk_i            (clk_i),
+      .rst_ni           (rst_ni),
+      // Interface to CSRs
+      .csr_pmp_cfg_i    (csr_pmp_cfg),
+      .csr_pmp_addr_i   (csr_pmp_addr),
+      .csr_pmp_mseccfg_i(csr_pmp_mseccfg),
+      .priv_mode_i      (pmp_priv_lvl),
+      // Access checking channels
+      .pmp_req_addr_i   (pmp_req_addr),
+      .pmp_req_type_i   (pmp_req_type),
+      .pmp_req_err_o    (pmp_req_err)
     );
   end else begin : g_no_pmp
     // Unused signal tieoff
-    priv_lvl_e unused_priv_lvl_if, unused_priv_lvl_ls;
+    priv_lvl_e unused_priv_lvl_ls;
     logic [33:0] unused_csr_pmp_addr [PMPNumRegions];
     pmp_cfg_t    unused_csr_pmp_cfg  [PMPNumRegions];
     pmp_mseccfg_t unused_csr_pmp_mseccfg;
-    assign unused_priv_lvl_if = priv_mode_if;
     assign unused_priv_lvl_ls = priv_mode_lsu;
     assign unused_csr_pmp_addr = csr_pmp_addr;
     assign unused_csr_pmp_cfg = csr_pmp_cfg;
     assign unused_csr_pmp_mseccfg = csr_pmp_mseccfg;
 
     // Output tieoff
-    assign pmp_req_err[PMP_I] = 1'b0;
-    assign pmp_req_err[PMP_D] = 1'b0;
+    assign pmp_req_err[PMP_I]  = 1'b0;
+    assign pmp_req_err[PMP_I2] = 1'b0;
+    assign pmp_req_err[PMP_D]  = 1'b0;
   end
 
 `ifdef RVFI
@@ -1111,6 +1076,59 @@
   logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES];
   logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES];
 
+  logic        rvfi_instr_new_wb;
+  logic        rvfi_intr_d;
+  logic        rvfi_intr_q;
+  logic        rvfi_set_trap_pc_d;
+  logic        rvfi_set_trap_pc_q;
+  logic [31:0] rvfi_insn_id;
+  logic [4:0]  rvfi_rs1_addr_d;
+  logic [4:0]  rvfi_rs1_addr_q;
+  logic [4:0]  rvfi_rs2_addr_d;
+  logic [4:0]  rvfi_rs2_addr_q;
+  logic [4:0]  rvfi_rs3_addr_d;
+  logic [31:0] rvfi_rs1_data_d;
+  logic [31:0] rvfi_rs1_data_q;
+  logic [31:0] rvfi_rs2_data_d;
+  logic [31:0] rvfi_rs2_data_q;
+  logic [31:0] rvfi_rs3_data_d;
+  logic [4:0]  rvfi_rd_addr_wb;
+  logic [4:0]  rvfi_rd_addr_q;
+  logic [4:0]  rvfi_rd_addr_d;
+  logic [31:0] rvfi_rd_wdata_wb;
+  logic [31:0] rvfi_rd_wdata_d;
+  logic [31:0] rvfi_rd_wdata_q;
+  logic        rvfi_rd_we_wb;
+  logic [3:0]  rvfi_mem_mask_int;
+  logic [31:0] rvfi_mem_rdata_d;
+  logic [31:0] rvfi_mem_rdata_q;
+  logic [31:0] rvfi_mem_wdata_d;
+  logic [31:0] rvfi_mem_wdata_q;
+  logic [31:0] rvfi_mem_addr_d;
+  logic [31:0] rvfi_mem_addr_q;
+  logic        rvfi_trap_id;
+  logic        rvfi_trap_wb;
+  logic [63:0] rvfi_stage_order_d;
+  logic        rvfi_id_done;
+  logic        rvfi_wb_done;
+
+  logic            new_debug_req;
+  logic            new_nmi;
+  logic            new_irq;
+  ibex_pkg::irqs_t captured_mip;
+  logic            captured_nmi;
+  logic            captured_debug_req;
+  logic            captured_valid;
+
+  // RVFI extension for co-simulation support
+  // debug_req and MIP captured at IF -> ID transition so one extra stage
+  ibex_pkg::irqs_t rvfi_ext_stage_mip          [RVFI_STAGES+1];
+  logic            rvfi_ext_stage_nmi          [RVFI_STAGES+1];
+  logic            rvfi_ext_stage_debug_req    [RVFI_STAGES+1];
+  logic [63:0]     rvfi_ext_stage_mcycle       [RVFI_STAGES];
+
+
+
   logic        rvfi_stage_valid_d   [RVFI_STAGES];
 
   assign rvfi_valid     = rvfi_stage_valid    [RVFI_STAGES-1];
@@ -1137,6 +1155,34 @@
   assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1];
   assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1];
 
+  assign rvfi_rd_addr_wb  = rf_waddr_wb;
+  assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
+  assign rvfi_rd_we_wb    = rf_we_wb | rf_we_lsu;
+
+  always_comb begin
+    // Use always_comb instead of continuous assign so first assign can set 0 as default everywhere
+    // that is overridden by more specific settings.
+    rvfi_ext_mip                                     = '0;
+    rvfi_ext_mip[CSR_MSIX_BIT]                       = rvfi_ext_stage_mip[RVFI_STAGES].irq_software;
+    rvfi_ext_mip[CSR_MTIX_BIT]                       = rvfi_ext_stage_mip[RVFI_STAGES].irq_timer;
+    rvfi_ext_mip[CSR_MEIX_BIT]                       = rvfi_ext_stage_mip[RVFI_STAGES].irq_external;
+    rvfi_ext_mip[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = rvfi_ext_stage_mip[RVFI_STAGES].irq_fast;
+  end
+
+  assign rvfi_ext_nmi       = rvfi_ext_stage_nmi[RVFI_STAGES];
+  assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req[RVFI_STAGES];
+  assign rvfi_ext_mcycle    = rvfi_ext_stage_mcycle[RVFI_STAGES-1];
+
+  // When an instruction takes a trap the `rvfi_trap` signal will be set. Instructions that take
+  // traps flush the pipeline so ordinarily wouldn't be seen to be retire. The RVFI tracking
+  // pipeline is kept going for flushed instructions that trapped so they are still visible on the
+  // RVFI interface.
+
+  // Factor in exceptions taken in ID so RVFI tracking picks up flushed instructions that took
+  // a trap
+  assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next &
+                                         id_stage_i.controller_i.id_exception_o);
+
   if (WritebackStage) begin : gen_rvfi_wb_stage
     logic unused_instr_new_id;
 
@@ -1146,91 +1192,181 @@
     // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB
     // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until
     // instruction leaves WB
-    assign rvfi_stage_valid_d[0] = (instr_id_done & ~dummy_instr_id) |
-                                   (rvfi_stage_valid[0] & ~instr_done_wb);
+    assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) |
+                                   (rvfi_stage_valid[0] & ~rvfi_wb_done);
     // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has
     // retired)
-    assign rvfi_stage_valid_d[1] = instr_done_wb;
+    assign rvfi_stage_valid_d[1] = rvfi_wb_done;
 
     // Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB)
     logic rvfi_instr_new_wb_q;
 
-    assign rvfi_instr_new_wb = rvfi_instr_new_wb_q;
+    // Signal new instruction in WB either when one has just entered or when a trap is progressing
+    // through the tracking pipeline
+    assign rvfi_instr_new_wb = rvfi_instr_new_wb_q | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
-      if (~rst_ni) begin
+      if (!rst_ni) begin
         rvfi_instr_new_wb_q <= 0;
       end else begin
-        rvfi_instr_new_wb_q <= instr_id_done;
+        rvfi_instr_new_wb_q <= rvfi_id_done;
       end
     end
+
+    assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o;
+    assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu;
+    // WB is instantly done in the tracking pipeline when a trap is progress through the pipeline
+    assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
   end else begin : gen_rvfi_no_wb_stage
     // Without writeback stage first RVFI stage is output stage so simply valid the cycle after
     // instruction leaves ID/EX (and so has retired)
-    assign rvfi_stage_valid_d[0] = instr_id_done & ~dummy_instr_id;
+    assign rvfi_stage_valid_d[0] = rvfi_id_done & ~dummy_instr_id;
     // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly
     // setup register write signals
     assign rvfi_instr_new_wb = instr_new_id;
+    assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu;
+    assign rvfi_trap_wb = 1'b0;
+    assign rvfi_wb_done = instr_done_wb;
   end
 
-  for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
+  assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order[0] : rvfi_stage_order[0] + 64'd1;
+
+  // For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID
+  // finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV
+  // environment with information about the irq/debug_req/nmi state that applies to a particular
+  // instruction.
+  //
+  // When a irq/debug_req/nmi appears the ID stage will finish whatever instruction it is currently
+  // executing (if any) then take the trap the cycle after that instruction leaves the ID stage. The
+  // trap taken depends upon the state of irq/debug_req/nmi on that cycle. In the cycles following
+  // that before the first instruction of the trap handler enters the ID stage the state of
+  // irq/debug_req/nmi could change but this has no effect on the trap handler (e.g. a higher
+  // priority interrupt might appear but this wouldn't stop the lower priority interrupt trap
+  // handler executing first as it's already being fetched). To provide the DV environment with the
+  // correct information for it to verify execution we need to capture the irq/debug_req/nmi state
+  // the cycle the trap decision is made. Which the captured_X signals below do.
+  //
+  // The new_X signals take the raw irq/debug_req/nmi inputs and factor in the enable terms required
+  // to determine if a trap will actually happen.
+  //
+  // These signals and the comment above are referred to in the documentation (cosim.rst). If
+  // altering the names or meanings of these signals or this comment please adjust the documentation
+  // appropriately.
+  assign new_debug_req = (debug_req_i & ~debug_mode);
+  assign new_nmi = irq_nm_i & ~nmi_mode & ~debug_mode;
+  assign new_irq = irq_pending_o & csr_mstatus_mie & ~nmi_mode & ~debug_mode;
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      captured_valid     <= 1'b0;
+      captured_mip       <= '0;
+      captured_nmi       <= 1'b0;
+      captured_debug_req <= 1'b0;
+    end else  begin
+      // Capture when ID stage has emptied out and something occurs that will cause a trap and we
+      // haven't yet captured
+      if (~instr_valid_id & (new_debug_req | new_irq | new_nmi) & ~captured_valid) begin
+        captured_valid     <= 1'b1;
+        captured_nmi       <= irq_nm_i;
+        captured_mip       <= cs_registers_i.mip;
+        captured_debug_req <= debug_req_i;
+      end
+
+      // Capture cleared out as soon as a new instruction appears in ID
+      if (if_stage_i.instr_valid_id_d) begin
+        captured_valid <= 1'b0;
+      end
+    end
+  end
+
+  // Pass the captured irq/debug_req/nmi state to the rvfi_ext interface tracking pipeline.
+  //
+  // To correctly capture we need to factor in various enable terms, should there be a fault in this
+  // logic we won't tell the DV environment about a trap that should have been taken. So if there's
+  // no valid capture we grab the raw values of the irq/debug_req/nmi inputs whatever they are and
+  // the DV environment will see if a trap should have been taken but wasn't.
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      rvfi_ext_stage_mip[0]       <= '0;
+      rvfi_ext_stage_nmi[0]       <= '0;
+      rvfi_ext_stage_debug_req[0] <= '0;
+    end else if (if_stage_i.instr_valid_id_d & if_stage_i.instr_new_id_d) begin
+      rvfi_ext_stage_mip[0]       <= instr_valid_id | ~captured_valid ? cs_registers_i.mip :
+                                                                        captured_mip;
+      rvfi_ext_stage_nmi[0]       <= instr_valid_id | ~captured_valid ? irq_nm_i :
+                                                                        captured_nmi;
+      rvfi_ext_stage_debug_req[0] <= instr_valid_id | ~captured_valid ? debug_req_i        :
+                                                                        captured_debug_req;
+    end
+  end
+
+  for (genvar i = 0; i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
     always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
-        rvfi_stage_halt[i]      <= '0;
-        rvfi_stage_trap[i]      <= '0;
-        rvfi_stage_intr[i]      <= '0;
-        rvfi_stage_order[i]     <= '0;
-        rvfi_stage_insn[i]      <= '0;
-        rvfi_stage_mode[i]      <= {PRIV_LVL_M};
-        rvfi_stage_ixl[i]       <= CSR_MISA_MXL;
-        rvfi_stage_rs1_addr[i]  <= '0;
-        rvfi_stage_rs2_addr[i]  <= '0;
-        rvfi_stage_rs3_addr[i]  <= '0;
-        rvfi_stage_pc_rdata[i]  <= '0;
-        rvfi_stage_pc_wdata[i]  <= '0;
-        rvfi_stage_mem_rmask[i] <= '0;
-        rvfi_stage_mem_wmask[i] <= '0;
-        rvfi_stage_valid[i]     <= '0;
-        rvfi_stage_rs1_rdata[i] <= '0;
-        rvfi_stage_rs2_rdata[i] <= '0;
-        rvfi_stage_rs3_rdata[i] <= '0;
-        rvfi_stage_rd_wdata[i]  <= '0;
-        rvfi_stage_rd_addr[i]   <= '0;
-        rvfi_stage_mem_rdata[i] <= '0;
-        rvfi_stage_mem_wdata[i] <= '0;
-        rvfi_stage_mem_addr[i]  <= '0;
+        rvfi_stage_halt[i]            <= '0;
+        rvfi_stage_trap[i]            <= '0;
+        rvfi_stage_intr[i]            <= '0;
+        rvfi_stage_order[i]           <= '0;
+        rvfi_stage_insn[i]            <= '0;
+        rvfi_stage_mode[i]            <= {PRIV_LVL_M};
+        rvfi_stage_ixl[i]             <= CSR_MISA_MXL;
+        rvfi_stage_rs1_addr[i]        <= '0;
+        rvfi_stage_rs2_addr[i]        <= '0;
+        rvfi_stage_rs3_addr[i]        <= '0;
+        rvfi_stage_pc_rdata[i]        <= '0;
+        rvfi_stage_pc_wdata[i]        <= '0;
+        rvfi_stage_mem_rmask[i]       <= '0;
+        rvfi_stage_mem_wmask[i]       <= '0;
+        rvfi_stage_valid[i]           <= '0;
+        rvfi_stage_rs1_rdata[i]       <= '0;
+        rvfi_stage_rs2_rdata[i]       <= '0;
+        rvfi_stage_rs3_rdata[i]       <= '0;
+        rvfi_stage_rd_wdata[i]        <= '0;
+        rvfi_stage_rd_addr[i]         <= '0;
+        rvfi_stage_mem_rdata[i]       <= '0;
+        rvfi_stage_mem_wdata[i]       <= '0;
+        rvfi_stage_mem_addr[i]        <= '0;
+        rvfi_ext_stage_mip[i+1]       <= '0;
+        rvfi_ext_stage_nmi[i+1]       <= '0;
+        rvfi_ext_stage_debug_req[i+1] <= '0;
+        rvfi_ext_stage_mcycle[i]      <= '0;
       end else begin
         rvfi_stage_valid[i] <= rvfi_stage_valid_d[i];
 
         if (i == 0) begin
-          if(instr_id_done) begin
+          if (rvfi_id_done) begin
             rvfi_stage_halt[i]      <= '0;
-            rvfi_stage_trap[i]      <= illegal_insn_id;
-            rvfi_stage_intr[i]      <= rvfi_intr_d;
-            rvfi_stage_order[i]     <= rvfi_stage_order[i] + 64'(rvfi_stage_valid_d[i]);
-            rvfi_stage_insn[i]      <= rvfi_insn_id;
-            rvfi_stage_mode[i]      <= {priv_mode_id};
-            rvfi_stage_ixl[i]       <= CSR_MISA_MXL;
-            rvfi_stage_rs1_addr[i]  <= rvfi_rs1_addr_d;
-            rvfi_stage_rs2_addr[i]  <= rvfi_rs2_addr_d;
-            rvfi_stage_rs3_addr[i]  <= rvfi_rs3_addr_d;
-            rvfi_stage_pc_rdata[i]  <= pc_id;
-            rvfi_stage_pc_wdata[i]  <= pc_set ? branch_target_ex : pc_if;
-            rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
-            rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
-            rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
-            rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
-            rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
-            rvfi_stage_rd_addr[i]   <= rvfi_rd_addr_d;
-            rvfi_stage_rd_wdata[i]  <= rvfi_rd_wdata_d;
-            rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
-            rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
-            rvfi_stage_mem_addr[i]  <= rvfi_mem_addr_d;
+            // TODO: Sort this out for writeback stage
+            rvfi_stage_trap[i]            <= rvfi_trap_id;
+            rvfi_stage_intr[i]            <= rvfi_intr_d;
+            rvfi_stage_order[i]           <= rvfi_stage_order_d;
+            rvfi_stage_insn[i]            <= rvfi_insn_id;
+            rvfi_stage_mode[i]            <= {priv_mode_id};
+            rvfi_stage_ixl[i]             <= CSR_MISA_MXL;
+            rvfi_stage_rs1_addr[i]        <= rvfi_rs1_addr_d;
+            rvfi_stage_rs2_addr[i]        <= rvfi_rs2_addr_d;
+            rvfi_stage_rs3_addr[i]        <= rvfi_rs3_addr_d;
+            rvfi_stage_pc_rdata[i]        <= pc_id;
+            rvfi_stage_pc_wdata[i]        <= pc_set ? branch_target_ex : pc_if;
+            rvfi_stage_mem_rmask[i]       <= rvfi_mem_mask_int;
+            rvfi_stage_mem_wmask[i]       <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
+            rvfi_stage_rs1_rdata[i]       <= rvfi_rs1_data_d;
+            rvfi_stage_rs2_rdata[i]       <= rvfi_rs2_data_d;
+            rvfi_stage_rs3_rdata[i]       <= rvfi_rs3_data_d;
+            rvfi_stage_rd_addr[i]         <= rvfi_rd_addr_d;
+            rvfi_stage_rd_wdata[i]        <= rvfi_rd_wdata_d;
+            rvfi_stage_mem_rdata[i]       <= rvfi_mem_rdata_d;
+            rvfi_stage_mem_wdata[i]       <= rvfi_mem_wdata_d;
+            rvfi_stage_mem_addr[i]        <= rvfi_mem_addr_d;
+            rvfi_ext_stage_mip[i+1]       <= rvfi_ext_stage_mip[i];
+            rvfi_ext_stage_nmi[i+1]       <= rvfi_ext_stage_nmi[i];
+            rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
+            rvfi_ext_stage_mcycle[i]      <= cs_registers_i.mcycle_counter_i.counter_val_o;
           end
         end else begin
-          if(instr_done_wb) begin
+          if (rvfi_wb_done) begin
             rvfi_stage_halt[i]      <= rvfi_stage_halt[i-1];
-            rvfi_stage_trap[i]      <= rvfi_stage_trap[i-1];
+            rvfi_stage_trap[i]      <= rvfi_stage_trap[i-1] | rvfi_trap_wb;
             rvfi_stage_intr[i]      <= rvfi_stage_intr[i-1];
             rvfi_stage_order[i]     <= rvfi_stage_order[i-1];
             rvfi_stage_insn[i]      <= rvfi_stage_insn[i-1];
@@ -1256,6 +1392,11 @@
             rvfi_stage_rd_addr[i]   <= rvfi_rd_addr_d;
             rvfi_stage_rd_wdata[i]  <= rvfi_rd_wdata_d;
             rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
+
+            rvfi_ext_stage_mip[i+1]       <= rvfi_ext_stage_mip[i];
+            rvfi_ext_stage_nmi[i+1]       <= rvfi_ext_stage_nmi[i];
+            rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
+            rvfi_ext_stage_mcycle[i]      <= rvfi_ext_stage_mcycle[i-1];
           end
         end
       end
@@ -1347,16 +1488,16 @@
   end
 
   always_comb begin
-    if(rvfi_rd_we_wb) begin
+    if (rvfi_rd_we_wb) begin
       // Capture address/data of write to register file
-      rvfi_rd_addr_d  = rvfi_rd_addr_wb;
+      rvfi_rd_addr_d = rvfi_rd_addr_wb;
       // If writing to x0 zero write data as required by RVFI specification
-      if(rvfi_rd_addr_wb == 5'b0) begin
+      if (rvfi_rd_addr_wb == 5'b0) begin
         rvfi_rd_wdata_d = '0;
       end else begin
         rvfi_rd_wdata_d = rvfi_rd_wdata_wb;
       end
-    end else if(rvfi_instr_new_wb) begin
+    end else if (rvfi_instr_new_wb) begin
       // If no RF write but new instruction in Writeback (when present) or ID/EX (when no writeback
       // stage present) then zero RF write address/data as required by RVFI specification
       rvfi_rd_addr_d  = '0;
@@ -1392,7 +1533,7 @@
         (exc_pc_mux_id == EXC_PC_EXC || exc_pc_mux_id == EXC_PC_IRQ)) begin
       // PC is set to enter a trap handler
       rvfi_set_trap_pc_d = 1'b1;
-    end else if (rvfi_set_trap_pc_q && instr_id_done) begin
+    end else if (rvfi_set_trap_pc_q && rvfi_id_done) begin
       // first instruction has been executed after PC is set to trap handler
       rvfi_set_trap_pc_d = 1'b0;
     end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
index 0091d5a..a6187b7 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
@@ -1,5 +1,9 @@
 module ibex_counter #(
-  parameter int CounterWidth = 32
+  parameter int CounterWidth = 32,
+  // When set `counter_val_upd_o` provides an incremented version of the counter value, otherwise
+  // the output is hard-wired to 0. This is required to allow Xilinx DSP inference to work
+  // correctly. When `ProvideValUpd` is set no DSPs are inferred.
+  parameter bit ProvideValUpd = 0
 ) (
   input  logic        clk_i,
   input  logic        rst_ni,
@@ -8,7 +12,8 @@
   input  logic        counterh_we_i,
   input  logic        counter_we_i,
   input  logic [31:0] counter_val_i,
-  output logic [63:0] counter_val_o
+  output logic [63:0] counter_val_o,
+  output logic [63:0] counter_val_upd_o
 );
 
   logic [63:0]             counter;
@@ -17,9 +22,11 @@
   logic                    we;
   logic [CounterWidth-1:0] counter_d;
 
+  // Increment
+  assign counter_upd = counter[CounterWidth-1:0] + {{CounterWidth - 1{1'b0}}, 1'b1};
+
   // Update
   always_comb begin
-
     // Write
     we = counter_we_i | counterh_we_i;
     counter_load[63:32] = counter[63:32];
@@ -29,13 +36,10 @@
       counter_load[31:0]  = counter[31:0];
     end
 
-    // Increment
-    counter_upd = counter[CounterWidth-1:0] + {{CounterWidth-1{1'b0}},1'b1};
-
     // Next value logic
     if (we) begin
       counter_d = counter_load[CounterWidth-1:0];
-    end else if (counter_inc_i)begin
+    end else if (counter_inc_i) begin
       counter_d = counter_upd[CounterWidth-1:0];
     end else begin
       counter_d = counter[CounterWidth-1:0];
@@ -44,7 +48,7 @@
 
 `ifdef FPGA_XILINX
   // Set DSP pragma for supported xilinx FPGAs
-  localparam int DspPragma = CounterWidth < 49  ? "yes" : "no";
+  localparam int DspPragma = CounterWidth < 49 ? "yes" : "no";
   (* use_dsp = DspPragma *) logic [CounterWidth-1:0] counter_q;
 
   // DSP output register requires synchronous reset.
@@ -67,11 +71,24 @@
   if (CounterWidth < 64) begin : g_counter_narrow
     logic [63:CounterWidth] unused_counter_load;
 
-    assign counter[CounterWidth-1:0] = counter_q;
-    assign counter[63:CounterWidth]  = '0;
-    assign unused_counter_load       = counter_load[63:CounterWidth];
+    assign counter[CounterWidth-1:0]           = counter_q;
+    assign counter[63:CounterWidth]            = '0;
+
+    if (ProvideValUpd) begin : g_counter_val_upd_o
+      assign counter_val_upd_o[CounterWidth-1:0] = counter_upd;
+    end else begin : g_no_counter_val_upd_o
+      assign counter_val_upd_o[CounterWidth-1:0] = '0;
+    end
+    assign counter_val_upd_o[63:CounterWidth]  = '0;
+    assign unused_counter_load                 = counter_load[63:CounterWidth];
   end else begin : g_counter_full
-    assign counter = counter_q;
+    assign counter           = counter_q;
+
+    if (ProvideValUpd) begin : g_counter_val_upd_o
+      assign counter_val_upd_o = counter_upd;
+    end else begin : g_no_counter_val_upd_o
+      assign counter_val_upd_o = '0;
+    end
   end
 
   assign counter_val_o = counter;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index 75ef2e5..559e607 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -13,110 +13,111 @@
 `include "prim_assert.sv"
 
 module ibex_cs_registers #(
-    parameter bit               DbgTriggerEn      = 0,
-    parameter int unsigned      DbgHwBreakNum     = 1,
-    parameter bit               DataIndTiming     = 1'b0,
-    parameter bit               DummyInstructions = 1'b0,
-    parameter bit               ShadowCSR         = 1'b0,
-    parameter bit               ICache            = 1'b0,
-    parameter int unsigned      MHPMCounterNum    = 10,
-    parameter int unsigned      MHPMCounterWidth  = 40,
-    parameter bit               PMPEnable         = 0,
-    parameter int unsigned      PMPGranularity    = 0,
-    parameter int unsigned      PMPNumRegions     = 4,
-    parameter bit               RV32E             = 0,
-    parameter ibex_pkg::rv32m_e RV32M             = ibex_pkg::RV32MFast,
-    parameter ibex_pkg::rv32b_e RV32B             = ibex_pkg::RV32BNone
+  parameter bit               DbgTriggerEn      = 0,
+  parameter int unsigned      DbgHwBreakNum     = 1,
+  parameter bit               DataIndTiming     = 1'b0,
+  parameter bit               DummyInstructions = 1'b0,
+  parameter bit               ShadowCSR         = 1'b0,
+  parameter bit               ICache            = 1'b0,
+  parameter int unsigned      MHPMCounterNum    = 10,
+  parameter int unsigned      MHPMCounterWidth  = 40,
+  parameter bit               PMPEnable         = 0,
+  parameter int unsigned      PMPGranularity    = 0,
+  parameter int unsigned      PMPNumRegions     = 4,
+  parameter bit               RV32E             = 0,
+  parameter ibex_pkg::rv32m_e RV32M             = ibex_pkg::RV32MFast,
+  parameter ibex_pkg::rv32b_e RV32B             = ibex_pkg::RV32BNone
 ) (
-    // Clock and Reset
-    input  logic                 clk_i,
-    input  logic                 rst_ni,
+  // Clock and Reset
+  input  logic                 clk_i,
+  input  logic                 rst_ni,
 
-    // Hart ID
-    input  logic [31:0]          hart_id_i,
+  // Hart ID
+  input  logic [31:0]          hart_id_i,
 
-    // Privilege mode
-    output ibex_pkg::priv_lvl_e  priv_mode_id_o,
-    output ibex_pkg::priv_lvl_e  priv_mode_if_o,
-    output ibex_pkg::priv_lvl_e  priv_mode_lsu_o,
-    output logic                 csr_mstatus_tw_o,
+  // Privilege mode
+  output ibex_pkg::priv_lvl_e  priv_mode_id_o,
+  output ibex_pkg::priv_lvl_e  priv_mode_lsu_o,
+  output logic                 csr_mstatus_tw_o,
 
-    // mtvec
-    output logic [31:0]          csr_mtvec_o,
-    input  logic                 csr_mtvec_init_i,
-    input  logic [31:0]          boot_addr_i,
+  // mtvec
+  output logic [31:0]          csr_mtvec_o,
+  input  logic                 csr_mtvec_init_i,
+  input  logic [31:0]          boot_addr_i,
 
-    // Interface to registers (SRAM like)
-    input  logic                 csr_access_i,
-    input  ibex_pkg::csr_num_e   csr_addr_i,
-    input  logic [31:0]          csr_wdata_i,
-    input  ibex_pkg::csr_op_e    csr_op_i,
-    input                        csr_op_en_i,
-    output logic [31:0]          csr_rdata_o,
+  // Interface to registers (SRAM like)
+  input  logic                 csr_access_i,
+  input  ibex_pkg::csr_num_e   csr_addr_i,
+  input  logic [31:0]          csr_wdata_i,
+  input  ibex_pkg::csr_op_e    csr_op_i,
+  input                        csr_op_en_i,
+  output logic [31:0]          csr_rdata_o,
 
-    // interrupts
-    input  logic                 irq_software_i,
-    input  logic                 irq_timer_i,
-    input  logic                 irq_external_i,
-    input  logic [14:0]          irq_fast_i,
-    input  logic                 nmi_mode_i,
-    output logic                 irq_pending_o,          // interrupt request pending
-    output ibex_pkg::irqs_t      irqs_o,                 // interrupt requests qualified with mie
-    output logic                 csr_mstatus_mie_o,
-    output logic [31:0]          csr_mepc_o,
+  // interrupts
+  input  logic                 irq_software_i,
+  input  logic                 irq_timer_i,
+  input  logic                 irq_external_i,
+  input  logic [14:0]          irq_fast_i,
+  input  logic                 nmi_mode_i,
+  output logic                 irq_pending_o,          // interrupt request pending
+  output ibex_pkg::irqs_t      irqs_o,                 // interrupt requests qualified with mie
+  output logic                 csr_mstatus_mie_o,
+  output logic [31:0]          csr_mepc_o,
 
-    // PMP
-    output ibex_pkg::pmp_cfg_t     csr_pmp_cfg_o  [PMPNumRegions],
-    output logic [33:0]            csr_pmp_addr_o [PMPNumRegions],
-    output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o,
+  // PMP
+  output ibex_pkg::pmp_cfg_t     csr_pmp_cfg_o  [PMPNumRegions],
+  output logic [33:0]            csr_pmp_addr_o [PMPNumRegions],
+  output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o,
 
-    // debug
-    input  logic                 debug_mode_i,
-    input  ibex_pkg::dbg_cause_e debug_cause_i,
-    input  logic                 debug_csr_save_i,
-    output logic [31:0]          csr_depc_o,
-    output logic                 debug_single_step_o,
-    output logic                 debug_ebreakm_o,
-    output logic                 debug_ebreaku_o,
-    output logic                 trigger_match_o,
+  // debug
+  input  logic                 debug_mode_i,
+  input  ibex_pkg::dbg_cause_e debug_cause_i,
+  input  logic                 debug_csr_save_i,
+  output logic [31:0]          csr_depc_o,
+  output logic                 debug_single_step_o,
+  output logic                 debug_ebreakm_o,
+  output logic                 debug_ebreaku_o,
+  output logic                 trigger_match_o,
 
-    input  logic [31:0]          pc_if_i,
-    input  logic [31:0]          pc_id_i,
-    input  logic [31:0]          pc_wb_i,
+  input  logic [31:0]          pc_if_i,
+  input  logic [31:0]          pc_id_i,
+  input  logic [31:0]          pc_wb_i,
 
-    // CPU control bits
-    output logic                 data_ind_timing_o,
-    output logic                 dummy_instr_en_o,
-    output logic [2:0]           dummy_instr_mask_o,
-    output logic                 dummy_instr_seed_en_o,
-    output logic [31:0]          dummy_instr_seed_o,
-    output logic                 icache_enable_o,
-    output logic                 csr_shadow_err_o,
+  // CPU control bits
+  output logic                 data_ind_timing_o,
+  output logic                 dummy_instr_en_o,
+  output logic [2:0]           dummy_instr_mask_o,
+  output logic                 dummy_instr_seed_en_o,
+  output logic [31:0]          dummy_instr_seed_o,
+  output logic                 icache_enable_o,
+  output logic                 csr_shadow_err_o,
 
-    // Exception save/restore
-    input  logic                 csr_save_if_i,
-    input  logic                 csr_save_id_i,
-    input  logic                 csr_save_wb_i,
-    input  logic                 csr_restore_mret_i,
-    input  logic                 csr_restore_dret_i,
-    input  logic                 csr_save_cause_i,
-    input  ibex_pkg::exc_cause_e csr_mcause_i,
-    input  logic [31:0]          csr_mtval_i,
-    output logic                 illegal_csr_insn_o,     // access to non-existent CSR,
-                                                         // with wrong priviledge level, or
-                                                         // missing write permissions
-    // Performance Counters
-    input  logic                 instr_ret_i,            // instr retired in ID/EX stage
-    input  logic                 instr_ret_compressed_i, // compressed instr retired
-    input  logic                 iside_wait_i,           // core waiting for the iside
-    input  logic                 jump_i,                 // jump instr seen (j, jr, jal, jalr)
-    input  logic                 branch_i,               // branch instr seen (bf, bnf)
-    input  logic                 branch_taken_i,         // branch was taken
-    input  logic                 mem_load_i,             // load from memory in this cycle
-    input  logic                 mem_store_i,            // store to memory in this cycle
-    input  logic                 dside_wait_i,           // core waiting for the dside
-    input  logic                 mul_wait_i,             // core waiting for multiply
-    input  logic                 div_wait_i              // core waiting for divide
+  // Exception save/restore
+  input  logic                 csr_save_if_i,
+  input  logic                 csr_save_id_i,
+  input  logic                 csr_save_wb_i,
+  input  logic                 csr_restore_mret_i,
+  input  logic                 csr_restore_dret_i,
+  input  logic                 csr_save_cause_i,
+  input  ibex_pkg::exc_cause_e csr_mcause_i,
+  input  logic [31:0]          csr_mtval_i,
+  output logic                 illegal_csr_insn_o,     // access to non-existent CSR,
+                                                        // with wrong priviledge level, or
+                                                        // missing write permissions
+  // Performance Counters
+  input  logic                 instr_ret_i,                 // instr retired in ID/EX stage
+  input  logic                 instr_ret_compressed_i,      // compressed instr retired
+  input  logic                 instr_ret_spec_i,            // speculative instr_ret_i
+  input  logic                 instr_ret_compressed_spec_i, // speculative instr_ret_compressed_i
+  input  logic                 iside_wait_i,                // core waiting for the iside
+  input  logic                 jump_i,                      // jump instr seen (j, jr, jal, jalr)
+  input  logic                 branch_i,                    // branch instr seen (bf, bnf)
+  input  logic                 branch_taken_i,              // branch was taken
+  input  logic                 mem_load_i,                  // load from memory in this cycle
+  input  logic                 mem_store_i,                 // store to memory in this cycle
+  input  logic                 dside_wait_i,                // core waiting for the dside
+  input  logic                 mul_wait_i,                  // core waiting for multiply
+  input  logic                 div_wait_i                   // core waiting for divide
 );
 
   import ibex_pkg::*;
@@ -242,6 +243,8 @@
   logic        unused_mhpmcounterh_we_1;
   logic        unused_mhpmcounter_incr_1;
 
+  logic [63:0] minstret_next, minstret_raw;
+
   // Debug / trigger registers
   logic [31:0] tselect_rdata;
   logic [31:0] tmatch_control_rdata;
@@ -294,6 +297,12 @@
     illegal_csr   = 1'b0;
 
     unique case (csr_addr_i)
+      // mvendorid: encoding of manufacturer/provider
+      CSR_MVENDORID: csr_rdata_int = CSR_MVENDORID_VALUE;
+      // marchid: encoding of base microarchitecture
+      CSR_MARCHID: csr_rdata_int = CSR_MARCHID_VALUE;
+      // mimpid: encoding of processor implementation version
+      CSR_MIMPID: csr_rdata_int = CSR_MIMPID_VALUE;
       // mhartid: unique hardware thread id
       CSR_MHARTID: csr_rdata_int = hart_id_i;
 
@@ -476,7 +485,7 @@
 
       // Custom CSR for controlling CPU features
       CSR_CPUCTRL: begin
-        csr_rdata_int = {{32-$bits(cpu_ctrl_t){1'b0}},cpuctrl_q};
+        csr_rdata_int = {{32 - $bits(cpu_ctrl_t) {1'b0}}, cpuctrl_q};
       end
 
       // Custom CSR for LFSR re-seeding (cannot be read)
@@ -719,8 +728,6 @@
 
   // Send current priv level to the decoder
   assign priv_mode_id_o = priv_lvl_q;
-  // New instruction fetches need to account for updates to priv_lvl_q this cycle
-  assign priv_mode_if_o = priv_lvl_d;
   // Load/store instructions must factor in MPRV for PMP checking
   assign priv_mode_lsu_o = mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q;
 
@@ -769,30 +776,30 @@
                                           mprv: 1'b0,
                                           tw:   1'b0};
   ibex_csr #(
-    .Width      ($bits(status_t)),
-    .ShadowCopy (ShadowCSR),
-    .ResetValue ({MSTATUS_RST_VAL})
+    .Width     ($bits(status_t)),
+    .ShadowCopy(ShadowCSR),
+    .ResetValue({MSTATUS_RST_VAL})
   ) u_mstatus_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  ({mstatus_d}),
-    .wr_en_i    (mstatus_en),
-    .rd_data_o  (mstatus_q),
-    .rd_error_o (mstatus_err)
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i ({mstatus_d}),
+    .wr_en_i   (mstatus_en),
+    .rd_data_o (mstatus_q),
+    .rd_error_o(mstatus_err)
   );
 
   // MEPC
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mepc_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mepc_d),
-    .wr_en_i    (mepc_en),
-    .rd_data_o  (mepc_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mepc_d),
+    .wr_en_i   (mepc_en),
+    .rd_data_o (mepc_q),
+    .rd_error_o()
   );
 
   // MIE
@@ -801,180 +808,177 @@
   assign mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT];
   assign mie_d.irq_fast     = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW];
   ibex_csr #(
-    .Width      ($bits(irqs_t)),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     ($bits(irqs_t)),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mie_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  ({mie_d}),
-    .wr_en_i    (mie_en),
-    .rd_data_o  (mie_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i ({mie_d}),
+    .wr_en_i   (mie_en),
+    .rd_data_o (mie_q),
+    .rd_error_o()
   );
 
   // MSCRATCH
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mscratch_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (csr_wdata_int),
-    .wr_en_i    (mscratch_en),
-    .rd_data_o  (mscratch_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (csr_wdata_int),
+    .wr_en_i   (mscratch_en),
+    .rd_data_o (mscratch_q),
+    .rd_error_o()
   );
 
   // MCAUSE
   ibex_csr #(
-    .Width      (6),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (6),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mcause_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mcause_d),
-    .wr_en_i    (mcause_en),
-    .rd_data_o  (mcause_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mcause_d),
+    .wr_en_i   (mcause_en),
+    .rd_data_o (mcause_q),
+    .rd_error_o()
   );
 
   // MTVAL
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mtval_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mtval_d),
-    .wr_en_i    (mtval_en),
-    .rd_data_o  (mtval_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mtval_d),
+    .wr_en_i   (mtval_en),
+    .rd_data_o (mtval_q),
+    .rd_error_o()
   );
 
   // MTVEC
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (ShadowCSR),
-    .ResetValue (32'd1)
+    .Width     (32),
+    .ShadowCopy(ShadowCSR),
+    .ResetValue(32'd1)
   ) u_mtvec_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mtvec_d),
-    .wr_en_i    (mtvec_en),
-    .rd_data_o  (mtvec_q),
-    .rd_error_o (mtvec_err)
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mtvec_d),
+    .wr_en_i   (mtvec_en),
+    .rd_data_o (mtvec_q),
+    .rd_error_o(mtvec_err)
   );
 
   // DCSR
   localparam dcsr_t DCSR_RESET_VAL = '{
       xdebugver: XDEBUGVER_STD,
-      cause:     DBG_CAUSE_NONE, // 3'h0
-      prv:       PRIV_LVL_M,
-      default:   '0
+      cause: DBG_CAUSE_NONE,  // 3'h0
+      prv: PRIV_LVL_M,
+      default: '0
   };
   ibex_csr #(
-    .Width      ($bits(dcsr_t)),
-    .ShadowCopy (1'b0),
-    .ResetValue ({DCSR_RESET_VAL})
+    .Width     ($bits(dcsr_t)),
+    .ShadowCopy(1'b0),
+    .ResetValue({DCSR_RESET_VAL})
   ) u_dcsr_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  ({dcsr_d}),
-    .wr_en_i    (dcsr_en),
-    .rd_data_o  (dcsr_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i ({dcsr_d}),
+    .wr_en_i   (dcsr_en),
+    .rd_data_o (dcsr_q),
+    .rd_error_o()
   );
 
   // DEPC
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_depc_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (depc_d),
-    .wr_en_i    (depc_en),
-    .rd_data_o  (depc_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (depc_d),
+    .wr_en_i   (depc_en),
+    .rd_data_o (depc_q),
+    .rd_error_o()
   );
 
   // DSCRATCH0
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_dscratch0_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (csr_wdata_int),
-    .wr_en_i    (dscratch0_en),
-    .rd_data_o  (dscratch0_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (csr_wdata_int),
+    .wr_en_i   (dscratch0_en),
+    .rd_data_o (dscratch0_q),
+    .rd_error_o()
   );
 
   // DSCRATCH1
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_dscratch1_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (csr_wdata_int),
-    .wr_en_i    (dscratch1_en),
-    .rd_data_o  (dscratch1_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (csr_wdata_int),
+    .wr_en_i   (dscratch1_en),
+    .rd_data_o (dscratch1_q),
+    .rd_error_o()
   );
 
   // MSTACK
-  localparam status_stk_t MSTACK_RESET_VAL = '{
-      mpie: 1'b1,
-      mpp:  PRIV_LVL_U
-  };
+  localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U};
   ibex_csr #(
-    .Width      ($bits(status_stk_t)),
-    .ShadowCopy (1'b0),
-    .ResetValue ({MSTACK_RESET_VAL})
+    .Width     ($bits(status_stk_t)),
+    .ShadowCopy(1'b0),
+    .ResetValue({MSTACK_RESET_VAL})
   ) u_mstack_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  ({mstack_d}),
-    .wr_en_i    (mstack_en),
-    .rd_data_o  (mstack_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i ({mstack_d}),
+    .wr_en_i   (mstack_en),
+    .rd_data_o (mstack_q),
+    .rd_error_o()
   );
 
   // MSTACK_EPC
   ibex_csr #(
-    .Width      (32),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (32),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mstack_epc_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mstack_epc_d),
-    .wr_en_i    (mstack_en),
-    .rd_data_o  (mstack_epc_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mstack_epc_d),
+    .wr_en_i   (mstack_en),
+    .rd_data_o (mstack_epc_q),
+    .rd_error_o()
   );
 
   // MSTACK_CAUSE
   ibex_csr #(
-    .Width      (6),
-    .ShadowCopy (1'b0),
-    .ResetValue ('0)
+    .Width     (6),
+    .ShadowCopy(1'b0),
+    .ResetValue('0)
   ) u_mstack_cause_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  (mstack_cause_d),
-    .wr_en_i    (mstack_en),
-    .rd_data_o  (mstack_cause_q),
-    .rd_error_o ()
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i (mstack_cause_d),
+    .wr_en_i   (mstack_en),
+    .rd_data_o (mstack_cause_q),
+    .rd_error_o()
   );
 
   // -----------------
@@ -1021,7 +1025,7 @@
           // For G >= 2, bits are masked to one or zero depending on the mode
           always_comb begin
             // In NAPOT mode, bits [G-2:0] must read as one
-            pmp_addr_rdata[i] = {pmp_addr[i], {PMPGranularity-1{1'b1}}};
+            pmp_addr_rdata[i] = {pmp_addr[i], {PMPGranularity - 1{1'b1}}};
 
             if ((pmp_cfg[i].mode == PMP_MODE_OFF) || (pmp_cfg[i].mode == PMP_MODE_TOR)) begin
               // In TOR or OFF mode, bits [G-1:0] must read as zero
@@ -1066,16 +1070,16 @@
       assign pmp_cfg_wdata[i].read  = csr_wdata_int[(i%4)*PMP_CFG_W];
 
       ibex_csr #(
-        .Width      ($bits(pmp_cfg_t)),
-        .ShadowCopy (ShadowCSR),
-        .ResetValue ('0)
+        .Width     ($bits(pmp_cfg_t)),
+        .ShadowCopy(ShadowCSR),
+        .ResetValue('0)
       ) u_pmp_cfg_csr (
-        .clk_i      (clk_i),
-        .rst_ni     (rst_ni),
-        .wr_data_i  ({pmp_cfg_wdata[i]}),
-        .wr_en_i    (pmp_cfg_we[i]),
-        .rd_data_o  (pmp_cfg[i]),
-        .rd_error_o (pmp_cfg_err[i])
+        .clk_i     (clk_i),
+        .rst_ni    (rst_ni),
+        .wr_data_i ({pmp_cfg_wdata[i]}),
+        .wr_en_i   (pmp_cfg_we[i]),
+        .rd_data_o (pmp_cfg[i]),
+        .rd_error_o(pmp_cfg_err[i])
       );
 
       // MSECCFG.RLB allows the lock bit to be bypassed (allowing cfg writes when MSECCFG.RLB is
@@ -1095,16 +1099,16 @@
       end
 
       ibex_csr #(
-        .Width      (PMPAddrWidth),
-        .ShadowCopy (ShadowCSR),
-        .ResetValue ('0)
+        .Width     (PMPAddrWidth),
+        .ShadowCopy(ShadowCSR),
+        .ResetValue('0)
       ) u_pmp_addr_csr (
-        .clk_i      (clk_i),
-        .rst_ni     (rst_ni),
-        .wr_data_i  (csr_wdata_int[31-:PMPAddrWidth]),
-        .wr_en_i    (pmp_addr_we[i]),
-        .rd_data_o  (pmp_addr[i]),
-        .rd_error_o (pmp_addr_err[i])
+        .clk_i     (clk_i),
+        .rst_ni    (rst_ni),
+        .wr_data_i (csr_wdata_int[31-:PMPAddrWidth]),
+        .wr_en_i   (pmp_addr_we[i]),
+        .rd_data_o (pmp_addr[i]),
+        .rd_error_o(pmp_addr_err[i])
       );
 
       assign csr_pmp_cfg_o[i]  = pmp_cfg[i];
@@ -1126,16 +1130,16 @@
     assign pmp_mseccfg_d.rlb = any_pmp_entry_locked ? 1'b0 : csr_wdata_int[CSR_MSECCFG_RLB_BIT];
 
     ibex_csr #(
-      .Width      ($bits(pmp_mseccfg_t)),
-      .ShadowCopy (ShadowCSR),
-      .ResetValue ('0)
+      .Width     ($bits(pmp_mseccfg_t)),
+      .ShadowCopy(ShadowCSR),
+      .ResetValue('0)
     ) u_pmp_mseccfg (
-      .clk_i      (clk_i),
-      .rst_ni     (rst_ni),
-      .wr_data_i  (pmp_mseccfg_d),
-      .wr_en_i    (pmp_mseccfg_we),
-      .rd_data_o  (pmp_mseccfg_q),
-      .rd_error_o (pmp_mseccfg_err)
+      .clk_i     (clk_i),
+      .rst_ni    (rst_ni),
+      .wr_data_i (pmp_mseccfg_d),
+      .wr_en_i   (pmp_mseccfg_we),
+      .rd_data_o (pmp_mseccfg_q),
+      .rd_error_o(pmp_mseccfg_err)
     );
 
     assign pmp_csr_err = (|pmp_cfg_err) | (|pmp_addr_err) | pmp_mseccfg_err;
@@ -1175,7 +1179,7 @@
   always_comb begin : gen_mhpmcounter_incr
 
     // Assign inactive counters (first to prevent latch inference)
-    for (int unsigned i=0; i<32; i++) begin : gen_mhpmcounter_incr_inactive
+    for (int unsigned i = 0; i < 32; i++) begin : gen_mhpmcounter_incr_inactive
       mhpmcounter_incr[i] = 1'b0;
     end
 
@@ -1203,14 +1207,14 @@
   always_comb begin : gen_mhpmevent
 
     // activate all
-    for (int i=0; i<32; i++) begin : gen_mhpmevent_active
+    for (int i = 0; i < 32; i++) begin : gen_mhpmevent_active
       mhpmevent[i]    =   '0;
       mhpmevent[i][i] = 1'b1;
     end
 
     // deactivate
     mhpmevent[1] = '0; // not existing, reserved
-    for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmevent_inactive
+    for (int unsigned i = 3 + MHPMCounterNum; i < 32; i++) begin : gen_mhpmevent_inactive
       mhpmevent[i] = '0;
     end
   end
@@ -1225,12 +1229,15 @@
     .counterh_we_i(mhpmcounterh_we[0]),
     .counter_we_i(mhpmcounter_we[0]),
     .counter_val_i(csr_wdata_int),
-    .counter_val_o(mhpmcounter[0])
+    .counter_val_o(mhpmcounter[0]),
+    .counter_val_upd_o()
   );
 
+
   // minstret
   ibex_counter #(
-    .CounterWidth(64)
+    .CounterWidth(64),
+    .ProvideValUpd(1)
   ) minstret_counter_i (
     .clk_i(clk_i),
     .rst_ni(rst_ni),
@@ -1238,39 +1245,74 @@
     .counterh_we_i(mhpmcounterh_we[2]),
     .counter_we_i(mhpmcounter_we[2]),
     .counter_val_i(csr_wdata_int),
-    .counter_val_o(mhpmcounter[2])
+    .counter_val_o(minstret_raw),
+    .counter_val_upd_o(minstret_next)
   );
 
+  // Where the writeback stage is present instruction in ID observing value of minstret must take
+  // into account any instruction in the writeback stage. If one is present the incremented value of
+  // minstret is used. A speculative version of the signal is used to aid timing. When the writeback
+  // stage sees an exception (so the speculative signal is incorrect) the ID stage will be flushed
+  // so the incorrect value doesn't matter. A similar behaviour is required for the compressed
+  // instruction retired counter below. When the writeback stage isn't present the speculative
+  // signals are always 0.
+  assign mhpmcounter[2] = instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw;
+
   // reserved:
   assign mhpmcounter[1]            = '0;
   assign unused_mhpmcounter_we_1   = mhpmcounter_we[1];
   assign unused_mhpmcounterh_we_1  = mhpmcounterh_we[1];
   assign unused_mhpmcounter_incr_1 = mhpmcounter_incr[1];
 
-  for (genvar cnt=0; cnt < 29; cnt++) begin : gen_cntrs
-    if (cnt < MHPMCounterNum) begin : gen_imp
+  // Iterate through optionally included counters (MHPMCounterNum controls how many are included)
+  for (genvar i = 0; i < 29; i++) begin : gen_cntrs
+    localparam int Cnt = i + 3;
+
+    if (i < MHPMCounterNum) begin : gen_imp
+      logic [63:0] mhpmcounter_raw, mhpmcounter_next;
+
       ibex_counter #(
-        .CounterWidth(MHPMCounterWidth)
+        .CounterWidth(MHPMCounterWidth),
+        .ProvideValUpd(Cnt == 10)
       ) mcounters_variable_i (
         .clk_i(clk_i),
         .rst_ni(rst_ni),
-        .counter_inc_i(mhpmcounter_incr[cnt+3] & ~mcountinhibit[cnt+3]),
-        .counterh_we_i(mhpmcounterh_we[cnt+3]),
-        .counter_we_i(mhpmcounter_we[cnt+3]),
+        .counter_inc_i(mhpmcounter_incr[Cnt] & ~mcountinhibit[Cnt]),
+        .counterh_we_i(mhpmcounterh_we[Cnt]),
+        .counter_we_i(mhpmcounter_we[Cnt]),
         .counter_val_i(csr_wdata_int),
-        .counter_val_o(mhpmcounter[cnt+3])
+        .counter_val_o(mhpmcounter_raw),
+        .counter_val_upd_o(mhpmcounter_next)
       );
+
+      if (Cnt == 10) begin : gen_compressed_instr_cnt
+        // Special behaviour for reading compressed instruction retired counter, see comment on
+        // `mhpmcounter[2]` above for further information.
+        assign mhpmcounter[Cnt] =
+          instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next:
+                                                              mhpmcounter_raw;
+      end else begin : gen_other_cnts
+        logic [63:0] unused_mhpmcounter_next;
+        // All other counters just see the raw counter value directly.
+        assign mhpmcounter[Cnt] = mhpmcounter_raw;
+        assign unused_mhpmcounter_next = mhpmcounter_next;
+      end
     end else begin : gen_unimp
-      assign mhpmcounter[cnt+3] = '0;
+      assign mhpmcounter[Cnt] = '0;
+
+      if (Cnt == 10) begin : gen_no_compressed_instr_cnt
+        logic unused_instr_ret_compressed_spec_i;
+        assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i;
+      end
     end
   end
 
-  if(MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
+  if (MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
     logic [29-MHPMCounterNum-1:0] unused_mhphcounter_we;
     logic [29-MHPMCounterNum-1:0] unused_mhphcounterh_we;
     logic [29-MHPMCounterNum-1:0] unused_mhphcounter_incr;
 
-    assign mcountinhibit = {{29-MHPMCounterNum{1'b1}}, mcountinhibit_q};
+    assign mcountinhibit = {{29 - MHPMCounterNum{1'b1}}, mcountinhibit_q};
     // Lint tieoffs for unused bits
     assign unused_mhphcounter_we   = mhpmcounter_we[31:MHPMCounterNum+3];
     assign unused_mhphcounterh_we  = mhpmcounterh_we[31:MHPMCounterNum+3];
@@ -1331,43 +1373,43 @@
 
     // Registers
     ibex_csr #(
-      .Width      (DbgHwNumLen),
-      .ShadowCopy (1'b0),
-      .ResetValue ('0)
+      .Width     (DbgHwNumLen),
+      .ShadowCopy(1'b0),
+      .ResetValue('0)
     ) u_tselect_csr (
-      .clk_i      (clk_i),
-      .rst_ni     (rst_ni),
-      .wr_data_i  (tselect_d),
-      .wr_en_i    (tselect_we),
-      .rd_data_o  (tselect_q),
-      .rd_error_o ()
+      .clk_i     (clk_i),
+      .rst_ni    (rst_ni),
+      .wr_data_i (tselect_d),
+      .wr_en_i   (tselect_we),
+      .rd_data_o (tselect_q),
+      .rd_error_o()
     );
 
     for (genvar i = 0; i < DbgHwBreakNum; i++) begin : g_dbg_tmatch_reg
       ibex_csr #(
-        .Width      (1),
-        .ShadowCopy (1'b0),
-        .ResetValue ('0)
+        .Width     (1),
+        .ShadowCopy(1'b0),
+        .ResetValue('0)
       ) u_tmatch_control_csr (
-        .clk_i      (clk_i),
-        .rst_ni     (rst_ni),
-        .wr_data_i  (tmatch_control_d),
-        .wr_en_i    (tmatch_control_we[i]),
-        .rd_data_o  (tmatch_control_q[i]),
-        .rd_error_o ()
-    );
+        .clk_i     (clk_i),
+        .rst_ni    (rst_ni),
+        .wr_data_i (tmatch_control_d),
+        .wr_en_i   (tmatch_control_we[i]),
+        .rd_data_o (tmatch_control_q[i]),
+        .rd_error_o()
+      );
 
       ibex_csr #(
-        .Width      (32),
-        .ShadowCopy (1'b0),
-        .ResetValue ('0)
+        .Width     (32),
+        .ShadowCopy(1'b0),
+        .ResetValue('0)
       ) u_tmatch_value_csr (
-        .clk_i      (clk_i),
-        .rst_ni     (rst_ni),
-        .wr_data_i  (tmatch_value_d),
-        .wr_en_i    (tmatch_value_we[i]),
-        .rd_data_o  (tmatch_value_q[i]),
-        .rd_error_o ()
+        .clk_i     (clk_i),
+        .rst_ni    (rst_ni),
+        .wr_data_i (tmatch_value_d),
+        .wr_en_i   (tmatch_value_we[i]),
+        .rd_data_o (tmatch_value_q[i]),
+        .rd_error_o()
       );
     end
 
@@ -1483,16 +1525,16 @@
   assign icache_enable_o = cpuctrl_q.icache_enable;
 
   ibex_csr #(
-    .Width      ($bits(cpu_ctrl_t)),
-    .ShadowCopy (ShadowCSR),
-    .ResetValue ('0)
+    .Width     ($bits(cpu_ctrl_t)),
+    .ShadowCopy(ShadowCSR),
+    .ResetValue('0)
   ) u_cpuctrl_csr (
-    .clk_i      (clk_i),
-    .rst_ni     (rst_ni),
-    .wr_data_i  ({cpuctrl_d}),
-    .wr_en_i    (cpuctrl_we),
-    .rd_data_o  (cpuctrl_q),
-    .rd_error_o (cpuctrl_err)
+    .clk_i     (clk_i),
+    .rst_ni    (rst_ni),
+    .wr_data_i ({cpuctrl_d}),
+    .wr_en_i   (cpuctrl_we),
+    .rd_data_o (cpuctrl_q),
+    .rd_error_o(cpuctrl_err)
   );
 
   assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
index 8623fa5..309a325 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
@@ -9,18 +9,18 @@
 `include "prim_assert.sv"
 
 module ibex_csr #(
-    parameter int unsigned    Width      = 32,
-    parameter bit             ShadowCopy = 1'b0,
-    parameter bit [Width-1:0] ResetValue = '0
+  parameter int unsigned    Width      = 32,
+  parameter bit             ShadowCopy = 1'b0,
+  parameter bit [Width-1:0] ResetValue = '0
  ) (
-    input  logic             clk_i,
-    input  logic             rst_ni,
+  input  logic             clk_i,
+  input  logic             rst_ni,
 
-    input  logic [Width-1:0] wr_data_i,
-    input  logic             wr_en_i,
-    output logic [Width-1:0] rd_data_o,
+  input  logic [Width-1:0] wr_data_i,
+  input  logic             wr_en_i,
+  output logic [Width-1:0] rd_data_o,
 
-    output logic             rd_error_o
+  output logic             rd_error_o
 );
 
   logic [Width-1:0] rdata_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
index 0f10608..fbc754a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
@@ -14,87 +14,87 @@
 `include "prim_assert.sv"
 
 module ibex_decoder #(
-    parameter bit RV32E               = 0,
-    parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
-    parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
-    parameter bit BranchTargetALU     = 0
+  parameter bit RV32E               = 0,
+  parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
+  parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
+  parameter bit BranchTargetALU     = 0
 ) (
-    input  logic                 clk_i,
-    input  logic                 rst_ni,
+  input  logic                 clk_i,
+  input  logic                 rst_ni,
 
-    // to/from controller
-    output logic                 illegal_insn_o,        // illegal instr encountered
-    output logic                 ebrk_insn_o,           // trap instr encountered
-    output logic                 mret_insn_o,           // return from exception instr
-                                                        // encountered
-    output logic                 dret_insn_o,           // return from debug instr encountered
-    output logic                 ecall_insn_o,          // syscall instr encountered
-    output logic                 wfi_insn_o,            // wait for interrupt instr encountered
-    output logic                 jump_set_o,            // jump taken set signal
-    input  logic                 branch_taken_i,        // registered branch decision
-    output logic                 icache_inval_o,
+  // to/from controller
+  output logic                 illegal_insn_o,        // illegal instr encountered
+  output logic                 ebrk_insn_o,           // trap instr encountered
+  output logic                 mret_insn_o,           // return from exception instr
+                                                      // encountered
+  output logic                 dret_insn_o,           // return from debug instr encountered
+  output logic                 ecall_insn_o,          // syscall instr encountered
+  output logic                 wfi_insn_o,            // wait for interrupt instr encountered
+  output logic                 jump_set_o,            // jump taken set signal
+  input  logic                 branch_taken_i,        // registered branch decision
+  output logic                 icache_inval_o,
 
-    // from IF-ID pipeline register
-    input  logic                 instr_first_cycle_i,   // instruction read is in its first cycle
-    input  logic [31:0]          instr_rdata_i,         // instruction read from memory/cache
-    input  logic [31:0]          instr_rdata_alu_i,     // instruction read from memory/cache
-                                                        // replicated to ease fan-out)
+  // from IF-ID pipeline register
+  input  logic                 instr_first_cycle_i,   // instruction read is in its first cycle
+  input  logic [31:0]          instr_rdata_i,         // instruction read from memory/cache
+  input  logic [31:0]          instr_rdata_alu_i,     // instruction read from memory/cache
+                                                      // replicated to ease fan-out)
 
-    input  logic                 illegal_c_insn_i,      // compressed instruction decode failed
+  input  logic                 illegal_c_insn_i,      // compressed instruction decode failed
 
-    // immediates
-    output ibex_pkg::imm_a_sel_e  imm_a_mux_sel_o,       // immediate selection for operand a
-    output ibex_pkg::imm_b_sel_e  imm_b_mux_sel_o,       // immediate selection for operand b
-    output ibex_pkg::op_a_sel_e   bt_a_mux_sel_o,        // branch target selection operand a
-    output ibex_pkg::imm_b_sel_e  bt_b_mux_sel_o,        // branch target selection operand b
-    output logic [31:0]           imm_i_type_o,
-    output logic [31:0]           imm_s_type_o,
-    output logic [31:0]           imm_b_type_o,
-    output logic [31:0]           imm_u_type_o,
-    output logic [31:0]           imm_j_type_o,
-    output logic [31:0]           zimm_rs1_type_o,
+  // immediates
+  output ibex_pkg::imm_a_sel_e  imm_a_mux_sel_o,       // immediate selection for operand a
+  output ibex_pkg::imm_b_sel_e  imm_b_mux_sel_o,       // immediate selection for operand b
+  output ibex_pkg::op_a_sel_e   bt_a_mux_sel_o,        // branch target selection operand a
+  output ibex_pkg::imm_b_sel_e  bt_b_mux_sel_o,        // branch target selection operand b
+  output logic [31:0]           imm_i_type_o,
+  output logic [31:0]           imm_s_type_o,
+  output logic [31:0]           imm_b_type_o,
+  output logic [31:0]           imm_u_type_o,
+  output logic [31:0]           imm_j_type_o,
+  output logic [31:0]           zimm_rs1_type_o,
 
-    // register file
-    output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o,   // RF write data selection
-    output logic                 rf_we_o,          // write enable for regfile
-    output logic [4:0]           rf_raddr_a_o,
-    output logic [4:0]           rf_raddr_b_o,
-    output logic [4:0]           rf_waddr_o,
-    output logic                 rf_ren_a_o,          // Instruction reads from RF addr A
-    output logic                 rf_ren_b_o,          // Instruction reads from RF addr B
+  // register file
+  output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o,   // RF write data selection
+  output logic                 rf_we_o,          // write enable for regfile
+  output logic [4:0]           rf_raddr_a_o,
+  output logic [4:0]           rf_raddr_b_o,
+  output logic [4:0]           rf_waddr_o,
+  output logic                 rf_ren_a_o,          // Instruction reads from RF addr A
+  output logic                 rf_ren_b_o,          // Instruction reads from RF addr B
 
-    // ALU
-    output ibex_pkg::alu_op_e    alu_operator_o,        // ALU operation selection
-    output ibex_pkg::op_a_sel_e  alu_op_a_mux_sel_o,    // operand a selection: reg value, PC,
-                                                        // immediate or zero
-    output ibex_pkg::op_b_sel_e  alu_op_b_mux_sel_o,    // operand b selection: reg value or
-                                                        // immediate
-    output logic                 alu_multicycle_o,      // ternary bitmanip instruction
+  // ALU
+  output ibex_pkg::alu_op_e    alu_operator_o,        // ALU operation selection
+  output ibex_pkg::op_a_sel_e  alu_op_a_mux_sel_o,    // operand a selection: reg value, PC,
+                                                      // immediate or zero
+  output ibex_pkg::op_b_sel_e  alu_op_b_mux_sel_o,    // operand b selection: reg value or
+                                                      // immediate
+  output logic                 alu_multicycle_o,      // ternary bitmanip instruction
 
-    // MULT & DIV
-    output logic                 mult_en_o,             // perform integer multiplication
-    output logic                 div_en_o,              // perform integer division or remainder
-    output logic                 mult_sel_o,            // as above but static, for data muxes
-    output logic                 div_sel_o,             // as above but static, for data muxes
+  // MULT & DIV
+  output logic                 mult_en_o,             // perform integer multiplication
+  output logic                 div_en_o,              // perform integer division or remainder
+  output logic                 mult_sel_o,            // as above but static, for data muxes
+  output logic                 div_sel_o,             // as above but static, for data muxes
 
-    output ibex_pkg::md_op_e     multdiv_operator_o,
-    output logic [1:0]           multdiv_signed_mode_o,
+  output ibex_pkg::md_op_e     multdiv_operator_o,
+  output logic [1:0]           multdiv_signed_mode_o,
 
-    // CSRs
-    output logic                 csr_access_o,          // access to CSR
-    output ibex_pkg::csr_op_e    csr_op_o,              // operation to perform on CSR
+  // CSRs
+  output logic                 csr_access_o,          // access to CSR
+  output ibex_pkg::csr_op_e    csr_op_o,              // operation to perform on CSR
 
-    // LSU
-    output logic                 data_req_o,            // start transaction to data memory
-    output logic                 data_we_o,             // write enable
-    output logic [1:0]           data_type_o,           // size of transaction: byte, half
-                                                        // word or word
-    output logic                 data_sign_extension_o, // sign extension for data read from
-                                                        // memory
+  // LSU
+  output logic                 data_req_o,            // start transaction to data memory
+  output logic                 data_we_o,             // write enable
+  output logic [1:0]           data_type_o,           // size of transaction: byte, half
+                                                      // word or word
+  output logic                 data_sign_extension_o, // sign extension for data read from
+                                                      // memory
 
-    // jump/branches
-    output logic                 jump_in_dec_o,         // jump is being calculated in ALU
-    output logic                 branch_in_dec_o
+  // jump/branches
+  output logic                 jump_in_dec_o,         // jump is being calculated in ALU
+  output logic                 branch_in_dec_o
 );
 
   import ibex_pkg::*;
@@ -362,10 +362,10 @@
           3'b001: begin
             unique case (instr[31:27])
               5'b0_0000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1;        // slli
-              5'b0_0100,                                                              // sloi
-              5'b0_1001,                                                              // sbclri
-              5'b0_0101,                                                              // sbseti
-              5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1;           // sbinvi
+              5'b0_0100: illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1;           // sloi
+              5'b0_1001,                                                              // bclri
+              5'b0_0101,                                                              // bseti
+              5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1;           // binvi
               5'b0_0001: if (instr[26] == 1'b0) begin
                 illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1;                    // shfl
               end else begin
@@ -375,7 +375,7 @@
                 unique case(instr[26:20])
                   7'b000_0000,                                                         // clz
                   7'b000_0001,                                                         // ctz
-                  7'b000_0010,                                                         // pcnt
+                  7'b000_0010,                                                         // cpop
                   7'b000_0100,                                                         // sext.b
                   7'b000_0101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1;      // sext.h
                   7'b001_0000,                                                         // crc32.b
@@ -400,20 +400,17 @@
                 5'b0_0000,                                                             // srli
                 5'b0_1000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1;       // srai
 
-                5'b0_0100,                                                             // sroi
+                5'b0_0100: illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1;          // sroi
                 5'b0_1100,                                                             // rori
-                5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1;          // sbexti
+                5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1;          // bexti
 
                 5'b0_1101: begin
                   if ((RV32B == RV32BFull)) begin
                     illegal_insn = 1'b0;                                               // grevi
+                  end else if (RV32B == RV32BBalanced) begin
+                    illegal_insn = (instr[24:20] == 5'b11000) ? 1'b0 : 1'b1;           // rev8
                   end else begin
-                    unique case (instr[24:20])
-                      5'b11111,                                                        // rev
-                      5'b11000: illegal_insn = (RV32B == RV32BBalanced) ? 1'b0 : 1'b1; // rev8
-
-                      default: illegal_insn = 1'b1;
-                    endcase
+                    illegal_insn = 1'b1;
                   end
                 end
                 5'b0_0101: begin
@@ -462,36 +459,43 @@
             {7'b000_0000, 3'b101},
             {7'b010_0000, 3'b101}: illegal_insn = 1'b0;
 
+            // RV32B zba
+            {7'b001_0000, 3'b010}, // sh1add
+            {7'b001_0000, 3'b100}, // sh2add
+            {7'b001_0000, 3'b110}, // sh3add
             // RV32B zbb
             {7'b010_0000, 3'b111}, // andn
             {7'b010_0000, 3'b110}, // orn
             {7'b010_0000, 3'b100}, // xnor
-            {7'b001_0000, 3'b001}, // slo
-            {7'b001_0000, 3'b101}, // sro
             {7'b011_0000, 3'b001}, // rol
             {7'b011_0000, 3'b101}, // ror
             {7'b000_0101, 3'b100}, // min
-            {7'b000_0101, 3'b101}, // max
-            {7'b000_0101, 3'b110}, // minu
+            {7'b000_0101, 3'b110}, // max
+            {7'b000_0101, 3'b101}, // minu
             {7'b000_0101, 3'b111}, // maxu
             {7'b000_0100, 3'b100}, // pack
             {7'b010_0100, 3'b100}, // packu
             {7'b000_0100, 3'b111}, // packh
             // RV32B zbs
-            {7'b010_0100, 3'b001}, // sbclr
-            {7'b001_0100, 3'b001}, // sbset
-            {7'b011_0100, 3'b001}, // sbinv
-            {7'b010_0100, 3'b101}, // sbext
+            {7'b010_0100, 3'b001}, // bclr
+            {7'b001_0100, 3'b001}, // bset
+            {7'b011_0100, 3'b001}, // binv
+            {7'b010_0100, 3'b101}, // bext
             // RV32B zbf
             {7'b010_0100, 3'b111}: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // bfp
             // RV32B zbe
-            {7'b010_0100, 3'b110}, // bdep
-            {7'b000_0100, 3'b110}, // bext
+            {7'b010_0100, 3'b110}, // bdecompress
+            {7'b000_0100, 3'b110}, // bcompress
             // RV32B zbp
             {7'b011_0100, 3'b101}, // grev
             {7'b001_0100, 3'b101}, // gorc
             {7'b000_0100, 3'b001}, // shfl
             {7'b000_0100, 3'b101}, // unshfl
+            {7'b001_0100, 3'b010}, // xperm.n
+            {7'b001_0100, 3'b100}, // xperm.b
+            {7'b001_0100, 3'b110}, // xperm.h
+            {7'b001_0000, 3'b001}, // slo
+            {7'b001_0000, 3'b101}, // sro
             // RV32B zbc
             {7'b000_0101, 3'b001}, // clmul
             {7'b000_0101, 3'b010}, // clmulr
@@ -819,17 +823,18 @@
             if (RV32B != RV32BNone) begin
               unique case (instr_alu[31:27])
                 5'b0_0000: alu_operator_o = ALU_SLL;    // Shift Left Logical by Immediate
-                5'b0_0100: alu_operator_o = ALU_SLO;    // Shift Left Ones by Immediate
-                5'b0_1001: alu_operator_o = ALU_SBCLR;  // Clear bit specified by immediate
-                5'b0_0101: alu_operator_o = ALU_SBSET;  // Set bit specified by immediate
-                5'b0_1101: alu_operator_o = ALU_SBINV;  // Invert bit specified by immediate.
+                // Shift Left Ones by Immediate
+                5'b0_0100: if (RV32B == RV32BFull) alu_operator_o = ALU_SLO;
+                5'b0_1001: alu_operator_o = ALU_BCLR; // Clear bit specified by immediate
+                5'b0_0101: alu_operator_o = ALU_BSET; // Set bit specified by immediate
+                5'b0_1101: alu_operator_o = ALU_BINV; // Invert bit specified by immediate.
                 // Shuffle with Immediate Control Value
                 5'b0_0001: if (instr_alu[26] == 0) alu_operator_o = ALU_SHFL;
                 5'b0_1100: begin
                   unique case (instr_alu[26:20])
                     7'b000_0000: alu_operator_o = ALU_CLZ;   // clz
                     7'b000_0001: alu_operator_o = ALU_CTZ;   // ctz
-                    7'b000_0010: alu_operator_o = ALU_PCNT;  // pcnt
+                    7'b000_0010: alu_operator_o = ALU_CPOP;  // cpop
                     7'b000_0100: alu_operator_o = ALU_SEXTB; // sext.b
                     7'b000_0101: alu_operator_o = ALU_SEXTH; // sext.h
                     7'b001_0000: begin
@@ -893,8 +898,9 @@
                 unique case (instr_alu[31:27])
                   5'b0_0000: alu_operator_o = ALU_SRL;   // Shift Right Logical by Immediate
                   5'b0_1000: alu_operator_o = ALU_SRA;   // Shift Right Arithmetically by Immediate
-                  5'b0_0100: alu_operator_o = ALU_SRO;   // Shift Right Ones by Immediate
-                  5'b0_1001: alu_operator_o = ALU_SBEXT; // Extract bit specified by immediate.
+                  // Shift Right Ones by Immediate
+                  5'b0_0100: if (RV32B == RV32BFull) alu_operator_o = ALU_SRO;
+                  5'b0_1001: alu_operator_o = ALU_BEXT;  // Extract bit specified by immediate.
                   5'b0_1100: begin
                     alu_operator_o = ALU_ROR;            // Rotate Right by Immediate
                     alu_multicycle_o = 1'b1;
@@ -985,8 +991,6 @@
             {7'b010_0000, 3'b101}: alu_operator_o = ALU_SRA;   // Shift Right Arithmetic
 
             // RV32B ALU Operations
-            {7'b001_0000, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SLO;   // slo
-            {7'b001_0000, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_SRO;   // sro
             {7'b011_0000, 3'b001}: begin
               if (RV32B != RV32BNone) begin
                 alu_operator_o = ALU_ROL;   // rol
@@ -1001,8 +1005,8 @@
             end
 
             {7'b000_0101, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_MIN;    // min
-            {7'b000_0101, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAX;    // max
-            {7'b000_0101, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_MINU;   // minu
+            {7'b000_0101, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAX;    // max
+            {7'b000_0101, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_MINU;   // minu
             {7'b000_0101, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAXU;   // maxu
 
             {7'b000_0100, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_PACK;   // pack
@@ -1013,20 +1017,30 @@
             {7'b010_0000, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_ORN;    // orn
             {7'b010_0000, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_ANDN;   // andn
 
+            // RV32B zba
+            {7'b001_0000, 3'b010}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH1ADD; // sh1add
+            {7'b001_0000, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH2ADD; // sh2add
+            {7'b001_0000, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH3ADD; // sh3add
+
             // RV32B zbs
-            {7'b010_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBCLR;  // sbclr
-            {7'b001_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBSET;  // sbset
-            {7'b011_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBINV;  // sbinv
-            {7'b010_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBEXT;  // sbext
+            {7'b010_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BCLR;   // bclr
+            {7'b001_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BSET;   // bset
+            {7'b011_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BINV;   // binv
+            {7'b010_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_BEXT;   // bext
 
             // RV32B zbf
             {7'b010_0100, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_BFP;    // bfp
 
             // RV32B zbp
-            {7'b011_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GREV;   // grev
-            {7'b001_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GORC;   // grev
-            {7'b000_0100, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SHFL;   // shfl
-            {7'b000_0100, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_UNSHFL; // unshfl
+            {7'b011_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GREV;    // grev
+            {7'b001_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GORC;    // gorc
+            {7'b000_0100, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SHFL;    // shfl
+            {7'b000_0100, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_UNSHFL;  // unshfl
+            {7'b001_0100, 3'b010}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_N; // xperm.n
+            {7'b001_0100, 3'b100}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_B; // xperm.b
+            {7'b001_0100, 3'b110}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_H; // xperm.h
+            {7'b001_0000, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SLO;     // slo
+            {7'b001_0000, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_SRO;     // sro
 
             // RV32B zbc
             {7'b000_0101, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_CLMUL;  // clmul
@@ -1036,13 +1050,13 @@
             // RV32B zbe
             {7'b010_0100, 3'b110}: begin
               if (RV32B == RV32BFull) begin
-                alu_operator_o = ALU_BDEP;   // bdep
+                alu_operator_o = ALU_BDECOMPRESS; // bdecompress
                 alu_multicycle_o = 1'b1;
               end
             end
             {7'b000_0100, 3'b110}: begin
               if (RV32B == RV32BFull) begin
-                alu_operator_o = ALU_BEXT;   // bext
+                alu_operator_o = ALU_BCOMPRESS;   // bcompress
                 alu_multicycle_o = 1'b1;
               end
             end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
index cae665a..979ea93 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
@@ -12,21 +12,21 @@
     parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
     parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
 ) (
-    // Clock and reset
-    input  logic        clk_i,
-    input  logic        rst_ni,
+  // Clock and reset
+  input  logic        clk_i,
+  input  logic        rst_ni,
 
-    // Interface to CSRs
-    input  logic        dummy_instr_en_i,
-    input  logic [2:0]  dummy_instr_mask_i,
-    input  logic        dummy_instr_seed_en_i,
-    input  logic [31:0] dummy_instr_seed_i,
+  // Interface to CSRs
+  input  logic        dummy_instr_en_i,
+  input  logic [2:0]  dummy_instr_mask_i,
+  input  logic        dummy_instr_seed_en_i,
+  input  logic [31:0] dummy_instr_seed_i,
 
-    // Interface to IF stage
-    input  logic        fetch_valid_i,
-    input  logic        id_in_ready_i,
-    output logic        insert_dummy_instr_o,
-    output logic [31:0] dummy_instr_data_o
+  // Interface to IF stage
+  input  logic        fetch_valid_i,
+  input  logic        id_in_ready_i,
+  output logic        insert_dummy_instr_o,
+  output logic [31:0] dummy_instr_data_o
 );
 
   localparam int unsigned TIMEOUT_CNT_W = 5;
@@ -116,31 +116,31 @@
   // Encode instruction
   always_comb begin
     unique case (lfsr_data.instr_type)
-      DUMMY_ADD : begin
+      DUMMY_ADD: begin
         dummy_set    = 7'b0000000;
         dummy_opcode = 3'b000;
       end
-      DUMMY_MUL : begin
+      DUMMY_MUL: begin
         dummy_set    = 7'b0000001;
         dummy_opcode = 3'b000;
       end
-      DUMMY_DIV : begin
+      DUMMY_DIV: begin
         dummy_set    = 7'b0000001;
         dummy_opcode = 3'b100;
       end
-      DUMMY_AND : begin
+      DUMMY_AND: begin
         dummy_set    = 7'b0000000;
         dummy_opcode = 3'b111;
       end
-      default : begin
+      default: begin
         dummy_set    = 7'b0000000;
         dummy_opcode = 3'b000;
       end
     endcase
   end
 
-  //                    SET       RS2            RS1            OP           RD
-  assign dummy_instr = {dummy_set,lfsr_data.op_b,lfsr_data.op_a,dummy_opcode,5'h00,7'h33};
+  //                    SET        RS2             RS1             OP            RD
+  assign dummy_instr = {dummy_set, lfsr_data.op_b, lfsr_data.op_a, dummy_opcode, 5'h00, 7'h33};
 
   // Assign outputs
   assign insert_dummy_instr_o = insert_dummy_instr;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
index 62e0396..ee90016 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
@@ -9,48 +9,48 @@
  * Execution block: Hosts ALU and MUL/DIV unit
  */
 module ibex_ex_block #(
-    parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
-    parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
-    parameter bit               BranchTargetALU = 0
+  parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
+  parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
+  parameter bit               BranchTargetALU = 0
 ) (
-    input  logic                  clk_i,
-    input  logic                  rst_ni,
+  input  logic                  clk_i,
+  input  logic                  rst_ni,
 
-    // ALU
-    input  ibex_pkg::alu_op_e     alu_operator_i,
-    input  logic [31:0]           alu_operand_a_i,
-    input  logic [31:0]           alu_operand_b_i,
-    input  logic                  alu_instr_first_cycle_i,
+  // ALU
+  input  ibex_pkg::alu_op_e     alu_operator_i,
+  input  logic [31:0]           alu_operand_a_i,
+  input  logic [31:0]           alu_operand_b_i,
+  input  logic                  alu_instr_first_cycle_i,
 
-    // Branch Target ALU
-    // All of these signals are unusued when BranchTargetALU == 0
-    input  logic [31:0]           bt_a_operand_i,
-    input  logic [31:0]           bt_b_operand_i,
+  // Branch Target ALU
+  // All of these signals are unusued when BranchTargetALU == 0
+  input  logic [31:0]           bt_a_operand_i,
+  input  logic [31:0]           bt_b_operand_i,
 
-    // Multiplier/Divider
-    input  ibex_pkg::md_op_e      multdiv_operator_i,
-    input  logic                  mult_en_i,             // dynamic enable signal, for FSM control
-    input  logic                  div_en_i,              // dynamic enable signal, for FSM control
-    input  logic                  mult_sel_i,            // static decoder output, for data muxes
-    input  logic                  div_sel_i,             // static decoder output, for data muxes
-    input  logic  [1:0]           multdiv_signed_mode_i,
-    input  logic [31:0]           multdiv_operand_a_i,
-    input  logic [31:0]           multdiv_operand_b_i,
-    input  logic                  multdiv_ready_id_i,
-    input  logic                  data_ind_timing_i,
+  // Multiplier/Divider
+  input  ibex_pkg::md_op_e      multdiv_operator_i,
+  input  logic                  mult_en_i,             // dynamic enable signal, for FSM control
+  input  logic                  div_en_i,              // dynamic enable signal, for FSM control
+  input  logic                  mult_sel_i,            // static decoder output, for data muxes
+  input  logic                  div_sel_i,             // static decoder output, for data muxes
+  input  logic  [1:0]           multdiv_signed_mode_i,
+  input  logic [31:0]           multdiv_operand_a_i,
+  input  logic [31:0]           multdiv_operand_b_i,
+  input  logic                  multdiv_ready_id_i,
+  input  logic                  data_ind_timing_i,
 
-    // intermediate val reg
-    output logic [1:0]            imd_val_we_o,
-    output logic [33:0]           imd_val_d_o[2],
-    input  logic [33:0]           imd_val_q_i[2],
+  // intermediate val reg
+  output logic [1:0]            imd_val_we_o,
+  output logic [33:0]           imd_val_d_o[2],
+  input  logic [33:0]           imd_val_q_i[2],
 
-    // Outputs
-    output logic [31:0]           alu_adder_result_ex_o, // to LSU
-    output logic [31:0]           result_ex_o,
-    output logic [31:0]           branch_target_o,       // to IF
-    output logic                  branch_decision_o,     // to ID
+  // Outputs
+  output logic [31:0]           alu_adder_result_ex_o, // to LSU
+  output logic [31:0]           result_ex_o,
+  output logic [31:0]           branch_target_o,       // to IF
+  output logic                  branch_decision_o,     // to ID
 
-    output logic                  ex_valid_o             // EX has valid output
+  output logic                  ex_valid_o             // EX has valid output
 );
 
   import ibex_pkg::*;
@@ -115,22 +115,22 @@
 
   ibex_alu #(
     .RV32B(RV32B)
-  ) alu_i                  (
-      .operator_i          ( alu_operator_i          ),
-      .operand_a_i         ( alu_operand_a_i         ),
-      .operand_b_i         ( alu_operand_b_i         ),
-      .instr_first_cycle_i ( alu_instr_first_cycle_i ),
-      .imd_val_q_i         ( alu_imd_val_q           ),
-      .imd_val_we_o        ( alu_imd_val_we          ),
-      .imd_val_d_o         ( alu_imd_val_d           ),
-      .multdiv_operand_a_i ( multdiv_alu_operand_a   ),
-      .multdiv_operand_b_i ( multdiv_alu_operand_b   ),
-      .multdiv_sel_i       ( multdiv_sel             ),
-      .adder_result_o      ( alu_adder_result_ex_o   ),
-      .adder_result_ext_o  ( alu_adder_result_ext    ),
-      .result_o            ( alu_result              ),
-      .comparison_result_o ( alu_cmp_result          ),
-      .is_equal_result_o   ( alu_is_equal_result     )
+  ) alu_i (
+    .operator_i         (alu_operator_i),
+    .operand_a_i        (alu_operand_a_i),
+    .operand_b_i        (alu_operand_b_i),
+    .instr_first_cycle_i(alu_instr_first_cycle_i),
+    .imd_val_q_i        (alu_imd_val_q),
+    .imd_val_we_o       (alu_imd_val_we),
+    .imd_val_d_o        (alu_imd_val_d),
+    .multdiv_operand_a_i(multdiv_alu_operand_a),
+    .multdiv_operand_b_i(multdiv_alu_operand_b),
+    .multdiv_sel_i      (multdiv_sel),
+    .adder_result_o     (alu_adder_result_ex_o),
+    .adder_result_ext_o (alu_adder_result_ext),
+    .result_o           (alu_result),
+    .comparison_result_o(alu_cmp_result),
+    .is_equal_result_o  (alu_is_equal_result)
   );
 
   ////////////////
@@ -139,55 +139,55 @@
 
   if (RV32M == RV32MSlow) begin : gen_multdiv_slow
     ibex_multdiv_slow multdiv_i (
-        .clk_i              ( clk_i                 ),
-        .rst_ni             ( rst_ni                ),
-        .mult_en_i          ( mult_en_i             ),
-        .div_en_i           ( div_en_i              ),
-        .mult_sel_i         ( mult_sel_i            ),
-        .div_sel_i          ( div_sel_i             ),
-        .operator_i         ( multdiv_operator_i    ),
-        .signed_mode_i      ( multdiv_signed_mode_i ),
-        .op_a_i             ( multdiv_operand_a_i   ),
-        .op_b_i             ( multdiv_operand_b_i   ),
-        .alu_adder_ext_i    ( alu_adder_result_ext  ),
-        .alu_adder_i        ( alu_adder_result_ex_o ),
-        .equal_to_zero_i    ( alu_is_equal_result   ),
-        .data_ind_timing_i  ( data_ind_timing_i     ),
-        .valid_o            ( multdiv_valid         ),
-        .alu_operand_a_o    ( multdiv_alu_operand_a ),
-        .alu_operand_b_o    ( multdiv_alu_operand_b ),
-        .imd_val_q_i        ( imd_val_q_i           ),
-        .imd_val_d_o        ( multdiv_imd_val_d     ),
-        .imd_val_we_o       ( multdiv_imd_val_we    ),
-        .multdiv_ready_id_i ( multdiv_ready_id_i    ),
-        .multdiv_result_o   ( multdiv_result        )
+      .clk_i             (clk_i),
+      .rst_ni            (rst_ni),
+      .mult_en_i         (mult_en_i),
+      .div_en_i          (div_en_i),
+      .mult_sel_i        (mult_sel_i),
+      .div_sel_i         (div_sel_i),
+      .operator_i        (multdiv_operator_i),
+      .signed_mode_i     (multdiv_signed_mode_i),
+      .op_a_i            (multdiv_operand_a_i),
+      .op_b_i            (multdiv_operand_b_i),
+      .alu_adder_ext_i   (alu_adder_result_ext),
+      .alu_adder_i       (alu_adder_result_ex_o),
+      .equal_to_zero_i   (alu_is_equal_result),
+      .data_ind_timing_i (data_ind_timing_i),
+      .valid_o           (multdiv_valid),
+      .alu_operand_a_o   (multdiv_alu_operand_a),
+      .alu_operand_b_o   (multdiv_alu_operand_b),
+      .imd_val_q_i       (imd_val_q_i),
+      .imd_val_d_o       (multdiv_imd_val_d),
+      .imd_val_we_o      (multdiv_imd_val_we),
+      .multdiv_ready_id_i(multdiv_ready_id_i),
+      .multdiv_result_o  (multdiv_result)
     );
   end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast
-    ibex_multdiv_fast #     (
-        .RV32M ( RV32M )
-    ) multdiv_i             (
-        .clk_i              ( clk_i                 ),
-        .rst_ni             ( rst_ni                ),
-        .mult_en_i          ( mult_en_i             ),
-        .div_en_i           ( div_en_i              ),
-        .mult_sel_i         ( mult_sel_i            ),
-        .div_sel_i          ( div_sel_i             ),
-        .operator_i         ( multdiv_operator_i    ),
-        .signed_mode_i      ( multdiv_signed_mode_i ),
-        .op_a_i             ( multdiv_operand_a_i   ),
-        .op_b_i             ( multdiv_operand_b_i   ),
-        .alu_operand_a_o    ( multdiv_alu_operand_a ),
-        .alu_operand_b_o    ( multdiv_alu_operand_b ),
-        .alu_adder_ext_i    ( alu_adder_result_ext  ),
-        .alu_adder_i        ( alu_adder_result_ex_o ),
-        .equal_to_zero_i    ( alu_is_equal_result   ),
-        .data_ind_timing_i  ( data_ind_timing_i     ),
-        .imd_val_q_i        ( imd_val_q_i           ),
-        .imd_val_d_o        ( multdiv_imd_val_d     ),
-        .imd_val_we_o       ( multdiv_imd_val_we    ),
-        .multdiv_ready_id_i ( multdiv_ready_id_i    ),
-        .valid_o            ( multdiv_valid         ),
-        .multdiv_result_o   ( multdiv_result        )
+    ibex_multdiv_fast #(
+      .RV32M(RV32M)
+    ) multdiv_i (
+      .clk_i             (clk_i),
+      .rst_ni            (rst_ni),
+      .mult_en_i         (mult_en_i),
+      .div_en_i          (div_en_i),
+      .mult_sel_i        (mult_sel_i),
+      .div_sel_i         (div_sel_i),
+      .operator_i        (multdiv_operator_i),
+      .signed_mode_i     (multdiv_signed_mode_i),
+      .op_a_i            (multdiv_operand_a_i),
+      .op_b_i            (multdiv_operand_b_i),
+      .alu_operand_a_o   (multdiv_alu_operand_a),
+      .alu_operand_b_o   (multdiv_alu_operand_b),
+      .alu_adder_ext_i   (alu_adder_result_ext),
+      .alu_adder_i       (alu_adder_result_ex_o),
+      .equal_to_zero_i   (alu_is_equal_result),
+      .data_ind_timing_i (data_ind_timing_i),
+      .imd_val_q_i       (imd_val_q_i),
+      .imd_val_d_o       (multdiv_imd_val_d),
+      .imd_val_we_o      (multdiv_imd_val_we),
+      .multdiv_ready_id_i(multdiv_ready_id_i),
+      .valid_o           (multdiv_valid),
+      .multdiv_result_o  (multdiv_result)
     );
   end
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
index 98fb287..61179ed 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
@@ -16,27 +16,26 @@
   parameter int unsigned NUM_REQS = 2,
   parameter bit          ResetAll = 1'b0
 ) (
-    input  logic                clk_i,
-    input  logic                rst_ni,
+  input  logic                clk_i,
+  input  logic                rst_ni,
 
-    // control signals
-    input  logic                clear_i,   // clears the contents of the FIFO
-    output logic [NUM_REQS-1:0] busy_o,
+  // control signals
+  input  logic                clear_i,   // clears the contents of the FIFO
+  output logic [NUM_REQS-1:0] busy_o,
 
-    // input port
-    input  logic                in_valid_i,
-    input  logic [31:0]         in_addr_i,
-    input  logic [31:0]         in_rdata_i,
-    input  logic                in_err_i,
+  // input port
+  input  logic                in_valid_i,
+  input  logic [31:0]         in_addr_i,
+  input  logic [31:0]         in_rdata_i,
+  input  logic                in_err_i,
 
-    // output port
-    output logic                out_valid_o,
-    input  logic                out_ready_i,
-    output logic [31:0]         out_addr_o,
-    output logic [31:0]         out_addr_next_o,
-    output logic [31:0]         out_rdata_o,
-    output logic                out_err_o,
-    output logic                out_err_plus2_o
+  // output port
+  output logic                out_valid_o,
+  input  logic                out_ready_i,
+  output logic [31:0]         out_addr_o,
+  output logic [31:0]         out_rdata_o,
+  output logic                out_err_o,
+  output logic                out_err_plus2_o
 );
 
   localparam int unsigned DEPTH = NUM_REQS+1;
@@ -166,10 +165,7 @@
     end
   end
 
-  // Output both PC of current instruction and instruction following. PC of instruction following is
-  // required for the branch predictor. It's used to fetch the instruction following a branch that
-  // was not-taken but (mis)predicted taken.
-  assign out_addr_next_o = {instr_addr_next, 1'b0};
+  // Output PC of current instruction
   assign out_addr_o      = {instr_addr_q, 1'b0};
 
   // The LSB of the address is unused, since all addresses are halfword aligned
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
index 202c721..f5e6a95 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
@@ -11,7 +11,6 @@
 `include "prim_assert.sv"
 
 module ibex_icache import ibex_pkg::*; #(
-  parameter bit          BranchPredictor = 1'b0,
   parameter bit          ICacheECC       = 1'b0,
   parameter bit          ResetAll        = 1'b0,
   parameter int unsigned BusSizeECC      = BUS_SIZE,
@@ -20,53 +19,51 @@
   // Only cache branch targets
   parameter bit          BranchCache     = 1'b0
 ) (
-    // Clock and reset
-    input  logic                           clk_i,
-    input  logic                           rst_ni,
+  // Clock and reset
+  input  logic                           clk_i,
+  input  logic                           rst_ni,
 
-    // Signal that the core would like instructions
-    input  logic                           req_i,
+  // Signal that the core would like instructions
+  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,
+  // Set the cache's address counter
+  input  logic                           branch_i,
+  input  logic                           branch_mispredict_i,
+  input  logic [31:0]                    mispredict_addr_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,
+  // 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,
 
-    // 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 [BUS_SIZE-1:0]            instr_rdata_i,
-    input  logic                           instr_err_i,
-    input  logic                           instr_pmp_err_i,
-    input  logic                           instr_rvalid_i,
+  // 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 [BUS_SIZE-1:0]            instr_rdata_i,
+  input  logic                           instr_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],
+  // 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  logic                           icache_enable_i,
-    input  logic                           icache_inval_i,
-    output logic                           busy_o
+  // Cache status
+  input  logic                           icache_enable_i,
+  input  logic                           icache_inval_i,
+  output logic                           busy_o
 );
 
   // Number of fill buffers (must be >= 2)
@@ -76,12 +73,10 @@
 
   // 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;
   // Cache pipelipe IC0 signals
-  logic                                   branch_suppress;
   logic                                   lookup_throttle;
   logic                                   lookup_req_ic0;
   logic [ADDR_W-1:0]                      lookup_addr_ic0;
@@ -121,7 +116,6 @@
   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;
@@ -198,41 +192,6 @@
   // Instruction prefetch //
   //////////////////////////
 
-  if (BranchPredictor) begin : g_branch_predictor
-    // Where the branch predictor is present record what address followed a predicted branch.  If
-    // that branch is predicted taken but mispredicted (so not-taken) this is used to resume on
-    // the not-taken code path.
-    logic [31:0] branch_mispredict_addr_q;
-    logic        branch_mispredict_addr_en;
-
-    assign branch_mispredict_addr_en = branch_i & predicted_branch_i;
-
-    if (ResetAll) begin : g_branch_misp_ra
-      always_ff @(posedge clk_i or negedge rst_ni) begin
-        if (!rst_ni) begin
-          branch_mispredict_addr_q <= '0;
-        end else if (branch_mispredict_addr_en) begin
-          branch_mispredict_addr_q <= {output_addr_incr, 1'b0};
-        end
-      end
-    end else begin : g_branch_misp_nr
-      always_ff @(posedge clk_i) begin
-        if (branch_mispredict_addr_en) begin
-          branch_mispredict_addr_q <= {output_addr_incr, 1'b0};
-        end
-      end
-    end
-
-    assign branch_mispredict_addr = branch_mispredict_addr_q;
-
-  end else begin : g_no_branch_predictor
-    logic        unused_predicted_branch;
-
-    assign unused_predicted_branch   = predicted_branch_i;
-
-    assign branch_mispredict_addr = '0;
-  end
-
   assign branch_or_mispredict = branch_i | branch_mispredict_i;
 
   assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}};
@@ -247,7 +206,7 @@
       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;
+                         mispredict_addr_i;
 
   assign prefetch_addr_en    = branch_or_mispredict | lookup_grant_ic0;
 
@@ -276,8 +235,8 @@
 
   assign lookup_req_ic0   = req_i & ~&fill_busy_q & (branch_or_mispredict | ~lookup_throttle) &
                             ~ecc_write_req;
-  assign lookup_addr_ic0  = branch_spec_i       ? addr_i :
-                            branch_mispredict_i ? branch_mispredict_addr :
+  assign lookup_addr_ic0  = branch_i            ? addr_i :
+                            branch_mispredict_i ? mispredict_addr_i :
                                                   prefetch_addr_q;
   assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W];
 
@@ -288,12 +247,9 @@
                            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)
-  assign branch_suppress   = branch_spec_i & ~branch_i;
-
   // Arbitrated signals - lookups have highest priority
-  assign lookup_grant_ic0  = lookup_req_ic0 & ~branch_suppress;
-  assign fill_grant_ic0    = fill_req_ic0 & (~lookup_req_ic0 | branch_suppress) & ~inval_prog_q &
+  assign lookup_grant_ic0  = lookup_req_ic0;
+  assign fill_grant_ic0    = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q &
                              ~ecc_write_req;
   // Qualified lookup grant to mask ram signals in IC1 if access was not made
   assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & ~start_inval;
@@ -322,12 +278,12 @@
     // 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-IC_TAG_SIZE:0] tag_ecc_output_unused;
+    logic [22-IC_TAG_SIZE:0] unused_tag_ecc_output;
 
     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];
+    assign unused_tag_ecc_output = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
 
-    prim_secded_28_22_enc tag_ecc_enc (
+    prim_secded_inv_28_22_enc tag_ecc_enc (
       .data_i (tag_ecc_input_padded),
       .data_o (tag_ecc_output_padded)
     );
@@ -336,7 +292,7 @@
 
     // Dataram ECC
     for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
-      prim_secded_39_32_enc data_ecc_enc (
+      prim_secded_inv_39_32_enc data_ecc_enc (
         .data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
         .data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
       );
@@ -458,7 +414,7 @@
                                      {22-IC_TAG_SIZE{1'b0}},
                                      tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
 
-      prim_secded_28_22_dec data_ecc_dec (
+      prim_secded_inv_28_22_dec data_ecc_dec (
         .data_i     (tag_rdata_padded_ic1),
         .data_o     (),
         .syndrome_o (),
@@ -470,7 +426,7 @@
     // Data ECC checking
     // Note - could generate for all ways and mux after
     for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
-      prim_secded_39_32_dec data_ecc_dec (
+      prim_secded_inv_39_32_dec data_ecc_dec (
         .data_i     (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
         .data_o     (),
         .syndrome_o (),
@@ -590,21 +546,18 @@
     fb_fill_level = '0;
     for (int i = 0; i < NUM_FB; i++) begin
       if (fill_busy_q[i] & ~fill_stale_q[i]) begin
-        fb_fill_level += {{$clog2(NUM_FB)-1{1'b0}},1'b1};
+        fb_fill_level += {{$clog2(NUM_FB) - 1{1'b0}}, 1'b1};
       end
     end
   end
 
-  // PMP errors might not / don't need to be granted (since the external request is masked)
-  assign gnt_or_pmp_err  = instr_gnt_i | instr_pmp_err_i;
-  assign gnt_not_pmp_err = instr_gnt_i & ~instr_pmp_err_i;
   // Allocate a new buffer for every granted lookup
   assign fill_new_alloc = lookup_grant_ic0;
   // Track whether a speculative external request was made from IC0, and whether it was granted
   // Speculative requests are only made for branches, or if the cache is disabled
   assign fill_spec_req  = (~icache_enable_i | branch_or_mispredict) & ~|fill_ext_req;
-  assign fill_spec_done = fill_spec_req & gnt_not_pmp_err;
-  assign fill_spec_hold = fill_spec_req & ~gnt_or_pmp_err;
+  assign fill_spec_done = fill_spec_req & instr_gnt_i;
+  assign fill_spec_hold = fill_spec_req & ~instr_gnt_i;
 
   for (genvar fb = 0; fb < NUM_FB; fb++) begin : gen_fbs
 
@@ -658,20 +611,17 @@
     assign fill_ext_req[fb]    = fill_busy_q[fb] & ~fill_ext_done_d[fb];
 
     // 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] ?
                                    {{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});
+                                                          fill_ext_arb[fb] & instr_gnt_i});
     // 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);
+                                 (fill_ext_arb[fb] & ~instr_gnt_i);
     // 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][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
-                                  fill_err_q[fb][fill_ext_off[fb]] |
                                   // 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
@@ -696,12 +646,10 @@
     // data output, and have data available to send.
     // Data is available if:
     // - The request hit in the cache
-    // - The current beat is an error (since a PMP error might not actually receive any data)
     // - Buffered data is available (fill_rvd_cnt_q is ahead of fill_out_cnt_q)
     // - 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][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.
@@ -859,15 +807,7 @@
 
     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[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[IC_LINE_BEATS_W-1:0])) |
-      //                           Or a data error with instr_rvalid_i
-                                   (fill_rvd_arb[fb] & instr_err_i &
+      assign fill_err_d[fb][b]   = (fill_rvd_arb[fb] & instr_err_i &
                                     (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]);
@@ -971,7 +911,7 @@
   always_comb begin
     line_data_muxed = '0;
     line_err_muxed  = 1'b0;
-    for (int i = 0; i < IC_LINE_BEATS; i++) begin
+    for (int unsigned i = 0; i < IC_LINE_BEATS; i++) begin
       // When data has been skidded, the output address is behind by one
       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
@@ -1047,7 +987,7 @@
 
   // Signal that valid data is available to the IF stage
   // Note that if the first half of an unaligned instruction reports an error, we do not need
-  // to wait for the second half (and for PMP errors we might not have fetched the second half)
+  // to wait for the second half
                         // Compressed instruction completely satisfied by skid buffer
   assign output_valid = skid_complete_instr |
                         // Output data available and, output stream aligned, or skid data available,
@@ -1068,7 +1008,7 @@
 
   // Redirect the address on branches or mispredicts
   assign output_addr_d = branch_i            ? addr_i[31:1] :
-                         branch_mispredict_i ? branch_mispredict_addr[31:1] :
+                         branch_mispredict_i ? mispredict_addr_i[31:1] :
                                                output_addr_incr;
 
   if (ResetAll) begin : g_output_addr_ra
@@ -1094,7 +1034,7 @@
   //        31   15   0     31   15   0
   always_comb begin
     output_data_lo = '0;
-    for (int i = 0; i < IC_OUTPUT_BEATS; i++) begin
+    for (int unsigned 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
@@ -1103,7 +1043,7 @@
 
   always_comb begin
     output_data_hi = '0;
-    for (int i = 0; i < IC_OUTPUT_BEATS-1; i++) begin
+    for (int unsigned 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
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index 7107ee6..2e79573 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -18,170 +18,169 @@
 `include "dv_fcov_macros.svh"
 
 module ibex_id_stage #(
-    parameter bit               RV32E           = 0,
-    parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
-    parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
-    parameter bit               DataIndTiming   = 1'b0,
-    parameter bit               BranchTargetALU = 0,
-    parameter bit               SpecBranch      = 0,
-    parameter bit               WritebackStage  = 0,
-    parameter bit               BranchPredictor = 0
+  parameter bit               RV32E           = 0,
+  parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
+  parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
+  parameter bit               DataIndTiming   = 1'b0,
+  parameter bit               BranchTargetALU = 0,
+  parameter bit               WritebackStage  = 0,
+  parameter bit               BranchPredictor = 0
 ) (
-    input  logic                      clk_i,
-    input  logic                      rst_ni,
+  input  logic                      clk_i,
+  input  logic                      rst_ni,
 
-    output logic                      ctrl_busy_o,
-    output logic                      illegal_insn_o,
+  output logic                      ctrl_busy_o,
+  output logic                      illegal_insn_o,
 
-    // Interface to IF stage
-    input  logic                      instr_valid_i,
-    input  logic [31:0]               instr_rdata_i,         // from IF-ID pipeline registers
-    input  logic [31:0]               instr_rdata_alu_i,     // from IF-ID pipeline registers
-    input  logic [15:0]               instr_rdata_c_i,       // from IF-ID pipeline registers
-    input  logic                      instr_is_compressed_i,
-    input  logic                      instr_bp_taken_i,
-    output logic                      instr_req_o,
-    output logic                      instr_first_cycle_id_o,
-    output logic                      instr_valid_clear_o,   // kill instr in IF-ID reg
-    output logic                      id_in_ready_o,         // ID stage is ready for next instr
-    output logic                      icache_inval_o,
+  // Interface to IF stage
+  input  logic                      instr_valid_i,
+  input  logic [31:0]               instr_rdata_i,         // from IF-ID pipeline registers
+  input  logic [31:0]               instr_rdata_alu_i,     // from IF-ID pipeline registers
+  input  logic [15:0]               instr_rdata_c_i,       // from IF-ID pipeline registers
+  input  logic                      instr_is_compressed_i,
+  input  logic                      instr_bp_taken_i,
+  output logic                      instr_req_o,
+  output logic                      instr_first_cycle_id_o,
+  output logic                      instr_valid_clear_o,   // kill instr in IF-ID reg
+  output logic                      id_in_ready_o,         // ID stage is ready for next instr
+  output logic                      icache_inval_o,
 
-    // Jumps and branches
-    input  logic                      branch_decision_i,
+  // Jumps and branches
+  input  logic                      branch_decision_i,
 
-    // IF and ID stage signals
-    output logic                      pc_set_o,
-    output logic                      pc_set_spec_o,
-    output ibex_pkg::pc_sel_e         pc_mux_o,
-    output logic                      nt_branch_mispredict_o,
-    output ibex_pkg::exc_pc_sel_e     exc_pc_mux_o,
-    output ibex_pkg::exc_cause_e      exc_cause_o,
+  // IF and ID stage signals
+  output logic                      pc_set_o,
+  output ibex_pkg::pc_sel_e         pc_mux_o,
+  output logic                      nt_branch_mispredict_o,
+  output logic [31:0]               nt_branch_addr_o,
+  output ibex_pkg::exc_pc_sel_e     exc_pc_mux_o,
+  output ibex_pkg::exc_cause_e      exc_cause_o,
 
-    input  logic                      illegal_c_insn_i,
-    input  logic                      instr_fetch_err_i,
-    input  logic                      instr_fetch_err_plus2_i,
+  input  logic                      illegal_c_insn_i,
+  input  logic                      instr_fetch_err_i,
+  input  logic                      instr_fetch_err_plus2_i,
 
-    input  logic [31:0]               pc_id_i,
+  input  logic [31:0]               pc_id_i,
 
-    // Stalls
-    input  logic                      ex_valid_i,       // EX stage has valid output
-    input  logic                      lsu_resp_valid_i, // LSU has valid output, or is done
-    // ALU
-    output ibex_pkg::alu_op_e         alu_operator_ex_o,
-    output logic [31:0]               alu_operand_a_ex_o,
-    output logic [31:0]               alu_operand_b_ex_o,
+  // Stalls
+  input  logic                      ex_valid_i,       // EX stage has valid output
+  input  logic                      lsu_resp_valid_i, // LSU has valid output, or is done
+  // ALU
+  output ibex_pkg::alu_op_e         alu_operator_ex_o,
+  output logic [31:0]               alu_operand_a_ex_o,
+  output logic [31:0]               alu_operand_b_ex_o,
 
-    // Multicycle Operation Stage Register
-    input  logic [1:0]                imd_val_we_ex_i,
-    input  logic [33:0]               imd_val_d_ex_i[2],
-    output logic [33:0]               imd_val_q_ex_o[2],
+  // Multicycle Operation Stage Register
+  input  logic [1:0]                imd_val_we_ex_i,
+  input  logic [33:0]               imd_val_d_ex_i[2],
+  output logic [33:0]               imd_val_q_ex_o[2],
 
-    // Branch target ALU
-    output logic [31:0]               bt_a_operand_o,
-    output logic [31:0]               bt_b_operand_o,
+  // Branch target ALU
+  output logic [31:0]               bt_a_operand_o,
+  output logic [31:0]               bt_b_operand_o,
 
-    // MUL, DIV
-    output logic                      mult_en_ex_o,
-    output logic                      div_en_ex_o,
-    output logic                      mult_sel_ex_o,
-    output logic                      div_sel_ex_o,
-    output ibex_pkg::md_op_e          multdiv_operator_ex_o,
-    output logic  [1:0]               multdiv_signed_mode_ex_o,
-    output logic [31:0]               multdiv_operand_a_ex_o,
-    output logic [31:0]               multdiv_operand_b_ex_o,
-    output logic                      multdiv_ready_id_o,
+  // MUL, DIV
+  output logic                      mult_en_ex_o,
+  output logic                      div_en_ex_o,
+  output logic                      mult_sel_ex_o,
+  output logic                      div_sel_ex_o,
+  output ibex_pkg::md_op_e          multdiv_operator_ex_o,
+  output logic  [1:0]               multdiv_signed_mode_ex_o,
+  output logic [31:0]               multdiv_operand_a_ex_o,
+  output logic [31:0]               multdiv_operand_b_ex_o,
+  output logic                      multdiv_ready_id_o,
 
-    // CSR
-    output logic                      csr_access_o,
-    output ibex_pkg::csr_op_e         csr_op_o,
-    output logic                      csr_op_en_o,
-    output logic                      csr_save_if_o,
-    output logic                      csr_save_id_o,
-    output logic                      csr_save_wb_o,
-    output logic                      csr_restore_mret_id_o,
-    output logic                      csr_restore_dret_id_o,
-    output logic                      csr_save_cause_o,
-    output logic [31:0]               csr_mtval_o,
-    input  ibex_pkg::priv_lvl_e       priv_mode_i,
-    input  logic                      csr_mstatus_tw_i,
-    input  logic                      illegal_csr_insn_i,
-    input  logic                      data_ind_timing_i,
+  // CSR
+  output logic                      csr_access_o,
+  output ibex_pkg::csr_op_e         csr_op_o,
+  output logic                      csr_op_en_o,
+  output logic                      csr_save_if_o,
+  output logic                      csr_save_id_o,
+  output logic                      csr_save_wb_o,
+  output logic                      csr_restore_mret_id_o,
+  output logic                      csr_restore_dret_id_o,
+  output logic                      csr_save_cause_o,
+  output logic [31:0]               csr_mtval_o,
+  input  ibex_pkg::priv_lvl_e       priv_mode_i,
+  input  logic                      csr_mstatus_tw_i,
+  input  logic                      illegal_csr_insn_i,
+  input  logic                      data_ind_timing_i,
 
-    // Interface to load store unit
-    output logic                      lsu_req_o,
-    output logic                      lsu_we_o,
-    output logic [1:0]                lsu_type_o,
-    output logic                      lsu_sign_ext_o,
-    output logic [31:0]               lsu_wdata_o,
+  // Interface to load store unit
+  output logic                      lsu_req_o,
+  output logic                      lsu_we_o,
+  output logic [1:0]                lsu_type_o,
+  output logic                      lsu_sign_ext_o,
+  output logic [31:0]               lsu_wdata_o,
 
-    input  logic                      lsu_req_done_i, // Data req to LSU is complete and
-                                                      // instruction can move to writeback
-                                                      // (only relevant where writeback stage is
-                                                      // present)
+  input  logic                      lsu_req_done_i, // Data req to LSU is complete and
+                                                    // instruction can move to writeback
+                                                    // (only relevant where writeback stage is
+                                                    // present)
 
-    input  logic                      lsu_addr_incr_req_i,
-    input  logic [31:0]               lsu_addr_last_i,
+  input  logic                      lsu_addr_incr_req_i,
+  input  logic [31:0]               lsu_addr_last_i,
 
-    // Interrupt signals
-    input  logic                      csr_mstatus_mie_i,
-    input  logic                      irq_pending_i,
-    input  ibex_pkg::irqs_t           irqs_i,
-    input  logic                      irq_nm_i,
-    output logic                      nmi_mode_o,
+  // Interrupt signals
+  input  logic                      csr_mstatus_mie_i,
+  input  logic                      irq_pending_i,
+  input  ibex_pkg::irqs_t           irqs_i,
+  input  logic                      irq_nm_i,
+  output logic                      nmi_mode_o,
 
-    input  logic                      lsu_load_err_i,
-    input  logic                      lsu_store_err_i,
+  input  logic                      lsu_load_err_i,
+  input  logic                      lsu_store_err_i,
 
-    // Debug Signal
-    output logic                      debug_mode_o,
-    output ibex_pkg::dbg_cause_e      debug_cause_o,
-    output logic                      debug_csr_save_o,
-    input  logic                      debug_req_i,
-    input  logic                      debug_single_step_i,
-    input  logic                      debug_ebreakm_i,
-    input  logic                      debug_ebreaku_i,
-    input  logic                      trigger_match_i,
+  // Debug Signal
+  output logic                      debug_mode_o,
+  output ibex_pkg::dbg_cause_e      debug_cause_o,
+  output logic                      debug_csr_save_o,
+  input  logic                      debug_req_i,
+  input  logic                      debug_single_step_i,
+  input  logic                      debug_ebreakm_i,
+  input  logic                      debug_ebreaku_i,
+  input  logic                      trigger_match_i,
 
-    // Write back signal
-    input  logic [31:0]               result_ex_i,
-    input  logic [31:0]               csr_rdata_i,
+  // Write back signal
+  input  logic [31:0]               result_ex_i,
+  input  logic [31:0]               csr_rdata_i,
 
-    // Register file read
-    output logic [4:0]                rf_raddr_a_o,
-    input  logic [31:0]               rf_rdata_a_i,
-    output logic [4:0]                rf_raddr_b_o,
-    input  logic [31:0]               rf_rdata_b_i,
-    output logic                      rf_ren_a_o,
-    output logic                      rf_ren_b_o,
+  // Register file read
+  output logic [4:0]                rf_raddr_a_o,
+  input  logic [31:0]               rf_rdata_a_i,
+  output logic [4:0]                rf_raddr_b_o,
+  input  logic [31:0]               rf_rdata_b_i,
+  output logic                      rf_ren_a_o,
+  output logic                      rf_ren_b_o,
 
-    // Register file write (via writeback)
-    output logic [4:0]                rf_waddr_id_o,
-    output logic [31:0]               rf_wdata_id_o,
-    output logic                      rf_we_id_o,
-    output logic                      rf_rd_a_wb_match_o,
-    output logic                      rf_rd_b_wb_match_o,
+  // Register file write (via writeback)
+  output logic [4:0]                rf_waddr_id_o,
+  output logic [31:0]               rf_wdata_id_o,
+  output logic                      rf_we_id_o,
+  output logic                      rf_rd_a_wb_match_o,
+  output logic                      rf_rd_b_wb_match_o,
 
-    // Register write information from writeback (for resolving data hazards)
-    input  logic [4:0]                rf_waddr_wb_i,
-    input  logic [31:0]               rf_wdata_fwd_wb_i,
-    input  logic                      rf_write_wb_i,
+  // Register write information from writeback (for resolving data hazards)
+  input  logic [4:0]                rf_waddr_wb_i,
+  input  logic [31:0]               rf_wdata_fwd_wb_i,
+  input  logic                      rf_write_wb_i,
 
-    output  logic                     en_wb_o,
-    output  ibex_pkg::wb_instr_type_e instr_type_wb_o,
-    output  logic                     instr_perf_count_id_o,
-    input logic                       ready_wb_i,
-    input logic                       outstanding_load_wb_i,
-    input logic                       outstanding_store_wb_i,
+  output  logic                     en_wb_o,
+  output  ibex_pkg::wb_instr_type_e instr_type_wb_o,
+  output  logic                     instr_perf_count_id_o,
+  input logic                       ready_wb_i,
+  input logic                       outstanding_load_wb_i,
+  input logic                       outstanding_store_wb_i,
 
-    // Performance Counters
-    output logic                      perf_jump_o,    // executing a jump instr
-    output logic                      perf_branch_o,  // executing a branch instr
-    output logic                      perf_tbranch_o, // executing a taken branch instr
-    output logic                      perf_dside_wait_o, // instruction in ID/EX is awaiting memory
-                                                         // access to finish before proceeding
-    output logic                      perf_mul_wait_o,
-    output logic                      perf_div_wait_o,
-    output logic                      instr_id_done_o
+  // Performance Counters
+  output logic                      perf_jump_o,    // executing a jump instr
+  output logic                      perf_branch_o,  // executing a branch instr
+  output logic                      perf_tbranch_o, // executing a taken branch instr
+  output logic                      perf_dside_wait_o, // instruction in ID/EX is awaiting memory
+                                                        // access to finish before proceeding
+  output logic                      perf_mul_wait_o,
+  output logic                      perf_div_wait_o,
+  output logic                      instr_id_done_o
 );
 
   import ibex_pkg::*;
@@ -195,9 +194,9 @@
   logic        wfi_insn_dec;
 
   logic        wb_exception;
+  logic        id_exception;
 
   logic        branch_in_dec;
-  logic        branch_spec, branch_set_spec, branch_set_raw_spec;
   logic        branch_set, branch_set_raw, branch_set_raw_d;
   logic        branch_jump_set_done_q, branch_jump_set_done_d;
   logic        branch_not_set;
@@ -388,7 +387,7 @@
   // Multicycle Operation Stage Register //
   /////////////////////////////////////////
 
-  for (genvar i=0; i<2; i++) begin : gen_intermediate_val_reg
+  for (genvar i = 0; i < 2; i++) begin : gen_intermediate_val_reg
     always_ff @(posedge clk_i or negedge rst_ni) begin : intermediate_val_reg
       if (!rst_ni) begin
         imd_val_q[i] <= '0;
@@ -421,81 +420,81 @@
   /////////////
 
   ibex_decoder #(
-      .RV32E           ( RV32E           ),
-      .RV32M           ( RV32M           ),
-      .RV32B           ( RV32B           ),
-      .BranchTargetALU ( BranchTargetALU )
+    .RV32E          (RV32E),
+    .RV32M          (RV32M),
+    .RV32B          (RV32B),
+    .BranchTargetALU(BranchTargetALU)
   ) decoder_i (
-      .clk_i                           ( clk_i                ),
-      .rst_ni                          ( rst_ni               ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      // controller
-      .illegal_insn_o                  ( illegal_insn_dec     ),
-      .ebrk_insn_o                     ( ebrk_insn            ),
-      .mret_insn_o                     ( mret_insn_dec        ),
-      .dret_insn_o                     ( dret_insn_dec        ),
-      .ecall_insn_o                    ( ecall_insn_dec       ),
-      .wfi_insn_o                      ( wfi_insn_dec         ),
-      .jump_set_o                      ( jump_set_dec         ),
-      .branch_taken_i                  ( branch_taken         ),
-      .icache_inval_o                  ( icache_inval_o       ),
+    // controller
+    .illegal_insn_o(illegal_insn_dec),
+    .ebrk_insn_o   (ebrk_insn),
+    .mret_insn_o   (mret_insn_dec),
+    .dret_insn_o   (dret_insn_dec),
+    .ecall_insn_o  (ecall_insn_dec),
+    .wfi_insn_o    (wfi_insn_dec),
+    .jump_set_o    (jump_set_dec),
+    .branch_taken_i(branch_taken),
+    .icache_inval_o(icache_inval_o),
 
-      // from IF-ID pipeline register
-      .instr_first_cycle_i             ( instr_first_cycle    ),
-      .instr_rdata_i                   ( instr_rdata_i        ),
-      .instr_rdata_alu_i               ( instr_rdata_alu_i    ),
-      .illegal_c_insn_i                ( illegal_c_insn_i     ),
+    // from IF-ID pipeline register
+    .instr_first_cycle_i(instr_first_cycle),
+    .instr_rdata_i      (instr_rdata_i),
+    .instr_rdata_alu_i  (instr_rdata_alu_i),
+    .illegal_c_insn_i   (illegal_c_insn_i),
 
-      // immediates
-      .imm_a_mux_sel_o                 ( imm_a_mux_sel        ),
-      .imm_b_mux_sel_o                 ( imm_b_mux_sel_dec    ),
-      .bt_a_mux_sel_o                  ( bt_a_mux_sel         ),
-      .bt_b_mux_sel_o                  ( bt_b_mux_sel         ),
+    // immediates
+    .imm_a_mux_sel_o(imm_a_mux_sel),
+    .imm_b_mux_sel_o(imm_b_mux_sel_dec),
+    .bt_a_mux_sel_o (bt_a_mux_sel),
+    .bt_b_mux_sel_o (bt_b_mux_sel),
 
-      .imm_i_type_o                    ( imm_i_type           ),
-      .imm_s_type_o                    ( imm_s_type           ),
-      .imm_b_type_o                    ( imm_b_type           ),
-      .imm_u_type_o                    ( imm_u_type           ),
-      .imm_j_type_o                    ( imm_j_type           ),
-      .zimm_rs1_type_o                 ( zimm_rs1_type        ),
+    .imm_i_type_o   (imm_i_type),
+    .imm_s_type_o   (imm_s_type),
+    .imm_b_type_o   (imm_b_type),
+    .imm_u_type_o   (imm_u_type),
+    .imm_j_type_o   (imm_j_type),
+    .zimm_rs1_type_o(zimm_rs1_type),
 
-      // register file
-      .rf_wdata_sel_o                  ( rf_wdata_sel         ),
-      .rf_we_o                         ( rf_we_dec            ),
+    // register file
+    .rf_wdata_sel_o(rf_wdata_sel),
+    .rf_we_o       (rf_we_dec),
 
-      .rf_raddr_a_o                    ( rf_raddr_a_o         ),
-      .rf_raddr_b_o                    ( rf_raddr_b_o         ),
-      .rf_waddr_o                      ( rf_waddr_id_o        ),
-      .rf_ren_a_o                      ( rf_ren_a_dec         ),
-      .rf_ren_b_o                      ( rf_ren_b_dec         ),
+    .rf_raddr_a_o(rf_raddr_a_o),
+    .rf_raddr_b_o(rf_raddr_b_o),
+    .rf_waddr_o  (rf_waddr_id_o),
+    .rf_ren_a_o  (rf_ren_a_dec),
+    .rf_ren_b_o  (rf_ren_b_dec),
 
-      // ALU
-      .alu_operator_o                  ( alu_operator         ),
-      .alu_op_a_mux_sel_o              ( alu_op_a_mux_sel_dec ),
-      .alu_op_b_mux_sel_o              ( alu_op_b_mux_sel_dec ),
-      .alu_multicycle_o                ( alu_multicycle_dec   ),
+    // ALU
+    .alu_operator_o    (alu_operator),
+    .alu_op_a_mux_sel_o(alu_op_a_mux_sel_dec),
+    .alu_op_b_mux_sel_o(alu_op_b_mux_sel_dec),
+    .alu_multicycle_o  (alu_multicycle_dec),
 
-      // MULT & DIV
-      .mult_en_o                       ( mult_en_dec          ),
-      .div_en_o                        ( div_en_dec           ),
-      .mult_sel_o                      ( mult_sel_ex_o        ),
-      .div_sel_o                       ( div_sel_ex_o         ),
-      .multdiv_operator_o              ( multdiv_operator     ),
-      .multdiv_signed_mode_o           ( multdiv_signed_mode  ),
+    // MULT & DIV
+    .mult_en_o            (mult_en_dec),
+    .div_en_o             (div_en_dec),
+    .mult_sel_o           (mult_sel_ex_o),
+    .div_sel_o            (div_sel_ex_o),
+    .multdiv_operator_o   (multdiv_operator),
+    .multdiv_signed_mode_o(multdiv_signed_mode),
 
-      // CSRs
-      .csr_access_o                    ( csr_access_o         ),
-      .csr_op_o                        ( csr_op_o             ),
+    // CSRs
+    .csr_access_o(csr_access_o),
+    .csr_op_o    (csr_op_o),
 
-      // LSU
-      .data_req_o                      ( lsu_req_dec          ),
-      .data_we_o                       ( lsu_we               ),
-      .data_type_o                     ( lsu_type             ),
-      .data_sign_extension_o           ( lsu_sign_ext         ),
+    // LSU
+    .data_req_o           (lsu_req_dec),
+    .data_we_o            (lsu_we),
+    .data_type_o          (lsu_type),
+    .data_sign_extension_o(lsu_sign_ext),
 
-      // jump/branches
-      .jump_in_dec_o                   ( jump_in_dec          ),
-      .branch_in_dec_o                 ( branch_in_dec        )
+    // jump/branches
+    .jump_in_dec_o  (jump_in_dec),
+    .branch_in_dec_o(branch_in_dec)
   );
 
   /////////////////////////////////
@@ -531,95 +530,94 @@
   assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i);
 
   ibex_controller #(
-    .WritebackStage  ( WritebackStage  ),
-    .BranchPredictor ( BranchPredictor )
+    .WritebackStage (WritebackStage),
+    .BranchPredictor(BranchPredictor)
   ) controller_i (
-      .clk_i                          ( clk_i                   ),
-      .rst_ni                         ( rst_ni                  ),
+    .clk_i (clk_i),
+    .rst_ni(rst_ni),
 
-      .ctrl_busy_o                    ( ctrl_busy_o             ),
+    .ctrl_busy_o(ctrl_busy_o),
 
-      // decoder related signals
-      .illegal_insn_i                 ( illegal_insn_o          ),
-      .ecall_insn_i                   ( ecall_insn_dec          ),
-      .mret_insn_i                    ( mret_insn_dec           ),
-      .dret_insn_i                    ( dret_insn_dec           ),
-      .wfi_insn_i                     ( wfi_insn_dec            ),
-      .ebrk_insn_i                    ( ebrk_insn               ),
-      .csr_pipe_flush_i               ( csr_pipe_flush          ),
+    // decoder related signals
+    .illegal_insn_i  (illegal_insn_o),
+    .ecall_insn_i    (ecall_insn_dec),
+    .mret_insn_i     (mret_insn_dec),
+    .dret_insn_i     (dret_insn_dec),
+    .wfi_insn_i      (wfi_insn_dec),
+    .ebrk_insn_i     (ebrk_insn),
+    .csr_pipe_flush_i(csr_pipe_flush),
 
-      // from IF-ID pipeline
-      .instr_valid_i                  ( instr_valid_i           ),
-      .instr_i                        ( instr_rdata_i           ),
-      .instr_compressed_i             ( instr_rdata_c_i         ),
-      .instr_is_compressed_i          ( instr_is_compressed_i   ),
-      .instr_bp_taken_i               ( instr_bp_taken_i        ),
-      .instr_fetch_err_i              ( instr_fetch_err_i       ),
-      .instr_fetch_err_plus2_i        ( instr_fetch_err_plus2_i ),
-      .pc_id_i                        ( pc_id_i                 ),
+    // from IF-ID pipeline
+    .instr_valid_i          (instr_valid_i),
+    .instr_i                (instr_rdata_i),
+    .instr_compressed_i     (instr_rdata_c_i),
+    .instr_is_compressed_i  (instr_is_compressed_i),
+    .instr_bp_taken_i       (instr_bp_taken_i),
+    .instr_fetch_err_i      (instr_fetch_err_i),
+    .instr_fetch_err_plus2_i(instr_fetch_err_plus2_i),
+    .pc_id_i                (pc_id_i),
 
-      // to IF-ID pipeline
-      .instr_valid_clear_o            ( instr_valid_clear_o     ),
-      .id_in_ready_o                  ( id_in_ready_o           ),
-      .controller_run_o               ( controller_run          ),
+    // to IF-ID pipeline
+    .instr_valid_clear_o(instr_valid_clear_o),
+    .id_in_ready_o      (id_in_ready_o),
+    .controller_run_o   (controller_run),
 
-      // to prefetcher
-      .instr_req_o                    ( instr_req_o             ),
-      .pc_set_o                       ( pc_set_o                ),
-      .pc_set_spec_o                  ( pc_set_spec_o           ),
-      .pc_mux_o                       ( pc_mux_o                ),
-      .nt_branch_mispredict_o         ( nt_branch_mispredict_o  ),
-      .exc_pc_mux_o                   ( exc_pc_mux_o            ),
-      .exc_cause_o                    ( exc_cause_o             ),
+    // to prefetcher
+    .instr_req_o           (instr_req_o),
+    .pc_set_o              (pc_set_o),
+    .pc_mux_o              (pc_mux_o),
+    .nt_branch_mispredict_o(nt_branch_mispredict_o),
+    .exc_pc_mux_o          (exc_pc_mux_o),
+    .exc_cause_o           (exc_cause_o),
 
-      // LSU
-      .lsu_addr_last_i                ( lsu_addr_last_i         ),
-      .load_err_i                     ( lsu_load_err_i          ),
-      .store_err_i                    ( lsu_store_err_i         ),
-      .wb_exception_o                 ( wb_exception            ),
+    // LSU
+    .lsu_addr_last_i(lsu_addr_last_i),
+    .load_err_i     (lsu_load_err_i),
+    .store_err_i    (lsu_store_err_i),
+    .wb_exception_o (wb_exception),
+    .id_exception_o (id_exception),
 
-      // jump/branch control
-      .branch_set_i                   ( branch_set              ),
-      .branch_set_spec_i              ( branch_set_spec         ),
-      .branch_not_set_i               ( branch_not_set          ),
-      .jump_set_i                     ( jump_set                ),
+    // jump/branch control
+    .branch_set_i     (branch_set),
+    .branch_not_set_i (branch_not_set),
+    .jump_set_i       (jump_set),
 
-      // interrupt signals
-      .csr_mstatus_mie_i              ( csr_mstatus_mie_i       ),
-      .irq_pending_i                  ( irq_pending_i           ),
-      .irqs_i                         ( irqs_i                  ),
-      .irq_nm_i                       ( irq_nm_i                ),
-      .nmi_mode_o                     ( nmi_mode_o              ),
+    // interrupt signals
+    .csr_mstatus_mie_i(csr_mstatus_mie_i),
+    .irq_pending_i    (irq_pending_i),
+    .irqs_i           (irqs_i),
+    .irq_nm_i         (irq_nm_i),
+    .nmi_mode_o       (nmi_mode_o),
 
-      // CSR Controller Signals
-      .csr_save_if_o                  ( csr_save_if_o           ),
-      .csr_save_id_o                  ( csr_save_id_o           ),
-      .csr_save_wb_o                  ( csr_save_wb_o           ),
-      .csr_restore_mret_id_o          ( csr_restore_mret_id_o   ),
-      .csr_restore_dret_id_o          ( csr_restore_dret_id_o   ),
-      .csr_save_cause_o               ( csr_save_cause_o        ),
-      .csr_mtval_o                    ( csr_mtval_o             ),
-      .priv_mode_i                    ( priv_mode_i             ),
-      .csr_mstatus_tw_i               ( csr_mstatus_tw_i        ),
+    // CSR Controller Signals
+    .csr_save_if_o        (csr_save_if_o),
+    .csr_save_id_o        (csr_save_id_o),
+    .csr_save_wb_o        (csr_save_wb_o),
+    .csr_restore_mret_id_o(csr_restore_mret_id_o),
+    .csr_restore_dret_id_o(csr_restore_dret_id_o),
+    .csr_save_cause_o     (csr_save_cause_o),
+    .csr_mtval_o          (csr_mtval_o),
+    .priv_mode_i          (priv_mode_i),
+    .csr_mstatus_tw_i     (csr_mstatus_tw_i),
 
-      // Debug Signal
-      .debug_mode_o                   ( debug_mode_o            ),
-      .debug_cause_o                  ( debug_cause_o           ),
-      .debug_csr_save_o               ( debug_csr_save_o        ),
-      .debug_req_i                    ( debug_req_i             ),
-      .debug_single_step_i            ( debug_single_step_i     ),
-      .debug_ebreakm_i                ( debug_ebreakm_i         ),
-      .debug_ebreaku_i                ( debug_ebreaku_i         ),
-      .trigger_match_i                ( trigger_match_i         ),
+    // Debug Signal
+    .debug_mode_o       (debug_mode_o),
+    .debug_cause_o      (debug_cause_o),
+    .debug_csr_save_o   (debug_csr_save_o),
+    .debug_req_i        (debug_req_i),
+    .debug_single_step_i(debug_single_step_i),
+    .debug_ebreakm_i    (debug_ebreakm_i),
+    .debug_ebreaku_i    (debug_ebreaku_i),
+    .trigger_match_i    (trigger_match_i),
 
-      .stall_id_i                     ( stall_id                ),
-      .stall_wb_i                     ( stall_wb                ),
-      .flush_id_o                     ( flush_id                ),
-      .ready_wb_i                     ( ready_wb_i              ),
+    .stall_id_i(stall_id),
+    .stall_wb_i(stall_wb),
+    .flush_id_o(flush_id),
+    .ready_wb_i(ready_wb_i),
 
-      // Performance Counters
-      .perf_jump_o                    ( perf_jump_o             ),
-      .perf_tbranch_o                 ( perf_tbranch_o          )
+    // Performance Counters
+    .perf_jump_o   (perf_jump_o),
+    .perf_tbranch_o(perf_tbranch_o)
   );
 
   assign multdiv_en_dec   = mult_en_dec | div_en_dec;
@@ -659,7 +657,6 @@
     // Branch set fed straight to controller with branch target ALU
     // (condition pass/fail used same cycle as generated instruction request)
     assign branch_set_raw      = branch_set_raw_d;
-    assign branch_set_raw_spec = branch_spec;
   end else begin : g_branch_set_flop
     // Branch set flopped without branch target ALU, or in fixed time execution mode
     // (condition pass/fail used next cycle where branch target is calculated)
@@ -679,9 +676,6 @@
     assign branch_set_raw      = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d :
                                                                            branch_set_raw_q;
 
-    // Use the speculative branch signal when BTALU is enabled
-    assign branch_set_raw_spec = (BranchTargetALU && !data_ind_timing_i) ? branch_spec :
-                                                                           branch_set_raw_q;
   end
 
   // Track whether the current instruction in ID/EX has done a branch or jump set.
@@ -705,7 +699,6 @@
   // needless extra IF flushes and fetches.
   assign jump_set        = jump_set_raw        & ~branch_jump_set_done_q;
   assign branch_set      = branch_set_raw      & ~branch_jump_set_done_q;
-  assign branch_set_spec = branch_set_raw_spec & ~branch_jump_set_done_q;
 
   // Branch condition is calculated in the first cycle and flopped for use in the second cycle
   // (only used in fixed time execution mode to determine branch destination).
@@ -736,6 +729,16 @@
   `ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set)
   `ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set)
 
+  //////////////////////////////
+  // Branch not-taken address //
+  //////////////////////////////
+
+  if (BranchPredictor) begin : g_calc_nt_addr
+    assign nt_branch_addr_o = pc_id_i + (instr_is_compressed_i ? 32'd2 : 32'd4);
+  end else begin : g_n_calc_nt_addr
+    assign nt_branch_addr_o = 32'd0;
+  end
+
   ///////////////
   // ID-EX FSM //
   ///////////////
@@ -764,7 +767,6 @@
     stall_branch            = 1'b0;
     stall_alu               = 1'b0;
     branch_set_raw_d        = 1'b0;
-    branch_spec             = 1'b0;
     branch_not_set          = 1'b0;
     jump_set_raw            = 1'b0;
     perf_branch_o           = 1'b0;
@@ -806,8 +808,6 @@
                 branch_not_set = ~branch_decision_i;
               end
 
-              // Speculative branch (excludes branch_decision_i)
-              branch_spec   = SpecBranch ? 1'b1 : branch_decision_i;
               perf_branch_o = 1'b1;
             end
             jump_in_dec: begin
@@ -906,6 +906,7 @@
     // - There was an error on instruction fetch
     assign instr_kill = instr_fetch_err_i |
                         wb_exception      |
+                        id_exception      |
                         ~controller_run;
 
     // With writeback stage instructions must be prevented from executing if there is:
@@ -1023,6 +1024,7 @@
     logic unused_outstanding_store_wb;
     logic unused_wb_exception;
     logic [31:0] unused_rf_wdata_fwd_wb;
+    logic unused_id_exception;
 
     assign unused_data_req_done_ex     = lsu_req_done_i;
     assign unused_rf_waddr_wb          = rf_waddr_wb_i;
@@ -1031,6 +1033,7 @@
     assign unused_outstanding_store_wb = outstanding_store_wb_i;
     assign unused_wb_exception         = wb_exception;
     assign unused_rf_wdata_fwd_wb      = rf_wdata_fwd_wb_i;
+    assign unused_id_exception         = id_exception;
 
     assign instr_type_wb_o = WB_INSTR_OTHER;
     assign stall_wb        = 1'b0;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index abd09af..7f9f4d8 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -13,102 +13,103 @@
 `include "prim_assert.sv"
 
 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          ResetAll          = 1'b0,
-    parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
-    parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
-    parameter bit          BranchPredictor   = 1'b0
+  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          ResetAll          = 1'b0,
+  parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
+  parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
+  parameter bit          BranchPredictor   = 1'b0
 ) (
-    input  logic                         clk_i,
-    input  logic                         rst_ni,
+  input  logic                         clk_i,
+  input  logic                         rst_ni,
 
-    input  logic [31:0]                  boot_addr_i,              // also used for mtvec
-    input  logic                         req_i,                    // instruction request control
+  input  logic [31:0]                  boot_addr_i,              // also used for mtvec
+  input  logic                         req_i,                    // instruction request control
 
-    // instruction cache interface
-    output logic                        instr_req_o,
-    output logic [31:0]                 instr_addr_o,
-    input  logic                        instr_gnt_i,
-    input  logic                        instr_rvalid_i,
-    input  logic [31:0]                 instr_rdata_i,
-    input  logic                        instr_err_i,
-    input  logic                        instr_pmp_err_i,
+  // instruction cache interface
+  output logic                        instr_req_o,
+  output logic [31:0]                 instr_addr_o,
+  input  logic                        instr_gnt_i,
+  input  logic                        instr_rvalid_i,
+  input  logic [31:0]                 instr_rdata_i,
+  input  logic                        instr_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],
+  // 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
-    output logic [31:0]                 instr_rdata_id_o,         // instr for ID stage
-    output logic [31:0]                 instr_rdata_alu_id_o,     // replicated instr for ID stage
-                                                                  // 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
-    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
-                                                                  // a taken branch
-    output logic                        instr_fetch_err_o,        // bus error on fetch
-    output logic                        instr_fetch_err_plus2_o,  // bus error misaligned
-    output logic                        illegal_c_insn_id_o,      // compressed decoder thinks this
-                                                                  // is an invalid instr
-    output logic                        dummy_instr_id_o,         // Instruction is a dummy
-    output logic [31:0]                 pc_if_o,
-    output logic [31:0]                 pc_id_o,
+  // 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
+  output logic [31:0]                 instr_rdata_id_o,         // instr for ID stage
+  output logic [31:0]                 instr_rdata_alu_id_o,     // replicated instr for ID stage
+                                                                // 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
+  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
+                                                                // a taken branch
+  output logic                        instr_fetch_err_o,        // bus error on fetch
+  output logic                        instr_fetch_err_plus2_o,  // bus error misaligned
+  output logic                        illegal_c_insn_id_o,      // compressed decoder thinks this
+                                                                // is an invalid instr
+  output logic                        dummy_instr_id_o,         // Instruction is a dummy
+  output logic [31:0]                 pc_if_o,
+  output logic [31:0]                 pc_id_o,
+  input  logic                        pmp_err_if_i,
+  input  logic                        pmp_err_if_plus2_i,
 
-    // control signals
-    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  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  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,
-    input logic                         dummy_instr_seed_en_i,
-    input logic [31:0]                  dummy_instr_seed_i,
-    input logic                         icache_enable_i,
-    input logic                         icache_inval_i,
+  // control signals
+  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  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  logic [31:0]                 nt_branch_addr_i,         // Not-taken branch address in ID/EX
+  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,
+  input logic                         dummy_instr_seed_en_i,
+  input logic [31:0]                  dummy_instr_seed_i,
+  input logic                         icache_enable_i,
+  input logic                         icache_inval_i,
 
-    // jump and branch target
-    input  logic [31:0]                 branch_target_ex_i,       // branch/jump target address
+  // jump and branch target
+  input  logic [31:0]                 branch_target_ex_i,       // branch/jump target address
 
-    // CSRs
-    input  logic [31:0]                 csr_mepc_i,               // PC to restore after handling
-                                                                  // the interrupt/exception
-    input  logic [31:0]                 csr_depc_i,               // PC to restore after handling
-                                                                  // the debug request
-    input  logic [31:0]                 csr_mtvec_i,              // base PC to jump to on exception
-    output logic                        csr_mtvec_init_o,         // tell CS regfile to init mtvec
+  // CSRs
+  input  logic [31:0]                 csr_mepc_i,               // PC to restore after handling
+                                                                // the interrupt/exception
+  input  logic [31:0]                 csr_depc_i,               // PC to restore after handling
+                                                                // the debug request
+  input  logic [31:0]                 csr_mtvec_i,              // base PC to jump to on exception
+  output logic                        csr_mtvec_init_o,         // tell CS regfile to init mtvec
 
-    // pipeline stall
-    input  logic                        id_in_ready_i,            // ID stage is ready for new instr
+  // pipeline stall
+  input  logic                        id_in_ready_i,            // ID stage is ready for new instr
 
-    // misc signals
-    output logic                        pc_mismatch_alert_o,
-    output logic                        if_busy_o                 // IF stage is busy fetching instr
+  // misc signals
+  output logic                        pc_mismatch_alert_o,
+  output logic                        if_busy_o                 // IF stage is busy fetching instr
 );
 
   logic              instr_valid_id_d, instr_valid_id_q;
@@ -117,8 +118,6 @@
   // prefetch buffer related signals
   logic              prefetch_busy;
   logic              branch_req;
-  logic              branch_spec;
-  logic              predicted_branch;
   logic       [31:0] fetch_addr_n;
   logic              unused_fetch_addr_n0;
 
@@ -129,10 +128,17 @@
   logic              fetch_err;
   logic              fetch_err_plus2;
 
+  logic [31:0]       instr_decompressed;
+  logic              illegal_c_insn;
+  logic              instr_is_compressed;
+
   logic              if_instr_valid;
   logic       [31:0] if_instr_rdata;
   logic       [31:0] if_instr_addr;
+  logic              if_instr_bus_err;
+  logic              if_instr_pmp_err;
   logic              if_instr_err;
+  logic              if_instr_err_plus2;
 
   logic       [31:0] exc_pc;
 
@@ -200,7 +206,6 @@
   if (ICache) begin : gen_icache
     // Full I-Cache option
     ibex_icache #(
-      .BranchPredictor (BranchPredictor),
       .ICacheECC       (ICacheECC),
       .ResetAll        (ResetAll),
       .BusSizeECC      (BusSizeECC),
@@ -213,9 +218,8 @@
         .req_i               ( req_i                      ),
 
         .branch_i            ( branch_req                 ),
-        .branch_spec_i       ( branch_spec                ),
-        .predicted_branch_i  ( predicted_branch           ),
         .branch_mispredict_i ( nt_branch_mispredict_i     ),
+        .mispredict_addr_i   ( nt_branch_addr_i           ),
         .addr_i              ( {fetch_addr_n[31:1], 1'b0} ),
 
         .ready_i             ( fetch_ready                ),
@@ -231,7 +235,6 @@
         .instr_rvalid_i      ( instr_rvalid_i             ),
         .instr_rdata_i       ( instr_rdata_i              ),
         .instr_err_i         ( instr_err_i                ),
-        .instr_pmp_err_i     ( instr_pmp_err_i            ),
 
         .ic_tag_req_o        ( ic_tag_req_o               ),
         .ic_tag_write_o      ( ic_tag_write_o             ),
@@ -251,7 +254,6 @@
   end else begin : gen_prefetch_buffer
     // prefetch buffer, caches a fixed number of instructions
     ibex_prefetch_buffer #(
-      .BranchPredictor (BranchPredictor),
       .ResetAll        (ResetAll)
     ) prefetch_buffer_i (
         .clk_i               ( clk_i                      ),
@@ -260,9 +262,8 @@
         .req_i               ( req_i                      ),
 
         .branch_i            ( branch_req                 ),
-        .branch_spec_i       ( branch_spec                ),
-        .predicted_branch_i  ( predicted_branch           ),
         .branch_mispredict_i ( nt_branch_mispredict_i     ),
+        .mispredict_addr_i   ( nt_branch_addr_i           ),
         .addr_i              ( {fetch_addr_n[31:1], 1'b0} ),
 
         .ready_i             ( fetch_ready                ),
@@ -278,7 +279,6 @@
         .instr_rvalid_i      ( instr_rvalid_i             ),
         .instr_rdata_i       ( instr_rdata_i              ),
         .instr_err_i         ( instr_err_i                ),
-        .instr_pmp_err_i     ( instr_pmp_err_i            ),
 
         .busy_o              ( prefetch_busy              )
     );
@@ -303,28 +303,36 @@
   assign unused_fetch_addr_n0 = fetch_addr_n[0];
 
   assign branch_req  = pc_set_i | predict_branch_taken;
-  assign branch_spec = pc_set_spec_i | predict_branch_taken;
 
   assign pc_if_o     = if_instr_addr;
   assign if_busy_o   = prefetch_busy;
 
+  // PMP errors
+  // An error can come from the instruction address, or the next instruction address for unaligned,
+  // uncompressed instructions.
+  assign if_instr_pmp_err = pmp_err_if_i |
+                            (if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i);
+
+  // Combine bus errors and pmp errors
+  assign if_instr_err = if_instr_bus_err | if_instr_pmp_err;
+
+  // Capture the second half of the address for errors on the second part of an instruction
+  assign if_instr_err_plus2 = ((if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) |
+                               fetch_err_plus2) & ~pmp_err_if_i;
+
   // compressed instruction decoding, or more precisely compressed instruction
   // expander
   //
   // since it does not matter where we decompress instructions, we do it here
   // to ease timing closure
-  logic [31:0] instr_decompressed;
-  logic        illegal_c_insn;
-  logic        instr_is_compressed;
-
   ibex_compressed_decoder compressed_decoder_i (
-      .clk_i           ( clk_i                    ),
-      .rst_ni          ( rst_ni                   ),
-      .valid_i         ( fetch_valid & ~fetch_err ),
-      .instr_i         ( if_instr_rdata           ),
-      .instr_o         ( instr_decompressed       ),
-      .is_compressed_o ( instr_is_compressed      ),
-      .illegal_instr_o ( illegal_c_insn           )
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .valid_i        (fetch_valid & ~fetch_err),
+    .instr_i        (if_instr_rdata),
+    .instr_o        (instr_decompressed),
+    .is_compressed_o(instr_is_compressed),
+    .illegal_instr_o(illegal_c_insn)
   );
 
   // Dummy instruction insertion
@@ -336,16 +344,16 @@
       .RndCnstLfsrSeed (RndCnstLfsrSeed),
       .RndCnstLfsrPerm (RndCnstLfsrPerm)
     ) dummy_instr_i (
-      .clk_i                 ( clk_i                 ),
-      .rst_ni                ( rst_ni                ),
-      .dummy_instr_en_i      ( dummy_instr_en_i      ),
-      .dummy_instr_mask_i    ( dummy_instr_mask_i    ),
-      .dummy_instr_seed_en_i ( dummy_instr_seed_en_i ),
-      .dummy_instr_seed_i    ( dummy_instr_seed_i    ),
-      .fetch_valid_i         ( fetch_valid           ),
-      .id_in_ready_i         ( id_in_ready_i         ),
-      .insert_dummy_instr_o  ( insert_dummy_instr    ),
-      .dummy_instr_data_o    ( dummy_instr_data      )
+      .clk_i                (clk_i),
+      .rst_ni               (rst_ni),
+      .dummy_instr_en_i     (dummy_instr_en_i),
+      .dummy_instr_mask_i   (dummy_instr_mask_i),
+      .dummy_instr_seed_en_i(dummy_instr_seed_en_i),
+      .dummy_instr_seed_i   (dummy_instr_seed_i),
+      .fetch_valid_i        (fetch_valid),
+      .id_in_ready_i        (id_in_ready_i),
+      .insert_dummy_instr_o (insert_dummy_instr),
+      .dummy_instr_data_o   (dummy_instr_data)
     );
 
     // Mux between actual instructions and dummy instructions
@@ -426,7 +434,7 @@
         // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated.
         instr_rdata_alu_id_o     <= instr_out;
         instr_fetch_err_o        <= instr_err_out;
-        instr_fetch_err_plus2_o  <= fetch_err_plus2;
+        instr_fetch_err_plus2_o  <= if_instr_err_plus2;
         instr_rdata_c_id_o       <= if_instr_rdata[15:0];
         instr_is_compressed_id_o <= instr_is_compressed_out;
         illegal_c_insn_id_o      <= illegal_c_instr_out;
@@ -440,7 +448,7 @@
         // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated.
         instr_rdata_alu_id_o     <= instr_out;
         instr_fetch_err_o        <= instr_err_out;
-        instr_fetch_err_plus2_o  <= fetch_err_plus2;
+        instr_fetch_err_plus2_o  <= if_instr_err_plus2;
         instr_rdata_c_id_o       <= if_instr_rdata[15:0];
         instr_is_compressed_id_o <= instr_is_compressed_out;
         illegal_c_insn_id_o      <= illegal_c_instr_out;
@@ -457,7 +465,7 @@
     // Do not check for sequential increase after a branch, jump, exception, interrupt or debug
     // request, all of which will set branch_req. Also do not check after reset or for dummys.
     assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) &
-        ~branch_req & ~stall_dummy_instr;
+        ~branch_req & ~if_instr_err & ~stall_dummy_instr;
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
@@ -467,8 +475,7 @@
       end
     end
 
-    assign prev_instr_addr_incr = pc_id_o + ((instr_is_compressed_id_o && !instr_fetch_err_o) ?
-                                             32'd2 : 32'd4);
+    assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4);
 
     // Check that the address equals the previous address +2/+4
     assign pc_mismatch_alert_o = prev_instr_seq_q & (pc_if_o != prev_instr_addr_incr);
@@ -512,7 +519,7 @@
     // data_gnt_i -> instr_req_o (which needs to be avoided as for some interconnects this will
     // result in a combinational loop).
 
-    assign instr_skid_en = predicted_branch & ~id_in_ready_i & ~instr_skid_valid_q;
+    assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q;
 
     assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr) |
                                 instr_skid_en;
@@ -548,14 +555,14 @@
     end
 
     ibex_branch_predict branch_predict_i (
-      .clk_i                  ( clk_i                    ),
-      .rst_ni                 ( rst_ni                   ),
-      .fetch_rdata_i          ( fetch_rdata              ),
-      .fetch_pc_i             ( fetch_addr               ),
-      .fetch_valid_i          ( fetch_valid              ),
+      .clk_i        (clk_i),
+      .rst_ni       (rst_ni),
+      .fetch_rdata_i(fetch_rdata),
+      .fetch_pc_i   (fetch_addr),
+      .fetch_valid_i(fetch_valid),
 
-      .predict_branch_taken_o ( predict_branch_taken_raw ),
-      .predict_branch_pc_o    ( predict_branch_pc        )
+      .predict_branch_taken_o(predict_branch_taken_raw),
+      .predict_branch_pc_o   (predict_branch_pc)
     );
 
     // If there is an instruction in the skid buffer there must be no branch prediction.
@@ -564,16 +571,13 @@
     // Do not branch predict on instruction errors.
     assign predict_branch_taken = predict_branch_taken_raw & ~instr_skid_valid_q & ~fetch_err;
 
-    // pc_set_i takes precendence over branch prediction
-    assign predicted_branch = predict_branch_taken & ~pc_set_i;
-
-    assign if_instr_valid   = fetch_valid | instr_skid_valid_q;
+    assign if_instr_valid   = fetch_valid | (instr_skid_valid_q & ~nt_branch_mispredict_i);
     assign if_instr_rdata   = instr_skid_valid_q ? instr_skid_data_q : fetch_rdata;
     assign if_instr_addr    = instr_skid_valid_q ? instr_skid_addr_q : fetch_addr;
 
     // Don't branch predict on instruction error so only instructions without errors end up in the
     // skid buffer.
-    assign if_instr_err     = ~instr_skid_valid_q & fetch_err;
+    assign if_instr_bus_err = ~instr_skid_valid_q & fetch_err;
     assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken;
 
     assign fetch_ready = id_in_ready_i & ~stall_dummy_instr & ~instr_skid_valid_q;
@@ -585,13 +589,12 @@
   end else begin : g_no_branch_predictor
     assign instr_bp_taken_o     = 1'b0;
     assign predict_branch_taken = 1'b0;
-    assign predicted_branch     = 1'b0;
     assign predict_branch_pc    = 32'b0;
 
     assign if_instr_valid = fetch_valid;
     assign if_instr_rdata = fetch_rdata;
     assign if_instr_addr  = fetch_addr;
-    assign if_instr_err   = fetch_err;
+    assign if_instr_bus_err = fetch_err;
     assign fetch_ready = id_in_ready_i & ~stall_dummy_instr;
   end
 
@@ -638,6 +641,11 @@
 
     assign next_pc = fetch_addr + (instr_is_compressed_out ? 32'd2 : 32'd4);
 
+    logic predicted_branch;
+
+    // pc_set_i takes precendence over branch prediction
+    assign predicted_branch = predict_branch_taken & ~pc_set_i;
+
     always_comb begin
       predicted_branch_live_d = predicted_branch_live_q;
       mispredicted_d          = mispredicted_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
index 907bf61..14de33b 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
@@ -16,54 +16,54 @@
 
 module ibex_load_store_unit
 (
-    input  logic         clk_i,
-    input  logic         rst_ni,
+  input  logic         clk_i,
+  input  logic         rst_ni,
 
-    // data interface
-    output logic         data_req_o,
-    input  logic         data_gnt_i,
-    input  logic         data_rvalid_i,
-    input  logic         data_err_i,
-    input  logic         data_pmp_err_i,
+  // data interface
+  output logic         data_req_o,
+  input  logic         data_gnt_i,
+  input  logic         data_rvalid_i,
+  input  logic         data_err_i,
+  input  logic         data_pmp_err_i,
 
-    output logic [31:0]  data_addr_o,
-    output logic         data_we_o,
-    output logic [3:0]   data_be_o,
-    output logic [31:0]  data_wdata_o,
-    input  logic [31:0]  data_rdata_i,
+  output logic [31:0]  data_addr_o,
+  output logic         data_we_o,
+  output logic [3:0]   data_be_o,
+  output logic [31:0]  data_wdata_o,
+  input  logic [31:0]  data_rdata_i,
 
-    // signals to/from ID/EX stage
-    input  logic         lsu_we_i,             // write enable                     -> from ID/EX
-    input  logic [1:0]   lsu_type_i,           // data type: word, half word, byte -> from ID/EX
-    input  logic [31:0]  lsu_wdata_i,          // data to write to memory          -> from ID/EX
-    input  logic         lsu_sign_ext_i,       // sign extension                   -> from ID/EX
+  // signals to/from ID/EX stage
+  input  logic         lsu_we_i,             // write enable                     -> from ID/EX
+  input  logic [1:0]   lsu_type_i,           // data type: word, half word, byte -> from ID/EX
+  input  logic [31:0]  lsu_wdata_i,          // data to write to memory          -> from ID/EX
+  input  logic         lsu_sign_ext_i,       // sign extension                   -> from ID/EX
 
-    output logic [31:0]  lsu_rdata_o,          // requested data                   -> to ID/EX
-    output logic         lsu_rdata_valid_o,
-    input  logic         lsu_req_i,            // data request                     -> from ID/EX
+  output logic [31:0]  lsu_rdata_o,          // requested data                   -> to ID/EX
+  output logic         lsu_rdata_valid_o,
+  input  logic         lsu_req_i,            // data request                     -> from ID/EX
 
-    input  logic [31:0]  adder_result_ex_i,    // address computed in ALU          -> from ID/EX
+  input  logic [31:0]  adder_result_ex_i,    // address computed in ALU          -> from ID/EX
 
-    output logic         addr_incr_req_o,      // request address increment for
-                                               // misaligned accesses              -> to ID/EX
-    output logic [31:0]  addr_last_o,          // address of last transaction      -> to controller
-                                               // -> mtval
-                                               // -> AGU for misaligned accesses
+  output logic         addr_incr_req_o,      // request address increment for
+                                              // misaligned accesses              -> to ID/EX
+  output logic [31:0]  addr_last_o,          // address of last transaction      -> to controller
+                                              // -> mtval
+                                              // -> AGU for misaligned accesses
 
-    output logic         lsu_req_done_o,       // Signals that data request is complete
-                                               // (only need to await final data
-                                               // response)                        -> to ID/EX
+  output logic         lsu_req_done_o,       // Signals that data request is complete
+                                              // (only need to await final data
+                                              // response)                        -> to ID/EX
 
-    output logic         lsu_resp_valid_o,     // LSU has response from transaction -> to ID/EX
+  output logic         lsu_resp_valid_o,     // LSU has response from transaction -> to ID/EX
 
-    // exception signals
-    output logic         load_err_o,
-    output logic         store_err_o,
+  // exception signals
+  output logic         load_err_o,
+  output logic         store_err_o,
 
-    output logic         busy_o,
+  output logic         busy_o,
 
-    output logic         perf_load_o,
-    output logic         perf_store_o
+  output logic         perf_load_o,
+  output logic         perf_store_o
 );
 
   logic [31:0]  data_addr;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
index a95ef49..3d1e20f 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
@@ -7,97 +7,97 @@
 // 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          ResetAll          = 1'b0,
-    parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
-    parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
-    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
+  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          ResetAll          = 1'b0,
+  parameter lfsr_seed_t  RndCnstLfsrSeed   = RndCnstLfsrSeedDefault,
+  parameter lfsr_perm_t  RndCnstLfsrPerm   = RndCnstLfsrPermDefault,
+  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                         clk_i,
+  input  logic                         rst_ni,
 
-    input  logic [31:0]                  hart_id_i,
-    input  logic [31:0]                  boot_addr_i,
+  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 [6:0]                   instr_rdata_intg_i,
-    input  logic                         instr_err_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 [6:0]                   instr_rdata_intg_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,
-    output logic [6:0]                   data_wdata_intg_o,
-    input  logic [31:0]                  data_rdata_i,
-    input  logic [6:0]                   data_rdata_intg_i,
-    input  logic                         data_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,
+  output logic [6:0]                   data_wdata_intg_o,
+  input  logic [31:0]                  data_rdata_i,
+  input  logic [6:0]                   data_rdata_intg_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                         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 [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                         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,
+  input  logic                         debug_req_i,
+  input  crash_dump_t                  crash_dump_i,
 
-    input  logic                         fetch_enable_i,
-    output logic                         alert_minor_o,
-    output logic                         alert_major_o,
-    input  logic                         core_busy_i,
-    input  logic                         test_en_i,
-    input  logic                         scan_rst_ni
+  input  logic                         fetch_enable_i,
+  output logic                         alert_minor_o,
+  output logic                         alert_major_o,
+  input  logic                         core_busy_i,
+  input  logic                         test_en_i,
+  input  logic                         scan_rst_ni
 );
 
   localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset);
@@ -190,13 +190,13 @@
       data_rdata_intg_q  <= '0;
       for (int unsigned i = 0; i < LockstepOffset; i++) begin
         shadow_inputs_q[i]     <= delayed_inputs_t'('0);
-        shadow_tag_rdata_q[i]  <= '{default:0};
-        shadow_data_rdata_q[i] <= '{default:0};
+        shadow_tag_rdata_q[i]  <= '{default: 0};
+        shadow_data_rdata_q[i] <= '{default: 0};
       end
     end else begin
       instr_rdata_intg_q <= instr_rdata_intg_i;
       data_rdata_intg_q  <= data_rdata_intg_i;
-      for (int unsigned i = 0; i < LockstepOffset-1; 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];
@@ -216,14 +216,14 @@
   logic [31:0] unused_wdata;
 
   // Checks on incoming data
-  prim_secded_39_32_dec u_instr_intg_dec (
+  prim_secded_inv_39_32_dec u_instr_intg_dec (
     .data_i     ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}),
     .data_o     (),
     .syndrome_o (),
     .err_o      (instr_intg_err)
   );
 
-  prim_secded_39_32_dec u_data_intg_dec (
+  prim_secded_inv_39_32_dec u_data_intg_dec (
     .data_i     ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}),
     .data_o     (),
     .syndrome_o (),
@@ -234,7 +234,7 @@
                         (shadow_inputs_q[LockstepOffset-1].data_rvalid  & |data_intg_err);
 
   // Generate integrity bits
-  prim_secded_39_32_enc u_data_gen (
+  prim_secded_inv_39_32_enc u_data_gen (
     .data_i (data_wdata_i),
     .data_o ({data_wdata_intg_o, unused_wdata})
   );
@@ -302,7 +302,7 @@
 
   // Delay the outputs
   always_ff @(posedge clk_i) begin
-    for (int unsigned i = 0; i < OutputsOffset-1; i++) begin
+    for (int unsigned i = 0; i < OutputsOffset - 1; i++) begin
       core_outputs_q[i] <= core_outputs_q[i+1];
     end
     core_outputs_q[OutputsOffset-1] <= core_outputs_in;
@@ -397,29 +397,33 @@
     .crash_dump_o      (shadow_outputs_d.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    (),
+    .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     (),
+    .rvfi_ext_mip       (),
+    .rvfi_ext_nmi       (),
+    .rvfi_ext_debug_req (),
+    .rvfi_ext_mcycle    (),
 `endif
 
     .fetch_enable_i    (shadow_inputs_q[0].fetch_enable),
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
index 4da8f0d..79ed5bc 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
@@ -15,34 +15,34 @@
 `include "prim_assert.sv"
 
 module ibex_multdiv_fast #(
-    parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
+  parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
   ) (
-    input  logic             clk_i,
-    input  logic             rst_ni,
-    input  logic             mult_en_i,  // dynamic enable signal, for FSM control
-    input  logic             div_en_i,   // dynamic enable signal, for FSM control
-    input  logic             mult_sel_i, // static decoder output, for data muxes
-    input  logic             div_sel_i,  // static decoder output, for data muxes
-    input  ibex_pkg::md_op_e operator_i,
-    input  logic  [1:0]      signed_mode_i,
-    input  logic [31:0]      op_a_i,
-    input  logic [31:0]      op_b_i,
-    input  logic [33:0]      alu_adder_ext_i,
-    input  logic [31:0]      alu_adder_i,
-    input  logic             equal_to_zero_i,
-    input  logic             data_ind_timing_i,
+  input  logic             clk_i,
+  input  logic             rst_ni,
+  input  logic             mult_en_i,  // dynamic enable signal, for FSM control
+  input  logic             div_en_i,   // dynamic enable signal, for FSM control
+  input  logic             mult_sel_i, // static decoder output, for data muxes
+  input  logic             div_sel_i,  // static decoder output, for data muxes
+  input  ibex_pkg::md_op_e operator_i,
+  input  logic  [1:0]      signed_mode_i,
+  input  logic [31:0]      op_a_i,
+  input  logic [31:0]      op_b_i,
+  input  logic [33:0]      alu_adder_ext_i,
+  input  logic [31:0]      alu_adder_i,
+  input  logic             equal_to_zero_i,
+  input  logic             data_ind_timing_i,
 
-    output logic [32:0]      alu_operand_a_o,
-    output logic [32:0]      alu_operand_b_o,
+  output logic [32:0]      alu_operand_a_o,
+  output logic [32:0]      alu_operand_b_o,
 
-    input  logic [33:0]      imd_val_q_i[2],
-    output logic [33:0]      imd_val_d_o[2],
-    output logic [1:0]       imd_val_we_o,
+  input  logic [33:0]      imd_val_q_i[2],
+  output logic [33:0]      imd_val_d_o[2],
+  output logic [1:0]       imd_val_we_o,
 
-    input  logic             multdiv_ready_id_i,
+  input  logic             multdiv_ready_id_i,
 
-    output logic [31:0]      multdiv_result_o,
-    output logic             valid_o
+  output logic [31:0]      multdiv_result_o,
+  output logic             valid_o
 );
 
   import ibex_pkg::*;
@@ -415,7 +415,7 @@
     div_hold         = 1'b0;
     div_by_zero_d    = div_by_zero_q;
 
-    unique case(md_state_q)
+    unique case (md_state_q)
       MD_IDLE: begin
         if (operator_i == MD_OP_DIV) begin
           // Check if the Denominator is 0
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
index a8d60b4..b184c5a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
@@ -13,33 +13,33 @@
 
 module ibex_multdiv_slow
 (
-    input  logic             clk_i,
-    input  logic             rst_ni,
-    input  logic             mult_en_i,  // dynamic enable signal, for FSM control
-    input  logic             div_en_i,   // dynamic enable signal, for FSM control
-    input  logic             mult_sel_i, // static decoder output, for data muxes
-    input  logic             div_sel_i,  // static decoder output, for data muxes
-    input  ibex_pkg::md_op_e operator_i,
-    input  logic  [1:0]      signed_mode_i,
-    input  logic [31:0]      op_a_i,
-    input  logic [31:0]      op_b_i,
-    input  logic [33:0]      alu_adder_ext_i,
-    input  logic [31:0]      alu_adder_i,
-    input  logic             equal_to_zero_i,
-    input  logic             data_ind_timing_i,
+  input  logic             clk_i,
+  input  logic             rst_ni,
+  input  logic             mult_en_i,  // dynamic enable signal, for FSM control
+  input  logic             div_en_i,   // dynamic enable signal, for FSM control
+  input  logic             mult_sel_i, // static decoder output, for data muxes
+  input  logic             div_sel_i,  // static decoder output, for data muxes
+  input  ibex_pkg::md_op_e operator_i,
+  input  logic  [1:0]      signed_mode_i,
+  input  logic [31:0]      op_a_i,
+  input  logic [31:0]      op_b_i,
+  input  logic [33:0]      alu_adder_ext_i,
+  input  logic [31:0]      alu_adder_i,
+  input  logic             equal_to_zero_i,
+  input  logic             data_ind_timing_i,
 
-    output logic [32:0]      alu_operand_a_o,
-    output logic [32:0]      alu_operand_b_o,
+  output logic [32:0]      alu_operand_a_o,
+  output logic [32:0]      alu_operand_b_o,
 
-    input  logic [33:0]      imd_val_q_i[2],
-    output logic [33:0]      imd_val_d_o[2],
-    output logic  [1:0]      imd_val_we_o,
+  input  logic [33:0]      imd_val_q_i[2],
+  output logic [33:0]      imd_val_d_o[2],
+  output logic  [1:0]      imd_val_we_o,
 
-    input  logic             multdiv_ready_id_i,
+  input  logic             multdiv_ready_id_i,
 
-    output logic [31:0]      multdiv_result_o,
+  output logic [31:0]      multdiv_result_o,
 
-    output logic             valid_o
+  output logic             valid_o
 );
 
   import ibex_pkg::*;
@@ -96,7 +96,7 @@
   always_comb begin
     alu_operand_a_o = accum_window_q;
 
-    unique case(operator_i)
+    unique case (operator_i)
 
       MD_OP_MULL: begin
         alu_operand_b_o = op_a_bw_pp;
@@ -108,7 +108,7 @@
 
       MD_OP_DIV,
       MD_OP_REM: begin
-        unique case(md_state_q)
+        unique case (md_state_q)
           MD_IDLE: begin
             // 0 - B = 0 iff B == 0
             alu_operand_a_o = {32'h0  , 1'b1};
@@ -181,9 +181,9 @@
     multdiv_hold     = 1'b0;
     div_by_zero_d    = div_by_zero_q;
     if (mult_sel_i || div_sel_i) begin
-      unique case(md_state_q)
+      unique case (md_state_q)
         MD_IDLE: begin
-          unique case(operator_i)
+          unique case (operator_i)
             MD_OP_MULL: begin
               op_a_shift_d   = op_a_ext << 1;
               accum_window_d = {       ~(op_a_ext[32]   &     op_b_i[0]),
@@ -233,15 +233,15 @@
 
         MD_ABS_B: begin
           // remainder
-          accum_window_d = {32'h0,op_numerator_q[31]};
+          accum_window_d = {32'h0, op_numerator_q[31]};
           // B abs value
-          op_b_shift_d   = sign_b ? {1'b0,alu_adder_i} : {1'b0,op_b_i};
+          op_b_shift_d   = sign_b ? {1'b0, alu_adder_i} : {1'b0, op_b_i};
           md_state_d     = MD_COMP;
         end
 
         MD_COMP: begin
           multdiv_count_d = multdiv_count_q - 5'h1;
-          unique case(operator_i)
+          unique case (operator_i)
             MD_OP_MULL: begin
               accum_window_d = res_adder_l;
               op_a_shift_d   = op_a_shift_q << 1;
@@ -268,7 +268,7 @@
         end
 
         MD_LAST: begin
-          unique case(operator_i)
+          unique case (operator_i)
             MD_OP_MULL: begin
               accum_window_d = res_adder_l;
 
@@ -301,7 +301,7 @@
 
         MD_CHANGE_SIGN: begin
           md_state_d = MD_FINISH;
-          unique case(operator_i)
+          unique case (operator_i)
             MD_OP_DIV:
               accum_window_d = div_change_sign ? {1'b0,alu_adder_i} : accum_window_q;
             MD_OP_REM:
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
index 6d60ed2..33d2245 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
@@ -8,565 +8,595 @@
  */
 package ibex_pkg;
 
-////////////////
-// IO Structs //
-////////////////
+  ////////////////
+  // IO Structs //
+  ////////////////
 
-typedef struct packed {
-  logic [31:0] current_pc;
-  logic [31:0] next_pc;
-  logic [31:0] last_data_addr;
-  logic [31:0] exception_addr;
-} crash_dump_t;
+  typedef struct packed {
+    logic [31:0] current_pc;
+    logic [31:0] next_pc;
+    logic [31:0] last_data_addr;
+    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;
+  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 //
-/////////////////////
+  /////////////////////
+  // Parameter Enums //
+  /////////////////////
 
-typedef enum integer {
-  RegFileFF    = 0,
-  RegFileFPGA  = 1,
-  RegFileLatch = 2
-} regfile_e;
+  typedef enum integer {
+    RegFileFF    = 0,
+    RegFileFPGA  = 1,
+    RegFileLatch = 2
+  } regfile_e;
 
-typedef enum integer {
-  RV32MNone        = 0,
-  RV32MSlow        = 1,
-  RV32MFast        = 2,
-  RV32MSingleCycle = 3
-} rv32m_e;
+  typedef enum integer {
+    RV32MNone        = 0,
+    RV32MSlow        = 1,
+    RV32MFast        = 2,
+    RV32MSingleCycle = 3
+  } rv32m_e;
 
-typedef enum integer {
-  RV32BNone     = 0,
-  RV32BBalanced = 1,
-  RV32BFull     = 2
-} rv32b_e;
+  typedef enum integer {
+    RV32BNone     = 0,
+    RV32BBalanced = 1,
+    RV32BFull     = 2
+  } rv32b_e;
 
-/////////////
-// Opcodes //
-/////////////
+  /////////////
+  // Opcodes //
+  /////////////
 
-typedef enum logic [6:0] {
-  OPCODE_LOAD     = 7'h03,
-  OPCODE_MISC_MEM = 7'h0f,
-  OPCODE_OP_IMM   = 7'h13,
-  OPCODE_AUIPC    = 7'h17,
-  OPCODE_STORE    = 7'h23,
-  OPCODE_OP       = 7'h33,
-  OPCODE_LUI      = 7'h37,
-  OPCODE_BRANCH   = 7'h63,
-  OPCODE_JALR     = 7'h67,
-  OPCODE_JAL      = 7'h6f,
-  OPCODE_SYSTEM   = 7'h73
-} opcode_e;
+  typedef enum logic [6:0] {
+    OPCODE_LOAD     = 7'h03,
+    OPCODE_MISC_MEM = 7'h0f,
+    OPCODE_OP_IMM   = 7'h13,
+    OPCODE_AUIPC    = 7'h17,
+    OPCODE_STORE    = 7'h23,
+    OPCODE_OP       = 7'h33,
+    OPCODE_LUI      = 7'h37,
+    OPCODE_BRANCH   = 7'h63,
+    OPCODE_JALR     = 7'h67,
+    OPCODE_JAL      = 7'h6f,
+    OPCODE_SYSTEM   = 7'h73
+  } opcode_e;
 
 
-////////////////////
-// ALU operations //
-////////////////////
+  ////////////////////
+  // ALU operations //
+  ////////////////////
 
-typedef enum logic [5:0] {
-  // Arithmetics
-  ALU_ADD,
-  ALU_SUB,
+  typedef enum logic [6:0] {
+    // Arithmetics
+    ALU_ADD,
+    ALU_SUB,
 
-  // Logics
-  ALU_XOR,
-  ALU_OR,
-  ALU_AND,
-  // RV32B
-  ALU_XNOR,
-  ALU_ORN,
-  ALU_ANDN,
+    // Logics
+    ALU_XOR,
+    ALU_OR,
+    ALU_AND,
+    // RV32B
+    ALU_XNOR,
+    ALU_ORN,
+    ALU_ANDN,
 
-  // Shifts
-  ALU_SRA,
-  ALU_SRL,
-  ALU_SLL,
-  // RV32B
-  ALU_SRO,
-  ALU_SLO,
-  ALU_ROR,
-  ALU_ROL,
-  ALU_GREV,
-  ALU_GORC,
-  ALU_SHFL,
-  ALU_UNSHFL,
+    // Shifts
+    ALU_SRA,
+    ALU_SRL,
+    ALU_SLL,
+    // RV32B
+    ALU_SRO,
+    ALU_SLO,
+    ALU_ROR,
+    ALU_ROL,
+    ALU_GREV,
+    ALU_GORC,
+    ALU_SHFL,
+    ALU_UNSHFL,
+    ALU_XPERM_N,
+    ALU_XPERM_B,
+    ALU_XPERM_H,
 
-  // Comparisons
-  ALU_LT,
-  ALU_LTU,
-  ALU_GE,
-  ALU_GEU,
-  ALU_EQ,
-  ALU_NE,
-  // RV32B
-  ALU_MIN,
-  ALU_MINU,
-  ALU_MAX,
-  ALU_MAXU,
+    // Address Calculations
+    // RV32B
+    ALU_SH1ADD,
+    ALU_SH2ADD,
+    ALU_SH3ADD,
 
-  // Pack
-  // RV32B
-  ALU_PACK,
-  ALU_PACKU,
-  ALU_PACKH,
+    // Comparisons
+    ALU_LT,
+    ALU_LTU,
+    ALU_GE,
+    ALU_GEU,
+    ALU_EQ,
+    ALU_NE,
+    // RV32B
+    ALU_MIN,
+    ALU_MINU,
+    ALU_MAX,
+    ALU_MAXU,
 
-  // Sign-Extend
-  // RV32B
-  ALU_SEXTB,
-  ALU_SEXTH,
+    // Pack
+    // RV32B
+    ALU_PACK,
+    ALU_PACKU,
+    ALU_PACKH,
 
-  // Bitcounting
-  // RV32B
-  ALU_CLZ,
-  ALU_CTZ,
-  ALU_PCNT,
+    // Sign-Extend
+    // RV32B
+    ALU_SEXTB,
+    ALU_SEXTH,
 
-  // Set lower than
-  ALU_SLT,
-  ALU_SLTU,
+    // Bitcounting
+    // RV32B
+    ALU_CLZ,
+    ALU_CTZ,
+    ALU_CPOP,
 
-  // Ternary Bitmanip Operations
-  // RV32B
-  ALU_CMOV,
-  ALU_CMIX,
-  ALU_FSL,
-  ALU_FSR,
+    // Set lower than
+    ALU_SLT,
+    ALU_SLTU,
 
-  // Single-Bit Operations
-  // RV32B
-  ALU_SBSET,
-  ALU_SBCLR,
-  ALU_SBINV,
-  ALU_SBEXT,
+    // Ternary Bitmanip Operations
+    // RV32B
+    ALU_CMOV,
+    ALU_CMIX,
+    ALU_FSL,
+    ALU_FSR,
 
-  // Bit Extract / Deposit
-  // RV32B
-  ALU_BEXT,
-  ALU_BDEP,
+    // Single-Bit Operations
+    // RV32B
+    ALU_BSET,
+    ALU_BCLR,
+    ALU_BINV,
+    ALU_BEXT,
 
-  // Bit Field Place
-  // RV32B
-  ALU_BFP,
+    // Bit Compress / Decompress
+    // RV32B
+    ALU_BCOMPRESS,
+    ALU_BDECOMPRESS,
 
-  // Carry-less Multiply
-  // RV32B
-  ALU_CLMUL,
-  ALU_CLMULR,
-  ALU_CLMULH,
+    // Bit Field Place
+    // RV32B
+    ALU_BFP,
 
-  // Cyclic Redundancy Check
-  ALU_CRC32_B,
-  ALU_CRC32C_B,
-  ALU_CRC32_H,
-  ALU_CRC32C_H,
-  ALU_CRC32_W,
-  ALU_CRC32C_W
-} alu_op_e;
+    // Carry-less Multiply
+    // RV32B
+    ALU_CLMUL,
+    ALU_CLMULR,
+    ALU_CLMULH,
 
-typedef enum logic [1:0] {
-  // Multiplier/divider
-  MD_OP_MULL,
-  MD_OP_MULH,
-  MD_OP_DIV,
-  MD_OP_REM
-} md_op_e;
+    // Cyclic Redundancy Check
+    ALU_CRC32_B,
+    ALU_CRC32C_B,
+    ALU_CRC32_H,
+    ALU_CRC32C_H,
+    ALU_CRC32_W,
+    ALU_CRC32C_W
+  } alu_op_e;
 
+  typedef enum logic [1:0] {
+    // Multiplier/divider
+    MD_OP_MULL,
+    MD_OP_MULH,
+    MD_OP_DIV,
+    MD_OP_REM
+  } md_op_e;
 
-//////////////////////////////////
-// Control and status registers //
-//////////////////////////////////
 
-// CSR operations
-typedef enum logic [1:0] {
-  CSR_OP_READ,
-  CSR_OP_WRITE,
-  CSR_OP_SET,
-  CSR_OP_CLEAR
-} csr_op_e;
+  //////////////////////////////////
+  // Control and status registers //
+  //////////////////////////////////
 
-// Privileged mode
-typedef enum logic[1:0] {
-  PRIV_LVL_M = 2'b11,
-  PRIV_LVL_H = 2'b10,
-  PRIV_LVL_S = 2'b01,
-  PRIV_LVL_U = 2'b00
-} priv_lvl_e;
+  // CSR operations
+  typedef enum logic [1:0] {
+    CSR_OP_READ,
+    CSR_OP_WRITE,
+    CSR_OP_SET,
+    CSR_OP_CLEAR
+  } csr_op_e;
 
-// Constants for the dcsr.xdebugver fields
-typedef enum logic[3:0] {
-   XDEBUGVER_NO     = 4'd0, // no external debug support
-   XDEBUGVER_STD    = 4'd4, // external debug according to RISC-V debug spec
-   XDEBUGVER_NONSTD = 4'd15 // debug not conforming to RISC-V debug spec
-} x_debug_ver_e;
+  // Privileged mode
+  typedef enum logic[1:0] {
+    PRIV_LVL_M = 2'b11,
+    PRIV_LVL_H = 2'b10,
+    PRIV_LVL_S = 2'b01,
+    PRIV_LVL_U = 2'b00
+  } priv_lvl_e;
 
-//////////////
-// WB stage //
-//////////////
+  // Constants for the dcsr.xdebugver fields
+  typedef enum logic[3:0] {
+    XDEBUGVER_NO     = 4'd0, // no external debug support
+    XDEBUGVER_STD    = 4'd4, // external debug according to RISC-V debug spec
+    XDEBUGVER_NONSTD = 4'd15 // debug not conforming to RISC-V debug spec
+  } x_debug_ver_e;
 
-// Type of instruction present in writeback stage
-typedef enum logic[1:0] {
-  WB_INSTR_LOAD,  // Instruction is awaiting load data
-  WB_INSTR_STORE, // Instruction is awaiting store response
-  WB_INSTR_OTHER  // Instruction doesn't fit into above categories
-} wb_instr_type_e;
+  //////////////
+  // WB stage //
+  //////////////
 
-//////////////
-// ID stage //
-//////////////
+  // Type of instruction present in writeback stage
+  typedef enum logic[1:0] {
+    WB_INSTR_LOAD,  // Instruction is awaiting load data
+    WB_INSTR_STORE, // Instruction is awaiting store response
+    WB_INSTR_OTHER  // Instruction doesn't fit into above categories
+  } wb_instr_type_e;
 
-// Operand a selection
-typedef enum logic[1:0] {
-  OP_A_REG_A,
-  OP_A_FWD,
-  OP_A_CURRPC,
-  OP_A_IMM
-} op_a_sel_e;
+  //////////////
+  // ID stage //
+  //////////////
 
-// Immediate a selection
-typedef enum logic {
-  IMM_A_Z,
-  IMM_A_ZERO
-} imm_a_sel_e;
+  // Operand a selection
+  typedef enum logic[1:0] {
+    OP_A_REG_A,
+    OP_A_FWD,
+    OP_A_CURRPC,
+    OP_A_IMM
+  } op_a_sel_e;
 
-// Operand b selection
-typedef enum logic {
-  OP_B_REG_B,
-  OP_B_IMM
-} op_b_sel_e;
+  // Immediate a selection
+  typedef enum logic {
+    IMM_A_Z,
+    IMM_A_ZERO
+  } imm_a_sel_e;
 
-// Immediate b selection
-typedef enum logic [2:0] {
-  IMM_B_I,
-  IMM_B_S,
-  IMM_B_B,
-  IMM_B_U,
-  IMM_B_J,
-  IMM_B_INCR_PC,
-  IMM_B_INCR_ADDR
-} imm_b_sel_e;
+  // Operand b selection
+  typedef enum logic {
+    OP_B_REG_B,
+    OP_B_IMM
+  } op_b_sel_e;
 
-// Regfile write data selection
-typedef enum logic {
-  RF_WD_EX,
-  RF_WD_CSR
-} rf_wd_sel_e;
+  // Immediate b selection
+  typedef enum logic [2:0] {
+    IMM_B_I,
+    IMM_B_S,
+    IMM_B_B,
+    IMM_B_U,
+    IMM_B_J,
+    IMM_B_INCR_PC,
+    IMM_B_INCR_ADDR
+  } imm_b_sel_e;
 
-//////////////
-// IF stage //
-//////////////
+  // Regfile write data selection
+  typedef enum logic {
+    RF_WD_EX,
+    RF_WD_CSR
+  } rf_wd_sel_e;
 
-// PC mux selection
-typedef enum logic [2:0] {
-  PC_BOOT,
-  PC_JUMP,
-  PC_EXC,
-  PC_ERET,
-  PC_DRET,
-  PC_BP
-} pc_sel_e;
+  //////////////
+  // IF stage //
+  //////////////
 
-// Exception PC mux selection
-typedef enum logic [1:0] {
-  EXC_PC_EXC,
-  EXC_PC_IRQ,
-  EXC_PC_DBD,
-  EXC_PC_DBG_EXC // Exception while in debug mode
-} exc_pc_sel_e;
+  // PC mux selection
+  typedef enum logic [2:0] {
+    PC_BOOT,
+    PC_JUMP,
+    PC_EXC,
+    PC_ERET,
+    PC_DRET,
+    PC_BP
+  } pc_sel_e;
+
+  // Exception PC mux selection
+  typedef enum logic [1:0] {
+    EXC_PC_EXC,
+    EXC_PC_IRQ,
+    EXC_PC_DBD,
+    EXC_PC_DBG_EXC // Exception while in debug mode
+  } exc_pc_sel_e;
+
+  // Interrupt requests
+  typedef struct packed {
+    logic        irq_software;
+    logic        irq_timer;
+    logic        irq_external;
+    logic [14:0] irq_fast; // 15 fast interrupts,
+                          // one interrupt is reserved for NMI (not visible through mip/mie)
+  } irqs_t;
+
+  // Exception cause
+  typedef enum logic [5:0] {
+    EXC_CAUSE_IRQ_SOFTWARE_M     = {1'b1, 5'd03},
+    EXC_CAUSE_IRQ_TIMER_M        = {1'b1, 5'd07},
+    EXC_CAUSE_IRQ_EXTERNAL_M     = {1'b1, 5'd11},
+    // EXC_CAUSE_IRQ_FAST_0      = {1'b1, 5'd16},
+    // EXC_CAUSE_IRQ_FAST_14     = {1'b1, 5'd30},
+    EXC_CAUSE_IRQ_NM             = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15
+    EXC_CAUSE_INSN_ADDR_MISA     = {1'b0, 5'd00},
+    EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01},
+    EXC_CAUSE_ILLEGAL_INSN       = {1'b0, 5'd02},
+    EXC_CAUSE_BREAKPOINT         = {1'b0, 5'd03},
+    EXC_CAUSE_LOAD_ACCESS_FAULT  = {1'b0, 5'd05},
+    EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
+    EXC_CAUSE_ECALL_UMODE        = {1'b0, 5'd08},
+    EXC_CAUSE_ECALL_MMODE        = {1'b0, 5'd11}
+  } exc_cause_e;
+
+  // Debug cause
+  typedef enum logic [2:0] {
+    DBG_CAUSE_NONE    = 3'h0,
+    DBG_CAUSE_EBREAK  = 3'h1,
+    DBG_CAUSE_TRIGGER = 3'h2,
+    DBG_CAUSE_HALTREQ = 3'h3,
+    DBG_CAUSE_STEP    = 3'h4
+  } dbg_cause_e;
 
-// Interrupt requests
-typedef struct packed {
-  logic        irq_software;
-  logic        irq_timer;
-  logic        irq_external;
-  logic [14:0] irq_fast; // 15 fast interrupts,
-                         // one interrupt is reserved for NMI (not visible through mip/mie)
-} irqs_t;
+  // 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
 
-// Exception cause
-typedef enum logic [5:0] {
-  EXC_CAUSE_IRQ_SOFTWARE_M     = {1'b1, 5'd03},
-  EXC_CAUSE_IRQ_TIMER_M        = {1'b1, 5'd07},
-  EXC_CAUSE_IRQ_EXTERNAL_M     = {1'b1, 5'd11},
-  // EXC_CAUSE_IRQ_FAST_0      = {1'b1, 5'd16},
-  // EXC_CAUSE_IRQ_FAST_14     = {1'b1, 5'd30},
-  EXC_CAUSE_IRQ_NM             = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15
-  EXC_CAUSE_INSN_ADDR_MISA     = {1'b0, 5'd00},
-  EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01},
-  EXC_CAUSE_ILLEGAL_INSN       = {1'b0, 5'd02},
-  EXC_CAUSE_BREAKPOINT         = {1'b0, 5'd03},
-  EXC_CAUSE_LOAD_ACCESS_FAULT  = {1'b0, 5'd05},
-  EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
-  EXC_CAUSE_ECALL_UMODE        = {1'b0, 5'd08},
-  EXC_CAUSE_ECALL_MMODE        = {1'b0, 5'd11}
-} exc_cause_e;
+  // PMP constants
+  parameter int unsigned PMP_MAX_REGIONS      = 16;
+  parameter int unsigned PMP_CFG_W            = 8;
 
-// Debug cause
-typedef enum logic [2:0] {
-  DBG_CAUSE_NONE    = 3'h0,
-  DBG_CAUSE_EBREAK  = 3'h1,
-  DBG_CAUSE_TRIGGER = 3'h2,
-  DBG_CAUSE_HALTREQ = 3'h3,
-  DBG_CAUSE_STEP    = 3'h4
-} dbg_cause_e;
+  // PMP acces type
+  parameter int unsigned PMP_I  = 0;
+  parameter int unsigned PMP_I2 = 1;
+  parameter int unsigned PMP_D  = 2;
 
-// 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
+  typedef enum logic [1:0] {
+    PMP_ACC_EXEC    = 2'b00,
+    PMP_ACC_WRITE   = 2'b01,
+    PMP_ACC_READ    = 2'b10
+  } pmp_req_e;
 
-// PMP constants
-parameter int unsigned PMP_MAX_REGIONS      = 16;
-parameter int unsigned PMP_CFG_W            = 8;
+  // PMP cfg structures
+  typedef enum logic [1:0] {
+    PMP_MODE_OFF   = 2'b00,
+    PMP_MODE_TOR   = 2'b01,
+    PMP_MODE_NA4   = 2'b10,
+    PMP_MODE_NAPOT = 2'b11
+  } pmp_cfg_mode_e;
 
-// PMP acces type
-parameter int unsigned PMP_I = 0;
-parameter int unsigned PMP_D = 1;
+  typedef struct packed {
+    logic          lock;
+    pmp_cfg_mode_e mode;
+    logic          exec;
+    logic          write;
+    logic          read;
+  } pmp_cfg_t;
 
-typedef enum logic [1:0] {
-  PMP_ACC_EXEC    = 2'b00,
-  PMP_ACC_WRITE   = 2'b01,
-  PMP_ACC_READ    = 2'b10
-} pmp_req_e;
+  // Machine Security Configuration (ePMP)
+  typedef struct packed {
+    logic rlb;  // Rule Locking Bypass
+    logic mmwp; // Machine Mode Whitelist Policy
+    logic mml;  // Machine Mode Lockdown
+  } pmp_mseccfg_t;
 
-// PMP cfg structures
-typedef enum logic [1:0] {
-  PMP_MODE_OFF   = 2'b00,
-  PMP_MODE_TOR   = 2'b01,
-  PMP_MODE_NA4   = 2'b10,
-  PMP_MODE_NAPOT = 2'b11
-} pmp_cfg_mode_e;
+  // CSRs
+  typedef enum logic[11:0] {
+    // Machine information
+    CSR_MVENDORID = 12'hF11,
+    CSR_MARCHID   = 12'hF12,
+    CSR_MIMPID    = 12'hF13,
+    CSR_MHARTID   = 12'hF14,
 
-typedef struct packed {
-  logic          lock;
-  pmp_cfg_mode_e mode;
-  logic          exec;
-  logic          write;
-  logic          read;
-} pmp_cfg_t;
+    // Machine trap setup
+    CSR_MSTATUS   = 12'h300,
+    CSR_MISA      = 12'h301,
+    CSR_MIE       = 12'h304,
+    CSR_MTVEC     = 12'h305,
+    CSR_MCOUNTEREN= 12'h306,
 
-// Machine Security Configuration (ePMP)
-typedef struct packed {
-  logic rlb;  // Rule Locking Bypass
-  logic mmwp; // Machine Mode Whitelist Policy
-  logic mml;  // Machine Mode Lockdown
-} pmp_mseccfg_t;
+    // Machine trap handling
+    CSR_MSCRATCH  = 12'h340,
+    CSR_MEPC      = 12'h341,
+    CSR_MCAUSE    = 12'h342,
+    CSR_MTVAL     = 12'h343,
+    CSR_MIP       = 12'h344,
 
-// CSRs
-typedef enum logic[11:0] {
-  // Machine information
-  CSR_MHARTID   = 12'hF14,
+    // Physical memory protection
+    CSR_PMPCFG0   = 12'h3A0,
+    CSR_PMPCFG1   = 12'h3A1,
+    CSR_PMPCFG2   = 12'h3A2,
+    CSR_PMPCFG3   = 12'h3A3,
+    CSR_PMPADDR0  = 12'h3B0,
+    CSR_PMPADDR1  = 12'h3B1,
+    CSR_PMPADDR2  = 12'h3B2,
+    CSR_PMPADDR3  = 12'h3B3,
+    CSR_PMPADDR4  = 12'h3B4,
+    CSR_PMPADDR5  = 12'h3B5,
+    CSR_PMPADDR6  = 12'h3B6,
+    CSR_PMPADDR7  = 12'h3B7,
+    CSR_PMPADDR8  = 12'h3B8,
+    CSR_PMPADDR9  = 12'h3B9,
+    CSR_PMPADDR10 = 12'h3BA,
+    CSR_PMPADDR11 = 12'h3BB,
+    CSR_PMPADDR12 = 12'h3BC,
+    CSR_PMPADDR13 = 12'h3BD,
+    CSR_PMPADDR14 = 12'h3BE,
+    CSR_PMPADDR15 = 12'h3BF,
 
-  // Machine trap setup
-  CSR_MSTATUS   = 12'h300,
-  CSR_MISA      = 12'h301,
-  CSR_MIE       = 12'h304,
-  CSR_MTVEC     = 12'h305,
-  CSR_MCOUNTEREN= 12'h306,
+    // ePMP control
+    CSR_MSECCFG   = 12'h747,
+    CSR_MSECCFGH  = 12'h757,
 
-  // Machine trap handling
-  CSR_MSCRATCH  = 12'h340,
-  CSR_MEPC      = 12'h341,
-  CSR_MCAUSE    = 12'h342,
-  CSR_MTVAL     = 12'h343,
-  CSR_MIP       = 12'h344,
+    // Debug trigger
+    CSR_TSELECT   = 12'h7A0,
+    CSR_TDATA1    = 12'h7A1,
+    CSR_TDATA2    = 12'h7A2,
+    CSR_TDATA3    = 12'h7A3,
+    CSR_MCONTEXT  = 12'h7A8,
+    CSR_SCONTEXT  = 12'h7AA,
 
-  // Physical memory protection
-  CSR_PMPCFG0   = 12'h3A0,
-  CSR_PMPCFG1   = 12'h3A1,
-  CSR_PMPCFG2   = 12'h3A2,
-  CSR_PMPCFG3   = 12'h3A3,
-  CSR_PMPADDR0  = 12'h3B0,
-  CSR_PMPADDR1  = 12'h3B1,
-  CSR_PMPADDR2  = 12'h3B2,
-  CSR_PMPADDR3  = 12'h3B3,
-  CSR_PMPADDR4  = 12'h3B4,
-  CSR_PMPADDR5  = 12'h3B5,
-  CSR_PMPADDR6  = 12'h3B6,
-  CSR_PMPADDR7  = 12'h3B7,
-  CSR_PMPADDR8  = 12'h3B8,
-  CSR_PMPADDR9  = 12'h3B9,
-  CSR_PMPADDR10 = 12'h3BA,
-  CSR_PMPADDR11 = 12'h3BB,
-  CSR_PMPADDR12 = 12'h3BC,
-  CSR_PMPADDR13 = 12'h3BD,
-  CSR_PMPADDR14 = 12'h3BE,
-  CSR_PMPADDR15 = 12'h3BF,
+    // Debug/trace
+    CSR_DCSR      = 12'h7b0,
+    CSR_DPC       = 12'h7b1,
 
-  // ePMP control
-  CSR_MSECCFG   = 12'h747,
-  CSR_MSECCFGH  = 12'h757,
+    // Debug
+    CSR_DSCRATCH0 = 12'h7b2, // optional
+    CSR_DSCRATCH1 = 12'h7b3, // optional
 
-  // Debug trigger
-  CSR_TSELECT   = 12'h7A0,
-  CSR_TDATA1    = 12'h7A1,
-  CSR_TDATA2    = 12'h7A2,
-  CSR_TDATA3    = 12'h7A3,
-  CSR_MCONTEXT  = 12'h7A8,
-  CSR_SCONTEXT  = 12'h7AA,
+    // Machine Counter/Timers
+    CSR_MCOUNTINHIBIT  = 12'h320,
+    CSR_MHPMEVENT3     = 12'h323,
+    CSR_MHPMEVENT4     = 12'h324,
+    CSR_MHPMEVENT5     = 12'h325,
+    CSR_MHPMEVENT6     = 12'h326,
+    CSR_MHPMEVENT7     = 12'h327,
+    CSR_MHPMEVENT8     = 12'h328,
+    CSR_MHPMEVENT9     = 12'h329,
+    CSR_MHPMEVENT10    = 12'h32A,
+    CSR_MHPMEVENT11    = 12'h32B,
+    CSR_MHPMEVENT12    = 12'h32C,
+    CSR_MHPMEVENT13    = 12'h32D,
+    CSR_MHPMEVENT14    = 12'h32E,
+    CSR_MHPMEVENT15    = 12'h32F,
+    CSR_MHPMEVENT16    = 12'h330,
+    CSR_MHPMEVENT17    = 12'h331,
+    CSR_MHPMEVENT18    = 12'h332,
+    CSR_MHPMEVENT19    = 12'h333,
+    CSR_MHPMEVENT20    = 12'h334,
+    CSR_MHPMEVENT21    = 12'h335,
+    CSR_MHPMEVENT22    = 12'h336,
+    CSR_MHPMEVENT23    = 12'h337,
+    CSR_MHPMEVENT24    = 12'h338,
+    CSR_MHPMEVENT25    = 12'h339,
+    CSR_MHPMEVENT26    = 12'h33A,
+    CSR_MHPMEVENT27    = 12'h33B,
+    CSR_MHPMEVENT28    = 12'h33C,
+    CSR_MHPMEVENT29    = 12'h33D,
+    CSR_MHPMEVENT30    = 12'h33E,
+    CSR_MHPMEVENT31    = 12'h33F,
+    CSR_MCYCLE         = 12'hB00,
+    CSR_MINSTRET       = 12'hB02,
+    CSR_MHPMCOUNTER3   = 12'hB03,
+    CSR_MHPMCOUNTER4   = 12'hB04,
+    CSR_MHPMCOUNTER5   = 12'hB05,
+    CSR_MHPMCOUNTER6   = 12'hB06,
+    CSR_MHPMCOUNTER7   = 12'hB07,
+    CSR_MHPMCOUNTER8   = 12'hB08,
+    CSR_MHPMCOUNTER9   = 12'hB09,
+    CSR_MHPMCOUNTER10  = 12'hB0A,
+    CSR_MHPMCOUNTER11  = 12'hB0B,
+    CSR_MHPMCOUNTER12  = 12'hB0C,
+    CSR_MHPMCOUNTER13  = 12'hB0D,
+    CSR_MHPMCOUNTER14  = 12'hB0E,
+    CSR_MHPMCOUNTER15  = 12'hB0F,
+    CSR_MHPMCOUNTER16  = 12'hB10,
+    CSR_MHPMCOUNTER17  = 12'hB11,
+    CSR_MHPMCOUNTER18  = 12'hB12,
+    CSR_MHPMCOUNTER19  = 12'hB13,
+    CSR_MHPMCOUNTER20  = 12'hB14,
+    CSR_MHPMCOUNTER21  = 12'hB15,
+    CSR_MHPMCOUNTER22  = 12'hB16,
+    CSR_MHPMCOUNTER23  = 12'hB17,
+    CSR_MHPMCOUNTER24  = 12'hB18,
+    CSR_MHPMCOUNTER25  = 12'hB19,
+    CSR_MHPMCOUNTER26  = 12'hB1A,
+    CSR_MHPMCOUNTER27  = 12'hB1B,
+    CSR_MHPMCOUNTER28  = 12'hB1C,
+    CSR_MHPMCOUNTER29  = 12'hB1D,
+    CSR_MHPMCOUNTER30  = 12'hB1E,
+    CSR_MHPMCOUNTER31  = 12'hB1F,
+    CSR_MCYCLEH        = 12'hB80,
+    CSR_MINSTRETH      = 12'hB82,
+    CSR_MHPMCOUNTER3H  = 12'hB83,
+    CSR_MHPMCOUNTER4H  = 12'hB84,
+    CSR_MHPMCOUNTER5H  = 12'hB85,
+    CSR_MHPMCOUNTER6H  = 12'hB86,
+    CSR_MHPMCOUNTER7H  = 12'hB87,
+    CSR_MHPMCOUNTER8H  = 12'hB88,
+    CSR_MHPMCOUNTER9H  = 12'hB89,
+    CSR_MHPMCOUNTER10H = 12'hB8A,
+    CSR_MHPMCOUNTER11H = 12'hB8B,
+    CSR_MHPMCOUNTER12H = 12'hB8C,
+    CSR_MHPMCOUNTER13H = 12'hB8D,
+    CSR_MHPMCOUNTER14H = 12'hB8E,
+    CSR_MHPMCOUNTER15H = 12'hB8F,
+    CSR_MHPMCOUNTER16H = 12'hB90,
+    CSR_MHPMCOUNTER17H = 12'hB91,
+    CSR_MHPMCOUNTER18H = 12'hB92,
+    CSR_MHPMCOUNTER19H = 12'hB93,
+    CSR_MHPMCOUNTER20H = 12'hB94,
+    CSR_MHPMCOUNTER21H = 12'hB95,
+    CSR_MHPMCOUNTER22H = 12'hB96,
+    CSR_MHPMCOUNTER23H = 12'hB97,
+    CSR_MHPMCOUNTER24H = 12'hB98,
+    CSR_MHPMCOUNTER25H = 12'hB99,
+    CSR_MHPMCOUNTER26H = 12'hB9A,
+    CSR_MHPMCOUNTER27H = 12'hB9B,
+    CSR_MHPMCOUNTER28H = 12'hB9C,
+    CSR_MHPMCOUNTER29H = 12'hB9D,
+    CSR_MHPMCOUNTER30H = 12'hB9E,
+    CSR_MHPMCOUNTER31H = 12'hB9F,
+    CSR_CPUCTRL        = 12'h7C0,
+    CSR_SECURESEED     = 12'h7C1
+  } csr_num_e;
 
-  // Debug/trace
-  CSR_DCSR      = 12'h7b0,
-  CSR_DPC       = 12'h7b1,
+  // CSR pmp-related offsets
+  parameter logic [11:0] CSR_OFF_PMP_CFG  = 12'h3A0; // pmp_cfg  @ 12'h3a0 - 12'h3a3
+  parameter logic [11:0] CSR_OFF_PMP_ADDR = 12'h3B0; // pmp_addr @ 12'h3b0 - 12'h3bf
 
-  // Debug
-  CSR_DSCRATCH0 = 12'h7b2, // optional
-  CSR_DSCRATCH1 = 12'h7b3, // optional
+  // CSR status bits
+  parameter int unsigned CSR_MSTATUS_MIE_BIT      = 3;
+  parameter int unsigned CSR_MSTATUS_MPIE_BIT     = 7;
+  parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW  = 11;
+  parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12;
+  parameter int unsigned CSR_MSTATUS_MPRV_BIT     = 17;
+  parameter int unsigned CSR_MSTATUS_TW_BIT       = 21;
 
-  // Machine Counter/Timers
-  CSR_MCOUNTINHIBIT  = 12'h320,
-  CSR_MHPMEVENT3     = 12'h323,
-  CSR_MHPMEVENT4     = 12'h324,
-  CSR_MHPMEVENT5     = 12'h325,
-  CSR_MHPMEVENT6     = 12'h326,
-  CSR_MHPMEVENT7     = 12'h327,
-  CSR_MHPMEVENT8     = 12'h328,
-  CSR_MHPMEVENT9     = 12'h329,
-  CSR_MHPMEVENT10    = 12'h32A,
-  CSR_MHPMEVENT11    = 12'h32B,
-  CSR_MHPMEVENT12    = 12'h32C,
-  CSR_MHPMEVENT13    = 12'h32D,
-  CSR_MHPMEVENT14    = 12'h32E,
-  CSR_MHPMEVENT15    = 12'h32F,
-  CSR_MHPMEVENT16    = 12'h330,
-  CSR_MHPMEVENT17    = 12'h331,
-  CSR_MHPMEVENT18    = 12'h332,
-  CSR_MHPMEVENT19    = 12'h333,
-  CSR_MHPMEVENT20    = 12'h334,
-  CSR_MHPMEVENT21    = 12'h335,
-  CSR_MHPMEVENT22    = 12'h336,
-  CSR_MHPMEVENT23    = 12'h337,
-  CSR_MHPMEVENT24    = 12'h338,
-  CSR_MHPMEVENT25    = 12'h339,
-  CSR_MHPMEVENT26    = 12'h33A,
-  CSR_MHPMEVENT27    = 12'h33B,
-  CSR_MHPMEVENT28    = 12'h33C,
-  CSR_MHPMEVENT29    = 12'h33D,
-  CSR_MHPMEVENT30    = 12'h33E,
-  CSR_MHPMEVENT31    = 12'h33F,
-  CSR_MCYCLE         = 12'hB00,
-  CSR_MINSTRET       = 12'hB02,
-  CSR_MHPMCOUNTER3   = 12'hB03,
-  CSR_MHPMCOUNTER4   = 12'hB04,
-  CSR_MHPMCOUNTER5   = 12'hB05,
-  CSR_MHPMCOUNTER6   = 12'hB06,
-  CSR_MHPMCOUNTER7   = 12'hB07,
-  CSR_MHPMCOUNTER8   = 12'hB08,
-  CSR_MHPMCOUNTER9   = 12'hB09,
-  CSR_MHPMCOUNTER10  = 12'hB0A,
-  CSR_MHPMCOUNTER11  = 12'hB0B,
-  CSR_MHPMCOUNTER12  = 12'hB0C,
-  CSR_MHPMCOUNTER13  = 12'hB0D,
-  CSR_MHPMCOUNTER14  = 12'hB0E,
-  CSR_MHPMCOUNTER15  = 12'hB0F,
-  CSR_MHPMCOUNTER16  = 12'hB10,
-  CSR_MHPMCOUNTER17  = 12'hB11,
-  CSR_MHPMCOUNTER18  = 12'hB12,
-  CSR_MHPMCOUNTER19  = 12'hB13,
-  CSR_MHPMCOUNTER20  = 12'hB14,
-  CSR_MHPMCOUNTER21  = 12'hB15,
-  CSR_MHPMCOUNTER22  = 12'hB16,
-  CSR_MHPMCOUNTER23  = 12'hB17,
-  CSR_MHPMCOUNTER24  = 12'hB18,
-  CSR_MHPMCOUNTER25  = 12'hB19,
-  CSR_MHPMCOUNTER26  = 12'hB1A,
-  CSR_MHPMCOUNTER27  = 12'hB1B,
-  CSR_MHPMCOUNTER28  = 12'hB1C,
-  CSR_MHPMCOUNTER29  = 12'hB1D,
-  CSR_MHPMCOUNTER30  = 12'hB1E,
-  CSR_MHPMCOUNTER31  = 12'hB1F,
-  CSR_MCYCLEH        = 12'hB80,
-  CSR_MINSTRETH      = 12'hB82,
-  CSR_MHPMCOUNTER3H  = 12'hB83,
-  CSR_MHPMCOUNTER4H  = 12'hB84,
-  CSR_MHPMCOUNTER5H  = 12'hB85,
-  CSR_MHPMCOUNTER6H  = 12'hB86,
-  CSR_MHPMCOUNTER7H  = 12'hB87,
-  CSR_MHPMCOUNTER8H  = 12'hB88,
-  CSR_MHPMCOUNTER9H  = 12'hB89,
-  CSR_MHPMCOUNTER10H = 12'hB8A,
-  CSR_MHPMCOUNTER11H = 12'hB8B,
-  CSR_MHPMCOUNTER12H = 12'hB8C,
-  CSR_MHPMCOUNTER13H = 12'hB8D,
-  CSR_MHPMCOUNTER14H = 12'hB8E,
-  CSR_MHPMCOUNTER15H = 12'hB8F,
-  CSR_MHPMCOUNTER16H = 12'hB90,
-  CSR_MHPMCOUNTER17H = 12'hB91,
-  CSR_MHPMCOUNTER18H = 12'hB92,
-  CSR_MHPMCOUNTER19H = 12'hB93,
-  CSR_MHPMCOUNTER20H = 12'hB94,
-  CSR_MHPMCOUNTER21H = 12'hB95,
-  CSR_MHPMCOUNTER22H = 12'hB96,
-  CSR_MHPMCOUNTER23H = 12'hB97,
-  CSR_MHPMCOUNTER24H = 12'hB98,
-  CSR_MHPMCOUNTER25H = 12'hB99,
-  CSR_MHPMCOUNTER26H = 12'hB9A,
-  CSR_MHPMCOUNTER27H = 12'hB9B,
-  CSR_MHPMCOUNTER28H = 12'hB9C,
-  CSR_MHPMCOUNTER29H = 12'hB9D,
-  CSR_MHPMCOUNTER30H = 12'hB9E,
-  CSR_MHPMCOUNTER31H = 12'hB9F,
-  CSR_CPUCTRL        = 12'h7C0,
-  CSR_SECURESEED     = 12'h7C1
-} csr_num_e;
+  // CSR machine ISA
+  parameter logic [1:0] CSR_MISA_MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32
 
-// CSR pmp-related offsets
-parameter logic [11:0] CSR_OFF_PMP_CFG  = 12'h3A0; // pmp_cfg  @ 12'h3a0 - 12'h3a3
-parameter logic [11:0] CSR_OFF_PMP_ADDR = 12'h3B0; // pmp_addr @ 12'h3b0 - 12'h3bf
+  // CSR interrupt pending/enable bits
+  parameter int unsigned CSR_MSIX_BIT      = 3;
+  parameter int unsigned CSR_MTIX_BIT      = 7;
+  parameter int unsigned CSR_MEIX_BIT      = 11;
+  parameter int unsigned CSR_MFIX_BIT_LOW  = 16;
+  parameter int unsigned CSR_MFIX_BIT_HIGH = 30;
 
-// CSR status bits
-parameter int unsigned CSR_MSTATUS_MIE_BIT      = 3;
-parameter int unsigned CSR_MSTATUS_MPIE_BIT     = 7;
-parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW  = 11;
-parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12;
-parameter int unsigned CSR_MSTATUS_MPRV_BIT     = 17;
-parameter int unsigned CSR_MSTATUS_TW_BIT       = 21;
+  // CSR Machine Security Configuration bits
+  parameter int unsigned CSR_MSECCFG_MML_BIT  = 0;
+  parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1;
+  parameter int unsigned CSR_MSECCFG_RLB_BIT  = 2;
 
-// CSR machine ISA
-parameter logic [1:0] CSR_MISA_MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32
+  // Vendor ID
+  // No JEDEC ID has been allocated to lowRISC so the value is 0 to indicate the field is not
+  // implemented
+  localparam logic [31:0] CSR_MVENDORID_VALUE  = 32'b0;
 
-// CSR interrupt pending/enable bits
-parameter int unsigned CSR_MSIX_BIT      = 3;
-parameter int unsigned CSR_MTIX_BIT      = 7;
-parameter int unsigned CSR_MEIX_BIT      = 11;
-parameter int unsigned CSR_MFIX_BIT_LOW  = 16;
-parameter int unsigned CSR_MFIX_BIT_HIGH = 30;
+  // Architecture ID
+  // Top bit is unset to indicate an open source project. The lower bits are an ID allocated by the
+  // RISC-V Foundation. Note this is allocated specifically to Ibex, should significant changes be
+  // made a different architecture ID should be supplied.
+  localparam logic [31:0] CSR_MARCHID_VALUE = {1'b0, 31'd22};
 
-// CSR Machine Security Configuration bits
-parameter int unsigned CSR_MSECCFG_MML_BIT  = 0;
-parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1;
-parameter int unsigned CSR_MSECCFG_RLB_BIT  = 2;
+  // Implementation ID
+  // 0 indicates this field is not implemeted. Ibex implementors may wish to indicate an RTL/netlist
+  // version here using their own unique encoding (e.g. 32 bits of the git hash of the implemented
+  // commit).
+  localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0;
 
-// These LFSR parameters have been generated with
-// $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix ""
-parameter int LfsrWidth = 32;
-typedef logic [LfsrWidth-1:0] lfsr_seed_t;
-typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t;
-parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4;
-parameter lfsr_perm_t RndCnstLfsrPermDefault = {
-  160'h1e35ecba467fd1b12e958152c04fa43878a8daed
-};
+  // These LFSR parameters have been generated with
+  // $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix ""
+  parameter int LfsrWidth = 32;
+  typedef logic [LfsrWidth-1:0] lfsr_seed_t;
+  typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t;
+  parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4;
+  parameter lfsr_perm_t RndCnstLfsrPermDefault = {
+    160'h1e35ecba467fd1b12e958152c04fa43878a8daed
+  };
 
 endpackage
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
index 3d110f6..16e806a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
@@ -3,28 +3,28 @@
 // SPDX-License-Identifier: Apache-2.0
 
 module ibex_pmp #(
-    // Granularity of NAPOT access,
-    // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc.
-    parameter int unsigned PMPGranularity = 0,
-    // Number of access channels (e.g. i-side + d-side)
-    parameter int unsigned PMPNumChan     = 2,
-    // Number of implemented regions
-    parameter int unsigned PMPNumRegions  = 4
+  // Granularity of NAPOT access,
+  // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc.
+  parameter int unsigned PMPGranularity = 0,
+  // Number of access channels (e.g. i-side + d-side)
+  parameter int unsigned PMPNumChan     = 2,
+  // Number of implemented regions
+  parameter int unsigned PMPNumRegions  = 4
 ) (
-    // Clock and Reset
-    input  logic                    clk_i,
-    input  logic                    rst_ni,
+  // Clock and Reset
+  input  logic                    clk_i,
+  input  logic                    rst_ni,
 
-    // Interface to CSRs
-    input  ibex_pkg::pmp_cfg_t      csr_pmp_cfg_i     [PMPNumRegions],
-    input  logic [33:0]             csr_pmp_addr_i    [PMPNumRegions],
-    input  ibex_pkg::pmp_mseccfg_t  csr_pmp_mseccfg_i,
+  // Interface to CSRs
+  input  ibex_pkg::pmp_cfg_t      csr_pmp_cfg_i     [PMPNumRegions],
+  input  logic [33:0]             csr_pmp_addr_i    [PMPNumRegions],
+  input  ibex_pkg::pmp_mseccfg_t  csr_pmp_mseccfg_i,
 
-    input  ibex_pkg::priv_lvl_e     priv_mode_i    [PMPNumChan],
-    // Access checking channels
-    input  logic [33:0]             pmp_req_addr_i [PMPNumChan],
-    input  ibex_pkg::pmp_req_e      pmp_req_type_i [PMPNumChan],
-    output logic                    pmp_req_err_o  [PMPNumChan]
+  input  ibex_pkg::priv_lvl_e     priv_mode_i    [PMPNumChan],
+  // Access checking channels
+  input  logic [33:0]             pmp_req_addr_i [PMPNumChan],
+  input  ibex_pkg::pmp_req_e      pmp_req_type_i [PMPNumChan],
+  output logic                    pmp_req_err_o  [PMPNumChan]
 
 );
 
@@ -56,7 +56,7 @@
                                                                               csr_pmp_addr_i[r];
     end
     // Address mask for NA matching
-    for (genvar b = PMPGranularity+2; b < 34; b++) begin : g_bitmask
+    for (genvar b = PMPGranularity + 2; b < 34; b++) begin : g_bitmask
       if (b == 2) begin : g_bit0
         // Always mask bit 2 for NAPOT
         assign region_addr_mask[r][b] = (csr_pmp_cfg_i[r].mode != PMP_MODE_NAPOT);
@@ -92,14 +92,14 @@
       always_comb begin
         region_match_all[c][r] = 1'b0;
         unique case (csr_pmp_cfg_i[r].mode)
-          PMP_MODE_OFF   : region_match_all[c][r] = 1'b0;
-          PMP_MODE_NA4   : region_match_all[c][r] = region_match_eq[c][r];
-          PMP_MODE_NAPOT : region_match_all[c][r] = region_match_eq[c][r];
-          PMP_MODE_TOR   : begin
+          PMP_MODE_OFF:   region_match_all[c][r] = 1'b0;
+          PMP_MODE_NA4:   region_match_all[c][r] = region_match_eq[c][r];
+          PMP_MODE_NAPOT: region_match_all[c][r] = region_match_eq[c][r];
+          PMP_MODE_TOR: begin
             region_match_all[c][r] = (region_match_eq[c][r] | region_match_gt[c][r]) &
                                      region_match_lt[c][r];
           end
-          default        : region_match_all[c][r] = 1'b0;
+          default:        region_match_all[c][r] = 1'b0;
         endcase
       end
 
@@ -156,7 +156,7 @@
 
       // PMP entries are statically prioritized, from 0 to N-1
       // The lowest-numbered PMP entry which matches an address determines accessability
-      for (int r = PMPNumRegions-1; r >= 0; r--) begin
+      for (int r = PMPNumRegions - 1; r >= 0; r--) begin
         if (region_match_all[c][r]) begin
           if (csr_pmp_mseccfg_i.mml) begin
             // When MSECCFG.MML is set use MML specific permission check
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
index d2b0f17..5b834ce 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
@@ -10,61 +10,52 @@
  * paths to the instruction cache.
  */
 module ibex_prefetch_buffer #(
-  parameter bit BranchPredictor = 1'b0,
   parameter bit ResetAll        = 1'b0
 ) (
-    input  logic        clk_i,
-    input  logic        rst_ni,
+  input  logic        clk_i,
+  input  logic        rst_ni,
 
-    input  logic        req_i,
+  input  logic        req_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,
+  input  logic        branch_i,
+  input  logic        branch_mispredict_i,
+  input  logic [31:0] mispredict_addr_i,
+  input  logic [31:0] addr_i,
 
 
-    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,
 
+  // goes to instruction memory / instruction cache
+  output logic        instr_req_o,
+  input  logic        instr_gnt_i,
+  output logic [31:0] instr_addr_o,
+  input  logic [31:0] instr_rdata_i,
+  input  logic        instr_err_i,
+  input  logic        instr_rvalid_i,
 
-    // goes to instruction memory / instruction cache
-    output logic        instr_req_o,
-    input  logic        instr_gnt_i,
-    output logic [31:0] instr_addr_o,
-    input  logic [31:0] instr_rdata_i,
-    input  logic        instr_err_i,
-    input  logic        instr_pmp_err_i,
-    input  logic        instr_rvalid_i,
-
-    // Prefetch Buffer Status
-    output logic        busy_o
+  // Prefetch Buffer Status
+  output logic        busy_o
 );
 
   localparam int unsigned NUM_REQS  = 2;
 
-  logic                branch_suppress;
   logic                valid_new_req, valid_req;
   logic                valid_req_d, valid_req_q;
   logic                discard_req_d, discard_req_q;
-  logic                gnt_or_pmp_err, rvalid_or_pmp_err;
   logic [NUM_REQS-1:0] rdata_outstanding_n, rdata_outstanding_s, rdata_outstanding_q;
   logic [NUM_REQS-1:0] branch_discard_n, branch_discard_s, branch_discard_q;
-  logic [NUM_REQS-1:0] rdata_pmp_err_n, rdata_pmp_err_s, rdata_pmp_err_q;
   logic [NUM_REQS-1:0] rdata_outstanding_rev;
 
   logic [31:0]         stored_addr_d, stored_addr_q;
   logic                stored_addr_en;
   logic [31:0]         fetch_addr_d, fetch_addr_q;
   logic                fetch_addr_en;
-  logic [31:0]         branch_mispredict_addr;
   logic [31:0]         instr_addr, instr_addr_w_aligned;
-  logic                instr_or_pmp_err;
 
   logic                fifo_valid;
   logic [31:0]         fifo_addr;
@@ -74,8 +65,6 @@
 
   logic                valid_raw;
 
-  logic [31:0]         addr_next;
-
   logic                branch_or_mispredict;
 
   ////////////////////////////
@@ -90,10 +79,6 @@
   // Fetch fifo - consumes addresses and data //
   //////////////////////////////////////////////
 
-  // Instruction fetch errors are valid on the data phase of a request
-  // PMP errors are generated in the address phase, and registered into a fake data phase
-  assign instr_or_pmp_err = instr_err_i | rdata_pmp_err_q[0];
-
   // A branch will invalidate any previously fetched instructions.
   // Note that the FENCE.I instruction relies on this flushing behaviour on branch. If it is
   // altered the FENCE.I implementation may require changes.
@@ -122,13 +107,12 @@
       .in_valid_i            ( fifo_valid        ),
       .in_addr_i             ( fifo_addr         ),
       .in_rdata_i            ( instr_rdata_i     ),
-      .in_err_i              ( instr_or_pmp_err  ),
+      .in_err_i              ( instr_err_i       ),
 
       .out_valid_o           ( valid_raw         ),
       .out_ready_i           ( ready_i           ),
       .out_rdata_o           ( rdata_o           ),
       .out_addr_o            ( addr_o            ),
-      .out_addr_next_o       ( addr_next         ),
       .out_err_o             ( err_o             ),
       .out_err_plus2_o       ( err_plus2_o       )
   );
@@ -137,25 +121,14 @@
   // Requests //
   //////////////
 
-  // Suppress a new request on a not-taken branch (as the external address will be incorrect)
-  assign branch_suppress = branch_spec_i & ~branch_i;
-
   // Make a new request any time there is space in the FIFO, and space in the request queue
-  assign valid_new_req = ~branch_suppress & req_i & (fifo_ready | branch_or_mispredict) &
+  assign valid_new_req = req_i & (fifo_ready | branch_or_mispredict) &
                          ~rdata_outstanding_q[NUM_REQS-1];
 
   assign valid_req = valid_req_q | valid_new_req;
 
-  // If a request address triggers a PMP error, the external bus request is suppressed. We might
-  // therefore never receive a grant for such a request. The grant is faked in this case to make
-  // sure the request proceeds and the error is pushed to the FIFO.
-  assign gnt_or_pmp_err = instr_gnt_i | instr_pmp_err_i;
-
-  // As with the grant, the rvalid must be faked for a PMP error, since the request was suppressed.
-  assign rvalid_or_pmp_err = rdata_outstanding_q[0] & (instr_rvalid_i | rdata_pmp_err_q[0]);
-
   // Hold the request stable for requests that didn't get granted
-  assign valid_req_d = valid_req & ~gnt_or_pmp_err;
+  assign valid_req_d = valid_req & ~instr_gnt_i;
 
   // Record whether an outstanding bus request is cancelled by a branch
   assign discard_req_d = valid_req_q & (branch_or_mispredict | discard_req_q);
@@ -177,7 +150,7 @@
   // 1. stored_addr_q
 
   // Only update stored_addr_q for new ungranted requests
-  assign stored_addr_en = valid_new_req & ~valid_req_q & ~gnt_or_pmp_err;
+  assign stored_addr_en = valid_new_req & ~valid_req_q & ~instr_gnt_i;
 
   // Store whatever address was issued on the bus
   assign stored_addr_d = instr_addr;
@@ -198,50 +171,13 @@
       end
     end
   end
-
-  if (BranchPredictor) begin : g_branch_predictor
-    // Where the branch predictor is present record what address followed a predicted branch.  If
-    // that branch is predicted taken but mispredicted (so not-taken) this is used to resume on
-    // the not-taken code path.
-    logic [31:0] branch_mispredict_addr_q;
-    logic        branch_mispredict_addr_en;
-
-    assign branch_mispredict_addr_en = branch_i & predicted_branch_i;
-
-    if (ResetAll) begin : g_branch_misp_addr_ra
-      always_ff @(posedge clk_i or negedge rst_ni) begin
-        if (!rst_ni) begin
-          branch_mispredict_addr_q <= '0;
-        end else if (branch_mispredict_addr_en) begin
-          branch_mispredict_addr_q <= addr_next;
-        end
-      end
-    end else begin : g_branch_misp_addr_nr
-      always_ff @(posedge clk_i) begin
-        if (branch_mispredict_addr_en) begin
-          branch_mispredict_addr_q <= addr_next;
-        end
-      end
-    end
-
-    assign branch_mispredict_addr = branch_mispredict_addr_q;
-  end else begin : g_no_branch_predictor
-    logic        unused_predicted_branch;
-    logic [31:0] unused_addr_next;
-
-    assign unused_predicted_branch = predicted_branch_i;
-    assign unused_addr_next        = addr_next;
-
-    assign branch_mispredict_addr = '0;
-  end
-
   // 2. fetch_addr_q
 
   // Update on a branch or as soon as a request is issued
   assign fetch_addr_en = branch_or_mispredict | (valid_new_req & ~valid_req_q);
 
   assign fetch_addr_d = (branch_i            ? addr_i :
-                         branch_mispredict_i ? {branch_mispredict_addr[31:2], 2'b00} :
+                         branch_mispredict_i ? {mispredict_addr_i[31:2], 2'b00} :
                                                {fetch_addr_q[31:2], 2'b00}) +
                         // Current address + 4
                         {{29{1'b0}},(valid_new_req & ~valid_req_q),2'b00};
@@ -264,8 +200,8 @@
 
   // Address mux
   assign instr_addr = valid_req_q         ? stored_addr_q :
-                      branch_spec_i       ? addr_i :
-                      branch_mispredict_i ? branch_mispredict_addr :
+                      branch_i            ? addr_i :
+                      branch_mispredict_i ? mispredict_addr_i :
                                             fetch_addr_q;
 
   assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00};
@@ -279,46 +215,38 @@
     if (i == 0) begin : g_req0
       // A request becomes outstanding once granted, and is cleared once the rvalid is received.
       // Outstanding requests shift down the queue towards entry 0.
-      assign rdata_outstanding_n[i] = (valid_req & gnt_or_pmp_err) |
+      assign rdata_outstanding_n[i] = (valid_req & instr_gnt_i) |
                                       rdata_outstanding_q[i];
       // If a branch is received at any point while a request is outstanding, it must be tracked
       // to ensure we discard the data once received
-      assign branch_discard_n[i]    = (valid_req & gnt_or_pmp_err & discard_req_d) |
+      assign branch_discard_n[i]    = (valid_req & instr_gnt_i & discard_req_d) |
                                       (branch_or_mispredict & rdata_outstanding_q[i]) |
                                       branch_discard_q[i];
-      // Record whether this request received a PMP error
-      assign rdata_pmp_err_n[i]     = (valid_req & ~rdata_outstanding_q[i] & instr_pmp_err_i) |
-                                      rdata_pmp_err_q[i];
 
     end else begin : g_reqtop
     // Entries > 0 consider the FIFO fill state to calculate their next state (by checking
     // whether the previous entry is valid)
 
-      assign rdata_outstanding_n[i] = (valid_req & gnt_or_pmp_err &
+      assign rdata_outstanding_n[i] = (valid_req & instr_gnt_i &
                                        rdata_outstanding_q[i-1]) |
                                       rdata_outstanding_q[i];
-      assign branch_discard_n[i]    = (valid_req & gnt_or_pmp_err & discard_req_d &
+      assign branch_discard_n[i]    = (valid_req & instr_gnt_i & discard_req_d &
                                        rdata_outstanding_q[i-1]) |
                                       (branch_or_mispredict & rdata_outstanding_q[i]) |
                                       branch_discard_q[i];
-      assign rdata_pmp_err_n[i]     = (valid_req & ~rdata_outstanding_q[i] & instr_pmp_err_i &
-                                       rdata_outstanding_q[i-1]) |
-                                      rdata_pmp_err_q[i];
     end
   end
 
   // Shift the entries down on each instr_rvalid_i
-  assign rdata_outstanding_s = rvalid_or_pmp_err ? {1'b0,rdata_outstanding_n[NUM_REQS-1:1]} :
-                                                   rdata_outstanding_n;
-  assign branch_discard_s    = rvalid_or_pmp_err ? {1'b0,branch_discard_n[NUM_REQS-1:1]} :
-                                                   branch_discard_n;
-  assign rdata_pmp_err_s     = rvalid_or_pmp_err ? {1'b0,rdata_pmp_err_n[NUM_REQS-1:1]} :
-                                                   rdata_pmp_err_n;
+  assign rdata_outstanding_s = instr_rvalid_i ? {1'b0,rdata_outstanding_n[NUM_REQS-1:1]} :
+                                                rdata_outstanding_n;
+  assign branch_discard_s    = instr_rvalid_i ? {1'b0,branch_discard_n[NUM_REQS-1:1]} :
+                                                branch_discard_n;
 
   // Push a new entry to the FIFO once complete (and not cancelled by a branch)
-  assign fifo_valid = rvalid_or_pmp_err & ~branch_discard_q[0];
+  assign fifo_valid = instr_rvalid_i & ~branch_discard_q[0];
 
-  assign fifo_addr = branch_i ? addr_i : branch_mispredict_addr;
+  assign fifo_addr = branch_i ? addr_i : mispredict_addr_i;
 
   ///////////////
   // Registers //
@@ -330,13 +258,11 @@
       discard_req_q        <= 1'b0;
       rdata_outstanding_q  <= 'b0;
       branch_discard_q     <= 'b0;
-      rdata_pmp_err_q      <= 'b0;
     end else begin
       valid_req_q          <= valid_req_d;
       discard_req_q        <= discard_req_d;
       rdata_outstanding_q  <= rdata_outstanding_s;
       branch_discard_q     <= branch_discard_s;
-      rdata_pmp_err_q      <= rdata_pmp_err_s;
     end
   end
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
index 3e887b1..0cd5e6f 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -11,30 +11,31 @@
  * targeting FPGA synthesis or Verilator simulation.
  */
 module ibex_register_file_ff #(
-    parameter bit          RV32E             = 0,
-    parameter int unsigned DataWidth         = 32,
-    parameter bit          DummyInstructions = 0
+  parameter bit                   RV32E             = 0,
+  parameter int unsigned          DataWidth         = 32,
+  parameter bit                   DummyInstructions = 0,
+  parameter logic [DataWidth-1:0] WordZeroVal       = '0
 ) (
-    // Clock and Reset
-    input  logic                 clk_i,
-    input  logic                 rst_ni,
+  // Clock and Reset
+  input  logic                 clk_i,
+  input  logic                 rst_ni,
 
-    input  logic                 test_en_i,
-    input  logic                 dummy_instr_id_i,
+  input  logic                 test_en_i,
+  input  logic                 dummy_instr_id_i,
 
-    //Read port R1
-    input  logic [4:0]           raddr_a_i,
-    output logic [DataWidth-1:0] rdata_a_o,
+  //Read port R1
+  input  logic [4:0]           raddr_a_i,
+  output logic [DataWidth-1:0] rdata_a_o,
 
-    //Read port R2
-    input  logic [4:0]           raddr_b_i,
-    output logic [DataWidth-1:0] rdata_b_o,
+  //Read port R2
+  input  logic [4:0]           raddr_b_i,
+  output logic [DataWidth-1:0] rdata_b_o,
 
 
-    // Write port W1
-    input  logic [4:0]           waddr_a_i,
-    input  logic [DataWidth-1:0] wdata_a_i,
-    input  logic                 we_a_i
+  // Write port W1
+  input  logic [4:0]           waddr_a_i,
+  input  logic [DataWidth-1:0] wdata_a_i,
+  input  logic                 we_a_i
 
 );
 
@@ -47,7 +48,7 @@
 
   always_comb begin : we_a_decoder
     for (int unsigned i = 1; i < NUM_WORDS; i++) begin
-      we_a_dec[i] = (waddr_a_i == 5'(i)) ?  we_a_i : 1'b0;
+      we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
     end
   end
 
@@ -55,8 +56,8 @@
   for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
     always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
-        rf_reg_q[i] <= '0;
-      end else if(we_a_dec[i]) begin
+        rf_reg_q[i] <= WordZeroVal;
+      end else if (we_a_dec[i]) begin
         rf_reg_q[i] <= wdata_a_i;
       end
     end
@@ -73,21 +74,21 @@
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
-        rf_r0_q <= '0;
+        rf_r0_q <= WordZeroVal;
       end else if (we_r0_dummy) begin
         rf_r0_q <= wdata_a_i;
       end
     end
 
     // Output the dummy data for dummy instructions, otherwise R0 reads as zero
-    assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0;
+    assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal;
 
   end else begin : g_normal_r0
     logic unused_dummy_instr_id;
     assign unused_dummy_instr_id = dummy_instr_id_i;
 
     // R0 is nil
-    assign rf_reg[0] = '0;
+    assign rf_reg[0] = WordZeroVal;
   end
 
   assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1];
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
index e603dc4..678549a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
@@ -12,9 +12,10 @@
  * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested.
  */
 module ibex_register_file_fpga #(
-  parameter bit          RV32E             = 0,
-  parameter int unsigned DataWidth         = 32,
-  parameter bit          DummyInstructions = 0
+    parameter bit                   RV32E             = 0,
+    parameter int unsigned          DataWidth         = 32,
+    parameter bit                   DummyInstructions = 0,
+    parameter logic [DataWidth-1:0] WordZeroVal       = '0
 ) (
   // Clock and Reset
   input  logic                 clk_i,
@@ -36,7 +37,7 @@
 );
 
   localparam int ADDR_WIDTH = RV32E ? 4 : 5;
-  localparam int NUM_WORDS  = 2**ADDR_WIDTH;
+  localparam int NUM_WORDS = 2 ** ADDR_WIDTH;
 
   logic [DataWidth-1:0] mem[NUM_WORDS];
   logic we; // write enable if writing to any register other than R0
@@ -50,12 +51,24 @@
   // we select
   assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i;
 
-  always_ff @(posedge clk_i) begin : sync_write
+  // Note that the SystemVerilog LRM requires variables on the LHS of assignments within
+  // "always_ff" to not be written to by any other process. However, to enable the initialization
+  // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed.
+  // Therefore, we use "always" instead of the generally preferred "always_ff" for the synchronous
+  // write procedure.
+  always @(posedge clk_i) begin : sync_write
     if (we == 1'b1) begin
       mem[waddr_a_i] <= wdata_a_i;
     end
   end : sync_write
 
+  // Make sure we initialize the BRAM with the correct register reset value.
+  initial begin
+    for (int k = 0; k < NUM_WORDS; k++) begin
+      mem[k] = WordZeroVal;
+    end
+  end
+
   // Reset not used in this register file version
   logic unused_rst_ni;
   assign unused_rst_ni = rst_ni;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
index 8c5fb35..717bcaf 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -12,29 +12,30 @@
  * register file when targeting ASIC synthesis or event-based simulators.
  */
 module ibex_register_file_latch #(
-    parameter bit          RV32E             = 0,
-    parameter int unsigned DataWidth         = 32,
-    parameter bit          DummyInstructions = 0
+  parameter bit                   RV32E             = 0,
+  parameter int unsigned          DataWidth         = 32,
+  parameter bit                   DummyInstructions = 0,
+  parameter logic [DataWidth-1:0] WordZeroVal       = '0
 ) (
-    // Clock and Reset
-    input  logic                 clk_i,
-    input  logic                 rst_ni,
+  // Clock and Reset
+  input  logic                 clk_i,
+  input  logic                 rst_ni,
 
-    input  logic                 test_en_i,
-    input  logic                 dummy_instr_id_i,
+  input  logic                 test_en_i,
+  input  logic                 dummy_instr_id_i,
 
-    //Read port R1
-    input  logic [4:0]           raddr_a_i,
-    output logic [DataWidth-1:0] rdata_a_o,
+  //Read port R1
+  input  logic [4:0]           raddr_a_i,
+  output logic [DataWidth-1:0] rdata_a_o,
 
-    //Read port R2
-    input  logic [4:0]           raddr_b_i,
-    output logic [DataWidth-1:0] rdata_b_o,
+  //Read port R2
+  input  logic [4:0]           raddr_b_i,
+  output logic [DataWidth-1:0] rdata_b_o,
 
-    // Write port W1
-    input  logic [4:0]           waddr_a_i,
-    input  logic [DataWidth-1:0] wdata_a_i,
-    input  logic                 we_a_i
+  // Write port W1
+  input  logic [4:0]           waddr_a_i,
+  input  logic [DataWidth-1:0] wdata_a_i,
+  input  logic                 we_a_i
 
 );
 
@@ -78,7 +79,7 @@
   // Use clk_int here, since otherwise we don't want to write anything anyway.
   always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata
     if (!rst_ni) begin
-      wdata_a_q   <= '0;
+      wdata_a_q   <= WordZeroVal;
     end else begin
       if (we_a_i) begin
         wdata_a_q <= wdata_a_i;
@@ -143,13 +144,13 @@
     end
 
     // Output the dummy data for dummy instructions, otherwise R0 reads as zero
-    assign mem[0] = dummy_instr_id_i ? mem_r0 : '0;
+    assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal;
 
   end else begin : g_normal_r0
     logic unused_dummy_instr_id;
     assign unused_dummy_instr_id = dummy_instr_id_i;
 
-    assign mem[0] = '0;
+    assign mem[0] = WordZeroVal;
   end
 
 `ifdef VERILATOR
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
index c0148ea..71bc1ba 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
@@ -13,108 +13,112 @@
  * Top level module of the ibex RISC-V core
  */
 module ibex_top 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 regfile_e    RegFile          = 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 lfsr_seed_t  RndCnstLfsrSeed  = RndCnstLfsrSeedDefault,
-    parameter lfsr_perm_t  RndCnstLfsrPerm  = RndCnstLfsrPermDefault,
-    parameter int unsigned DmHaltAddr       = 32'h1A110800,
-    parameter int unsigned DmExceptionAddr  = 32'h1A110808
+  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 regfile_e    RegFile          = 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 lfsr_seed_t  RndCnstLfsrSeed  = RndCnstLfsrSeedDefault,
+  parameter lfsr_perm_t  RndCnstLfsrPerm  = RndCnstLfsrPermDefault,
+  parameter int unsigned DmHaltAddr       = 32'h1A110800,
+  parameter int unsigned DmExceptionAddr  = 32'h1A110808
 ) (
-    // Clock and Reset
-    input  logic                         clk_i,
-    input  logic                         rst_ni,
+  // 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                         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,
+  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 [6:0]                   instr_rdata_intg_i,
-    input  logic                         instr_err_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 [6:0]                   instr_rdata_intg_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,
-    output logic [6:0]                   data_wdata_intg_o,
-    input  logic [31:0]                  data_rdata_i,
-    input  logic [6:0]                   data_rdata_intg_i,
-    input  logic                         data_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,
+  output logic [6:0]                   data_wdata_intg_o,
+  input  logic [31:0]                  data_rdata_i,
+  input  logic [6:0]                   data_rdata_intg_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
+  // 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 crash_dump_t                  crash_dump_o,
+  // Debug Interface
+  input  logic                         debug_req_i,
+  output 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.
+  // 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,
+  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,
+  output logic [31:0]                  rvfi_ext_mip,
+  output logic                         rvfi_ext_nmi,
+  output logic                         rvfi_ext_debug_req,
+  output logic [63:0]                  rvfi_ext_mcycle,
 `endif
 
-    // CPU Control Signals
-    input  logic                         fetch_enable_i,
-    output logic                         alert_minor_o,
-    output logic                         alert_major_o,
-    output logic                         core_sleep_o,
+  // CPU Control Signals
+  input  logic                         fetch_enable_i,
+  output logic                         alert_minor_o,
+  output logic                         alert_major_o,
+  output logic                         core_sleep_o,
 
-    // DFT bypass controls
-    input logic                          scan_rst_ni
+  // DFT bypass controls
+  input logic                          scan_rst_ni
 );
 
   localparam bit          Lockstep          = SecureIbex;
@@ -172,10 +176,10 @@
   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             )
+    .clk_i    (clk_i),
+    .en_i     (clock_en),
+    .test_en_i(test_en_i),
+    .clk_o    (clk)
   );
 
   ////////////////////////
@@ -183,35 +187,35 @@
   ////////////////////////
 
   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    ),
-    .ResetAll          ( ResetAll          ),
-    .RndCnstLfsrSeed   ( RndCnstLfsrSeed   ),
-    .RndCnstLfsrPerm   ( RndCnstLfsrPerm   ),
-    .SecureIbex        ( SecureIbex        ),
-    .DummyInstructions ( DummyInstructions ),
-    .RegFileECC        ( RegFileECC        ),
-    .RegFileDataWidth  ( RegFileDataWidth  ),
-    .DmHaltAddr        ( DmHaltAddr        ),
-    .DmExceptionAddr   ( DmExceptionAddr   )
+    .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),
+    .ResetAll         (ResetAll),
+    .RndCnstLfsrSeed  (RndCnstLfsrSeed),
+    .RndCnstLfsrPerm  (RndCnstLfsrPerm),
+    .SecureIbex       (SecureIbex),
+    .DummyInstructions(DummyInstructions),
+    .RegFileECC       (RegFileECC),
+    .RegFileDataWidth (RegFileDataWidth),
+    .DmHaltAddr       (DmHaltAddr),
+    .DmExceptionAddr  (DmExceptionAddr)
   ) u_ibex_core (
-    .clk_i (clk),
+    .clk_i(clk),
     .rst_ni,
 
     .hart_id_i,
@@ -234,32 +238,32 @@
     .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),
+    .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),
+    .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),
+    .irq_pending_o(irq_pending),
 
     .debug_req_i,
     .crash_dump_o,
@@ -288,12 +292,16 @@
     .rvfi_mem_wmask,
     .rvfi_mem_rdata,
     .rvfi_mem_wdata,
+    .rvfi_ext_mip,
+    .rvfi_ext_nmi,
+    .rvfi_ext_debug_req,
+    .rvfi_ext_mcycle,
 `endif
 
     .fetch_enable_i,
-    .alert_minor_o (core_alert_minor),
-    .alert_major_o (core_alert_major),
-    .core_busy_o (core_busy_d)
+    .alert_minor_o(core_alert_minor),
+    .alert_major_o(core_alert_major),
+    .core_busy_o  (core_busy_d)
   );
 
   /////////////////////////////////
@@ -302,63 +310,66 @@
 
   if (RegFile == RegFileFF) begin : gen_regfile_ff
     ibex_register_file_ff #(
-        .RV32E             ( RV32E             ),
-        .DataWidth         ( RegFileDataWidth  ),
-        .DummyInstructions ( DummyInstructions )
+      .RV32E            (RV32E),
+      .DataWidth        (RegFileDataWidth),
+      .DummyInstructions(DummyInstructions),
+      .WordZeroVal      (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
     ) register_file_i (
-        .clk_i            ( clk             ),
-        .rst_ni           ( rst_ni          ),
+      .clk_i (clk),
+      .rst_ni(rst_ni),
 
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
+      .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        )
+      .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 )
+      .RV32E            (RV32E),
+      .DataWidth        (RegFileDataWidth),
+      .DummyInstructions(DummyInstructions),
+      .WordZeroVal      (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
     ) register_file_i (
-        .clk_i            ( clk             ),
-        .rst_ni           ( rst_ni          ),
+      .clk_i (clk),
+      .rst_ni(rst_ni),
 
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
+      .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        )
+      .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 )
+      .RV32E            (RV32E),
+      .DataWidth        (RegFileDataWidth),
+      .DummyInstructions(DummyInstructions),
+      .WordZeroVal      (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
     ) register_file_i (
-        .clk_i            ( clk             ),
-        .rst_ni           ( rst_ni          ),
+      .clk_i (clk),
+      .rst_ni(rst_ni),
 
-        .test_en_i        ( test_en_i       ),
-        .dummy_instr_id_i ( dummy_instr_id  ),
+      .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        )
+      .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
 
@@ -371,33 +382,33 @@
     for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner
       // Tag RAM instantiation
       prim_ram_1p #(
-        .Width           (TagSizeECC),
-        .Depth           (IC_NUM_LINES),
-        .DataBitsPerMask (TagSizeECC)
+        .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])
+        .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)
+        .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])
+        .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
 
@@ -643,33 +654,33 @@
 
     logic lockstep_alert_minor_local, lockstep_alert_major_local;
     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    ),
-      .ResetAll          ( ResetAll          ),
-      .RndCnstLfsrSeed   ( RndCnstLfsrSeed   ),
-      .RndCnstLfsrPerm   ( RndCnstLfsrPerm   ),
-      .SecureIbex        ( SecureIbex        ),
-      .DummyInstructions ( DummyInstructions ),
-      .RegFileECC        ( RegFileECC        ),
-      .RegFileDataWidth  ( RegFileDataWidth  ),
-      .DmHaltAddr        ( DmHaltAddr        ),
-      .DmExceptionAddr   ( DmExceptionAddr   )
+      .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),
+      .ResetAll         (ResetAll),
+      .RndCnstLfsrSeed  (RndCnstLfsrSeed),
+      .RndCnstLfsrPerm  (RndCnstLfsrPerm),
+      .SecureIbex       (SecureIbex),
+      .DummyInstructions(DummyInstructions),
+      .RegFileECC       (RegFileECC),
+      .RegFileDataWidth (RegFileDataWidth),
+      .DmHaltAddr       (DmHaltAddr),
+      .DmExceptionAddr  (DmExceptionAddr)
     ) u_ibex_lockstep (
       .clk_i              (clk),
       .rst_ni             (rst_ni),
@@ -742,12 +753,12 @@
     );
 
     prim_buf u_prim_buf_alert_minor (
-      .in_i(lockstep_alert_minor_local),
+      .in_i (lockstep_alert_minor_local),
       .out_o(lockstep_alert_minor)
     );
 
     prim_buf u_prim_buf_alert_major (
-      .in_i(lockstep_alert_major_local),
+      .in_i (lockstep_alert_major_local),
       .out_o(lockstep_alert_major)
     );
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
index 340d9ee..c08fc18 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
@@ -7,78 +7,78 @@
  */
 
 module ibex_top_tracing 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 regfile_e    RegFile          = 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 lfsr_seed_t  RndCnstLfsrSeed  = RndCnstLfsrSeedDefault,
-    parameter lfsr_perm_t  RndCnstLfsrPerm  = RndCnstLfsrPermDefault,
-    parameter int unsigned DmHaltAddr       = 32'h1A110800,
-    parameter int unsigned DmExceptionAddr  = 32'h1A110808
+  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 regfile_e    RegFile          = 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 lfsr_seed_t  RndCnstLfsrSeed  = RndCnstLfsrSeedDefault,
+  parameter lfsr_perm_t  RndCnstLfsrPerm  = RndCnstLfsrPermDefault,
+  parameter int unsigned DmHaltAddr       = 32'h1A110800,
+  parameter int unsigned DmExceptionAddr  = 32'h1A110808
 ) (
-    // Clock and Reset
-    input  logic                         clk_i,
-    input  logic                         rst_ni,
+  // Clock and Reset
+  input  logic                         clk_i,
+  input  logic                         rst_ni,
 
-    input  logic                         test_en_i,     // enable all clock gates for testing
-    input  logic                         scan_rst_ni,
-    input  prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
+  input  logic                         test_en_i,     // enable all clock gates for testing
+  input  logic                         scan_rst_ni,
+  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,
+  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 [6:0]                   instr_rdata_intg_i,
-    input  logic                         instr_err_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 [6:0]                   instr_rdata_intg_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,
-    output logic [6:0]                   data_wdata_intg_o,
-    input  logic [31:0]                  data_rdata_i,
-    input  logic [6:0]                   data_rdata_intg_i,
-    input  logic                         data_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,
+  output logic [6:0]                   data_wdata_intg_o,
+  input  logic [31:0]                  data_rdata_i,
+  input  logic [6:0]                   data_rdata_intg_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
+  // 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 crash_dump_t                  crash_dump_o,
+  // Debug Interface
+  input  logic                         debug_req_i,
+  output crash_dump_t                  crash_dump_o,
 
-    // CPU Control Signals
-    input  logic                         fetch_enable_i,
-    output logic                         alert_minor_o,
-    output logic                         alert_major_o,
-    output logic                         core_sleep_o
+  // CPU Control Signals
+  input  logic                         fetch_enable_i,
+  output logic                         alert_minor_o,
+  output logic                         alert_major_o,
+  output logic                         core_sleep_o
 
 );
 
@@ -110,6 +110,22 @@
   logic [ 3:0] rvfi_mem_wmask;
   logic [31:0] rvfi_mem_rdata;
   logic [31:0] rvfi_mem_wdata;
+  logic [31:0] rvfi_ext_mip;
+  logic        rvfi_ext_nmi;
+  logic        rvfi_ext_debug_req;
+  logic [63:0] rvfi_ext_mcycle;
+
+  logic [31:0] unused_rvfi_ext_mip;
+  logic        unused_rvfi_ext_nmi;
+  logic        unused_rvfi_ext_debug_req;
+  logic [63:0] unused_rvfi_ext_mcycle;
+
+  // Tracer doesn't use these signals, though other modules may probe down into tracer to observe
+  // them.
+  assign unused_rvfi_ext_mip = rvfi_ext_mip;
+  assign unused_rvfi_ext_nmi = rvfi_ext_nmi;
+  assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req;
+  assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle;
 
   ibex_top #(
     .PMPEnable        ( PMPEnable        ),
@@ -129,6 +145,8 @@
     .DbgHwBreakNum    ( DbgHwBreakNum    ),
     .WritebackStage   ( WritebackStage   ),
     .SecureIbex       ( SecureIbex       ),
+    .RndCnstLfsrSeed  ( RndCnstLfsrSeed  ),
+    .RndCnstLfsrPerm  ( RndCnstLfsrPerm  ),
     .DmHaltAddr       ( DmHaltAddr       ),
     .DmExceptionAddr  ( DmExceptionAddr  )
   ) u_ibex_top (
@@ -194,6 +212,10 @@
     .rvfi_mem_wmask,
     .rvfi_mem_rdata,
     .rvfi_mem_wdata,
+    .rvfi_ext_mip,
+    .rvfi_ext_nmi,
+    .rvfi_ext_debug_req,
+    .rvfi_ext_mcycle,
 
     .fetch_enable_i,
     .alert_minor_o,
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
index bbee71b..4a08446 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
@@ -490,7 +490,7 @@
              rvfi_insn[30:25], rvfi_insn[11:8], 1'b0 });
     branch_target = rvfi_pc_rdata + imm;
 
-    data_accessed = RS1 | RS2 | RD;
+    data_accessed = RS1 | RS2;
     decoded_str = $sformatf("%s\tx%0d,x%0d,%0x",
                             mnemonic, rvfi_rs1_addr, rvfi_rs2_addr, branch_target);
   endfunction
@@ -855,9 +855,12 @@
         INSN_SLTIU:      decode_i_insn("sltiu");
         INSN_XORI:       decode_i_insn("xori");
         INSN_ORI:        decode_i_insn("ori");
-        // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
-        // zext.b rd rs = andi rd, rs, 255.
-        // Currently instruction set simulators don't output this pseudo-instruction.
+        // Unlike the ratified v.1.0.0 bitmanip extension, the v.0.94 draft extension continues to
+        // define the pseudo-instruction
+        //   zext.b rd rs = andi rd, rs, 255.
+        // However, for now the tracer doesn't emit this due to a lack of support in the LLVM and
+        // GCC toolchains. Enabling this functionality when the time is right is tracked in
+        // https://github.com/lowRISC/ibex/issues/1228
         INSN_ANDI:       decode_i_insn("andi");
         // INSN_ANDI:begin
           // casez (rvfi_insn)
@@ -907,12 +910,12 @@
         // MISC-MEM
         INSN_FENCE:      decode_fence();
         INSN_FENCEI:     decode_mnemonic("fence.i");
+        // RV32B - ZBA
+        INSN_SH1ADD:     decode_r_insn("sh1add");
+        INSN_SH2ADD:     decode_r_insn("sh2add");
+        INSN_SH3ADD:     decode_r_insn("sh3add");
         // RV32B - ZBB
-        INSN_SLOI:       decode_i_shift_insn("sloi");
-        INSN_SROI:       decode_i_shift_insn("sroi");
         INSN_RORI:       decode_i_shift_insn("rori");
-        INSN_SLO:        decode_r_insn("slo");
-        INSN_SRO:        decode_r_insn("sro");
         INSN_ROL:        decode_r_insn("rol");
         INSN_ROR:        decode_r_insn("ror");
         INSN_MIN:        decode_r_insn("min");
@@ -922,9 +925,11 @@
         INSN_XNOR:       decode_r_insn("xnor");
         INSN_ORN:        decode_r_insn("orn");
         INSN_ANDN:       decode_r_insn("andn");
-        // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
-        // zext.h rd rs = pack rd, rs, zero.
-        // Currently instruction set simulators don't output this pseudo-instruction.
+        // The ratified v.1.0.0 bitmanip extension defines the pseudo-instruction
+        //   zext.h rd rs = pack rd, rs, zero.
+        // However, for now the tracer doesn't emit this due to a lack of support in the LLVM and
+        // GCC toolchains. Enabling this functionality when the time is right is tracked in
+        // https://github.com/lowRISC/ibex/issues/1228
         INSN_PACK:       decode_r_insn("pack");
         // INSN_PACK: begin
           // casez (rvfi_insn)
@@ -936,21 +941,21 @@
         INSN_PACKU:      decode_r_insn("packu");
         INSN_CLZ:        decode_r1_insn("clz");
         INSN_CTZ:        decode_r1_insn("ctz");
-        INSN_PCNT:       decode_r1_insn("pcnt");
+        INSN_CPOP:       decode_r1_insn("cpop");
         INSN_SEXTB:      decode_r1_insn("sext.b");
         INSN_SEXTH:      decode_r1_insn("sext.h");
         // RV32B - ZBS
-        INSN_SBCLRI:     decode_i_insn("sbclri");
-        INSN_SBSETI:     decode_i_insn("sbseti");
-        INSN_SBINVI:     decode_i_insn("sbinvi");
-        INSN_SBEXTI:     decode_i_insn("sbexti");
-        INSN_SBCLR:      decode_r_insn("sbclr");
-        INSN_SBSET:      decode_r_insn("sbset");
-        INSN_SBINV:      decode_r_insn("sbinv");
-        INSN_SBEXT:      decode_r_insn("sbext");
+        INSN_BCLRI:     decode_i_insn("bclri");
+        INSN_BSETI:     decode_i_insn("bseti");
+        INSN_BINVI:     decode_i_insn("binvi");
+        INSN_BEXTI:     decode_i_insn("bexti");
+        INSN_BCLR:      decode_r_insn("bclr");
+        INSN_BSET:      decode_r_insn("bset");
+        INSN_BINV:      decode_r_insn("binv");
+        INSN_BEXT:      decode_r_insn("bext");
         // RV32B - ZBE
-        INSN_BDEP:       decode_r_insn("bdep");
-        INSN_BEXT:       decode_r_insn("bext");
+        INSN_BDECOMPRESS: decode_r_insn("bdecompress");
+        INSN_BCOMPRESS:   decode_r_insn("bcompress");
         // RV32B - ZBP
         INSN_GREV:       decode_r_insn("grev");
         INSN_GREVI: begin
@@ -1026,6 +1031,13 @@
             default:       decode_i_insn("unshfli");
           endcase
         end
+        INSN_XPERM_N:    decode_r_insn("xperm_n");
+        INSN_XPERM_B:    decode_r_insn("xperm_b");
+        INSN_XPERM_H:    decode_r_insn("xperm_h");
+        INSN_SLO:        decode_r_insn("slo");
+        INSN_SRO:        decode_r_insn("sro");
+        INSN_SLOI:       decode_i_shift_insn("sloi");
+        INSN_SROI:       decode_i_shift_insn("sroi");
 
         // RV32B - ZBT
         INSN_CMIX:       decode_r_cmixcmov_insn("cmix");
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
index c794786..6dbbfc9 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
@@ -4,310 +4,332 @@
 // SPDX-License-Identifier: Apache-2.0
 
 package ibex_tracer_pkg;
-import ibex_pkg::*;
+  import ibex_pkg::*;
 
-parameter logic [1:0] OPCODE_C0 = 2'b00;
-parameter logic [1:0] OPCODE_C1 = 2'b01;
-parameter logic [1:0] OPCODE_C2 = 2'b10;
+  parameter logic [1:0] OPCODE_C0 = 2'b00;
+  parameter logic [1:0] OPCODE_C1 = 2'b01;
+  parameter logic [1:0] OPCODE_C2 = 2'b10;
 
-// instruction masks (for tracer)
-parameter logic [31:0] INSN_LUI     = { 25'h?,                           {OPCODE_LUI  } };
-parameter logic [31:0] INSN_AUIPC   = { 25'h?,                           {OPCODE_AUIPC} };
-parameter logic [31:0] INSN_JAL     = { 25'h?,                           {OPCODE_JAL  } };
-parameter logic [31:0] INSN_JALR    = { 17'h?,             3'b000, 5'h?, {OPCODE_JALR } };
+  // instruction masks (for tracer)
+  parameter logic [31:0] INSN_LUI     = { 25'h?,                           {OPCODE_LUI  } };
+  parameter logic [31:0] INSN_AUIPC   = { 25'h?,                           {OPCODE_AUIPC} };
+  parameter logic [31:0] INSN_JAL     = { 25'h?,                           {OPCODE_JAL  } };
+  parameter logic [31:0] INSN_JALR    = { 17'h?,             3'b000, 5'h?, {OPCODE_JALR } };
 
-// BRANCH
-parameter logic [31:0] INSN_BEQ     = { 17'h?,             3'b000, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BNE     = { 17'h?,             3'b001, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BLT     = { 17'h?,             3'b100, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BGE     = { 17'h?,             3'b101, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BLTU    = { 17'h?,             3'b110, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BGEU    = { 17'h?,             3'b111, 5'h?, {OPCODE_BRANCH} };
+  // BRANCH
+  parameter logic [31:0] INSN_BEQ     = { 17'h?,             3'b000, 5'h?, {OPCODE_BRANCH} };
+  parameter logic [31:0] INSN_BNE     = { 17'h?,             3'b001, 5'h?, {OPCODE_BRANCH} };
+  parameter logic [31:0] INSN_BLT     = { 17'h?,             3'b100, 5'h?, {OPCODE_BRANCH} };
+  parameter logic [31:0] INSN_BGE     = { 17'h?,             3'b101, 5'h?, {OPCODE_BRANCH} };
+  parameter logic [31:0] INSN_BLTU    = { 17'h?,             3'b110, 5'h?, {OPCODE_BRANCH} };
+  parameter logic [31:0] INSN_BGEU    = { 17'h?,             3'b111, 5'h?, {OPCODE_BRANCH} };
 
-// OPIMM
-parameter logic [31:0] INSN_ADDI    = { 17'h?,             3'b000, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLTI    = { 17'h?,             3'b010, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLTIU   = { 17'h?,             3'b011, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_XORI    = { 17'h?,             3'b100, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORI     = { 17'h?,             3'b110, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ANDI    = { 17'h?,             3'b111, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLLI    = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SRLI    = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SRAI    = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // OPIMM
+  parameter logic [31:0] INSN_ADDI    = { 17'h?,             3'b000, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SLTI    = { 17'h?,             3'b010, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SLTIU   = { 17'h?,             3'b011, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_XORI    = { 17'h?,             3'b100, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORI     = { 17'h?,             3'b110, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ANDI    = { 17'h?,             3'b111, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SLLI    = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SRLI    = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SRAI    = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
 
-// OP
-parameter logic [31:0] INSN_ADD     = { 7'b0000000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SUB     = { 7'b0100000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLL     = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLT     = { 7'b0000000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLTU    = { 7'b0000000, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_XOR     = { 7'b0000000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRL     = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRA     = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_OR      = { 7'b0000000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_AND     = { 7'b0000000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  // OP
+  parameter logic [31:0] INSN_ADD     = { 7'b0000000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SUB     = { 7'b0100000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SLL     = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SLT     = { 7'b0000000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SLTU    = { 7'b0000000, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_XOR     = { 7'b0000000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SRL     = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SRA     = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_OR      = { 7'b0000000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_AND     = { 7'b0000000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
 
-// SYSTEM
-parameter logic [31:0] INSN_CSRRW   = { 17'h?,             3'b001, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRS   = { 17'h?,             3'b010, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRC   = { 17'h?,             3'b011, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRWI  = { 17'h?,             3'b101, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRSI  = { 17'h?,             3'b110, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRCI  = { 17'h?,             3'b111, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_ECALL   = { 12'b000000000000,         13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_EBREAK  = { 12'b000000000001,         13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_MRET    = { 12'b001100000010,         13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_DRET    = { 12'b011110110010,         13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_WFI     = { 12'b000100000101,         13'b0, {OPCODE_SYSTEM} };
+  // SYSTEM
+  parameter logic [31:0] INSN_CSRRW   = { 17'h?,             3'b001, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_CSRRS   = { 17'h?,             3'b010, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_CSRRC   = { 17'h?,             3'b011, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_CSRRWI  = { 17'h?,             3'b101, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_CSRRSI  = { 17'h?,             3'b110, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_CSRRCI  = { 17'h?,             3'b111, 5'h?, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_ECALL   = { 12'b000000000000,         13'b0, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_EBREAK  = { 12'b000000000001,         13'b0, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_MRET    = { 12'b001100000010,         13'b0, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_DRET    = { 12'b011110110010,         13'b0, {OPCODE_SYSTEM} };
+  parameter logic [31:0] INSN_WFI     = { 12'b000100000101,         13'b0, {OPCODE_SYSTEM} };
 
-// RV32M
-parameter logic [31:0] INSN_DIV     = { 7'b0000001, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_DIVU    = { 7'b0000001, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_REM     = { 7'b0000001, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_REMU    = { 7'b0000001, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMUL    = { 7'b0000001, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMUH    = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMULHU  = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+  // RV32M
+  parameter logic [31:0] INSN_DIV     = { 7'b0000001, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_DIVU    = { 7'b0000001, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_REM     = { 7'b0000001, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_REMU    = { 7'b0000001, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PMUL    = { 7'b0000001, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PMUH    = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PMULHU  = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
 
-// RV32B
-// ZBB
-parameter logic [31:0] INSN_SLOI = { 5'b00100        , 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
-// fsri.
-parameter logic [31:0] INSN_SROI = { 5'b00100  , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_RORI = { 5'b01100  , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CLZ  = { 12'b011000000000, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CTZ  = { 12'b011000000001, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_PCNT = { 12'b011000000010, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SEXTB = { 12'b011000000100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SEXTH = { 12'b011000000101, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// The ZEXT.B and ZEXT.H pseudo-instructions are currently not emitted by the tracer due to a lack
-// of support in the LLVM and GCC toolchains. Enabling this functionality when the time is right is
-// tracked in https://github.com/lowRISC/ibex/issues/1228
-// sext -- pseudoinstruction: andi rd, rs 255
-// parameter logic [31:0] INSN_ZEXTB = { 4'b0000, 8'b11111111, 5'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
-// sext -- pseudoinstruction: pack rd, rs zero
-// parameter logic [31:0] INSN_ZEXTH = { 7'b0000100, 5'b00000, 5'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  // RV32B
+  // ZBA
+  parameter logic [31:0] INSN_SH1ADD = { 7'b0010000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SH2ADD = { 7'b0010000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SH3ADD = { 7'b0010000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
 
-parameter logic [31:0] INSN_SLO   = { 7'b0010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRO   = { 7'b0010000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ROL   = { 7'b0110000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ROR   = { 7'b0110000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MIN   = { 7'b0000101, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MAX   = { 7'b0000101, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MINU  = { 7'b0000101, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MAXU  = { 7'b0000101, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_XNOR  = { 7'b0100000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ORN   = { 7'b0100000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ANDN  = { 7'b0100000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACK  = { 7'b0000100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACKU = { 7'b0100100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACKH = { 7'b0000100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  // ZBB
+  // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+  // instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
+  // fsri.
+  parameter logic [31:0] INSN_RORI = { 5'b01100  , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CLZ  = { 12'b011000000000, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CTZ  = { 12'b011000000001, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CPOP = { 12'b011000000010, 5'h?,  3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SEXTB = { 12'b011000000100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_SEXTH = { 12'b011000000101, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
 
-// ZBS
-parameter logic [31:0] INSN_SBCLRI = { 5'b01001, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SBSETI = { 5'b00101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SBINVI = { 5'b01101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, sbexti is instead decoded as fsri.
-parameter logic [31:0] INSN_SBEXTI = { 5'b01001, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // The zext.h and zext.b pseudo-instructions are defined in the ratified v.1.0.0 and draft v.0.94
+  // specifications of the bitmanip extension, respectively. They are currently not emitted by the
+  // tracer due to a lack of support in the LLVM and GCC toolchains. Enabling this functionality
+  // when the time is right is tracked in https://github.com/lowRISC/ibex/issues/1228
+  // zext.b -- pseudo-instruction: andi rd, rs 255
+  // parameter logic [31:0] INSN_ZEXTB =
+  //     { 4'b0000, 8'b11111111, 5'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
+  // zext.h -- pseudo-instruction: pack rd, rs zero
+  // parameter logic [31:0] INSN_ZEXTH = { 7'b0000100, 5'b00000, 5'h?, 3'b100, 5'h?, {OPCODE_OP} };
 
-parameter logic [31:0] INSN_SBCLR = { 7'b0100100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBSET = { 7'b0010100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBINV = { 7'b0110100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBEXT = { 7'b0100100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_ROL   = { 7'b0110000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_ROR   = { 7'b0110000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_MIN   = { 7'b0000101, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_MAX   = { 7'b0000101, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_MINU  = { 7'b0000101, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_MAXU  = { 7'b0000101, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_XNOR  = { 7'b0100000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_ORN   = { 7'b0100000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_ANDN  = { 7'b0100000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PACK  = { 7'b0000100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PACKU = { 7'b0100100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_PACKH = { 7'b0000100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
 
-// ZBP
-// grevi
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, grevi is instead decoded as fsri.
-parameter logic [31:0] INSN_GREVI = { 5'b01101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// grevi -- pseudo-instructions
-parameter logic [31:0] INSN_REV_P =
-    { 5'b01101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_N =
-    { 5'b01101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_N =
-    { 5'b01101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4_B =
-    { 5'b01101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_B =
-    { 5'b01101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_B =
-    { 5'b01101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV8_H =
-    { 5'b01101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4_H =
-    { 5'b01101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_H =
-    { 5'b01101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_H =
-    { 5'b01101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV16 =
-    { 5'b01101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV8 =
-    { 5'b01101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4 =
-    { 5'b01101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2 =
-    { 5'b01101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV =
-    { 5'b01101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// gorci
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, gorci is instead decoded as fsri.
-parameter logic [31:0] INSN_GORCI = { 5'b00101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// gorci -- pseudo-instructions
-parameter logic [31:0] INSN_ORC_P =
-    { 5'b00101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_N =
-    { 5'b00101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_N =
-    { 5'b00101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4_B =
-    { 5'b00101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_B =
-    { 5'b00101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_B =
-    { 5'b00101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC8_H =
-    { 5'b00101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4_H =
-    { 5'b00101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_H =
-    { 5'b00101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_H =
-    { 5'b00101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC16 =
-    { 5'b00101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC8 =
-    { 5'b00101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4 =
-    { 5'b00101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2 =
-    { 5'b00101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC =
-    { 5'b00101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// shfli
-parameter logic [31:0] INSN_SHFLI = { 6'b000010, 11'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// shfli -- pseudo-instructions
-parameter logic [31:0] INSN_ZIP_N =
-    { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2_B =
-    { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP_B =
-    { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP4_H =
-    { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2_H =
-    { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP_H =
-    { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP8 =
-    { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP4 =
-    { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2 =
-    { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP =
-    { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// unshfli
-parameter logic [31:0] INSN_UNSHFLI = { 6'b000010, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// unshfli -- pseudo-instructions
-parameter logic [31:0] INSN_UNZIP_N =
-    { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2_B =
-    { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP_B =
-    { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP4_H =
-    { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2_H =
-    { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP_H =
-    { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP8 =
-    { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP4 =
-    { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2 =
-    { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP =
-    { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // ZBS
+  parameter logic [31:0] INSN_BCLRI = { 5'b01001, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_BSETI = { 5'b00101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_BINVI = { 5'b01101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+  // instr[24:20] are effectively used. Whenever instr[26] is set, bexti is instead decoded as fsri.
+  parameter logic [31:0] INSN_BEXTI = { 5'b01001, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
 
-parameter logic [31:0] INSN_GREV   = { 7'b0110100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_GORC   = { 7'b0010100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SHFL   = { 7'b0000100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_UNSHFL = { 7'b0000100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_BCLR = { 7'b0100100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_BSET = { 7'b0010100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_BINV = { 7'b0110100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_BEXT = { 7'b0100100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
 
-// ZBE
-parameter logic [31:0] INSN_BDEP = {7'b0100100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_BEXT = {7'b0000100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  // ZBP
+  // grevi
+  // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+  // instr[24:20] are effectively used. Whenever instr[26] is set, grevi is instead decoded as fsri.
+  parameter logic [31:0] INSN_GREVI = { 5'b01101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // grevi -- pseudo-instructions
+  parameter logic [31:0] INSN_REV_P =
+      { 5'b01101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV2_N =
+      { 5'b01101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV_N =
+      { 5'b01101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV4_B =
+      { 5'b01101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV2_B =
+      { 5'b01101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV_B =
+      { 5'b01101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV8_H =
+      { 5'b01101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV4_H =
+      { 5'b01101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV2_H =
+      { 5'b01101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV_H =
+      { 5'b01101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV16 =
+      { 5'b01101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV8 =
+      { 5'b01101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV4 =
+      { 5'b01101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV2 =
+      { 5'b01101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_REV =
+      { 5'b01101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // gorci
+  // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+  // instr[24:20] are effectively used. Whenever instr[26] is set, gorci is instead decoded as fsri.
+  parameter logic [31:0] INSN_GORCI = { 5'b00101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // gorci -- pseudo-instructions
+  parameter logic [31:0] INSN_ORC_P =
+      { 5'b00101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC2_N =
+      { 5'b00101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC_N =
+      { 5'b00101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC4_B =
+      { 5'b00101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC2_B =
+      { 5'b00101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC_B =
+      { 5'b00101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC8_H =
+      { 5'b00101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC4_H =
+      { 5'b00101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC2_H =
+      { 5'b00101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC_H =
+      { 5'b00101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC16 =
+      { 5'b00101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC8 =
+      { 5'b00101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC4 =
+      { 5'b00101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC2 =
+      { 5'b00101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ORC =
+      { 5'b00101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // shfli
+  parameter logic [31:0] INSN_SHFLI = { 6'b000010, 11'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  // shfli -- pseudo-instructions
+  parameter logic [31:0] INSN_ZIP_N =
+      { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP2_B =
+      { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP_B =
+      { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP4_H =
+      { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP2_H =
+      { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP_H =
+      { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP8 =
+      { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP4 =
+      { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP2 =
+      { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_ZIP =
+      { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  // unshfli
+  parameter logic [31:0] INSN_UNSHFLI = { 6'b000010, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  // unshfli -- pseudo-instructions
+  parameter logic [31:0] INSN_UNZIP_N =
+      { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP2_B =
+      { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP_B =
+      { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP4_H =
+      { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP2_H =
+      { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP_H =
+      { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP8 =
+      { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP4 =
+      { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP2 =
+      { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_UNZIP =
+      { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
 
-// ZBT
-parameter logic [31:0] INSN_FSRI = { 5'h?, 1'b1, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_GREV   = { 7'b0110100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_GORC   = { 7'b0010100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SHFL   = { 7'b0000100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_UNSHFL = { 7'b0000100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
 
-parameter logic [31:0] INSN_CMIX = {5'h?, 2'b11, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CMOV = {5'h?, 2'b11, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_FSL  = {5'h?, 2'b10, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_FSR  = {5'h?, 2'b10, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_XPERM_N = { 7'b0010100, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_XPERM_B = { 7'b0010100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_XPERM_H = { 7'b0010100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
 
-// ZBF
-parameter logic [31:0] INSN_BFP  = {7'b0100100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SLO    = { 7'b0010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SRO    = { 7'b0010000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_SLOI   = { 5'b00100        , 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+  // instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
+  // fsri.
+  parameter logic [31:0] INSN_SROI   = { 5'b00100  , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
 
-// ZBC
-parameter logic [31:0] INSN_CLMUL  = {7'b0000101, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CLMULR = {7'b0000101, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CLMULH = {7'b0000101, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+  // ZBE
+  parameter logic [31:0] INSN_BDECOMPRESS = {7'b0100100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_BCOMPRESS   = {7'b0000100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
 
-// ZBR
-parameter logic [31:0] INSN_CRC32_B  = {7'b0110000, 5'b10000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32_H  = {7'b0110000, 5'b10001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32_W  = {7'b0110000, 5'b10010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_B = {7'b0110000, 5'b11000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_H = {7'b0110000, 5'b11001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_W = {7'b0110000, 5'b11010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  // ZBT
+  parameter logic [31:0] INSN_FSRI = { 5'h?, 1'b1, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
 
-// LOAD & STORE
-parameter logic [31:0] INSN_LOAD    = {25'h?,                            {OPCODE_LOAD } };
-parameter logic [31:0] INSN_STORE   = {25'h?,                            {OPCODE_STORE} };
+  parameter logic [31:0] INSN_CMIX = {5'h?, 2'b11, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_CMOV = {5'h?, 2'b11, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_FSL  = {5'h?, 2'b10, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_FSR  = {5'h?, 2'b10, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
 
-// MISC-MEM
-parameter logic [31:0] INSN_FENCE   = { 17'h?,             3'b000, 5'h?, {OPCODE_MISC_MEM} };
-parameter logic [31:0] INSN_FENCEI  = { 17'h0,             3'b001, 5'h0, {OPCODE_MISC_MEM} };
+  // ZBF
+  parameter logic [31:0] INSN_BFP  = {7'b0100100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
 
-// Compressed Instructions
-// C0
-parameter logic [15:0] INSN_CADDI4SPN  = { 3'b000,       11'h?,                    {OPCODE_C0} };
-parameter logic [15:0] INSN_CLW        = { 3'b010,       11'h?,                    {OPCODE_C0} };
-parameter logic [15:0] INSN_CSW        = { 3'b110,       11'h?,                    {OPCODE_C0} };
+  // ZBC
+  parameter logic [31:0] INSN_CLMUL  = {7'b0000101, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_CLMULR = {7'b0000101, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+  parameter logic [31:0] INSN_CLMULH = {7'b0000101, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
 
-// C1
-parameter logic [15:0] INSN_CADDI      = { 3'b000,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CJAL       = { 3'b001,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CJ         = { 3'b101,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CLI        = { 3'b010,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CLUI       = { 3'b011,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CBEQZ      = { 3'b110,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CBNEZ      = { 3'b111,       11'h?,                    {OPCODE_C1} };
-parameter logic [15:0] INSN_CSRLI      = { 3'b100, 1'h?, 2'b00, 8'h?,              {OPCODE_C1} };
-parameter logic [15:0] INSN_CSRAI      = { 3'b100, 1'h?, 2'b01, 8'h?,              {OPCODE_C1} };
-parameter logic [15:0] INSN_CANDI      = { 3'b100, 1'h?, 2'b10, 8'h?,              {OPCODE_C1} };
-parameter logic [15:0] INSN_CSUB       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b00, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CXOR       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b01, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_COR        = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b10, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CAND       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b11, 3'h?, {OPCODE_C1} };
+  // ZBR
+  parameter logic [31:0] INSN_CRC32_B  =
+      {7'b0110000, 5'b10000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CRC32_H  =
+      {7'b0110000, 5'b10001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CRC32_W  =
+      {7'b0110000, 5'b10010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CRC32C_B =
+      {7'b0110000, 5'b11000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CRC32C_H =
+      {7'b0110000, 5'b11001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+  parameter logic [31:0] INSN_CRC32C_W =
+      {7'b0110000, 5'b11010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
 
-// C2
-parameter logic [15:0] INSN_CSLLI      = { 3'b000,       11'h?,                    {OPCODE_C2} };
-parameter logic [15:0] INSN_CLWSP      = { 3'b010,       11'h?,                    {OPCODE_C2} };
-parameter logic [15:0] INSN_SWSP       = { 3'b110,       11'h?,                    {OPCODE_C2} };
-parameter logic [15:0] INSN_CMV        = { 3'b100, 1'b0, 10'h?,                    {OPCODE_C2} };
-parameter logic [15:0] INSN_CADD       = { 3'b100, 1'b1, 10'h?,                    {OPCODE_C2} };
-parameter logic [15:0] INSN_CEBREAK    = { 3'b100, 1'b1,        5'h0,  5'h0,       {OPCODE_C2} };
-parameter logic [15:0] INSN_CJR        = { 3'b100, 1'b0,        5'h0,  5'h0,       {OPCODE_C2} };
-parameter logic [15:0] INSN_CJALR      = { 3'b100, 1'b1,        5'h?,  5'h0,       {OPCODE_C2} };
+  // LOAD & STORE
+  parameter logic [31:0] INSN_LOAD    = {25'h?,                            {OPCODE_LOAD } };
+  parameter logic [31:0] INSN_STORE   = {25'h?,                            {OPCODE_STORE} };
+
+  // MISC-MEM
+  parameter logic [31:0] INSN_FENCE   = { 17'h?,             3'b000, 5'h?, {OPCODE_MISC_MEM} };
+  parameter logic [31:0] INSN_FENCEI  = { 17'h0,             3'b001, 5'h0, {OPCODE_MISC_MEM} };
+
+  // Compressed Instructions
+  // C0
+  parameter logic [15:0] INSN_CADDI4SPN  = { 3'b000,       11'h?,                    {OPCODE_C0} };
+  parameter logic [15:0] INSN_CLW        = { 3'b010,       11'h?,                    {OPCODE_C0} };
+  parameter logic [15:0] INSN_CSW        = { 3'b110,       11'h?,                    {OPCODE_C0} };
+
+  // C1
+  parameter logic [15:0] INSN_CADDI      = { 3'b000,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CJAL       = { 3'b001,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CJ         = { 3'b101,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CLI        = { 3'b010,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CLUI       = { 3'b011,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CBEQZ      = { 3'b110,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CBNEZ      = { 3'b111,       11'h?,                    {OPCODE_C1} };
+  parameter logic [15:0] INSN_CSRLI      = { 3'b100, 1'h?, 2'b00, 8'h?,              {OPCODE_C1} };
+  parameter logic [15:0] INSN_CSRAI      = { 3'b100, 1'h?, 2'b01, 8'h?,              {OPCODE_C1} };
+  parameter logic [15:0] INSN_CANDI      = { 3'b100, 1'h?, 2'b10, 8'h?,              {OPCODE_C1} };
+  parameter logic [15:0] INSN_CSUB       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b00, 3'h?, {OPCODE_C1} };
+  parameter logic [15:0] INSN_CXOR       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b01, 3'h?, {OPCODE_C1} };
+  parameter logic [15:0] INSN_COR        = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b10, 3'h?, {OPCODE_C1} };
+  parameter logic [15:0] INSN_CAND       = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b11, 3'h?, {OPCODE_C1} };
+
+  // C2
+  parameter logic [15:0] INSN_CSLLI      = { 3'b000,       11'h?,                    {OPCODE_C2} };
+  parameter logic [15:0] INSN_CLWSP      = { 3'b010,       11'h?,                    {OPCODE_C2} };
+  parameter logic [15:0] INSN_SWSP       = { 3'b110,       11'h?,                    {OPCODE_C2} };
+  parameter logic [15:0] INSN_CMV        = { 3'b100, 1'b0, 10'h?,                    {OPCODE_C2} };
+  parameter logic [15:0] INSN_CADD       = { 3'b100, 1'b1, 10'h?,                    {OPCODE_C2} };
+  parameter logic [15:0] INSN_CEBREAK    = { 3'b100, 1'b1,        5'h0,  5'h0,       {OPCODE_C2} };
+  parameter logic [15:0] INSN_CJR        = { 3'b100, 1'b0,        5'h0,  5'h0,       {OPCODE_C2} };
+  parameter logic [15:0] INSN_CJALR      = { 3'b100, 1'b1,        5'h?,  5'h0,       {OPCODE_C2} };
 
 endpackage
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
index b3317c0..d0a2360 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
@@ -34,6 +34,8 @@
   output logic [31:0]              pc_wb_o,
   output logic                     perf_instr_ret_wb_o,
   output logic                     perf_instr_ret_compressed_wb_o,
+  output logic                     perf_instr_ret_wb_spec_o,
+  output logic                     perf_instr_ret_compressed_wb_spec_o,
 
   input  logic [4:0]               rf_waddr_id_i,
   input  logic [31:0]              rf_wdata_id_i,
@@ -61,7 +63,7 @@
   logic [31:0] rf_wdata_wb_mux    [2];
   logic [1:0]  rf_wdata_wb_mux_we;
 
-  if(WritebackStage) begin : g_writeback_stage
+  if (WritebackStage) begin : g_writeback_stage
     logic [31:0]    rf_wdata_wb_q;
     logic           rf_we_wb_q;
     logic [4:0]     rf_waddr_wb_q;
@@ -86,7 +88,7 @@
     assign wb_done = (wb_instr_type_q == WB_INSTR_OTHER) | lsu_resp_valid_i;
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
-      if(~rst_ni) begin
+      if (!rst_ni) begin
         wb_valid_q <= 1'b0;
       end else begin
         wb_valid_q <= wb_valid_d;
@@ -144,10 +146,15 @@
 
     assign instr_done_wb_o = wb_valid_q & wb_done;
 
-    // Increment instruction retire counters for valid instructions which are not lsu errors
-    assign perf_instr_ret_wb_o            = instr_done_wb_o & wb_count_q &
-                                            ~(lsu_resp_valid_i & lsu_resp_err_i);
-    assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q;
+    // Increment instruction retire counters for valid instructions which are not lsu errors.
+    // Speculative versions of the signals do not factor in exceptions and whether the instruction
+    // is done yet. These are used to get correct values for instructions reading the relevant
+    // performance counters in the ID stage.
+    assign perf_instr_ret_wb_spec_o            = wb_count_q;
+    assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q;
+    assign perf_instr_ret_wb_o                 = instr_done_wb_o & wb_count_q &
+                                                 ~(lsu_resp_valid_i & lsu_resp_err_i);
+    assign perf_instr_ret_compressed_wb_o      = perf_instr_ret_wb_o & wb_compressed_q;
 
     // Forward data that will be written to the RF back to ID to resolve data hazards. The flopped
     // rf_wdata_wb_q is used rather than rf_wdata_wb_o as the latter includes read data from memory
@@ -159,10 +166,14 @@
     assign rf_wdata_wb_mux[0]    = rf_wdata_id_i;
     assign rf_wdata_wb_mux_we[0] = rf_we_id_i;
 
-    // Increment instruction retire counters for valid instructions which are not lsu errors
-    assign perf_instr_ret_wb_o            = instr_perf_count_id_i & en_wb_i &
-                                            ~(lsu_resp_valid_i & lsu_resp_err_i);
-    assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i;
+    // Increment instruction retire counters for valid instructions which are not lsu errors.
+    // The speculative signals are always 0 when no writeback stage is present as the raw counter
+    // values will be correct.
+    assign perf_instr_ret_wb_spec_o            = 1'b0;
+    assign perf_instr_ret_compressed_wb_spec_o = 1'b0;
+    assign perf_instr_ret_wb_o                 = instr_perf_count_id_i & en_wb_i &
+                                                 ~(lsu_resp_valid_i & lsu_resp_err_i);
+    assign perf_instr_ret_compressed_wb_o      = perf_instr_ret_wb_o & instr_is_compressed_id_i;
 
     // ready needs to be constant 1 without writeback stage (otherwise ID/EX stage will stall)
     assign ready_wb_o    = 1'b1;
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 07359c4..80f9443 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
@@ -14,7 +14,7 @@
   write_sdc_out $lr_synth_sdc_file_in $lr_synth_sdc_file_out
 }
 
-yosys "read_verilog -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
+yosys "read_verilog -defer -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
 
 if { $lr_synth_ibex_branch_target_alu } {
   yosys "chparam -set BranchTargetALU 1 $lr_synth_top_module"
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 66c7185..88dadea 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: 59dcd8c813484eb6dcca67e7e36089fe772b9cc8
+    rev: 605301400555c235564f9336cc5fc220af7e951c
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md
new file mode 100644
index 0000000..09c9dc8
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md
@@ -0,0 +1,99 @@
+## Overview
+
+RISCV-DV-PyFlow is a purely Python based open-source instruction generator for RISC-V processor
+verification. It uses [PyVSC](https://github.com/fvutils/pyvsc) as the main library for
+randomization and coverage collection. It currently supports the following features:
+
+- Supported instruction set: RV32IMAFDC
+- Supported privileged modes: For now only machine mode is supported.
+- Illegal instruction and HINT instruction generation
+- Random forward/backward branch instructions
+- Supports mixing directed instructions with random instruction stream
+- Support for direct & vectored interrupt table.
+- Multi-hart support
+- Functional coverage framework (reports GUI as well as text, currently
+  supports RV32IMFDC extensions)
+- Supported ISS : Spike, OVPsim
+
+## Supported tests
+
+- riscv_arithmetic_basic_test
+- riscv_amo_test
+- riscv_floating_point_arithmetic_test
+- riscv_floating_point_rand_test
+- riscv_floating_point_mmu_stress_test
+- riscv_b_ext_test
+- riscv_rand_instr_test
+- riscv_jump_stress_test
+- riscv_rand_jump_test
+- riscv_mmu_stress_test
+- riscv_illegal_instr_test
+- riscv_unaligned_load_store_test
+- riscv_single_hart_test
+- riscv_non_compressed_instr_test
+- riscv_loop_test
+
+
+## Getting Started
+
+### Prerequisites
+
+To be able to run the generator, you need to have RISCV-GCC compiler toolchain and ISS
+(Instruction Set Simulator) installed (Spike is preferred).
+
+
+### Install RISCV-DV-PyFlow
+
+Getting the source
+```bash
+git clone https://github.com/google/riscv-dv.git
+```
+
+```bash
+pip3 install -r requirements.txt    # install dependencies (only once)
+python3 run.py --help
+```
+
+## Running the Generator
+
+Command to run a single test:
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow
+```
+--simulator=pyflow will invoke the Python generator.
+
+Run a single test 10 times
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --iterations=10 --simulator=pyflow
+```
+Run the generator only, do not compile and simluation with ISS
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow --steps gen
+```
+## Coverage Model
+The coverage model of PyFlow is developed using PyVSC library.
+
+Command to generate the coverage report.
+#### Process spike simulation log and collect functional coverage
+```bash
+python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization
+```
+--enable_visualization helps enabling coverage report visualization for pyflow.
+#### Get the command reference
+```bash
+cov --help
+```
+#### Run the coverage flow with predefined targets
+```bash
+python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization --target rv32imc
+```
+The coverage reports can be viewed using two ways:
+1) Text format: By opening the CoverageReport.txt file.
+2) GUI format: By opening the cov_db.xml using pyucis-viewer.
+The GUI format could be enabled using "--enable_visualization" command option.
+```bash
+pyucis-viewer cov_db.xml
+```
+## Note
+Currently, time to generate a single program with larger than 10k instructions is around
+12 minutes. We are working on improving the overall performance.
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 9ed8f85..8b89abd 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
@@ -223,6 +223,6 @@
     def get_c_opcode(self):
         pass
 
-    # TOD0
+    # TODO
     def get_func3(self):
         pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
index a5e75c4..a8cff5a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
@@ -19,11 +19,11 @@
 import logging
 from importlib import import_module
 from enum import Enum, IntEnum, auto
-from bitstring import BitArray
 from pygen_src.riscv_instr_pkg import *
 from pygen_src.riscv_instr_gen_config import cfg
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
+
 class operand_sign_e(IntEnum):
     POSITIVE = 0
     NEGATIVE = auto()
@@ -35,6 +35,11 @@
     DIV_OVERFLOW = auto()
 
 
+class div_result_ex_overflow_e(IntEnum):
+    DIV_NORMAL = 0
+    DIV_BY_ZERO = auto()
+
+
 class compare_result_e(IntEnum):
     EQUAL = 0
     LARGER = auto()
@@ -142,7 +147,7 @@
             if self.imm_type.name == "UIMM":
                 self.imm_len = 5
             else:
-                self.imm_len = 11
+                self.imm_len = 12
 
     def set_mode(self):
         # mode setting for Instruction Format
@@ -320,10 +325,11 @@
         the result of the check_hazard_condition won't be accurate. Need to
         explicitly extract the destination register from the operands '''
         if pre_instr.has_rd:
-            if ((self.has_rs1 and self.rs1 == pre_instr.rd) or
-                    (self.has_rs2 and self.rs1 == pre_instr.rd)):
+            if ((self.has_rs1 and (self.rs1 == pre_instr.rd)) or
+                    (self.has_rs2 and (self.rs1 == pre_instr.rd))):
+                logging.info("pre_instr {}".format(pre_instr.instr.name))
                 self.gpr_hazard = hazard_e["RAW_HAZARD"]
-            elif self.has_rd and self.rd == pre_instr.rd:
+            elif self.has_rd and (self.rd == pre_instr.rd):
                 self.gpr_hazard = hazard_e["WAW_HAZARD"]
             elif (self.has_rd and
                   ((pre_instr.has_rs1 and (pre_instr.rs1 == self.rd)) or
@@ -333,16 +339,16 @@
                 self.gpr_hazard = hazard_e["NO_HAZARD"]
         if self.category == riscv_instr_category_t.LOAD:
             if (pre_instr.category == riscv_instr_category_t.STORE and
-                    pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+                    (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
                 self.lsu_hazard = hazard_e["RAW_HAZARD"]
             else:
                 self.lsu_hazard = hazard_e["NO_HAZARD"]
         if self.category == riscv_instr_category_t.STORE:
             if (pre_instr.category == riscv_instr_category_t.STORE and
-                    pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+                    (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
                 self.lsu_hazard = hazard_e["WAW_HAZARD"]
             elif (pre_instr.category == riscv_instr_category_t.LOAD and
-                  pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+                  (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
                 self.lsu_hazard = hazard_e["WAR_HAZARD"]
             else:
                 self.lsu_hazard = hazard_e["NO_HAZARD"]
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
index 4d4dcba..3169c5b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
@@ -116,7 +116,7 @@
             self.has_fs1 = 0
             self.has_fd = 0
         else:
-            logging.info("Unsupported format %0s", self.format.name)
+            logging.info("Unsupported format {}".format(self.format.name))
 
     def pre_randomize(self):
         super().pre_randomize()
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 74d922c..b592511 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
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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 logging
@@ -110,12 +108,32 @@
             with vsc.if_then(self.XLEN != 32):
                 self.imm[11:6] == 0
 
+    @vsc.constraint
+    def csr_c(self):
+        # TODO
+        pass
+
     @classmethod
     def register(cls, instr_name, instr_group):
         logging.info("Registering {}".format(instr_name.name))
         cls.instr_registry[instr_name] = instr_group
         return 1
 
+    def __deepcopy__(self, memo):
+        cls = self.__class__  # Extract the class of the object.
+        # Create a new instance of the object based on extracted class.
+        result = cls.__new__(cls)
+        memo[id(self)] = result
+        for k, v in self.__dict__.items():
+            if k in ["_ro_int", "tname", "__field_info"]:
+                continue  # Skip the fields which are not required.
+            else:
+                # Copy over attributes by copying directly.
+                setattr(result, k, copy.deepcopy(v, memo))
+        return result
+
+    # Create the list of instructions based on the supported ISA extensions and configuration
+    # of the generator
     @classmethod
     def create_instr_list(cls, cfg):
         cls.instr_names.clear()
@@ -129,6 +147,7 @@
 
             if not instr_inst.is_supported(cfg):
                 continue
+            # C_JAL is RV32C only instruction
             if ((rcs.XLEN != 32) and (instr_name == riscv_instr_name_t.C_JAL)):
                 continue
             if ((riscv_reg_t.SP in cfg.reserved_regs) and
@@ -310,7 +329,7 @@
             if self.imm_type.name == "UIMM":
                 self.imm_len = 5
             else:
-                self.imm_len = 11
+                self.imm_len = 12
         self.imm_mask = (self.imm_mask << self.imm_len) & self.shift_t
 
     def extend_imm(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
index f3f1b5e..46f8a21 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
@@ -14,13 +14,13 @@
 import vsc
 import random
 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_pseudo_instr import riscv_pseudo_instr
 from pygen_src.riscv_directed_instr_lib import riscv_mem_access_stream
 from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t,
                                        riscv_instr_name_t, riscv_instr_category_t,
                                        riscv_instr_group_t)
-from pygen_src.riscv_instr_gen_config import cfg
-from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
-from pygen_src.isa.riscv_instr import riscv_instr
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
 
@@ -62,7 +62,6 @@
 
     @vsc.constraint
     def aligned_amo_c(self):
-
         with vsc.foreach(self.offset, idx = True) as i:
             with vsc.if_then(self.XLEN == 32):
                 self.offset[i] % 4 == 0
@@ -73,7 +72,7 @@
         self.data_page = cfg.amo_region
         max_data_page_id = len(self.data_page)
         self.data_page_id = random.randrange(0, max_data_page_id - 1)
-        self.max_offset = self.data_page[self.data_page_id]['size_in_bytes']
+        self.max_offset = self.data_page[self.data_page_id].size_in_bytes
 
     # Use "la" instruction to initialize the offset regiseter
     def init_offset_reg(self):
@@ -81,7 +80,7 @@
             la_instr = riscv_pseudo_instr()
             la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA
             la_instr.rd = self.rs1_reg[i]
-            la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id]['name'],
+            la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id].name,
                                               self.offset[i])
             self.instr_list.insert(0, la_instr)
 
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 cf751b3..4d8c180 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
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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 logging
@@ -31,35 +29,43 @@
 from pygen_src.riscv_utils import factory
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
-'''
-    RISC-V assembly program generator
 
-    This is the main class to generate a complete RISC-V program, including the init routine,
-    instruction section, data section, stack section, page table, interrupt and exception
-    handling etc. Check gen_program() function to see how the program is generated.
-'''
+# ----------------------------------------------------------------------------------
+# RISC-V assembly program generator
+
+# This is the main class to generate a complete RISC-V program, including the init routine,
+# instruction section, data section, stack section, page table, interrupt and exception
+# handling etc. Check gen_program() function to see how the program is generated.
+# ----------------------------------------------------------------------------------
 
 
+@vsc.randobj
 class riscv_asm_program_gen:
 
     def __init__(self):
         self.instr_stream = []
+        # Directed instruction ratio, occurance per 1000 instructions
         self.directed_instr_stream_ratio = {}
         self.hart = 0
         self.page_table_list = []
         self.main_program = []
         self.sub_program = []
         self.data_page_gen = None
+        self.spf_val = vsc.rand_bit_t(32)
+        self.dpf_val = vsc.rand_bit_t(64)
 
+    # ----------------------------------------------------------------------------------
     # Main function to generate the whole program
+    # ----------------------------------------------------------------------------------
 
     # This is the main function to generate all sections of the program.
     def gen_program(self):
-        # Generate program header
         self.instr_stream.clear()
+        # Generate program header
         self.gen_program_header()
         for hart in range(cfg.num_of_harts):
             # Commenting out for now
+            # TODO support for sub_program
             # sub_program_name = []
             self.instr_stream.append(f"h{int(hart)}_start:")
             if not cfg.bare_program_mode:
@@ -70,7 +76,6 @@
                 self.pre_enter_privileged_mode(hart)
             # Init section
             self.gen_init_section(hart)
-            # To DO
             '''
             If PMP is supported, we want to generate the associated trap handlers and the test_done
             section at the start of the program so we can allow access through the pmpcfg0 CSR
@@ -87,7 +92,8 @@
                 self.gen_store_fault_handler(hart)
                 if hart == 0:
                     self.gen_test_done()
-
+            # Generate sub program
+            # TODO gen_sub_program()
             # Generate main program
             gt_lbl_str = pkg_ins.get_label("main", hart)
             label_name = gt_lbl_str
@@ -103,8 +109,10 @@
                                                 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)
-
+            # Setup jump instruction among main program and sub programs
+            # TODO gen_callstack()
             self.main_program[hart].post_process_instr()
+            logging.info("Post-processing main program...done")
             self.main_program[hart].generate_instr_stream()
             logging.info("Generating main program instruction stream...done")
             self.instr_stream.extend(self.main_program[hart].instr_string_list)
@@ -113,14 +121,14 @@
             to test_done section at the end of main_program, as the test_done
             will have moved to the beginning of the program
             """
-            self.instr_stream.append("{}j test_done".format(pkg_ins.indent))
-            '''
-            Test done section
-            If PMP isn't supported, generate this in the normal location
-            '''
+            self.instr_stream.extend(("{}la x{}, test_done".format(pkg_ins.indent, cfg.scratch_reg),
+                                      "{}jalr x0, x{}, 0".format(pkg_ins.indent, cfg.scratch_reg)))
+            # Test done section
+            # If PMP isn't supported, generate this in the normal location
             if(hart == 0 and not(rcs.support_pmp)):
                 self.gen_test_done()
-
+            # Shuffle the sub programs and insert to the instruction stream
+            # TODO inser_sub_program()
             logging.info("Main/sub program generation...done")
             # program end
             self.gen_program_end(hart)
@@ -138,6 +146,7 @@
                 # AMO memory region
                 if(hart == 0 and riscv_instr_group_t.RV32A in rcs.supported_isa):
                     self.gen_data_page(hart, amo = 1)
+            # Stack section
             self.gen_stack_section(hart)
             if not cfg.bare_program_mode:
                 # Generate kernel program/data/stack section
@@ -145,6 +154,10 @@
                 # Page table
                 self.gen_page_table_section(hart)
 
+    # ----------------------------------------------------------------------------------
+    # Generate kernel program/data/stack sections
+    # ----------------------------------------------------------------------------------
+
     def gen_kernel_sections(self, hart):
         if rcs.SATP_MODE != satp_mode_t.BARE:
             self.instr_stream.append(".align 12")
@@ -152,56 +165,84 @@
             self.instr_stream.append(".align 2")
         self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart))
         self.instr_stream.append(".text")
+        # Kernel programs
+        # TODO
 
+        # All trap/interrupt handling is in the kernel region
+        # Trap/interrupt delegation to user mode is not supported now
+        # Trap handler
         self.gen_all_trap_handler(hart)
+        # Interrupt handling subroutine
         for mode in rcs.supported_privileged_mode:
             self.gen_interrupt_handler_section(mode, hart)
         self.instr_stream.append(pkg_ins.get_label("kernel_instr_end: nop", hart))
+        # User stack and data pages may not be accessible when executing trap handling programs in
+        # machine/supervisor mode. Generate separate kernel data/stack sections to solve it.
+        if not cfg.virtual_addr_translation_on:
+            if rcs.SATP_MODE != satp_mode_t.BARE:
+                self.instr_stream.append(".align 12")
+            else:
+                self.instr_stream.append(".align 2")
+            # Kernel data pages
+            self.instr_stream.append(pkg_ins.get_label("kernel_data_start:", hart))
+            if not cfg.no_data_page:
+                # Data section
+                self.gen_data_page(hart, 1)
+        # Kernel stack section
         self.gen_kernel_stack_section(hart)
 
     def gen_kernel_program(self, hart, seq):
+        # TODO
         pass
 
+    # ----------------------------------------------------------------------------------
+    # Generate any subprograms and set up the callstack
+    # ----------------------------------------------------------------------------------
+
     def gen_sub_program(self, hart, sub_program,
                         sub_program_name, num_sub_program,
                         is_debug = 0, prefix = "sub"):
+        # TODO
         pass
 
     def gen_callstack(self, main_program, sub_program,
                       sub_program_name, num_sub_program):
+        # TODO
         pass
 
     def insert_sub_program(self, sub_program, instr_list):
+        # TODO
         pass
+    # ----------------------------------------------------------------------------------
+    # Major sections - init, stack, data, test_done etc.
+    # ----------------------------------------------------------------------------------
 
     def gen_program_header(self):
-        string = []
-        self.instr_stream.append(".include \"user_define.h\"")
-        self.instr_stream.append(".globl _start")
-        self.instr_stream.append(".section .text")
+        header_string = []
+        self.instr_stream.extend((".include \"user_define.h\"", ".globl _start", ".section .text"))
         if cfg.disable_compressed_instr:
             self.instr_stream.append(".option norvc;")
-        string.append(".include \"user_init.s\"")
-        string.append("csrr x5, mhartid")
-
+        header_string.extend((".include \"user_init.s\"",
+                              "csrr x5, {}".format(hex(privileged_reg_t.MHARTID))))
         for hart in range(cfg.num_of_harts):
-            string.append("li x6, {}\n{}beq x5, x6, {}f".format(hart, pkg_ins.indent, hart))
-
-        self.gen_section("_start", string)
-
+            header_string.extend(("li x6, {}".format(hart),
+                                  "beq x5, x6, {}f".format(hart)))
+        self.gen_section("_start", header_string)
         for hart in range(cfg.num_of_harts):
-            self.instr_stream.append("{}: j h{}_start".format(hart, hart))
+            self.instr_stream.extend(("{}: la x{}, h{}_start".format(hart, cfg.scratch_reg, hart),
+                                      "jalr x0, x{}, 0".format(cfg.scratch_reg)))
 
     def gen_program_end(self, hart):
         if hart == 0:
+            # Use write_tohost to terminate spike simulation
             self.gen_section("write_tohost", ["sw gp, tohost, t5"])
             self.gen_section("_exit", ["j write_tohost"])
 
     def gen_data_page_begin(self, hart):
         self.instr_stream.append(".section .data")
         if hart == 0:
-            self.instr_stream.append(".align 6; .global tohost; tohost: .dword 0;")
-            self.instr_stream.append(".align 6; .global fromhost; fromhost: .dword 0;")
+            self.instr_stream.extend((".align 6; .global tohost; tohost: .dword 0;",
+                                      ".align 6; .global fromhost; fromhost: .dword 0;"))
 
     def gen_data_page(self, hart, is_kernel = 0, amo = 0):
         self.data_page_gen = riscv_data_page_gen()
@@ -221,15 +262,15 @@
         else:
             self.instr_stream.append(".align 2")
 
-        self.instr_stream.append(pkg_ins.get_label("user_stack_start:", hart))
-        self.instr_stream.append(".rept {}".format(cfg.stack_len - 1))
-        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
-        self.instr_stream.append(".endr")
-        self.instr_stream.append(pkg_ins.get_label("user_stack_end:", hart))
-        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+        self.instr_stream.extend((pkg_ins.get_label("user_stack_start:", hart),
+                                  ".rept {}".format(cfg.stack_len - 1),
+                                  ".{}byte 0x0".format(rcs.XLEN // 8), ".endr",
+                                  pkg_ins.get_label("user_stack_end:", hart),
+                                  ".{}byte 0x0".format(rcs.XLEN // 8)))
         if cfg.use_push_data_section:
-            self.instr_stream.push_back(".popsection;")
+            self.instr_stream.append(".popsection;")
 
+    # The kernal stack is used to save user program context before executing exception handling
     def gen_kernel_stack_section(self, hart):
         hart_prefix_string = pkg_ins.hart_prefix(hart)
         if cfg.use_push_data_section:
@@ -242,33 +283,31 @@
             self.instr_stream.append(".align 12")
         else:
             self.instr_stream.append(".align 2")
-
-        self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart))
-        self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1))
-        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
-        self.instr_stream.append(".endr")
-        self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart))
-        self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+        self.instr_stream.extend((pkg_ins.get_label("kernel_stack_start:", hart),
+                                  ".rept {}".format(cfg.stack_len - 1),
+                                  ".{}byte 0x0".format(rcs.XLEN // 8), ".endr",
+                                  pkg_ins.get_label("kernel_stack_end:", hart),
+                                  ".{}byte 0x0".format(rcs.XLEN // 8)))
         if cfg.use_push_data_section:
-            self.instr_stream.push_back(".popsection;")
+            self.instr_stream.append(".popsection;")
 
     def gen_init_section(self, hart):
-        string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
-        self.instr_stream.append(string)
+        init_string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
+        self.instr_stream.append(init_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(
+        init_string = "{}la x{}, {}user_stack_end".format(
             pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart))
-        self.instr_stream.append(string)
+        self.instr_stream.append(init_string)
         if cfg.enable_vector_extension:
-            self.init_vector_engine()
+            self.randomize_vec_gpr_and_csr()
         self.core_is_initialized()
         self.gen_dummy_csr_write()
         if rcs.support_pmp:
-            string = pkg_ins.indent + "j main"
-            self.instr_stream.append(string)
+            init_string = pkg_ins.indent + "j main"
+            self.instr_stream.append(init_string)
 
     # Setup MISA based on supported extensions
     def setup_misa(self):
@@ -316,21 +355,37 @@
             else:
                 logging.critical("{} is not yet supported".format(group.name))
                 sys.exit(1)
-        if privileged_mode_t.SUPERVISOR_MODE.name in rcs.supported_privileged_mode:
+        if privileged_mode_t.SUPERVISOR_MODE 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],
-                                                       hex(misa.get_val())))
-        self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, hex(privileged_reg_t.MISA),
-                                                         cfg.gpr[0]))
+        self.instr_stream.extend(("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0],
+                                                        hex(misa.get_val())),
+                                  "{}csrw {}, x{}".format(pkg_ins.indent,
+                                                          hex(privileged_reg_t.MISA), cfg.gpr[0])))
 
+    # Write to the signature_addr with values to indicate to the core testbench
+    # that is safe to start sending interrupt and debug stimulus
     def core_is_initialized(self):
-        pass
+        instr = []
+        if cfg.require_signature_addr:
+            if cfg.signature_addr != 0xdeadbeef:
+                self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+                                             core_status_t.INITIALIZED)
+                self.format_section(instr)
+                self.instr_stream.append(instr)
+            else:
+                logging.critical("The signature_addr is not properly configured!")
+                sys.exit(1)
 
+    # Generate some dummy writes to xSTATUS/xIE at the beginning of the test to check
+    # repeated writes to these CSRs.
     def gen_dummy_csr_write(self):
+        # TODO
         pass
 
+    # Initialize general purpose registers with random value
     def init_gpr(self):
         reg_val = vsc.rand_bit_t(pkg_ins.DATA_WIDTH)
+        # Init general purpose registers with random values
         for i in range(rcs.NUM_GPR):
             if i in [cfg.sp.value, cfg.tp.value]:
                 continue
@@ -343,19 +398,25 @@
             except Exception:
                 logging.critical("Cannot Randomize reg_val")
                 sys.exit(1)
-            init_string = "{}li x{}, {}".format(pkg_ins.indent, i, hex(reg_val.get_val()))
-            self.instr_stream.append(init_string)
+            self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, i,
+                                                           hex(reg_val.get_val())))
 
+    # Initialize vector general purpose registers
+    def init_vec_gpr(self):
+        # TODO
+        pass
+
+    # Initialize floating point general purpose registers
     def init_floating_point_gpr(self):
         for i in range(rcs.NUM_FLOAT_GPR):
             vsc.randselect([
                 (1, lambda: self.init_floating_point_gpr_with_spf(i)),
                 (riscv_instr_group_t.RV64D in rcs.supported_isa,
                  lambda: self.init_floating_point_gpr_with_dpf(i))])
-        # Initialize rounding mode of FCSR
-        fsrmi_instr = "{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm)
-        self.instr_stream.append(fsrmi_instr)
+        # Initialize rounding mode of FCSR and append to the instr_stream
+        self.instr_stream.append("{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm))
 
+    # get instructions initialize floating_point_gpr with single precision floating value
     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], hex(imm))
@@ -363,6 +424,7 @@
                                                 cfg.gpr[0])
         self.instr_stream.extend((li_instr, fmv_instr))
 
+    # get instructions initialize floating_point_gpr with double precision floating value
     def init_floating_point_gpr_with_dpf(self, int_floating_gpr):
         imm = vsc.bit_t(64)
         imm = self.get_rand_dpf_value()
@@ -378,114 +440,205 @@
         fmv_instr = "{}fmv.d.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr, int_gpr2)
         self.instr_stream.extend((li_instr0, slli_instr, li_instr1, or_instr, fmv_instr))
 
-    # Get a random single precision floating value
+    def get_randselect(self, addr_range1, addr_range2, flag):
+        if flag:
+            # Get a random double precision floating value
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.dpf_val):
+                    self.dpf_val in vsc.rangelist(addr_range1, addr_range2)
+        else:
+            # Get a random single precision floating value
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.spf_val):
+                    self.spf_val in vsc.rangelist(addr_range1, addr_range2)
+
+    def get_rng(self, val0, val1, spf_dpf, flag):
+        if flag == 0 and spf_dpf == 32:
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] > 0
+        elif flag == 0 and spf_dpf == 64:
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] > 0
+        elif flag == 1 and spf_dpf == 32:
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] == 0
+        else:
+            with vsc.raw_mode():
+                with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] == 0
+
     def get_rand_spf_value(self):
-        # TODO randcase
-        value = random.randrange(0, 2**32 - 1)
-        return value
+        vsc.randselect([
+            # Infinity
+            (1, lambda: self.get_randselect(0x7f80_0000, 0xff80_0000, 0)),
+            # Largest
+            (1, lambda: self.get_randselect(0x7f7f_ffff, 0xff7f_ffff, 0)),
+            # Zero
+            (1, lambda: self.get_randselect(0x0000_0000, 0x8000_0000, 0)),
+            # NaN
+            (1, lambda: self.get_randselect(0x7f80_0001, 0x7fc0_0000, 0)),
+            # Normal
+            (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 0)),
+            # Subnormal
+            (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 1))])
+        return self.spf_val
 
-    # Get a random double precision floating value
     def get_rand_dpf_value(self):
-        value = vsc.bit_t(64)
-        # TODO randcase
-        return value
+        vsc.randselect([
+            # Infinity
+            (1, lambda: self.get_randselect(0x7ff0_0000_0000_0000, 0xfff0_0000_0000_0000, 1)),
+            # largest
+            (1, lambda: self.get_randselect(0x7fef_ffff_ffff_ffff, 0xffef_ffff_ffff_ffff, 1)),
+            # Zero
+            (1, lambda: self.get_randselect(0x0000_0000_0000_0000, 0x8000_0000_0000_0000, 1)),
+            # NaN
+            (1, lambda: self.get_randselect(0x7ff0_0000_0000_0001, 0x7ff8_0000_0000_0000, 1)),
+            # Normal
+            (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64 , 0)),
+            # Subnormal
+            (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64, 1))])
+        return self.dpf_val
 
-    def init_vector_engine(self):
-        pass
+    # Generate "test_done" section, test is finished by an ECALL instruction
+    # The ECALL trap handler will handle the clean up procedure before finishing the test.
 
     def gen_test_done(self):
-        string = pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN)
-        self.instr_stream.append(string)
-        self.instr_stream.append(pkg_ins.indent + "li gp, 1")
-
+        self.instr_stream.extend((pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN),
+                                  pkg_ins.indent + "li gp, 1"))
         if cfg.bare_program_mode:
             self.instr_stream.append(pkg_ins.indent + "j write_tohost")
         else:
             self.instr_stream.append(pkg_ins.indent + "ecall")
 
-    def gen_register_dump(self):
-        string = ""
+    # Dump all GPR to the starting point of the program
+    # TB can check the GPR value for this memory location to compare with expected value generated
+    # by the ISA simulator. If the processor doesn't have a good tracer unit, it might not be
+    # possible to compare the GPR value after each instruction execution.
+    def gen_register_dump(self, instr):
         # load base address
-        string = "{}la x{}, _start".format(pkg_ins.indent, cfg.gpr[0])
-        self.instr_stream.append(string)
-
+        instr.append("la x{}, _start".format(cfg.gpr[0]))
         # 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])
+                dump_str = "sd x{}, {}(x{})".format(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])
-            self.instr_stream.append(string)
+                dump_str = "sw x{}, {}(x{})".format(i, i * (rcs.XLEN // 8), cfg.gpr[0])
+            instr.append(dump_str)
+
+    # ----------------------------------------------------------------------------------
+    # Privileged mode entering routine
+    # ----------------------------------------------------------------------------------
 
     def pre_enter_privileged_mode(self, hart):
         instr = []
-        string = []
-
-        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)
-
+        privil_str = []
+        # Setup kernel stack pointer
+        privil_str.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart)))
+        self.gen_section(pkg_ins.get_label("kernel_sp", hart), privil_str)
+        # Setup interrupt and exception delegation
         if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE):
             self.gen_delegation(hart)
+        # Setup trap vector register
         self.trap_vector_init(hart)
+        # Setup PMP CSRs
         self.setup_pmp(hart)
-
+        # Generate PMPADDR write test sequence
+        self.gen_pmp_csr_write(hart)
+        # Initialize PTE (link page table based on their real physical address)
         if cfg.virtual_addr_translation_on:
-            self.page_table_list.process_page_table(instr)
+            # TODO
+            # self.page_table_list.process_page_table(instr)
             self.gen_section(pkg_ins.get_label("process_pt", hart), instr)
+        # Setup mepc register, jump to init entry
         self.setup_epc(hart)
+        # Initialization of any implementation-specific custom CSRs
+        self.setup_custom_csrs(hart)
+        # Setup initial privilege mode
         self.gen_privileged_mode_switch_routine(hart)
 
     def gen_privileged_mode_switch_routine(self, hart):
         privil_seq = riscv_privileged_common_seq()
-        for i in range(len(rcs.supported_privileged_mode)):
+        for privil_mode in rcs.supported_privileged_mode:
             instr = []
             # csr_handshake = []
-            if rcs.supported_privileged_mode[i] != cfg.init_privileged_mode:
+            if privil_mode != cfg.init_privileged_mode:
                 continue
             logging.info("Generating privileged mode routing for {}"
-                         .format(rcs.supported_privileged_mode[i]))
+                         .format(privil_mode.name))
             # Enter Privileged mode
             privil_seq.hart = hart
             privil_seq.randomize()
-            privil_seq.enter_privileged_mode(rcs.supported_privileged_mode[i], instr)
-            # TODO
+            privil_seq.enter_privileged_mode(privil_mode, instr)
             if cfg.require_signature_addr:
+                # TODO
                 pass
         self.instr_stream.extend(instr)
 
+    # Setup EPC before entering target privileged mode
     def setup_epc(self, hart):
         instr = []
         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], 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.extend(("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)))
         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)
 
+    # Setup PMP CSR configuration
     def setup_pmp(self, hart):
+        # TODO
+        pass
+    # Generates a directed stream of instructions to write random values to all supported
+    # pmpaddr CSRs to test write accessibility.
+    # The original CSR values are restored afterwards.
+
+    def gen_pmp_csr_write(self, hart):
+        # TODO
         pass
 
+    # Handles creation of a subroutine to initialize any custom CSRs
+    def setup_custom_csrs(self, hart):
+        # TODO
+        pass
+
+    # This function should be overridden in the riscv_asm_program_gen extended class
+    # corresponding to the RTL implementation if it has any custom CSRs defined.
+
+    # All that needs to be done in the overridden function is to manually create
+    # the instruction strings to set up any custom CSRs and then to push those strings
+    # into the instr queue.
+    def init_custom_csr(self, instr):
+        # TODO
+        pass
+
+    # ---------------------------------------------------------------------------------------
+    # Privileged CSR setup for interrupt and exception handling and delegation
+    # ---------------------------------------------------------------------------------------
+
+    # Interrupt and exception delegation setting.
+    # The lower level exception and interrupt can be delegated to higher level handler.
     def gen_delegation(self, hart):
-        self.gen_delegation_instr(hart, "MEDELEG", "MIDELEG",
+        self.gen_delegation_instr(hart,
+                                  privileged_reg_t.MEDELEG,
+                                  privileged_reg_t.MIDELEG,
                                   cfg.m_mode_exception_delegation,
                                   cfg.m_mode_interrupt_delegation)
         if rcs.support_umode_trap:
-            self.gen_delegation_instr(hart, "SEDELEG", "SIDELEG",
+            self.gen_delegation_instr(hart,
+                                      privileged_reg_t.SEDELEG,
+                                      privileged_reg_t.SIDELEG,
                                       cfg.s_mode_exception_delegation,
                                       cfg.s_mode_interrupt_delegation)
 
     def gen_delegation_instr(self, hart, edeleg, ideleg,
                              edeleg_enable, ideleg_enable):
+        # TODO
         pass
 
+    # Setup trap vector - MTVEC, STVEC, UTVEC
     def trap_vector_init(self, hart):
         instr = []
         for mode in rcs.supported_privileged_mode:
@@ -498,43 +651,73 @@
             else:
                 logging.critical("Unsupported privileged_mode {}".format(mode.name))
                 sys.exit(1)
-
+            # Skip utvec init if trap delegation to u_mode is not supported
             if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)):
                 continue
-
             if mode < cfg.init_privileged_mode:
                 continue
-
             tvec_name = trap_vec_reg.name
             tvec_name = tvec_name.lower()
             instr.append("la x{}, {}{}_handler".format(
                 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):
+                # For supervisor and user mode, use virtual address instead of physical address.
+                # Virtual address starts from address 0x0, here only the lower 20 bits are kept
+                # as virtual address offset.
                 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], cfg.gpr[0], cfg.mtvec_mode))
-            instr.append("csrw {}, x{} # {}".format(
-                hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name))
-
+            instr.extend(("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode),
+                          "csrw {}, x{} # {}".format(hex(trap_vec_reg), cfg.gpr[0],
+                                                     trap_vec_reg.name)))
         self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
 
+    # ---------------------------------------------------------------------------------------
+    # Exception handling routine
+    # ---------------------------------------------------------------------------------------
+
+    # Trap handling routine
     def gen_all_trap_handler(self, hart):
+        instr = []
+        # If PMP isn't supported, generate the relevant trap handler sections as per usual
         if not rcs.support_pmp:
             self.gen_trap_handlers(hart)
+            # Ecall handler
             self.gen_ecall_handler(hart)
+            # Instruction fault handler
             self.gen_instr_fault_handler(hart)
+            # Load fault handler
             self.gen_load_fault_handler(hart)
+            # Store fault handler
             self.gen_store_fault_handler(hart)
+        # Ebreak handler
+        self.gen_ebreak_handler(hart)
+        # Illegal instruction handler
         self.gen_illegal_instr_handler(hart)
+        # Generate page table fault handling routine
+        # Page table fault is always handled in machine mode, as virtual address translation may be
+        # broken when page fault happens.
+        self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+                                     core_status_t.HANDLING_EXCEPTION)
+        if not self.page_table_list:
+            # TODO
+            # self.page_table_list.gen_page_fault_handling_routine(instr)
+            pass
+        else:
+            instr.append("nop")
+        self.gen_section(pkg_ins.get_label("pt_fault_handler", hart), instr)
 
     def gen_trap_handlers(self, hart):
+        # TODO
         self.gen_trap_handler_section(hart, "m", privileged_reg_t.MCAUSE,
                                       privileged_reg_t.MTVEC, privileged_reg_t.MTVAL,
                                       privileged_reg_t.MEPC, privileged_reg_t.MSCRATCH,
                                       privileged_reg_t.MSTATUS, privileged_reg_t.MIE,
                                       privileged_reg_t.MIP)
 
+    # Generate the interrupt and trap handler for different privileged mode.
+    # The trap handler checks the xCAUSE to determine the type of the exception and jumps to
+    # corresponding exeception handling routine.
     def gen_trap_handler_section(self, hart, mode, cause, tvec,
                                  tval, epc, scratch, status, ie, ip):
         # is_interrupt = 1
@@ -546,7 +729,6 @@
             # Push user mode GPR to kernel stack before executing exception handling,
             # this is to avoid exception handling routine modify user program state
             # unexpectedly
-            # TODO
             pkg_ins.push_gpr_to_kernel_stack(
                 status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
             # Checking xStatus can be optional if ISS (like spike) has different implementation of
@@ -554,6 +736,9 @@
             if cfg.check_xstatus:
                 instr.append("csrr x{}, {} # {}".format(
                     cfg.gpr[0], hex(status), status.name))
+            # Use scratch CSR to save a GPR value
+            # Check if the exception is caused by an interrupt, if yes, jump to interrupt
+            # handler Interrupt is indicated by xCause[XLEN-1]
             instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(cause),
                                                       cause.name) +
                          "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0],
@@ -564,26 +749,29 @@
                                                                        mode))
         # The trap handler will occupy one 4KB page, it will be allocated one entry in
         # the page table with a specific privileged mode.
-
         if rcs.SATP_MODE != satp_mode_t.BARE:
             self.instr_stream.append(".align 12")
         else:
             self.instr_stream.append(".align {}".format(cfg.tvec_alignment))
-
         tvec_name = tvec.name
         self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr)
-        # TODO Exception handlers
+
+        # Exception handler
         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),
+        # TODO
+        instr.extend(("csrr x{}, {} # {}".format(cfg.gpr[0], hex(epc), epc.name),
+                      "csrr x{}, {} # {}".format(cfg.gpr[0], hex(cause), cause.name),
+                      # Check if it's an ECALL exception. Jump to ECALL exception handler
+                      # TODO ECALL_SMODE, ECALL_UMODE
+                      "li x{}, {} # ECALL_MMODE".format(cfg.gpr[1],
+                                                        hex(exception_cause_t.ECALL_MMODE)),
+                      "beq x{}, x{}, {}ecall_handler".format(
+                      cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)),
                       # Illegal instruction exception
                       "li x{}, {} # ILLEGAL_INSTRUCTION".format(
                       cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)),
@@ -596,6 +784,7 @@
                       "jalr x1, x{}, 0".format(cfg.scratch_reg)))
         self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
 
+    # Generate for interrupt vector table
     def gen_interrupt_vector_table(self, hart, mode, status, cause, ie,
                                    ip, scratch, instr):
         '''In vector mode, the BASE address is shared between interrupt 0 and exception handling.
@@ -634,21 +823,37 @@
                                  "jalr x0, x{}, 0".format(cfg.scratch_reg)))
             self.gen_section(pkg_ins.get_label(
                 "{}mode_intr_vector_{}".format(mode, i), hart), intr_handler)
+    # ECALL trap handler
+    # It does some clean up like dump GPRs before communicating with host to terminate the test.
+    # User can extend this function if some custom clean up routine is needed.
 
     def gen_ecall_handler(self, hart):
-        string = ""
-        string = pkg_ins.format_string(pkg_ins.get_label(
-            "ecall_handler:", hart), pkg_ins.LABEL_STR_LEN)
-        self.instr_stream.append(string)
-        self.dump_perf_stats()
-        self.gen_register_dump()
-        string = pkg_ins.format_string(" ", pkg_ins.LABEL_STR_LEN)
-        string = string + "j write_tohost"
-        self.instr_stream.append(string)
+        instr = []
+        self.dump_perf_stats(instr)
+        self.gen_register_dump(instr)
+        instr.extend(("la x{}, write_tohost".format(cfg.scratch_reg),
+                      "jalr x0, x{}, 0".format(cfg.scratch_reg)))
+        self.gen_section(pkg_ins.get_label("ecall_handler", hart), instr)
 
+    # Ebreak trap handler
+    # When breakpoint exception happens, epc will be written with ebreak instruction
+    # itself. Add epc by 4 and resume execution.
+    # Note the breakpoint could be triggered by a C.EBREAK instruction, the generated program
+    # guarantees that epc + 4 is a valid instruction boundary
+    # TODO: Support random operations in debug mode
+    # TODO: Support ebreak exception delegation
+    # TODO: handshake the correct Xcause CSR based on delegation privil. mode
     def gen_ebreak_handler(self, hart):
+        # TODO
         pass
 
+    # Illegal instruction handler
+    # Note: Save the illegal instruction to MTVAL is optional in the spec, and mepc could be
+    # a virtual address that cannot be used in machine mode handler. As a result, there's no way to
+    # know the illegal instruction is compressed or not. This hanlder just simply adds the PC by
+    # 4 and resumes execution. The way that the illegal instruction is injected guarantees that
+    # PC + 4 is a valid instruction boundary.
+    # TODO: handshake the corret Xcause CSR based on delegation setup
     def gen_illegal_instr_handler(self, hart):
         instr = []
         self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
@@ -662,24 +867,47 @@
         instr.append("mret")
         self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart), instr)
 
+    # TODO: handshake correct csr based on delegation
     def gen_instr_fault_handler(self, hart):
+        # TODO
         pass
 
+    # TODO: handshake correct csr based on delegation
     def gen_load_fault_handler(self, hart):
+        # TODO
         pass
 
+    # TODO: handshake correct csr based on delegation
     def gen_store_fault_handler(self, hart):
+        # TODO
         pass
 
+    # ---------------------------------------------------------------------------------------
+    # Page table setup
+    # ---------------------------------------------------------------------------------------
+
+    # Create page table if virtual address translation is supported.
+    # The page is created based on the address translation mode - SV32, SV39, SV48
+    # Right now only the lowest level 4KB page table is configured as leaf page table entry (PTE),
+    # all the other super pages are link PTE.
     def create_page_table(self, hart):
+        # TODO
         pass
 
+    # Generate the page table section of the program
+    # The page table is generated as a group of continuous 4KB data sections.
     def gen_page_table_section(self, hart):
+        # TODO
         pass
 
+    # Only extend this function if the core utilizes a PLIC for handling interrupts
+    # In this case, the core will write to a specific location as the response to the interrupt, and
+    # external PLIC unit can detect this response and process the interrupt clean up accordingly.
     def gen_plic_section(self, interrupt_handler_instr):
+        # TODO
         pass
 
+    # Interrupt handler routine
     def gen_interrupt_handler_section(self, mode, hart):
         interrupt_handler_instr = []
         # ls_unit = "w" if rcs.XLEN == 32 else "d"
@@ -708,11 +936,12 @@
         else:
             logging.critical("Unsupported mode: {}".format(mode.name))
             sys.exit(1)
-
+        # If nested interrupts are enabled, set xSTATUS.xIE in the interrupt handler
+        # to re-enable interrupt handling capabilities
         if cfg.enable_nested_interrupt:
-            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)))
+            interrupt_handler_instr.extend(("csrr x{}, {}".format(cfg.gpr[0], hex(scratch)),
+                                            "bgtz x{}, 1f".format(cfg.gpr[0]),
+                                            "csrwi {}, 0x1".format(hex(scratch))))
 
             if status == privileged_reg_t.MSTATUS:
                 interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(8)))
@@ -725,7 +954,8 @@
                 sys.exit(1)
 
             interrupt_handler_instr.append("1: csrwi {},0".format(hex(scratch)))
-
+        # Read back interrupt related privileged CSR
+        # The value of these CSR are checked by comparing with spike simulation result.
         to_extend_interrupt_hanlder_instr = ["csrr  x{}, {} # {};".format(cfg.gpr[0],
                                                                           hex(status),
                                                                           status.name),
@@ -739,21 +969,30 @@
                                                                                ip.name)]
         interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
         self.gen_plic_section(interrupt_handler_instr)
+        # Restore user mode GPR value from kernel stack before return
         pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv,
                                           cfg.sp, cfg.tp, interrupt_handler_instr)
         interrupt_handler_instr.append("{}ret;".format(mode_prefix))
 
         if rcs.SATP_MODE != satp_mode_t.BARE:
+            # The interrupt handler will use one 4KB page
             self.instr_stream.append(".align 12")
         else:
             self.instr_stream.append(".align 2")
 
-        self.gen_section(pkg_ins.get_label("%0smode_intr_handler" %
-                                           (mode_prefix), hart), interrupt_handler_instr)
+        self.gen_section(pkg_ins.get_label("{}mode_intr_handler".format(mode_prefix), hart),
+                         interrupt_handler_instr)
 
+    # ---------------------------------------------------------------------------------------
+    # Helper functions
+    # ---------------------------------------------------------------------------------------
+
+    # Format a code section, without generating it
     def format_section(self, instr):
+        # TODO
         pass
 
+    # Generate a code section
     def gen_section(self, label, instr):
         if label != "":
             string = pkg_ins.format_string("{}:".format(label), pkg_ins.LABEL_STR_LEN)
@@ -763,9 +1002,12 @@
             self.instr_stream.append(string)
         self.instr_stream.append("")
 
-    def dump_perf_stats(self):
+    # Dump performance CSRs if applicable
+    def dump_perf_stats(self, instr):
+        # TODO
         pass
 
+    # Write the generated program to a file
     def gen_test_file(self, test_name):
         file = open(test_name, "w+")
         for items in self.instr_stream:
@@ -774,6 +1016,8 @@
         file.close()
         logging.info("{} is generated".format(test_name))
 
+    # Helper function to generate the proper sequence of handshake instructions
+    # to signal the testbench (see riscv_signature_pkg.sv)
     def gen_signature_handshake(self, instr, signature_type,
                                 core_status=core_status_t.INITIALIZED,
                                 test_result=test_result_t.TEST_FAIL,
@@ -828,6 +1072,10 @@
                 logging.critical("signature_type is not defined")
                 sys.exit(1)
 
+    # ---------------------------------------------------------------------------------------
+    # Inject directed instruction stream
+    # ---------------------------------------------------------------------------------------
+
     def add_directed_instr_stream(self, name, ratio):
         self.directed_instr_stream_ratio[name] = ratio
         logging.info("Adding directed instruction stream:%0s ratio:%0d/1000", name, ratio)
@@ -852,6 +1100,7 @@
                 stream_freq = cfg.args_dict[stream_freq_opts]
                 self.add_directed_instr_stream(stream_name, stream_freq)
 
+    # Generate directed instruction stream based on the ratio setting
     def generate_directed_instr_stream(self, hart = 0, label = "", original_instr_cnt = 0,
                                        min_insert_cnt = 0, kernel_mode = 0, instr_stream = []):
         instr_insert_cnt = 0
@@ -885,5 +1134,18 @@
                 idx += 1
         random.shuffle(instr_stream)
 
+    # ----------------------------------------------------------------------------------
+    # Generate the debug ROM, and any related programs
+    # ----------------------------------------------------------------------------------
+
     def gen_debug_rom(self, hart):
+        # TODO
+        pass
+
+    # ----------------------------------------------------------------------------------
+    # Vector extension generation
+    # ----------------------------------------------------------------------------------
+
+    def randomize_vec_gpr_and_csr(self):
+        # TODO
         pass
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 03a4499..ac8e91f 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
@@ -14,16 +14,23 @@
 import vsc
 import random
 from collections import defaultdict
-from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t
 from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t
 
 
+# -----------------------------------------------------------------------------------------
+# RISC-V assmebly program data section generator
+# There can be user mode and supervisor(kernel) mode data pages
+# -----------------------------------------------------------------------------------------
+
 @vsc.randobj
 class riscv_data_page_gen:
     def __init__(self):
         self.data_page_str = []
         self.mem_region_setting = defaultdict(list)
 
+    # The data section can be initialized with different data pattern:
+    # - Random value, incremental value, all zeros
     @staticmethod
     def gen_data(idx, pattern, num_of_bytes, data):
         temp_data = 0
@@ -36,10 +43,9 @@
                 data[i] = (idx + i) % 256
         return data
 
+    # Generate data pages for all memory regions
     def gen_data_page(self, hart_id, pattern, is_kernel=0, amo=0):
-        tmp_str = ""
         temp_data = []
-        page_size = 0
         self.data_page_str.clear()
         if is_kernel:
             self.mem_region_setting = cfg.s_mem_region
@@ -48,8 +54,6 @@
         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,
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
index cbdbb26..3b545f3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
@@ -1,7 +1,6 @@
 """
 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
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 0d6784b..91e4823 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
@@ -1,7 +1,6 @@
 """
 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
@@ -20,14 +19,13 @@
 from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
 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,
-                                       mem_region_t)
+from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t,
+                                       riscv_instr_name_t, mem_region_t, pkg_ins)
 from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
 
+# Base class for directed instruction stream
 class riscv_directed_instr_stream(riscv_rand_instr_stream):
 
     label = ""
@@ -47,6 +45,7 @@
             self.instr_list[0].has_label = 1
 
 
+# Base class for memory access stream
 @vsc.randobj
 class riscv_mem_access_stream(riscv_directed_instr_stream):
     def __init__(self):
@@ -65,6 +64,7 @@
             self.data_page.extend(cfg.mem_region)
         self.max_data_page_id = len(self.data_page)
 
+    # Use "la" instruction to initialize the base regiseter
     def add_rs1_init_la_instr(self, gpr, idx, base = 0):
         la_instr = riscv_pseudo_instr()
         la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA
@@ -79,6 +79,7 @@
                                                 cfg.mem_region[idx].name, base)
         self.instr_list.insert(0, la_instr)
 
+    # Insert some other instructions to mix with mem_access instruction
     def add_mixed_instr(self, instr_cnt):
         self.setup_allowed_instr(1, 1)
         for i in range(instr_cnt):
@@ -87,6 +88,7 @@
             self.insert_instr(instr)
 
 
+# Stress back to back jump instruction
 @vsc.randobj
 class riscv_jal_instr(riscv_rand_instr_stream):
     def __init__(self):
@@ -96,6 +98,7 @@
         self.jump_start = riscv_instr()
         self.jump_end = riscv_instr()
         self.num_of_jump_instr = vsc.rand_int_t()
+        self.jal = []
 
     @vsc.constraint
     def instr_c(self):
@@ -115,6 +118,8 @@
             jal.append(riscv_instr_name_t.C_J)
             if rcs.XLEN == 32:
                 jal.append(riscv_instr_name_t.C_JAL)
+
+        # First instruction
         self.jump_start = riscv_instr.get_instr(riscv_instr_name_t.JAL)
         with self.jump_start.randomize_with() as it:
             self.jump_start.rd == RA
@@ -157,6 +162,7 @@
     NegativeMax = auto()
 
 
+# Strees the numeric corner cases of integer arithmetic operations
 @vsc.randobj
 class riscv_int_numeric_corner_stream(riscv_directed_instr_stream):
     def __init__(self):
@@ -185,6 +191,7 @@
             self.avail_regs[i] != riscv_reg_t.ZERO
 
     def pre_randomize(self):
+        # TODO
         pass
 
     def post_randomize(self):
@@ -212,7 +219,6 @@
 
 # Push Stack Instructions
 class riscv_push_stack_instr(riscv_rand_instr_stream):
-
     def __init__(self):
         super().__init__()
         self.stack_len = 0
@@ -225,12 +231,13 @@
         self.push_start_label = ''
 
     def init(self):
+        # Save RA, T0
         self.reserved_rd = [cfg.ra]
         self.saved_regs = [cfg.ra]
         self.num_of_reg_to_save = len(self.saved_regs)
         if self.num_of_reg_to_save * (rcs.XLEN / 8) > self.stack_len:
-            logging.error('stack len [%0d] is not enough to store %d regs',
-                          self.stack_len, self.num_of_reg_to_save)
+            logging.error('stack len [{}] is not enough to store {} regs'
+                          .format(self.stack_len, self.num_of_reg_to_save))
             sys.exit(1)
         self.num_of_redundant_instr = random.randrange(3, 10)
         self.initialize_instr_list(self.num_of_redundant_instr)
@@ -288,7 +295,6 @@
 
 # Pop stack instruction stream
 class riscv_pop_stack_instr(riscv_rand_instr_stream):
-
     def __init__(self):
         super().__init__()
         self.stack_len = 0
@@ -301,8 +307,8 @@
         self.reserved_rd = [cfg.ra]
         self.num_of_reg_to_save = len(self.saved_regs)
         if self.num_of_reg_to_save * 4 > self.stack_len:
-            logging.error('stack len [%0d] is not enough to store %d regs',
-                          self.stack_len, self.num_of_reg_to_save)
+            logging.error('stack len [{}] is not enough to store {} regs'
+                          .format(self.stack_len, self.num_of_reg_to_save))
             sys.exit(1)
         self.num_of_redundant_instr = random.randrange(3, 10)
         self.initialize_instr_list(self.num_of_redundant_instr)
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
index 3f534a4..4be43bc 100644
--- 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
@@ -162,8 +162,8 @@
     @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]):
+            with vsc.if_then(self.exception.inside(vsc.rangelist(illegal_instr_type_e.kIllegalFunc3,
+                                                illegal_instr_type_e.kIllegalFunc7))):
                 self.opcode.inside(vsc.rangelist([51, 19, 59]))
 
     @vsc.constraint
@@ -338,7 +338,7 @@
     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)
+            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:
@@ -347,8 +347,8 @@
                 (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)
+            self.legal_c00_opcode.extend((3, 7))
+            self.legal_c10_opcode.extend((3, 7))
         # TODO csr
 
     def get_bin_str(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
index b020e3d..4912fac 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
@@ -13,6 +13,7 @@
 limitations under the License.

 """

 

+import traceback

 from pygen_src.isa.riscv_cov_instr import *

 

 

@@ -1381,6 +1382,195 @@
             self.cp_align = vsc.cross([self.cp_imm_align, self.cp_rs1_align])

             self.cp_ras = vsc.cross([self.cp_rs1_link, self.cp_rd_link])

 

+    '''MUL instructions'''

+    @vsc.covergroup

+    class mul_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+    @vsc.covergroup

+    class mulh_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+    @vsc.covergroup

+    class mulhsu_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+    @vsc.covergroup

+    class mulhu_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+    @vsc.covergroup

+    class div_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+            self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,

+                                                cp_t=vsc.enum_t(div_result_e))

+

+    @vsc.covergroup

+    class divu_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+            self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,

+                                                cp_t=vsc.enum_t(div_result_ex_overflow_e))

+

+    @vsc.covergroup

+    class rem_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+            self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,

+                                                cp_t=vsc.enum_t(div_result_e))

+

+    @vsc.covergroup

+    class remu_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_t))

+            self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,

+                                             cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,

+                                            self.cp_rd_sign])

+            self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,

+                                                cp_t=vsc.enum_t(div_result_ex_overflow_e))

+

     '''CSR instructions'''

 

     @vsc.covergroup

@@ -1402,7 +1592,7 @@
             super().__init__()

 

             self.instr = None

-            self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[7:2],

+            self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[6:2],

                                             bins={

                                                 "a": vsc.bin_array([], [0, 31])

                                             }

@@ -1430,11 +1620,430 @@
                                            }

                                            )

 

+    @vsc.covergroup

+    class hint_cg(object):

+        def __init__(self):

+            super().__init__()

+            self.instr = None

+            self.cp_hint0 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                          bins=dict(addi=vsc.wildcard_bin_array([],

+                                                    "0b0000_1xxx_x000_0001",

+                                                    "0b0000_x1xx_x000_0001",

+                                                    "0b0000_xx1x_x000_0001",

+                                                    "0b0000_xxx1_x000_0001",

+                                                    "0b0000_xxxx_1000_0001")))

+            self.cp_hint1 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(li=vsc.wildcard_bin(

+                                           "0b010x_0000_0xxx_xx01")))

+            self.cp_hint2 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(lui=vsc.wildcard_bin(

+                                           "0b011x_0000_0xxx_xx01")))

+            self.cp_hint3 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(srli64=vsc.wildcard_bin(

+                                           "0b1000_00xx_x000_0001")))

+            self.cp_hint4 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(srai64=vsc.wildcard_bin(

+                                           "0b1000_01xx_x000_0001")))

+            self.cp_hint5 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(slli=vsc.wildcard_bin(

+                                           "0b000x_0000_0xxx_xx10")))

+            self.cp_hint6 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(slli64=vsc.wildcard_bin(

+                                           "0b0000_xxxx_x000_0010")))

+            self.cp_hint7 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(mv=vsc.wildcard_bin_array([],

+                                                    "0b1000_0000_01xx_xx10",

+                                                    "0b1000_0000_0x1x_xx10",

+                                                    "0b1000_0000_0xx1_xx10",

+                                                    "0b1000_0000_0xxx_1x10",

+                                                    "0b1000_0000_0xxx_x110")))

+            self.cp_hint8 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins=dict(add=vsc.wildcard_bin_array([],

+                                                    "0b1001_0000_01xx_xx10",

+                                                    "0b1001_0000_0x1x_xx10",

+                                                    "0b1001_0000_0xx1_xx10",

+                                                    "0b1001_0000_0xxx_1x10",

+                                                    "0b1001_0000_0xxx_x110"

+                                                 )))

+

+    @vsc.covergroup

+    class illegal_compressed_instr_cg(object):

+        def __init__(self):

+            super().__init__()

+            self.instr = None

+            self.cp_point0 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_illegal=vsc.wildcard_bin(

+                                           "0b0000_0000_0000_0000")))

+            self.cp_point1 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_addi4spn=vsc.wildcard_bin_array([],

+                                           "0b0000_0000_000x_x100",

+                                           "0b0000_0000_000x_1x00",

+                                           "0b0000_0000_0001_xx00")))

+            self.cp_point2 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_addiw=vsc.wildcard_bin(

+                                           "0b001x_0000_0xxx_xx01")))

+            self.cp_point3 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_addi16sp=vsc.wildcard_bin(

+                                           "0b0110_0001_0000_0001")))

+            self.cp_point4 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_lui=vsc.wildcard_bin_array([],

+                                           "0b0110_xxxx_1000_0001",

+                                           "0b0110_xx1x_x000_0001",

+                                           "0b0110_x1xx_x000_0001",

+                                           "0b0110_1xxx_x000_0001")))

+            self.cp_point5 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_reserv_0=vsc.wildcard_bin(

+                                           "0b1001_11xx_x10x_xx01")))

+            self.cp_point6 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_reserv_1=vsc.wildcard_bin(

+                                           "0b1001_11xx_x11x_xx01")))

+            self.cp_point7 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_jr=vsc.wildcard_bin(

+                                           "0b1000_0000_0000_0010")))

+            self.cp_point8 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_lwsp=vsc.wildcard_bin(

+                                           "0b010x_0000_0xxx_xx10")))

+            self.cp_point9 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_lqsp=vsc.wildcard_bin(

+                                           "0b001x_0000_0xxx_xx10")))

+            self.cp_point10 = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                           bins = dict(c_ldsp=vsc.wildcard_bin(

+                                           "0b011x_0000_0xxx_xx10")))

+

+    '''Compressed instructions'''

+

+    @vsc.covergroup

+    class compressed_opcode_cg(object):

+        # TODO issue with iff parameter

+        def __init__(self):

+            super().__init__()

+            self.instr = None

+            '''self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[15:0],

+                                            bins={

+                                                "a": vsc.bin_array([], [0, 31])

+                                            }

+                                            )'''

+

+    @vsc.covergroup

+    class c_lw_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+            self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+

+    @vsc.covergroup

+    class c_lwsp_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+

+    @vsc.covergroup

+    class c_sw_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+            self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,

+                                                cp_t=vsc.enum_t(store_lsu_hazard_e))

+

+    @vsc.covergroup

+    class c_swsp_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+

+    @vsc.covergroup

+    class c_addi4spn_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(store_lsu_hazard_e))

+

+    @vsc.covergroup

+    class c_addi_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(store_lsu_hazard_e))

+

+    @vsc.covergroup

+    class c_addi16sp_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(store_lsu_hazard_e))

+

+    @vsc.covergroup

+    class c_li_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(store_lsu_hazard_e))

+

+    @vsc.covergroup

+    class c_lui_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_sp_t))

+

+    @vsc.covergroup

+    class c_sub_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_add_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                                cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_mv_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_andi_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+

+    @vsc.covergroup

+    class c_xor_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_or_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_and_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,

+                                         cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(hazard_e))

+

+    @vsc.covergroup

+    class c_beqz_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+

+    @vsc.covergroup

+    class c_bnez_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+

+    @vsc.covergroup

+    class c_srli_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+

+    @vsc.covergroup

+    class c_srai_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(compressed_gpr))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+

+    @vsc.covergroup

+    class c_slli_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,

+                                                cp_t=vsc.enum_t(branch_hazard_e))

+

+    @vsc.covergroup

+    class c_j_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+

+    @vsc.covergroup

+    class c_jal_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,

+                                              cp_t=vsc.enum_t(operand_sign_e))

+

+    @vsc.covergroup

+    class c_jr_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],

+                                               bins={

+                                                   "Zero" : vsc.bin(0),

+                                                   "One"  : vsc.bin(1),

+                                                   "Two"  : vsc.bin(2),

+                                                   "Three": vsc.bin(3)

+                                                    })

+

+    @vsc.covergroup

+    class c_jalr_cg(object):

+        def __init__(self):

+            super().__init__()

+

+            self.instr = None

+            self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,

+                                        cp_t=vsc.enum_t(riscv_reg_ex_zero_t))

+            self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],

+                                               bins={

+                                                   "Zero" : vsc.bin(0),

+                                                   "One"  : vsc.bin(1),

+                                                   "Two"  : vsc.bin(2),

+                                                   "Three": vsc.bin(3)

+                                                    })

+            self.cp_rd_align = vsc.coverpoint(lambda: self.instr.rd_value[1],

+                                              bins={

+                                                  "Aligned"    : vsc.bin(1),

+                                                  "Not-aligned": vsc.bin(0)

+                                                   })

+

     def cg_instantiation(self):

         self.opcode_cg_i = self.opcode_cg()

         self.csrrw_cg_i = self.csrrw_cg()

         self.rv32i_misc_cg_i = self.rv32i_misc_cg()

         self.mepc_alignment_cg_i = self.mepc_alignment_cg()

+        # self.compressed_opcode_cg_i = self.compressed_opcode_cg()

         self.beq_cg_i = self.beq_cg()

         self.jal_cg_i = self.jal_cg()

         self.lui_cg_i = self.lui_cg()

@@ -1458,13 +2067,56 @@
         self.srai_cg_i = self.srai_cg()

         self.slt_cg_i = self.slt_cg()

         self.slli_cg_i = self.slli_cg()

+        self.mul_cg_i = self.mul_cg()

+        self.mulh_cg_i = self.mulh_cg()

+        self.mulhsu_cg_i = self.mulhsu_cg()

+        self.mulhu_cg_i = self.mulhu_cg()

+        self.div_cg_i = self.div_cg()

+        self.divu_cg_i = self.divu_cg()

+        self.rem_cg_i = self.rem_cg()

+        self.remu_cg_i = self.remu_cg()

+        self.c_lw_cg_i = self.c_lw_cg()

+        self.c_lwsp_cg_i = self.c_lwsp_cg()

+        self.c_sw_cg_i = self.c_sw_cg()

+        self.c_swsp_cg_i = self.c_swsp_cg()

+        self.c_addi4spn_cg_i = self.c_addi4spn_cg()

+        self.c_addi_cg_i = self.c_addi_cg()

+        self.c_addi16sp_cg_i = self.c_addi16sp_cg()

+        self.c_li_cg_i = self.c_li_cg()

+        self.c_lui_cg_i = self.c_lui_cg()

+        self.c_sub_cg_i = self.c_sub_cg()

+        self.c_add_cg_i = self.c_add_cg()

+        self.c_mv_cg_i = self.c_mv_cg()

+        self.c_andi_cg_i = self.c_andi_cg()

+        self.c_xor_cg_i = self.c_xor_cg()

+        self.c_or_cg_i = self.c_or_cg()

+        self.c_and_cg_i = self.c_and_cg()

+        self.c_beqz_cg_i = self.c_beqz_cg()

+        self.c_bnez_cg_i = self.c_bnez_cg()

+        self.c_srli_cg_i = self.c_srli_cg()

+        self.c_srai_cg_i = self.c_srai_cg()

+        self.c_slli_cg_i = self.c_slli_cg()

+        self.c_j_cg_i = self.c_j_cg()

+        self.c_jal_cg_i = self.c_jal_cg()

+        self.c_jr_cg_i = self.c_jr_cg()

+        self.c_jalr_cg_i = self.c_jalr_cg()

+        self.hint_cg_i = self.hint_cg()

+        self.illegal_compressed_instr_cg_i = self.illegal_compressed_instr_cg()

 

     def sample(self, instr):

         self.instr_cnt += 1

         if self.instr_cnt > 1:

             instr.check_hazard_condition(self.pre_instr)

-        # TODO: sampling for hint, compressed, and illegal_compressed insts

-        if instr.binary[2:0] == 3:

+        # TODO: sampling for compressed_instr_cg

+        if ((instr.binary[1:0] != 3) and (riscv_instr_group_t.RV32C in rcs.supported_isa)):

+            # self.compressed_opcode_cg_i.instr = instr

+            # self.compressed_opcode_cg_i.sample()

+            self.hint_cg_i.instr = instr

+            self.hint_cg_i.sample()

+            self.illegal_compressed_instr_cg_i.instr = instr

+            self.illegal_compressed_instr_cg_i.sample()

+

+        if instr.binary[1:0] == 3:

             self.opcode_cg_i.instr = instr

             self.opcode_cg_i.sample()

         try:

@@ -1474,6 +2126,9 @@
         except Exception:

             logging.info("Covergroup for instr {} is not supported yet".format(

                 instr.instr.name))

+            # Trace the error if there is an Exception

+            logging.info("Traceback error log: {}".format(traceback.format_exc()))

+

         if instr.group.name == "RV32I":

             self.rv32i_misc_cg_i.instr = instr

             self.rv32i_misc_cg_i.sample()

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 0de86af..f99fd4b 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
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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
@@ -22,19 +20,48 @@
                                        riscv_reg_t, privileged_mode_t,
                                        riscv_instr_group_t, data_pattern_t,
                                        riscv_instr_category_t, satp_mode_t,
-                                       mem_region_t)
+                                       mem_region_t, vreg_init_method_t)
 
 
+# ----------------------------------------------------------------------------
+# RISC-V assembly program generator configuration class
+# ----------------------------------------------------------------------------
+
 @vsc.randobj
 class riscv_instr_gen_config:
+
     def __init__(self):
-        self.main_program_instr_cnt = vsc.rand_int32_t()  # count of main_prog
-        self.sub_program_instr_cnt = []  # count of sub_prog
-        self.debug_program_instr_cnt = 0  # count of debug_rom
-        self.debug_sub_program_instr_cnt = []  # count of debug sub_progrms
-        self.max_directed_instr_stream_seq = 20
+        # ---------------------------------------------------------------------------
+        # Random instruction generation settings
+        # ---------------------------------------------------------------------------
+
+        # Instruction count of the main program
+        self.main_program_instr_cnt = vsc.rand_int32_t()
+
+        # Instruction count of each sub-program
+        self.sub_program_instr_cnt = []
+
+        # Instruction count of the debug rom
+        self.debug_program_instr_cnt = 0
+
+        # Instruction count of debug sub-programs
+        self.debug_sub_program_instr_cnt = []
+
+        # Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
         self.data_page_pattern = vsc.rand_enum_t(data_pattern_t)
 
+        # Initialization of the vregs
+        # SAME_VALUES_ALL_ELEMS - Using vmv.v.x to fill all the elements of the vreg with
+        # the same value as the one in the GPR selected
+        # RANDOM_VALUES_VMV     - Using vmv.v.x + vslide1up.vx to randomize the contents
+        # of each vector element
+        # RANDOM_VALUES_LOAD    - Using vle.v, same approach as RANDOM_VALUES_VMV but more
+        # efficient for big VLEN
+        self.vreg_init_method = vreg_init_method_t.RANDOM_VALUES_VMV
+
+        # Maximum directed instruction stream sequence count
+        self.max_directed_instr_stream_seq = 20
+
         self.init_delegation()
         self.argv = self.parse_args()
         self.args_dict = vars(self.argv)
@@ -42,12 +69,16 @@
         global rcs
         rcs = import_module("pygen_src.target." + self.argv.target + ".riscv_core_setting")
 
+        # Dict for delegation configuration for each exception and interrupt
+        # When the bit is 1, the corresponding delegation is enabled.
+        # TODO
         self.m_mode_exception_delegation = {}
         self.s_mode_exception_delegation = {}
         self.m_mode_interrupt_delegation = {}
         self.s_mode_interrupt_delegation = {}
 
         # init_privileged_mode default to MACHINE_MODE
+        # TODO: remove defult machine_mode once all modes get supported
         self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
 
         self.mstatus = vsc.rand_bit_t(rcs.XLEN - 1)
@@ -57,6 +88,8 @@
         self.ustatus = vsc.rand_bit_t(rcs.XLEN - 1)
         self.uie = vsc.rand_bit_t(rcs.XLEN - 1)
 
+        # Key fields in xSTATUS
+        # Memory protection bits
         self.mstatus_mprv = vsc.rand_bit_t(1)
         self.mstatus_mxr = vsc.rand_bit_t(1)
         self.mstatus_sum = vsc.rand_bit_t(1)
@@ -65,25 +98,55 @@
         self.mstatus_vs = vsc.rand_bit_t(2)
         self.mtvec_mode = vsc.rand_enum_t(mtvec_mode_t)
 
-        self.tvec_alignment = vsc.rand_uint8_t(self.argv.tvec_alignment)
+        # TVEC alignment
+        # This value is the log_2 of the byte-alignment of TVEC.BASE field
+        # As per RISC-V privileged spec, default will be set to 2 (4-byte aligned)
+        self.tvec_alignment = vsc.rand_uint32_t(self.argv.tvec_alignment)
 
+        # Floating point rounding mode
         self.fcsr_rm = vsc.rand_enum_t(f_rounding_mode_t)
+
+        # Enable sfence.vma instruction
         self.enable_sfence = vsc.rand_bit_t(1)
+
+        # Reserved register
+        # Reserved for various hardcoded routines
         self.gpr = vsc.rand_list_t(vsc.enum_t(riscv_reg_t), sz=4)
 
+        # Used by any DCSR operations inside of the debug rom.
+        # Also used by the PMP generation.
         self.scratch_reg = vsc.rand_enum_t(riscv_reg_t)
+
+        # Reg used exclusively by the PMP exception handling routine.
+        # Can overlap with the other GPRs used in the random generation,
+        # as PMP exception handler is hardcoded and does not include any
+        # random instructions.
         self.pmp_reg = vsc.rand_enum_t(riscv_reg_t)
+
+        # Use a random register for stack pointer/thread pointer
         self.sp = vsc.rand_enum_t(riscv_reg_t)
         self.tp = vsc.rand_enum_t(riscv_reg_t)
         self.ra = vsc.rand_enum_t(riscv_reg_t)
+
+        # Options for privileged mode CSR checking
+        # Below checking can be made optional as the ISS implementation
+        # could be different with the processor.
         self.check_misa_init_val = 0
         self.check_xstatus = 1
-        self.virtual_addr_translation_on = 0
+
+        # Virtual address translation is on for this test
+        self.virtual_addr_translation_on = vsc.rand_bit_t(1)
 
         # Commenting out for now
-        # vector_cfg = riscv_vector_cfg # TODO
+        # vector_cfg = riscv_vector_cfg  # TODO
         # pmp_cfg = riscv_pmp_cfg  # TODO
 
+        # Stack section word length
+        self.stack_len = 5000
+
+        # -----------------------------------------------------------------------------
+        # User space memory region and stack setting
+        # -----------------------------------------------------------------------------
         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())
@@ -92,37 +155,52 @@
         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
+        # Kernel Stack section word length
         self.kernel_stack_len = 4000
+
+        # Number of instructions for each kernel program
         self.kernel_program_instr_cnt = 400
-        # list of main implemented CSRs
+
+        # List of all the main implemented CSRs that the boot privilege mode cannot access
+        # e.g. these CSRs are in higher privilege modes - access should raise an exception
         self.invalid_priv_mode_csrs = []
+
+        # -----------------------------------------------------------------------------
+        # Command line options or control knobs
+        # -----------------------------------------------------------------------------
+        # Main options for RISC-V assembly program generation
+        # Number of sub-programs per test
         self.num_of_sub_program = self.argv.num_of_sub_program
         self.instr_cnt = self.argv.instr_cnt
         self.num_of_tests = self.argv.num_of_tests
+        # For tests doesn't involve load/store, the data section generation could be skipped
         self.no_data_page = self.argv.no_data_page
-        self.no_branch_jump = self.argv.no_branch_jump
-        self.no_load_store = self.argv.no_load_store
-        self.no_csr_instr = self.argv.no_csr_instr
-        self.no_ebreak = self.argv.no_ebreak
-        self.no_dret = self.argv.no_dret
-        self.no_fence = self.argv.no_fence
-        self.no_wfi = self.argv.no_wfi
+        # Options to turn off some specific types of instructions
+        self.no_branch_jump = self.argv.no_branch_jump  # No branch/jump instruction
+        self.no_load_store = self.argv.no_load_store  # No load/store instruction
+        self.no_csr_instr = self.argv.no_csr_instr  # No csr instruction
+        self.no_ebreak = self.argv.no_ebreak  # No ebreak instruction
+        self.no_dret = self.argv.no_dret  # No dret instruction
+        self.no_fence = self.argv.no_fence  # No fence instruction
+        self.no_wfi = self.argv.no_wfi  # No WFI instruction
         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
+        # Number of harts to be simulated, must be <= NUM_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
+        # Use SP as stack pointer
+        self.fix_sp = vsc.bit_t(1)
         self.fix_sp = self.argv.fix_sp
+        # Use push/pop section for data pages
         self.use_push_data_section = self.argv.use_push_data_section
+        # Directed boot privileged mode, u, m, s
         self.boot_mode_opts = self.argv.boot_mode
         # self.isa = self.argv.isa
-
         if self.boot_mode_opts:
-            logging.info("Got boot mode option - %0s", self.boot_mode_opts)
+            logging.info("Got boot mode option - {}".format(self.boot_mode_opts))
             if self.boot_mode_opts == "m":
                 self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
             elif self.boot_mode_opts == "s":
@@ -130,50 +208,89 @@
             elif self.boot_mode_opts == "u":
                 self.init_privileged_mode = privileged_mode_t.USER_MODE
             else:
-                logging.error("Illegal boot mode option - %0s", self.boot_mode_opts)
-
+                logging.error("Illegal boot mode option - {}".format(self.boot_mode_opts))
         self.enable_page_table_exception = self.argv.enable_page_table_exception
         self.no_directed_instr = self.argv.no_directed_instr
         self.asm_test_suffix = self.argv.asm_test_suffix
+        # Enable interrupt bit in MSTATUS (MIE, SIE, UIE)
         self.enable_interrupt = self.argv.enable_interrupt
         self.enable_nested_interrupt = self.argv.enable_nested_interrupt
+        # We need a separate control knob for enabling timer interrupts, as Spike
+        # throws an exception if xIE.xTIE is enabled
         self.enable_timer_irq = self.argv.enable_timer_irq
+        # Generate a bare program without any init/exit/error handling/page table routines
+        # The generated program can be integrated with a larger program.
+        # Note that the bare mode program is not expected to run in standalone mode
         self.bare_program_mode = self.argv.bare_program_mode
+        # Enable accessing illegal CSR instruction
+        # - Accessing non-existence CSR
+        # - Accessing CSR with wrong privileged mode
         self.enable_illegal_csr_instruction = self.argv.enable_illegal_csr_instruction
+        # Enable accessing CSRs at an invalid privilege level
         self.enable_access_invalid_csr_level = self.argv.enable_access_invalid_csr_level
+        # Enable misaligned instruction (caused by JALR instruction)
         self.enable_misaligned_instr = self.argv.enable_misaligned_instr
+        # Enable some dummy writes to main system CSRs (xSTATUS/xIE) at beginning of test
+        # to check repeated writes
         self.enable_dummy_csr_write = self.argv.enable_dummy_csr_write
         self.randomize_csr = self.argv.randomize_csr
+        # sfence support
         self.allow_sfence_exception = self.argv.allow_sfence_exception
+        # Interrupt/Exception Delegation
         self.no_delegation = self.argv.no_delegation
         self.force_m_delegation = self.argv.force_m_delegation
         self.force_s_delegation = self.argv.force_s_delegation
-        self.support_supervisor_mode = 0
+        self.support_supervisor_mode = 0  # TODO
         self.disable_compressed_instr = self.argv.disable_compressed_instr
         self.require_signature_addr = self.argv.require_signature_addr
-
         if self.require_signature_addr:
             self.signature_addr = int(self.argv.signature_addr, 16)
         else:
             self.signature_addr = 0xdeadbeef
-
+        # Enable a full or empty debug_rom section.
+        # Full debug_rom will contain random instruction streams.
+        # Empty debug_rom will contain just dret instruction and will return immediately.
+        # Will be empty by default.
         self.gen_debug_section = self.argv.gen_debug_section
+        # Enable generation of a directed sequence of instructions containing
+        # ebreak inside the debug_rom.
+        # Disabled by default.
         self.enable_ebreak_in_debug_rom = self.argv.enable_ebreak_in_debug_rom
+        # Enable setting dcsr.ebreak(m/s/u)
         self.set_dcsr_ebreak = self.argv.set_dcsr_ebreak
+        # Number of sub programs in the debug rom
         self.num_debug_sub_program = self.argv.num_debug_sub_program
+        # Enable debug single stepping
         self.enable_debug_single_step = self.argv.enable_debug_single_step
-        self.single_step_iterations = 0
+        # Number of single stepping iterations
+        self.single_step_iterations = vsc.rand_uint32_t()
+        # Enable mstatus.tw bit - causes u-mode WFI to raise illegal instruction exceptions
         self.set_mstatus_tw = self.argv.set_mstatus_tw
+        # Enable users to set mstatus.mprv to enable privilege checks on memory accesses.
         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)
+        # Stack space allocated to each program, need to be enough to store necessary context
+        # Example: RA, SP, T0
+        self.min_stack_len_per_program = 10 * (rcs.XLEN // 8)
+        self.max_stack_len_per_program = 16 * (rcs.XLEN // 8)
+        # Maximum branch distance, avoid skipping large portion of the code
         self.max_branch_step = 20
+        # Reserved registers
         self.reserved_regs = vsc.list_t(vsc.enum_t(riscv_reg_t))
+        # Floating point support
+        self.enable_floating_point = vsc.bit_t(1)
         self.enable_floating_point = self.argv.enable_floating_point
+        # Vector extension support
         self.enable_vector_extension = self.argv.enable_vector_extension
+        # Only generate vector instructions
+        self. vector_instr_only = vsc.bit_t(1)
+        # Bit manipulation extension support
         self.enable_b_extension = self.argv.enable_b_extension
         self.enable_bitmanip_groups = self.argv.enable_bitmanip_groups
+
+        # -----------------------------------------------------------------------------
+        # Command line options for instruction distribution control
+        # -----------------------------------------------------------------------------
         self.dist_control_mode = 0
         self.category_dist = {}
         self.march_isa = self.argv.march_isa
@@ -198,35 +315,26 @@
 
     @vsc.constraint
     def default_c(self):
+        # TODO Add constraint related to sub_program
         self.main_program_instr_cnt in vsc.rangelist(vsc.rng(10, self.instr_cnt))
 
     @vsc.constraint
-    def sp_tp_c(self):
-        if self.fix_sp:
-            self.sp == riscv_reg_t.SP
-        self.sp != self.tp
-        self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP,
-                                         riscv_reg_t.RA, riscv_reg_t.ZERO))
-        self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
-                                         riscv_reg_t.RA, riscv_reg_t.ZERO))
+    def debug_mode_c(self):
+        # TODO
+        pass
 
+    # Keep the number of single step iterations relatively small
     @vsc.constraint
-    def gpr_c(self):
-        with vsc.foreach(self.gpr, idx = True) as i:
-            self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
-                                                 riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
-        vsc.unique(self.gpr)
+    def debug_single_step_c(self):
+        # TODO
+        pass
 
+    # Boot privileged mode distribution
     @vsc.constraint
-    def ra_c(self):
-        self.ra != riscv_reg_t.SP
-        self.ra != riscv_reg_t.TP
-        self.ra != riscv_reg_t.ZERO
-
-    @vsc.constraint
-    def reserve_scratch_reg_c(self):
-        self.scratch_reg.not_inside(vsc.rangelist(riscv_reg_t.ZERO, self.sp,
-                                                  self.tp, self.ra, riscv_reg_t.GP))
+    def boot_privileged_mode_dist_c(self):
+        # Boot to higher privileged mode more often
+        # TODO
+        pass
 
     @vsc.constraint
     def mtvec_c(self):
@@ -234,16 +342,11 @@
         with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT):
             vsc.soft(self.tvec_alignment == 2)
         with vsc.else_then():
+            # Setting MODE = Vectored may impose an additional alignmentconstraint on BASE,
+            # requiring up to 4×XLEN-byte alignment
             vsc.soft(self.tvec_alignment == self.tvec_ceil)
 
     @vsc.constraint
-    def floating_point_c(self):
-        with vsc.if_then(self.enable_floating_point):
-            self.mstatus_fs == 1
-        with vsc.else_then():
-            self.mstatus_fs == 0
-
-    @vsc.constraint
     def mstatus_c(self):
         with vsc.if_then(self.set_mstatus_mprv == 1):
             self.mstatus_mprv == 1
@@ -254,6 +357,124 @@
             self.mstatus_sum == 0
             self.mstatus_tvm == 0
 
+    # Exception delegation setting
+    @vsc.constraint
+    def exception_delegation_c(self):
+        # Do not delegate instruction page fault to supervisor/user mode because this may introduce
+        # dead loop. All the subsequent instruction fetches may fail and program cannot recover.
+        # TODO
+        pass
+
+    # Spike only supports a subset of exception and interrupt delegation
+    # You can modify this constraint if your ISS support different set of delegations
+    @vsc.constraint
+    def delegation_c(self):
+        # TODO
+        pass
+
+    @vsc.constraint
+    def ra_c(self):
+        self.ra != riscv_reg_t.SP
+        self.ra != riscv_reg_t.TP
+        self.ra != riscv_reg_t.ZERO
+
+    @vsc.constraint
+    def sp_tp_c(self):
+        with vsc.if_then(self.fix_sp == 1):
+            self.sp == riscv_reg_t.SP
+        self.sp != self.tp
+        self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP,
+                                         riscv_reg_t.RA, riscv_reg_t.ZERO))
+        self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
+                                         riscv_reg_t.RA, riscv_reg_t.ZERO))
+
+    # This reg is used in various places throughout the generator,
+    # so need more conservative constraints on it.
+    @vsc.constraint
+    def reserve_scratch_reg_c(self):
+        self.scratch_reg.not_inside(vsc.rangelist(riscv_reg_t.ZERO, self.sp,
+                                                  self.tp, self.ra, riscv_reg_t.GP))
+
+    # This reg is only used inside PMP exception routine,
+    # so we can be a bit looser with constraints.
+    @vsc.constraint
+    def reserved_pmp_reg_c(self):
+        # TODO
+        pass
+
+    @vsc.constraint
+    def gpr_c(self):
+        with vsc.foreach(self.gpr, idx = True) as i:
+            self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+                                                 riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+        vsc.unique(self.gpr)
+
+    @vsc.constraint
+    def addr_translation_rnd_order_c(self):
+        # TODO
+        pass
+
+    @vsc.constraint
+    def addr_translation_c(self):
+        with vsc.if_then((self.init_privil_mode != privileged_mode_t.MACHINE_MODE) &
+                         (self.SATP_MODE != satp_mode_t.BARE)):
+            self.virtual_addr_translation_on == 1
+        with vsc.else_then():
+            self.virtual_addr_translation_on == 0
+
+    @vsc.constraint
+    def floating_point_c(self):
+        with vsc.if_then(self.enable_floating_point == 1):
+            self.mstatus_fs == 1
+        with vsc.else_then():
+            self.mstatus_fs == 0
+
+    @vsc.constraint
+    def mstatus_vs_c(self):
+        # TODO
+        pass
+
+    def setup_instr_distribution(self):
+        if self.dist_control_mode:
+            category_iter = iter([x for x in riscv_instr_category_t.__members__])
+            category = riscv_instr_category_t(0)
+            while True:
+                opts = "dist_{}".format(category.name)
+                opts = opts.lower()
+                if self.args_dict[opts]:
+                    self.category_dist[category] = self.args_dict[opts]
+                else:
+                    self.category_dist[category] = 10  # Default ratio
+                logging.info("Set dist[{}] = {}".format(category, self.category_dist[category]))
+                category = next(category_iter)
+                if category != riscv_instr_category_t(0):
+                    break
+
+    # Initialize the exception/interrupt delegation associate array, set all delegation default to 0
+    def init_delegation(self):
+        # TODO
+        pass
+
+    def pre_randomize(self):
+        for mode in rcs.supported_privileged_mode:
+            if mode == privileged_mode_t.SUPERVISOR_MODE:
+                self.support_supervisor_mode = 1
+
+    def get_non_reserved_gpr(self):
+        pass
+
+    def post_randomize(self):
+        # Setup the list all reserved registers
+        self.reserved_regs.extend((self.tp, self.sp, self.scratch_reg))
+        # Need to save all loop registers, and RA/T0
+        self.min_stack_len_per_program = 2 * (rcs.XLEN // 8)
+        logging.info("min_stack_len_per_program value = {}"
+                     .format(self.min_stack_len_per_program))
+        self.check_setting()  # check if the setting is legal
+        # WFI is not supported in umode
+        if self.init_privileged_mode == privileged_mode_t.USER_MODE:
+            self.no_wfi = 1
+
     def check_setting(self):
         support_64b = 0
         support_128b = 0
@@ -296,47 +517,8 @@
                              .format(rcs.SATP_MODE.name))
             sys.exit("Supported SATP mode is not provided")
 
-    def setup_instr_distribution(self):
-        if self.dist_control_mode:
-            category_iter = iter([x for x in riscv_instr_category_t.__members__])
-            category = riscv_instr_category_t(0)
-            while True:
-                opts = "dist_{}".format(category.name)
-                opts = opts.lower()
-                if self.args_dict[opts]:
-                    self.category_dist[category] = self.args_dict[opts]
-                else:
-                    self.category_dist[category] = 10
-                logging.info("Set dist[{}] = {}".format(category, self.category_dist[category]))
-                category = next(category_iter)
-                if category != riscv_instr_category_t(0):
-                    break
-
-    # TODO
-    def init_delegation(self):
-        pass
-
-    def pre_randomize(self):
-        for mode in rcs.supported_privileged_mode:
-            if mode == privileged_mode_t.SUPERVISOR_MODE:
-                self.support_supervisor_mode = 1
-
-    def get_non_reserved_gpr(self):
-        pass
-
-    def post_randomize(self):
-        self.reserved_regs.append(self.tp)
-        self.reserved_regs.append(self.sp)
-        self.reserved_regs.append(self.scratch_reg)
-        self.min_stack_len_per_program = 2 * (rcs.XLEN / 8)
-        logging.info("min_stack_len_per_program value = {}"
-                     .format(self.min_stack_len_per_program))
-        self.check_setting()  # check if the setting is legal
-
-        if self.init_privileged_mode == privileged_mode_t.USER_MODE:
-            logging.info("mode = USER_MODE")
-            self.no_wfi = 1
-
+    # Populate invalid_priv_mode_csrs with the main implemented CSRs for each supported privilege
+    # mode
     def get_invalid_priv_lvl_csr(self):
         invalid_lvl = []
         # Debug CSRs are inaccessible from all but Debug Mode
@@ -416,7 +598,7 @@
                            help = 'illegal_instr_ratio', type = int, default = 0)
         parse.add_argument('--hint_instr_ratio', help = 'hint_instr_ratio', type = int, default = 0)
         parse.add_argument('--num_of_harts', help = 'num_of_harts',
-                           type = int, default = 1)
+                           type = int)
         parse.add_argument('--enable_unaligned_load_store',
                            help = 'enable_unaligned_load_store', choices = [0, 1],
                            type = int, default = 0)
@@ -486,7 +668,6 @@
         if ($value$plusargs("tvec_alignment=%0d", tvec_alignment)) begin
             tvec_alignment.rand_mode(0);
         end
-
         vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg");
         pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg");
         pmp_cfg.rand_mode(pmp_cfg.pmp_randomize);
@@ -495,7 +676,6 @@
         get_invalid_priv_lvl_csr();
         '''
         args = parse.parse_args()
-
         return args
 
 
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 41f4ba3..5808a4f 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
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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 logging
@@ -26,6 +24,14 @@
         self.size_in_bytes = vsc.uint32_t(i=size_in_bytes)
         self.xwr = vsc.uint8_t(i=xwr)
 
+# Initialization of the vregs
+
+
+class vreg_init_method_t(IntEnum):
+    SAME_VALUES_ALL_ELEMS = 0
+    RANDOM_VALUES_VMV = auto()
+    RANDOM_VALUES_LOAD = auto()
+
 
 class satp_mode_t(IntEnum):
     BARE = 0b0000
@@ -50,12 +56,13 @@
 
 
 class imm_t(IntEnum):
-    IMM = 0
-    UIMM = auto()
-    NZUIMM = auto()
-    NZIMM = auto()
+    IMM = 0  # Signed immediate
+    UIMM = auto()  # Unsigned immediate
+    NZUIMM = auto()  # Non-zero unsigned immediate
+    NZIMM = auto()  # Non-zero signed immediate
 
 
+# Privileged mode
 class privileged_mode_t(IntEnum):
     USER_MODE = 0b00
     SUPERVISOR_MODE = 0b01
@@ -90,6 +97,7 @@
 
 
 class riscv_instr_name_t(IntEnum):
+    # RV32I instructions
     LUI = 0
     AUIPC = auto()
     JAL = auto()
@@ -138,6 +146,7 @@
     CSRRWI = auto()
     CSRRSI = auto()
     CSRRCI = auto()
+    # RV32B instructions
     ANDN = auto()
     ORN = auto()
     XNOR = auto()
@@ -195,6 +204,7 @@
     BFP = auto()
     SHFLI = auto()
     UNSHFLI = auto()
+    # RV64B instructions
     ADDIWU = auto()
     SLLIU_W = auto()
     ADDWU = auto()
@@ -238,6 +248,7 @@
     PACKW = auto()
     PACKUW = auto()
     BFPW = auto()
+    # RV32M instructions
     MUL = auto()
     MULH = auto()
     MULHSU = auto()
@@ -246,11 +257,13 @@
     DIVU = auto()
     REM = auto()
     REMU = auto()
+    # RV64M instructions
     MULW = auto()
     DIVW = auto()
     DIVUW = auto()
     REMW = auto()
     REMUW = auto()
+    # RV32F instructions
     FLW = auto()
     FSW = auto()
     FMADD_S = auto()
@@ -277,10 +290,12 @@
     FCVT_S_W = auto()
     FCVT_S_WU = auto()
     FMV_W_X = auto()
+    # RV64F instructions
     FCVT_L_S = auto()
     FCVT_LU_S = auto()
     FCVT_S_L = auto()
     FCVT_S_LU = auto()
+    # RV32D instructions
     FLD = auto()
     FSD = auto()
     FMADD_D = auto()
@@ -307,12 +322,14 @@
     FCVT_WU_D = auto()
     FCVT_D_W = auto()
     FCVT_D_WU = auto()
+    # RV64D instructions
     FCVT_L_D = auto()
     FCVT_LU_D = auto()
     FMV_X_D = auto()
     FCVT_D_L = auto()
     FCVT_D_LU = auto()
     FMV_D_X = auto()
+    # RV64I instructions
     LWU = auto()
     LD = auto()
     SD = auto()
@@ -325,6 +342,7 @@
     SLLW = auto()
     SRLW = auto()
     SRAW = auto()
+    # RV32C instructions
     C_LW = auto()
     C_SW = auto()
     C_LWSP = auto()
@@ -352,6 +370,7 @@
     C_JAL = auto()
     C_JR = auto()
     C_JALR = auto()
+    # RV64C instructions
     C_ADDIW = auto()
     C_SUBW = auto()
     C_ADDW = auto()
@@ -359,6 +378,7 @@
     C_SD = auto()
     C_LDSP = auto()
     C_SDSP = auto()
+    # RV128C instructions
     C_SRLI64 = auto()
     C_SRAI64 = auto()
     C_SLLI64 = auto()
@@ -366,14 +386,17 @@
     C_SQ = auto()
     C_LQSP = auto()
     C_SQSP = auto()
+    # RV32FC instructions
     C_FLW = auto()
     C_FSW = auto()
     C_FLWSP = auto()
     C_FSWSP = auto()
+    # RV32DC instructions
     C_FLD = auto()
     C_FSD = auto()
     C_FLDSP = auto()
     C_FSDSP = auto()
+    # RV32A instructions
     LR_W = auto()
     SC_W = auto()
     AMOSWAP_W = auto()
@@ -385,6 +408,7 @@
     AMOMAX_W = auto()
     AMOMINU_W = auto()
     AMOMAXU_W = auto()
+    # RV64A instructions
     LR_D = auto()
     SC_D = auto()
     AMOSWAP_D = auto()
@@ -396,6 +420,7 @@
     AMOMAX_D = auto()
     AMOMINU_D = auto()
     AMOMAXU_D = auto()
+    # Vector instructions
     VSETVL = auto()
     VSETVLI = auto()
     VADD = auto()
@@ -448,6 +473,10 @@
     VWMACC = auto()
     VWMACCSU = auto()
     VWMACCUS = auto()
+    # VQMACCU = auto()
+    # VQMACC = auto()
+    # VQMACCSU = auto()
+    # VQMACCUS = auto()
     VMERGE = auto()
     VMV = auto()
     VSADDU = auto()
@@ -462,6 +491,7 @@
     VSSRA = auto()
     VNCLIPU = auto()
     VNCLIP = auto()
+    # 14. Vector Floating-Point instructions
     VFADD = auto()
     VFSUB = auto()
     VFRSUB = auto()
@@ -511,6 +541,7 @@
     VFNCVT_F_X_W = auto()
     VFNCVT_F_F_W = auto()
     VFNCVT_ROD_F_F_W = auto()
+    # 15. Vector reduction instructions
     VREDSUM_VS = auto()
     VREDMAXU_VS = auto()
     VREDMAX_VS = auto()
@@ -526,6 +557,7 @@
     VFREDMAX_VS = auto()
     VFWREDOSUM_VS = auto()
     VFWREDSUM_VS = auto()
+    # Vector mask instructions
     VMAND_MM = auto()
     VMNAND_MM = auto()
     VMANDNOT_MM = auto()
@@ -541,6 +573,7 @@
     VMSOF_M = auto()
     VIOTA_M = auto()
     VID_V = auto()
+    # Vector permutation instructions
     VMV_X_S = auto()
     VMV_S_X = auto()
     VFMV_F_S = auto()
@@ -555,12 +588,45 @@
     VMV2R_V = auto()
     VMV4R_V = auto()
     VMV8R_V = auto()
+    # Vector load/store instructions
+    VLE_V = auto()
+    VSE_V = auto()
+    VLSE_V = auto()
+    VSSE_V = auto()
+    VLXEI_V = auto()
+    VSXEI_V = auto()
+    VSUXEI_V = auto()
+    VLEFF_V = auto()
+    # Segmented load/store instruction
+    VLSEGE_V = auto()
+    VSSEGE_V = auto()
+    VLSEGEFF_V = auto()
+    VLSSEGE_V = auto()
+    VSSSEGE_V = auto()
+    VLXSEGEI_V = auto()
+    VSXSEGEI_V = auto()
+    VSUXSEGEI_V = auto()
+    # Vector AMO instruction
+    # EEW vector AMOs
+    VAMOSWAPE_V = auto()
+    VAMOADDE_V = auto()
+    VAMOXORE_V = auto()
+    VAMOANDE_V = auto()
+    VAMOORE_V = auto()
+    VAMOMINE_V = auto()
+    VAMOMAXE_V = auto()
+    VAMOMINUE_V = auto()
+    VAMOMAXUE_V = auto()
+    # Supervisor instruction
     DRET = auto()
     MRET = auto()
     URET = auto()
     SRET = auto()
     WFI = auto()
     SFENCE_VMA = auto()
+    # Custom instructions
+    # TODO add a way to import custom instructions here from isa/custom/riscv_custom_instr_enum.py
+    # You can add other instructions here
     INVALID_INSTR = auto()
 
 
@@ -677,6 +743,7 @@
     R_FORMAT = auto()
     S_FORMAT = auto()
     R4_FORMAT = auto()
+    # Compressed instruction format
     CI_FORMAT = auto()
     CB_FORMAT = auto()
     CJ_FORMAT = auto()
@@ -686,13 +753,15 @@
     CS_FORMAT = auto()
     CSS_FORMAT = auto()
     CIW_FORMAT = auto()
+    # Vector instruction format
     VSET_FORMAT = auto()
     VA_FORMAT = auto()
-    VS2_FORMAT = auto()
+    VS2_FORMAT = auto()  # op vd,vs2
     VL_FORMAT = auto()
     VS_FORMAT = auto()
 
 
+# Vector arithmetic instruction variant
 class va_variant_t(IntEnum):
     VV = 0
     VI = auto()
@@ -725,269 +794,277 @@
     CHANGELEVEL = auto()
     TRAP = auto()
     INTERRUPT = auto()
-    AMO = auto()
-
-
-# typedef bit[11:0] riscv_csr_t;
+    # TODO import vector_category
+    AMO = auto()  # (last one)
 
 
 class privileged_reg_t(IntEnum):
-    USTATUS = 0x000
-    UIE = 0x004
-    UTVEC = 0x005
-    USCRATCH = 0x040
-    UEPC = 0x041
-    UCAUSE = 0x042
-    UTVAL = 0x043
-    UIP = 0x044
-    FFLAGS = 0x001
-    FRM = 0x002
-    FCSR = 0x003
-    CYCLE = 0xC00
-    TIME = 0xC01
-    INSTRET = 0xC02
-    HPMCOUNTER3 = 0xC03
-    HPMCOUNTER4 = 0xC04
-    HPMCOUNTER5 = 0xC05
-    HPMCOUNTER6 = 0xC06
-    HPMCOUNTER7 = 0xC07
-    HPMCOUNTER8 = 0xC08
-    HPMCOUNTER9 = 0xC09
-    HPMCOUNTER10 = 0xC0A
-    HPMCOUNTER11 = 0xC0B
-    HPMCOUNTER12 = 0xC0C
-    HPMCOUNTER13 = 0xC0D
-    HPMCOUNTER14 = 0xC0E
-    HPMCOUNTER15 = 0xC0F
-    HPMCOUNTER16 = 0xC10
-    HPMCOUNTER17 = 0xC11
-    HPMCOUNTER18 = 0xC12
-    HPMCOUNTER19 = 0xC13
-    HPMCOUNTER20 = 0xC14
-    HPMCOUNTER21 = 0xC15
-    HPMCOUNTER22 = 0xC16
-    HPMCOUNTER23 = 0xC17
-    HPMCOUNTER24 = 0xC18
-    HPMCOUNTER25 = 0xC19
-    HPMCOUNTER26 = 0xC1A
-    HPMCOUNTER27 = 0xC1B
-    HPMCOUNTER28 = 0xC1C
-    HPMCOUNTER29 = 0xC1D
-    HPMCOUNTER30 = 0xC1E
-    HPMCOUNTER31 = 0xC1F
-    CYCLEH = 0xC80
-    TIMEH = 0xC81
-    INSTRETH = 0xC82
-    HPMCOUNTER3H = 0xC83
-    HPMCOUNTER4H = 0xC84
-    HPMCOUNTER5H = 0xC85
-    HPMCOUNTER6H = 0xC86
-    HPMCOUNTER7H = 0xC87
-    HPMCOUNTER8H = 0xC88
-    HPMCOUNTER9H = 0xC89
-    HPMCOUNTER10H = 0xC8A
-    HPMCOUNTER11H = 0xC8B
-    HPMCOUNTER12H = 0xC8C
-    HPMCOUNTER13H = 0xC8D
-    HPMCOUNTER14H = 0xC8E
-    HPMCOUNTER15H = 0xC8F
-    HPMCOUNTER16H = 0xC90
-    HPMCOUNTER17H = 0xC91
-    HPMCOUNTER18H = 0xC92
-    HPMCOUNTER19H = 0xC93
-    HPMCOUNTER20H = 0xC94
-    HPMCOUNTER21H = 0xC95
-    HPMCOUNTER22H = 0xC96
-    HPMCOUNTER23H = 0xC97
-    HPMCOUNTER24H = 0xC98
-    HPMCOUNTER25H = 0xC99
-    HPMCOUNTER26H = 0xC9A
-    HPMCOUNTER27H = 0xC9B
-    HPMCOUNTER28H = 0xC9C
-    HPMCOUNTER29H = 0xC9D
-    HPMCOUNTER30H = 0xC9E
-    HPMCOUNTER31H = 0xC9F
-    SSTATUS = 0x100
-    SEDELEG = 0x102
-    SIDELEG = 0x103
-    SIE = 0x104
-    STVEC = 0x105
-    SCOUNTEREN = 0x106
-    SSCRATCH = 0x140
-    SEPC = 0x141
-    SCAUSE = 0x142
-    STVAL = 0x143
-    SIP = 0x144
-    SATP = 0x180
-    MVENDORID = 0xF11
-    MARCHID = 0xF12
-    MIMPID = 0xF13
-    MHARTID = 0xF14
-    MSTATUS = 0x300
-    MISA = 0x301
-    MEDELEG = 0x302
-    MIDELEG = 0x303
-    MIE = 0x304
-    MTVEC = 0x305
-    MCOUNTEREN = 0x306
-    MSCRATCH = 0x340
-    MEPC = 0x341
-    MCAUSE = 0x342
-    MTVAL = 0x343
-    MIP = 0x344
-    PMPCFG0 = 0x3A0
-    PMPCFG1 = 0x3A1
-    PMPCFG2 = 0x3A2
-    PMPCFG3 = 0x3A3
-    PMPADDR0 = 0x3B0
-    PMPADDR1 = 0x3B1
-    PMPADDR2 = 0x3B2
-    PMPADDR3 = 0x3B3
-    PMPADDR4 = 0x3B4
-    PMPADDR5 = 0x3B5
-    PMPADDR6 = 0x3B6
-    PMPADDR7 = 0x3B7
-    PMPADDR8 = 0x3B8
-    PMPADDR9 = 0x3B9
-    PMPADDR10 = 0x3BA
-    PMPADDR11 = 0x3BB
-    PMPADDR12 = 0x3BC
-    PMPADDR13 = 0x3BD
-    PMPADDR14 = 0x3BE
-    PMPADDR15 = 0x3BF
-    MCYCLE = 0xB00
-    MINSTRET = 0xB02
-    MHPMCOUNTER3 = 0xB03
-    MHPMCOUNTER4 = 0xB04
-    MHPMCOUNTER5 = 0xB05
-    MHPMCOUNTER6 = 0xB06
-    MHPMCOUNTER7 = 0xB07
-    MHPMCOUNTER8 = 0xB08
-    MHPMCOUNTER9 = 0xB09
-    MHPMCOUNTER10 = 0xB0A
-    MHPMCOUNTER11 = 0xB0B
-    MHPMCOUNTER12 = 0xB0C
-    MHPMCOUNTER13 = 0xB0D
-    MHPMCOUNTER14 = 0xB0E
-    MHPMCOUNTER15 = 0xB0F
-    MHPMCOUNTER16 = 0xB10
-    MHPMCOUNTER17 = 0xB11
-    MHPMCOUNTER18 = 0xB12
-    MHPMCOUNTER19 = 0xB13
-    MHPMCOUNTER20 = 0xB14
-    MHPMCOUNTER21 = 0xB15
-    MHPMCOUNTER22 = 0xB16
-    MHPMCOUNTER23 = 0xB17
-    MHPMCOUNTER24 = 0xB18
-    MHPMCOUNTER25 = 0xB19
-    MHPMCOUNTER26 = 0xB1A
-    MHPMCOUNTER27 = 0xB1B
-    MHPMCOUNTER28 = 0xB1C
-    MHPMCOUNTER29 = 0xB1D
-    MHPMCOUNTER30 = 0xB1E
-    MHPMCOUNTER31 = 0xB1F
-    MCYCLEH = 0xB80
-    MINSTRETH = 0xB82
-    MHPMCOUNTER3H = 0xB83
-    MHPMCOUNTER4H = 0xB84
-    MHPMCOUNTER5H = 0xB85
-    MHPMCOUNTER6H = 0xB86
-    MHPMCOUNTER7H = 0xB87
-    MHPMCOUNTER8H = 0xB88
-    MHPMCOUNTER9H = 0xB89
-    MHPMCOUNTER10H = 0xB8A
-    MHPMCOUNTER11H = 0xB8B
-    MHPMCOUNTER12H = 0xB8C
-    MHPMCOUNTER13H = 0xB8D
-    MHPMCOUNTER14H = 0xB8E
-    MHPMCOUNTER15H = 0xB8F
-    MHPMCOUNTER17H = 0xB90
-    MHPMCOUNTER18H = 0xB91
-    MHPMCOUNTER19H = 0xB92
-    MHPMCOUNTER20H = 0xB93
-    MHPMCOUNTER21H = 0xB94
-    MHPMCOUNTER22H = 0xB95
-    MHPMCOUNTER23H = 0xB96
-    MHPMCOUNTER24H = 0xB97
-    MHPMCOUNTER25H = 0xB98
-    MHPMCOUNTER26H = 0xB99
-    MHPMCOUNTER27H = 0xB9A
-    MHPMCOUNTER28H = 0xB9B
-    MHPMCOUNTER29H = 0xB9C
-    MHPMCOUNTER30H = 0xB9D
-    MHPMCOUNTER31H = 0xB9E
-    MCOUNTINHIBIT = 0x320F
-    MHPMEVENT3 = 0x323
-    MHPMEVENT4 = 0x324
-    MHPMEVENT5 = 0x325
-    MHPMEVENT6 = 0x326
-    MHPMEVENT7 = 0x327
-    MHPMEVENT8 = 0x328
-    MHPMEVENT9 = 0x329
-    MHPMEVENT10 = 0x32A
-    MHPMEVENT11 = 0x32B
-    MHPMEVENT12 = 0x32C
-    MHPMEVENT13 = 0x32D
-    MHPMEVENT14 = 0x32E
-    MHPMEVENT15 = 0x32F
-    MHPMEVENT16 = 0x330
-    MHPMEVENT17 = 0x331
-    MHPMEVENT18 = 0x332
-    MHPMEVENT19 = 0x333
-    MHPMEVENT20 = 0x334
-    MHPMEVENT21 = 0x335
-    MHPMEVENT22 = 0x336
-    MHPMEVENT23 = 0x337
-    MHPMEVENT24 = 0x338
-    MHPMEVENT25 = 0x339
-    MHPMEVENT26 = 0x33A
-    MHPMEVENT27 = 0x33B
-    MHPMEVENT28 = 0x33C
-    MHPMEVENT29 = 0x33D
-    MHPMEVENT30 = 0x33E
-    MHPMEVENT31 = 0x33F
-    TSELECT = 0x7A0
-    TDATA1 = 0x7A1
-    TDATA2 = 0x7A2
-    TDATA3 = 0x7A3
-    DCSR = 0x7B0
-    DPC = 0x7B1
-    DSCRATCH0 = 0x7B2
-    DSCRATCH1 = 0x7B3
-    VSTART = 0x008
-    VXSTAT = 0x009
-    VXRM = 0x00A
-    VL = 0xC20
-    VTYPE = 0xC21
-    VLENB = 0xC22
+    # User mode register
+    USTATUS = 0x000  # User status
+    UIE = 0x004  # User interrupt-enable register
+    UTVEC = 0x005  # User trap-handler base address
+    USCRATCH = 0x040  # Scratch register for user trap handlers
+    UEPC = 0x041  # User exception program counter
+    UCAUSE = 0x042  # User trap cause
+    UTVAL = 0x043  # User bad address or instruction
+    UIP = 0x044  # User interrupt pending
+    FFLAGS = 0x001  # Floating-Point Accrued Exceptions
+    FRM = 0x002  # Floating-Point Dynamic Rounding Mode
+    FCSR = 0x003  # Floating-Point Control/Status Register (FRM + FFLAGS)
+    CYCLE = 0xC00  # Cycle counter for RDCYCLE instruction
+    TIME = 0xC01  # Timer for RDTIME instruction
+    INSTRET = 0xC02  # Instructions-retired counter for RDINSTRET instruction
+    HPMCOUNTER3 = 0xC03  # Performance-monitoring counter
+    HPMCOUNTER4 = 0xC04  # Performance-monitoring counter
+    HPMCOUNTER5 = 0xC05  # Performance-monitoring counter
+    HPMCOUNTER6 = 0xC06  # Performance-monitoring counter
+    HPMCOUNTER7 = 0xC07  # Performance-monitoring counter
+    HPMCOUNTER8 = 0xC08  # Performance-monitoring counter
+    HPMCOUNTER9 = 0xC09  # Performance-monitoring counter
+    HPMCOUNTER10 = 0xC0A  # Performance-monitoring counter
+    HPMCOUNTER11 = 0xC0B  # Performance-monitoring counter
+    HPMCOUNTER12 = 0xC0C  # Performance-monitoring counter
+    HPMCOUNTER13 = 0xC0D  # Performance-monitoring counter
+    HPMCOUNTER14 = 0xC0E  # Performance-monitoring counter
+    HPMCOUNTER15 = 0xC0F  # Performance-monitoring counter
+    HPMCOUNTER16 = 0xC10  # Performance-monitoring counter
+    HPMCOUNTER17 = 0xC11  # Performance-monitoring counter
+    HPMCOUNTER18 = 0xC12  # Performance-monitoring counter
+    HPMCOUNTER19 = 0xC13  # Performance-monitoring counter
+    HPMCOUNTER20 = 0xC14  # Performance-monitoring counter
+    HPMCOUNTER21 = 0xC15  # Performance-monitoring counter
+    HPMCOUNTER22 = 0xC16  # Performance-monitoring counter
+    HPMCOUNTER23 = 0xC17  # Performance-monitoring counter
+    HPMCOUNTER24 = 0xC18  # Performance-monitoring counter
+    HPMCOUNTER25 = 0xC19  # Performance-monitoring counter
+    HPMCOUNTER26 = 0xC1A  # Performance-monitoring counter
+    HPMCOUNTER27 = 0xC1B  # Performance-monitoring counter
+    HPMCOUNTER28 = 0xC1C  # Performance-monitoring counter
+    HPMCOUNTER29 = 0xC1D  # Performance-monitoring counter
+    HPMCOUNTER30 = 0xC1E  # Performance-monitoring counter
+    HPMCOUNTER31 = 0xC1F  # Performance-monitoring counter
+    CYCLEH = 0xC80  # Upper 32 bits of CYCLE, RV32I only
+    TIMEH = 0xC81  # Upper 32 bits of TIME, RV32I only
+    INSTRETH = 0xC82  # Upper 32 bits of INSTRET, RV32I only
+    HPMCOUNTER3H = 0xC83  # Upper 32 bits of HPMCOUNTER3, RV32I only
+    HPMCOUNTER4H = 0xC84  # Upper 32 bits of HPMCOUNTER4, RV32I only
+    HPMCOUNTER5H = 0xC85  # Upper 32 bits of HPMCOUNTER5, RV32I only
+    HPMCOUNTER6H = 0xC86  # Upper 32 bits of HPMCOUNTER6, RV32I only
+    HPMCOUNTER7H = 0xC87  # Upper 32 bits of HPMCOUNTER7, RV32I only
+    HPMCOUNTER8H = 0xC88  # Upper 32 bits of HPMCOUNTER8, RV32I only
+    HPMCOUNTER9H = 0xC89  # Upper 32 bits of HPMCOUNTER9, RV32I only
+    HPMCOUNTER10H = 0xC8A  # Upper 32 bits of HPMCOUNTER10, RV32I only
+    HPMCOUNTER11H = 0xC8B  # Upper 32 bits of HPMCOUNTER11, RV32I only
+    HPMCOUNTER12H = 0xC8C  # Upper 32 bits of HPMCOUNTER12, RV32I only
+    HPMCOUNTER13H = 0xC8D  # Upper 32 bits of HPMCOUNTER13, RV32I only
+    HPMCOUNTER14H = 0xC8E  # Upper 32 bits of HPMCOUNTER14, RV32I only
+    HPMCOUNTER15H = 0xC8F  # Upper 32 bits of HPMCOUNTER15, RV32I only
+    HPMCOUNTER16H = 0xC90  # Upper 32 bits of HPMCOUNTER16, RV32I only
+    HPMCOUNTER17H = 0xC91  # Upper 32 bits of HPMCOUNTER17, RV32I only
+    HPMCOUNTER18H = 0xC92  # Upper 32 bits of HPMCOUNTER18, RV32I only
+    HPMCOUNTER19H = 0xC93  # Upper 32 bits of HPMCOUNTER19, RV32I only
+    HPMCOUNTER20H = 0xC94  # Upper 32 bits of HPMCOUNTER20, RV32I only
+    HPMCOUNTER21H = 0xC95  # Upper 32 bits of HPMCOUNTER21, RV32I only
+    HPMCOUNTER22H = 0xC96  # Upper 32 bits of HPMCOUNTER22, RV32I only
+    HPMCOUNTER23H = 0xC97  # Upper 32 bits of HPMCOUNTER23, RV32I only
+    HPMCOUNTER24H = 0xC98  # Upper 32 bits of HPMCOUNTER24, RV32I only
+    HPMCOUNTER25H = 0xC99  # Upper 32 bits of HPMCOUNTER25, RV32I only
+    HPMCOUNTER26H = 0xC9A  # Upper 32 bits of HPMCOUNTER26, RV32I only
+    HPMCOUNTER27H = 0xC9B  # Upper 32 bits of HPMCOUNTER27, RV32I only
+    HPMCOUNTER28H = 0xC9C  # Upper 32 bits of HPMCOUNTER28, RV32I only
+    HPMCOUNTER29H = 0xC9D  # Upper 32 bits of HPMCOUNTER29, RV32I only
+    HPMCOUNTER30H = 0xC9E  # Upper 32 bits of HPMCOUNTER30, RV32I only
+    HPMCOUNTER31H = 0xC9F  # Upper 32 bits of HPMCOUNTER31, RV32I only
+    # Supervisor mode register
+    SSTATUS = 0x100  # Supervisor status
+    SEDELEG = 0x102  # Supervisor exception delegation register
+    SIDELEG = 0x103  # Supervisor interrupt delegation register
+    SIE = 0x104  # Supervisor interrupt-enable register
+    STVEC = 0x105  # Supervisor trap-handler base address
+    SCOUNTEREN = 0x106  # Supervisor counter enable
+    SSCRATCH = 0x140  # Scratch register for supervisor trap handlers
+    SEPC = 0x141  # Supervisor exception program counter
+    SCAUSE = 0x142  # Supervisor trap cause
+    STVAL = 0x143  # Supervisor bad address or instruction
+    SIP = 0x144  # Supervisor interrupt pending
+    SATP = 0x180  # Supervisor address translation and protection
+    # Machine mode register
+    MVENDORID = 0xF11  # Vendor ID
+    MARCHID = 0xF12  # Architecture ID
+    MIMPID = 0xF13  # Implementation ID
+    MHARTID = 0xF14  # Hardware thread ID
+    MSTATUS = 0x300  # Machine status
+    MISA = 0x301  # ISA and extensions
+    MEDELEG = 0x302  # Machine exception delegation register
+    MIDELEG = 0x303  # Machine interrupt delegation register
+    MIE = 0x304  # Machine interrupt-enable register
+    MTVEC = 0x305  # Machine trap-handler base address
+    MCOUNTEREN = 0x306  # Machine counter enable
+    MSCRATCH = 0x340  # Scratch register for machine trap handlers
+    MEPC = 0x341  # Machine exception program counter
+    MCAUSE = 0x342  # Machine trap cause
+    MTVAL = 0x343  # Machine bad address or instruction
+    MIP = 0x344  # Machine interrupt pending
+    PMPCFG0 = 0x3A0  # Physical memory protection configuration
+    PMPCFG1 = 0x3A1  # Physical memory protection configuration, RV32 only
+    PMPCFG2 = 0x3A2  # Physical memory protection configuration
+    PMPCFG3 = 0x3A3  # Physical memory protection configuration, RV32 only
+    PMPADDR0 = 0x3B0  # Physical memory protection address register
+    PMPADDR1 = 0x3B1  # Physical memory protection address register
+    PMPADDR2 = 0x3B2  # Physical memory protection address register
+    PMPADDR3 = 0x3B3  # Physical memory protection address register
+    PMPADDR4 = 0x3B4  # Physical memory protection address register
+    PMPADDR5 = 0x3B5  # Physical memory protection address register
+    PMPADDR6 = 0x3B6  # Physical memory protection address register
+    PMPADDR7 = 0x3B7  # Physical memory protection address register
+    PMPADDR8 = 0x3B8  # Physical memory protection address register
+    PMPADDR9 = 0x3B9  # Physical memory protection address register
+    PMPADDR10 = 0x3BA  # Physical memory protection address register
+    PMPADDR11 = 0x3BB  # Physical memory protection address register
+    PMPADDR12 = 0x3BC  # Physical memory protection address register
+    PMPADDR13 = 0x3BD  # Physical memory protection address register
+    PMPADDR14 = 0x3BE  # Physical memory protection address register
+    PMPADDR15 = 0x3BF  # Physical memory protection address register
+    MCYCLE = 0xB00  # Machine cycle counter
+    MINSTRET = 0xB02  # Machine instructions-retired counter
+    MHPMCOUNTER3 = 0xB03  # Machine performance-monitoring counter
+    MHPMCOUNTER4 = 0xB04  # Machine performance-monitoring counter
+    MHPMCOUNTER5 = 0xB05  # Machine performance-monitoring counter
+    MHPMCOUNTER6 = 0xB06  # Machine performance-monitoring counter
+    MHPMCOUNTER7 = 0xB07  # Machine performance-monitoring counter
+    MHPMCOUNTER8 = 0xB08  # Machine performance-monitoring counter
+    MHPMCOUNTER9 = 0xB09  # Machine performance-monitoring counter
+    MHPMCOUNTER10 = 0xB0A  # Machine performance-monitoring counter
+    MHPMCOUNTER11 = 0xB0B  # Machine performance-monitoring counter
+    MHPMCOUNTER12 = 0xB0C  # Machine performance-monitoring counter
+    MHPMCOUNTER13 = 0xB0D  # Machine performance-monitoring counter
+    MHPMCOUNTER14 = 0xB0E  # Machine performance-monitoring counter
+    MHPMCOUNTER15 = 0xB0F  # Machine performance-monitoring counter
+    MHPMCOUNTER16 = 0xB10  # Machine performance-monitoring counter
+    MHPMCOUNTER17 = 0xB11  # Machine performance-monitoring counter
+    MHPMCOUNTER18 = 0xB12  # Machine performance-monitoring counter
+    MHPMCOUNTER19 = 0xB13  # Machine performance-monitoring counter
+    MHPMCOUNTER20 = 0xB14  # Machine performance-monitoring counter
+    MHPMCOUNTER21 = 0xB15  # Machine performance-monitoring counter
+    MHPMCOUNTER22 = 0xB16  # Machine performance-monitoring counter
+    MHPMCOUNTER23 = 0xB17  # Machine performance-monitoring counter
+    MHPMCOUNTER24 = 0xB18  # Machine performance-monitoring counter
+    MHPMCOUNTER25 = 0xB19  # Machine performance-monitoring counter
+    MHPMCOUNTER26 = 0xB1A  # Machine performance-monitoring counter
+    MHPMCOUNTER27 = 0xB1B  # Machine performance-monitoring counter
+    MHPMCOUNTER28 = 0xB1C  # Machine performance-monitoring counter
+    MHPMCOUNTER29 = 0xB1D  # Machine performance-monitoring counter
+    MHPMCOUNTER30 = 0xB1E  # Machine performance-monitoring counter
+    MHPMCOUNTER31 = 0xB1F  # Machine performance-monitoring counter
+    MCYCLEH = 0xB80  # Upper 32 bits of MCYCLE, RV32I only
+    MINSTRETH = 0xB82  # Upper 32 bits of MINSTRET, RV32I only
+    MHPMCOUNTER3H = 0xB83  # Upper 32 bits of HPMCOUNTER3, RV32I only
+    MHPMCOUNTER4H = 0xB84  # Upper 32 bits of HPMCOUNTER4, RV32I only
+    MHPMCOUNTER5H = 0xB85  # Upper 32 bits of HPMCOUNTER5, RV32I only
+    MHPMCOUNTER6H = 0xB86  # Upper 32 bits of HPMCOUNTER6, RV32I only
+    MHPMCOUNTER7H = 0xB87  # Upper 32 bits of HPMCOUNTER7, RV32I only
+    MHPMCOUNTER8H = 0xB88  # Upper 32 bits of HPMCOUNTER8, RV32I only
+    MHPMCOUNTER9H = 0xB89  # Upper 32 bits of HPMCOUNTER9, RV32I only
+    MHPMCOUNTER10H = 0xB8A  # Upper 32 bits of HPMCOUNTER10, RV32I only
+    MHPMCOUNTER11H = 0xB8B  # Upper 32 bits of HPMCOUNTER11, RV32I only
+    MHPMCOUNTER12H = 0xB8C  # Upper 32 bits of HPMCOUNTER12, RV32I only
+    MHPMCOUNTER13H = 0xB8D  # Upper 32 bits of HPMCOUNTER13, RV32I only
+    MHPMCOUNTER14H = 0xB8E  # Upper 32 bits of HPMCOUNTER14, RV32I only
+    MHPMCOUNTER15H = 0xB8F  # Upper 32 bits of HPMCOUNTER15, RV32I only
+    MHPMCOUNTER16H = 0xB8F  # Upper 32 bits of HPMCOUNTER16, RV32I only
+    MHPMCOUNTER17H = 0xB90  # Upper 32 bits of HPMCOUNTER17, RV32I only
+    MHPMCOUNTER18H = 0xB91  # Upper 32 bits of HPMCOUNTER18, RV32I only
+    MHPMCOUNTER19H = 0xB92  # Upper 32 bits of HPMCOUNTER19, RV32I only
+    MHPMCOUNTER20H = 0xB93  # Upper 32 bits of HPMCOUNTER20, RV32I only
+    MHPMCOUNTER21H = 0xB94  # Upper 32 bits of HPMCOUNTER21, RV32I only
+    MHPMCOUNTER22H = 0xB95  # Upper 32 bits of HPMCOUNTER22, RV32I only
+    MHPMCOUNTER23H = 0xB96  # Upper 32 bits of HPMCOUNTER23, RV32I only
+    MHPMCOUNTER24H = 0xB97  # Upper 32 bits of HPMCOUNTER24, RV32I only
+    MHPMCOUNTER25H = 0xB98  # Upper 32 bits of HPMCOUNTER25, RV32I only
+    MHPMCOUNTER26H = 0xB99  # Upper 32 bits of HPMCOUNTER26, RV32I only
+    MHPMCOUNTER27H = 0xB9A  # Upper 32 bits of HPMCOUNTER27, RV32I only
+    MHPMCOUNTER28H = 0xB9B  # Upper 32 bits of HPMCOUNTER28, RV32I only
+    MHPMCOUNTER29H = 0xB9C  # Upper 32 bits of HPMCOUNTER29, RV32I only
+    MHPMCOUNTER30H = 0xB9D  # Upper 32 bits of HPMCOUNTER30, RV32I only
+    MHPMCOUNTER31H = 0xB9E  # Upper 32 bits of HPMCOUNTER31, RV32I only
+    MCOUNTINHIBIT = 0x320F  # Machine counter-inhibit register
+    MHPMEVENT3 = 0x323  # Machine performance-monitoring event selector
+    MHPMEVENT4 = 0x324  # Machine performance-monitoring event selector
+    MHPMEVENT5 = 0x325  # Machine performance-monitoring event selector
+    MHPMEVENT6 = 0x326  # Machine performance-monitoring event selector
+    MHPMEVENT7 = 0x327  # Machine performance-monitoring event selector
+    MHPMEVENT8 = 0x328  # Machine performance-monitoring event selector
+    MHPMEVENT9 = 0x329  # Machine performance-monitoring event selector
+    MHPMEVENT10 = 0x32A  # Machine performance-monitoring event selector
+    MHPMEVENT11 = 0x32B  # Machine performance-monitoring event selector
+    MHPMEVENT12 = 0x32C  # Machine performance-monitoring event selector
+    MHPMEVENT13 = 0x32D  # Machine performance-monitoring event selector
+    MHPMEVENT14 = 0x32E  # Machine performance-monitoring event selector
+    MHPMEVENT15 = 0x32F  # Machine performance-monitoring event selector
+    MHPMEVENT16 = 0x330  # Machine performance-monitoring event selector
+    MHPMEVENT17 = 0x331  # Machine performance-monitoring event selector
+    MHPMEVENT18 = 0x332  # Machine performance-monitoring event selector
+    MHPMEVENT19 = 0x333  # Machine performance-monitoring event selector
+    MHPMEVENT20 = 0x334  # Machine performance-monitoring event selector
+    MHPMEVENT21 = 0x335  # Machine performance-monitoring event selector
+    MHPMEVENT22 = 0x336  # Machine performance-monitoring event selector
+    MHPMEVENT23 = 0x337  # Machine performance-monitoring event selector
+    MHPMEVENT24 = 0x338  # Machine performance-monitoring event selector
+    MHPMEVENT25 = 0x339  # Machine performance-monitoring event selector
+    MHPMEVENT26 = 0x33A  # Machine performance-monitoring event selector
+    MHPMEVENT27 = 0x33B  # Machine performance-monitoring event selector
+    MHPMEVENT28 = 0x33C  # Machine performance-monitoring event selector
+    MHPMEVENT29 = 0x33D  # Machine performance-monitoring event selector
+    MHPMEVENT30 = 0x33E  # Machine performance-monitoring event selector
+    MHPMEVENT31 = 0x33F  # Machine performance-monitoring event selector
+    TSELECT = 0x7A0  # Debug/Trace trigger register select
+    TDATA1 = 0x7A1  # First Debug/Trace trigger data register
+    TDATA2 = 0x7A2  # Second Debug/Trace trigger data register
+    TDATA3 = 0x7A3  # Third Debug/Trace trigger data register
+    TINFO = 0x7A4  # Debug trigger info register
+    TCONTROL = 0x7A5  # Debug trigger control register
+    MCONTEXT = 0x7A8  # Machine mode trigger context register
+    SCONTEXT = 0x7AA  # Supervisor mode trigger context register
+    DCSR = 0x7B0  # Debug control and status register
+    DPC = 0x7B1  # Debug PC
+    DSCRATCH0 = 0x7B2  # Debug scratch register
+    DSCRATCH1 = 0x7B3  # Debug scratch register (last one)
+    VSTART = 0x008  # Vector start position
+    VXSTAT = 0x009  # Fixed point saturate flag
+    VXRM = 0x00A  # Fixed point rounding mode
+    VL = 0xC20  # Vector length
+    VTYPE = 0xC21  # Vector data type register
+    VLENB = 0xC22  # VLEN/8 (vector register length in bytes)
 
 
 class privileged_reg_fld_t(IntEnum):
-    RSVD = 0
-    MXL = auto()
-    EXTENSION = auto()
-    MODE = auto()
-    ASID = auto()
-    PPN = auto()
+    RSVD = 0  # Reserved field
+    MXL = auto()  # mis.mxl
+    EXTENSION = auto()  # mis.extension
+    MODE = auto()  # satp.mode
+    ASID = auto()  # satp.asid
+    PPN = auto()  # satp.ppn
 
 
 class privileged_level_t(IntEnum):
-    M_LEVEL = 0b11
-    S_LEVEL = 0b01
-    U_LEVEL = 0b00
+    M_LEVEL = 0b11  # Machine mode
+    S_LEVEL = 0b01  # Supervisor mode
+    U_LEVEL = 0b00  # User mode
 
 
 class reg_field_access_t(IntEnum):
-    WPRI = 0
-    WLRL = auto()
-    WARL = auto()
+    WPRI = 0  # Reserved Writes Preserve Values, Reads Ignore Value
+    WLRL = auto()  # Write/Read Only Legal Values
+    WARL = auto()  # Write Any Values, Reads Legal Values
 
 
+# Pseudo instructions
 class riscv_pseudo_instr_name_t(IntEnum):
     LI = 0
     LA = auto()
 
 
+# Data pattern of the memory model
 class data_pattern_t(IntEnum):
     RAND_DATA = 0
     ALL_ZERO = auto()
@@ -995,12 +1072,12 @@
 
 
 class pte_permission_t(IntEnum):
-    NEXT_LEVEL_PAGE = 0b000
-    READ_ONLY_PAGE = 0b001
-    READ_WRITE_PAGE = 0b011
-    EXECUTE_ONLY_PAGE = 0b100
-    READ_EXECUTE_PAGE = 0b101
-    R_W_EXECUTE_PAGE = 0b111
+    NEXT_LEVEL_PAGE = 0b000  # Pointer to next level of page table.
+    READ_ONLY_PAGE = 0b001  # Read-only page.
+    READ_WRITE_PAGE = 0b011  # Read-write page.
+    EXECUTE_ONLY_PAGE = 0b100  # Execute-only page.
+    READ_EXECUTE_PAGE = 0b101  # Read-execute page.
+    R_W_EXECUTE_PAGE = 0b111  # Read-write-execute page
 
 
 class interrupt_cause_t(IntEnum):
@@ -1098,42 +1175,7 @@
     RA = 0
     T1 = auto()
 
-
-# Ignore ZERO as src1 of load instructions
-class riscv_reg_ex_zero_t(IntEnum):
-    RA = 0
-    SP = auto()
-    GP = auto()
-    TP = auto()
-    T0 = auto()
-    T1 = auto()
-    T2 = auto()
-    S0 = auto()
-    S1 = auto()
-    A0 = auto()
-    A1 = auto()
-    A2 = auto()
-    A3 = auto()
-    A4 = auto()
-    A5 = auto()
-    A6 = auto()
-    A7 = auto()
-    S2 = auto()
-    S3 = auto()
-    S4 = auto()
-    S5 = auto()
-    S6 = auto()
-    S7 = auto()
-    S8 = auto()
-    S9 = auto()
-    S10 = auto()
-    S11 = auto()
-    T3 = auto()
-    T4 = auto()
-    T5 = auto()
-    T6 = auto()
-
-
+# PMP address matching mode
 class pmp_addr_mode_t(Enum):
     OFF = 0b00
     TOR = 0b01
@@ -1166,7 +1208,7 @@
     ZBR = auto()
     ZBM = auto()
     ZBT = auto()
-    ZB_TMP = auto()
+    ZB_TMP = auto()  # for uncategorized instructions
 
 
 class all_gpr(Enum):
@@ -1204,8 +1246,8 @@
     T6 = auto()
 
 
-class compressed_gpr(Enum):
-    S0 = 0
+class compressed_gpr(IntEnum):
+    S0 = 8
     S1 = auto()
     A0 = auto()
     A1 = auto()
@@ -1215,7 +1257,7 @@
     A5 = auto()
 
 
-class all_categories(Enum):
+class all_categories(IntEnum):
     LOAD = 0
     STORE = auto()
     SHIFT = auto()
@@ -1233,6 +1275,75 @@
     INTERRUPT = auto()
     AMO = auto()
 
+# Ignore ZERO and SP
+class riscv_reg_ex_zero_sp_t(IntEnum):
+    RA = 1
+    GP = 3
+    TP = auto()
+    T0 = auto()
+    T1 = auto()
+    T2 = auto()
+    S0 = auto()
+    S1 = auto()
+    A0 = auto()
+    A1 = auto()
+    A2 = auto()
+    A3 = auto()
+    A4 = auto()
+    A5 = auto()
+    A6 = auto()
+    A7 = auto()
+    S2 = auto()
+    S3 = auto()
+    S4 = auto()
+    S5 = auto()
+    S6 = auto()
+    S7 = auto()
+    S8 = auto()
+    S9 = auto()
+    S10 = auto()
+    S11 = auto()
+    T3 = auto()
+    T4 = auto()
+    T5 = auto()
+    T6 = auto()
+
+# Ignore ZERO only
+class riscv_reg_ex_zero_t(IntEnum):
+    RA = 1
+    SP = auto()
+    GP = auto()
+    TP = auto()
+    T0 = auto()
+    T1 = auto()
+    T2 = auto()
+    S0 = auto()
+    S1 = auto()
+    A0 = auto()
+    A1 = auto()
+    A2 = auto()
+    A3 = auto()
+    A4 = auto()
+    A5 = auto()
+    A6 = auto()
+    A7 = auto()
+    S2 = auto()
+    S3 = auto()
+    S4 = auto()
+    S5 = auto()
+    S6 = auto()
+    S7 = auto()
+    S8 = auto()
+    S9 = auto()
+    S10 = auto()
+    S11 = auto()
+    T3 = auto()
+    T4 = auto()
+    T5 = auto()
+    T6 = auto()
+
+# Currently PyVSC doesn't supports ignore bins
+# TODO riscv_reg_ex_zero_sp_t and riscv_reg_ex_zero_t is added as a WA and it can be removed later.
 
 def get_val(in_string, hexa=0):
     if len(in_string) > 2:
@@ -1422,6 +1533,113 @@
         riscv_instr_name_t.CSRRCI: [riscv_instr_format_t.I_FORMAT,
                                     riscv_instr_category_t.CSR,
                                     riscv_instr_group_t.RV32I, imm_t.UIMM],
+        #RV32M
+        riscv_instr_name_t.MUL: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.MULH: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.MULHU: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.MULHSU: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.DIV: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.DIVU: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.REM: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        riscv_instr_name_t.REMU: [riscv_instr_format_t.R_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32M],
+        # RV32C
+        riscv_instr_name_t.C_LW: [riscv_instr_format_t.CL_FORMAT,
+                                 riscv_instr_category_t.LOAD,
+                                 riscv_instr_group_t.RV32C, imm_t.UIMM],
+        riscv_instr_name_t.C_SW: [riscv_instr_format_t.CS_FORMAT,
+                                 riscv_instr_category_t.STORE,
+                                 riscv_instr_group_t.RV32C, imm_t.UIMM],
+        riscv_instr_name_t.C_LWSP: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.LOAD,
+                                 riscv_instr_group_t.RV32C, imm_t.UIMM],
+        riscv_instr_name_t.C_SWSP: [riscv_instr_format_t.CSS_FORMAT,
+                                 riscv_instr_category_t.STORE,
+                                 riscv_instr_group_t.RV32C, imm_t.UIMM],
+        riscv_instr_name_t.C_ADDI4SPN: [riscv_instr_format_t.CIW_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+        riscv_instr_name_t.C_ADDI: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C, imm_t.NZIMM],
+        riscv_instr_name_t.C_ADDI16SP: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C, imm_t.NZIMM],
+        riscv_instr_name_t.C_LI: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_LUI: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C, imm_t.NZIMM],
+        riscv_instr_name_t.C_SUB: [riscv_instr_format_t.CA_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_ADD: [riscv_instr_format_t.CR_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_NOP: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_MV: [riscv_instr_format_t.CR_FORMAT,
+                                 riscv_instr_category_t.ARITHMETIC,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_ANDI: [riscv_instr_format_t.CB_FORMAT,
+                                 riscv_instr_category_t.LOGICAL,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_XOR: [riscv_instr_format_t.CA_FORMAT,
+                                 riscv_instr_category_t.LOGICAL,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_OR: [riscv_instr_format_t.CA_FORMAT,
+                                 riscv_instr_category_t.LOGICAL,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_AND: [riscv_instr_format_t.CA_FORMAT,
+                                 riscv_instr_category_t.LOGICAL,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_BEQZ: [riscv_instr_format_t.CB_FORMAT,
+                                 riscv_instr_category_t.BRANCH,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_BNEZ: [riscv_instr_format_t.CB_FORMAT,
+                                 riscv_instr_category_t.BRANCH,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_SRLI: [riscv_instr_format_t.CB_FORMAT,
+                                 riscv_instr_category_t.SHIFT,
+                                 riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+        riscv_instr_name_t.C_SRAI: [riscv_instr_format_t.CB_FORMAT,
+                                 riscv_instr_category_t.SHIFT,
+                                 riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+        riscv_instr_name_t.C_SLLI: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.SHIFT,
+                                 riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+        riscv_instr_name_t.C_J: [riscv_instr_format_t.CJ_FORMAT,
+                                 riscv_instr_category_t.JUMP,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_JAL: [riscv_instr_format_t.CJ_FORMAT,
+                                 riscv_instr_category_t.JUMP,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_JR: [riscv_instr_format_t.CR_FORMAT,
+                                 riscv_instr_category_t.JUMP,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_JALR: [riscv_instr_format_t.CR_FORMAT,
+                                 riscv_instr_category_t.JUMP,
+                                 riscv_instr_group_t.RV32C],
+        riscv_instr_name_t.C_EBREAK: [riscv_instr_format_t.CI_FORMAT,
+                                 riscv_instr_category_t.SYSTEM,
+                                 riscv_instr_group_t.RV32C],
     }
     # if instruction is not present in the dictionary,second argument well
     # be assigned as default value of passed argument
@@ -1442,9 +1660,11 @@
     from pygen_src.riscv_instr_gen_config import cfg
     rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
+    # xSTATUS bit mask
     MPRV_BIT_MASK = BitArray(uint=0x1 << 0x17, length=rcs.XLEN)
     SUM_BIT_MASK = BitArray(uint=0x1 << 0x18, length=rcs.XLEN)
     MPP_BIT_MASK = BitArray(uint=0x3 << 0x11, length=rcs.XLEN)
+
     MAX_USED_VADDR_BITS = 30
     IMM25_WIDTH = 25
     IMM12_WIDTH = 12
@@ -1456,6 +1676,8 @@
     MAX_SUB_PROGRAM_CNT = 20
     MAX_CALL_PER_FUNC = 5
     indent = LABEL_STR_LEN * " "
+    SINGLE_PRECISION_FRACTION_BITS = 23
+    DOUBLE_PRECISION_FRACTION_BITS = 52
 
     def hart_prefix(self, hart=0):
         if rcs.NUM_HARTS <= 1:
@@ -1466,13 +1688,16 @@
     def get_label(self, label, hart=0):
         return (self.hart_prefix(hart) + label)
 
+    # Format the string to a fixed length
     def format_string(self, string, length=10):
         formatted_str = length * " "
-        if (int(length) < len(string)):
+        if int(length) < len(string):
             return string
         formatted_str = string + formatted_str[0: (int(length) - len(string))]
         return formatted_str
 
+    # Print the data in the following format
+    # 0xabcd, 0x1234, 0x3334 ...
     def format_data(self, data, byte_per_group=4):
         string = "0x"
         for i in range(len(data)):
@@ -1482,70 +1707,55 @@
             string = string + "{:02x}".format(data[i])
         return string
 
+    # Push general purpose register to stack, this is needed before trap handling
     def push_gpr_to_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
-        store_instr = ''
-        if rcs.XLEN == 32:
-            store_instr = "sw"
-        else:
-            store_instr = "sd"
+        store_instr = "sw" if rcs.XLEN == 32 else "sd"
         if scratch in rcs.implemented_csr:
             # Use kernal stack for handling exceptions. Save the user mode stack
             # pointer to the scratch register
-            instr.append(pkg_ins.format_string(
-                "csrrw x{}, {}, x{}".format(sp, hex(scratch.value), sp)))
-            # Move TP to SP
-            instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(sp, tp)))
+            instr.extend(("csrrw x{}, {}, x{}".format(sp, hex(scratch), sp),
+                          # Move TP to SP
+                          "add x{}, x{}, zero".format(sp, tp)))
         # If MPRV is set and MPP is S/U mode, it means the address translation and
         # memory protection for load/store instruction is the same as the mode indicated
         # by MPP. In this case, we need to use the virtual address to access the kernel stack.
-        if(status.name == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE):
+        if(status == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE):
             # We temporarily use tp to check mstatus to avoid changing other GPR. The value
             # of sp has been saved to xScratch and can be restored later.
             if mprv:
-                instr.append(pkg_ins.format_string(
-                    "csrr x{}, 0x{} // MSTATUS".format(tp, status.value)))
-                instr.append(pkg_ins.format_string(
-                    "srli x{}, x{}, 11".format(tp, tp)))  # Move MPP to bit 0
-                instr.append(pkg_ins.format_string(
-                    "andi x{}, x{}, 0x3".format(tp, tp)))  # keep the MPP bits
-                # Check if MPP equals to M-mode('b11)
-                instr.append(pkg_ins.format_string("xori x{}, x{}, 0x3".format(tp, tp)))
-                # Use physical address for kernel SP
-                instr.append(pkg_ins.format_string("bnez x{}, 1f".format(tp)))
-                # Use virtual address for stack pointer
-                instr.append(pkg_ins.format_string(
-                    "slli x{}, x{}, {}".format(sp, sp,
-                                               rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS)))
-                instr.append(pkg_ins.format_string(
-                    "srli x{}, x{}, {}".format(sp, sp,
-                                               rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS)))
+                instr.extend(("csrr x{}, {} // MSTATUS".format(tp, hex(status)),
+                              "srli x{}, x{}, 11".format(tp, tp),  # Move MPP to bit 0
+                              "andi x{}, x{}, 0x3".format(tp, tp),  # keep the MPP bits
+                              # Check if MPP equals to M-mode('b11)
+                              "xori x{}, x{}, 0x3".format(tp, tp),
+                              # Use physical address for kernel SP
+                              "bnez x{}, 1f".format(tp),
+                              # Use virtual address for stack pointer
+                              "slli x{}, x{}, {}".format(sp, sp,
+                                                         rcs.XLEN - self.MAX_USED_VADDR_BITS),
+                              "srli x{}, x{}, {}".format(sp, sp,
+                                                         rcs.XLEN - self.MAX_USED_VADDR_BITS)))
         # Reserve space from kernel stack to save all 32 GPR except for x0
-        instr.append(pkg_ins.format_string(
-            "1: addi x{}, x{}, -{}".format(sp, sp, int(31 * (rcs.XLEN / 8)))))
+        instr.append("1: addi x{}, x{}, -{}".format(sp, sp, 31 * (rcs.XLEN // 8)))
         # Push all GPRs to kernel stack
         for i in range(1, 32):
-            instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format(
-                store_instr, i, int(i * (rcs.XLEN / 8)), sp)))
+            instr.append("{} x{}, {}(x{})".format(
+                store_instr, i, i * (rcs.XLEN // 8), sp))
 
+    # Pop general purpose register from stack, this is needed before returning to user program
     def pop_gpr_from_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
-        load_instr = ''
-        if rcs.XLEN == 32:
-            load_instr = "lw"
-        else:
-            load_instr = "ld"
+        load_instr = "lw" if rcs.XLEN == 32 else "ld"
         # Pop user mode GPRs from kernel stack
         for i in range(1, 32):
-            instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format(
-                load_instr, i, int(i * (rcs.XLEN / 8)), sp)))
+            instr.append("{} x{}, {}(x{})".format(
+                load_instr, i, i * (rcs.XLEN // 8), sp))
         # Restore kernel stack pointer
-        instr.append(pkg_ins.format_string(
-            "addi x{}, x{}, {}".format(sp, sp, int(31 * (rcs.XLEN / 8)))))
+        instr.append("addi x{}, x{}, {}".format(sp, sp, 31 * (rcs.XLEN // 8)))
         if scratch in rcs.implemented_csr:
             # Move SP to TP
-            instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(tp, sp)))
-            # Restore user mode stack pointer
-            instr.append(pkg_ins.format_string(
-                "csrrw x{}, 0x{}, x{}".format(sp, scratch.value, sp)))
+            instr.extend(("add x{}, x{}, zero".format(tp, sp),
+                          # Restore user mode stack pointer
+                          "csrrw x{}, {}, x{}".format(sp, hex(scratch), sp)))
 
 
 pkg_ins = riscv_instr_pkg()
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 5c1a1f0..6227302 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
@@ -1,7 +1,6 @@
 """
 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
@@ -9,53 +8,83 @@
 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 re
-import logging
-import random
 import sys
+import random
+import logging
 import vsc
 from importlib import import_module
 from collections import defaultdict
+from pygen_src.riscv_instr_gen_config import cfg
 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_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr
 from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_name_t, riscv_reg_t,
                                        riscv_instr_category_t)
-from pygen_src.riscv_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
 
+# -----------------------------------------------------------------------------------------
+# RISC-V instruction sequence
+
+# This class is used to generate a single instruction sequence for a RISC-V assembly program.
+# It's used by riscv_asm_program_gen to generate the main program and all sub-programs. The
+# flow is explained below:
+# For main program:
+# - Generate instruction sequence body.
+# - Post-process the load/store/branch instructions.
+# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen).
+# For sub program:
+# - Generate the stack push instructions which are executed when entering this program.
+# - Generate instruction sequence body.
+# - Generate the stack pop instructions which are executed before exiting this program.
+# - Post-process the load/store/branch instructions.
+# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen).
+# - Generate a return instruction at the end of the program.
+# -----------------------------------------------------------------------------------------
+
 class riscv_instr_sequence:
 
     def __init__(self):
-        self.instr_cnt = 0
+        self.instr_cnt = 0  # Instruction count of this sequence
         self.instr_stream = riscv_rand_instr_stream()
-        self.is_main_program = 0
-        self.is_debug_program = 0
-        self.label_name = ""
+        self.is_main_program = 0  # Main instruction streams
+        self.is_debug_program = 0  # Indicates whether sequence is debug program
+        self.label_name = ""  # Label of the sequence (program name)
         self.instr_string_list = []  # Save the instruction list
         self.program_stack_len = vsc.int32_t(0)  # Stack space allocated for this program
         self.directed_instr = []    # List of all directed instruction stream
         self.illegal_instr_pct = 0  # Percentage of illegal instructions
         self.hint_instr_pct = 0     # Percentage of hint instructions
-        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):
+    # Main function to generate the instruction stream
+    # The main random instruction stream is generated by instr_stream.gen_instr(), which generates
+    # each instruction one by one with a separate randomization call. It's not done by a single
+    # randomization call for the entire instruction stream because this solution won't scale if
+    # we have hundreds of thousands of instructions to generate. The constraint solver slows down
+    # considerably as the instruction stream becomes longer. The downside is we cannot specify
+    # constraints between instructions. The way to solve it is to have a dedicated directed
+    # instruction stream for such scenarios, like hazard sequence.
+    def gen_instr(self, is_main_program, no_branch = 0):
         self.is_main_program = is_main_program
         self.instr_stream.initialize_instr_list(self.instr_cnt)
-        logging.info("Start generating %d instruction" % len(self.instr_stream.instr_list))
+        logging.info("Start generating {} instruction".format(len(self.instr_stream.instr_list)))
+        # Do not generate load/store instruction here
+        # The load/store instruction will be inserted as directed instruction stream
         self.instr_stream.gen_instr(no_branch = no_branch, no_load_store = 1,
                                     is_debug_program = self.is_debug_program)
-
         if not is_main_program:
             self.gen_stack_enter_instr()
             self.gen_stack_exit_instr()
+        logging.info("Finishing instruction generation")
 
+    # Generate the stack push operations for this program
+    # It pushes the necessary context to the stack like RA, T0,loop registers etc. The stack
+    # pointer(SP) is reduced by the amount the stack space allocated to this program.
     def gen_stack_enter_instr(self):
         allow_branch = 0 if (self.illegal_instr_pct > 0 or self.hint_instr_pct > 0) else 1
         allow_branch &= not cfg.no_branch_jump
@@ -63,6 +92,7 @@
             with vsc.randomize_with(self.program_stack_len):
                 self.program_stack_len in vsc.rangelist(vsc.rng(cfg.min_stack_len_per_program,
                                                                 cfg.max_stack_len_per_program))
+                # Keep stack len word aligned to avoid unaligned load/store
                 self.program_stack_len % (rcs.XLEN // 8) == 0
         except Exception:
             logging.critical("Cannot randomize program_stack_len")
@@ -79,50 +109,44 @@
         self.instr_stack_exit.gen_pop_stack_instr(self.program_stack_len,
                                                   self.instr_stack_enter.saved_regs)
 
-    '''
-    ----------------------------------------------------------------------------------------------
-    Instruction post-process
+    # ----------------------------------------------------------------------------------------------
+    # Instruction post-process
 
-    Post-process is required for branch instructions:
+    # Post-process is required for branch instructions:
 
-    Need to assign a valid branch target. This is done by picking a random instruction label in
-    this sequence and assigning to the branch instruction. All the non-atomic instructions
-    will have a unique numeric label as the local branch target identifier.
-    The atomic instruction streams don't have labels except for the first instruction. This is
-    to avoid branching into an atomic instruction stream which breaks its atomicy. The
-    definition of an atomic instruction stream here is a sequence of instructions which must be
-    executed in-order.
-    In this sequence, only forward branch is handled. The backward branch target is implemented
-    in a dedicated loop instruction sequence. Randomly choosing a backward branch target could
-    lead to dead loops in the absence of proper loop exiting conditions.
-    ----------------------------------------------------------------------------------------------
-    '''
-
+    # Need to assign a valid branch target. This is done by picking a random instruction label in
+    # this sequence and assigning to the branch instruction. All the non-atomic instructions
+    # will have a unique numeric label as the local branch target identifier.
+    # The atomic instruction streams don't have labels except for the first instruction. This is
+    # to avoid branching into an atomic instruction stream which breaks its atomicy. The
+    # definition of an atomic instruction stream here is a sequence of instructions which must be
+    # executed in-order.
+    # In this sequence, only forward branch is handled. The backward branch target is implemented
+    # in a dedicated loop instruction sequence. Randomly choosing a backward branch target could
+    # lead to dead loops in the absence of proper loop exiting conditions.
+    # ----------------------------------------------------------------------------------------------
     def post_process_instr(self):
         label_idx = 0
         branch_cnt = 0
+        branch_idx = [None] * 30
         j = 0
         branch_target = defaultdict(lambda: None)
-
+        # Insert directed instructions, it's randomly mixed with the random instruction stream.
         for instr in self.directed_instr:
             self.instr_stream.insert_instr_stream(instr.instr_list)
-        '''
-        Assign an index for all instructions, these indexes wont change
-        even a new instruction is injected in the post process.
-        '''
+        # Assign an index for all instructions, these indexes wont change
+        # even a new instruction is injected in the post process.
         for i in range(len(self.instr_stream.instr_list)):
             self.instr_stream.instr_list[i].idx = label_idx
             if(self.instr_stream.instr_list[i].has_label and
                     not(self.instr_stream.instr_list[i].atomic)):
                 if((self.illegal_instr_pct > 0) and
                    (self.instr_stream.instr_list[i].insert_illegal_instr == 0)):
-                    '''
-                    The illegal instruction generator always increase PC by 4 when resume execution,
-                    need to make sure PC + 4 is at the correct instruction boundary.
-                    '''
-                    if(self.instr_stream.instr_list[i].is_compressed):
+                    # The illegal instruction generator always increase PC by 4 when resume
+                    # execution, need to make sure PC + 4 is at the correct instruction boundary.
+                    if self.instr_stream.instr_list[i].is_compressed:
                         if(i < (len(self.instr_stream.instr_list) - 1)):
-                            if(self.instr_stream.instr_list[i + 1].is_compressed):
+                            if self.instr_stream.instr_list[i + 1].is_compressed:
                                 self.instr_stream.instr_list[i].is_illegal_instr = random.randrange(
                                     0, min(100, self.illegal_instr_pct))
                     else:
@@ -130,54 +154,54 @@
                             0, min(100, self.illegal_instr_pct))
                 if(self.hint_instr_pct > 0 and
                         (self.instr_stream.instr_list[i].is_illegal_instr == 0)):
-                    if(self.instr_stream.instr_list[i].is_compressed):
+                    if self.instr_stream.instr_list[i].is_compressed:
                         self.instr_stream.instr_list[i].is_hint_instr = random.randrange(
                             0, min(100, self.hint_instr_pct))
 
                 self.instr_stream.instr_list[i].label = "{}".format(label_idx)
                 self.instr_stream.instr_list[i].is_local_numeric_label = 1
                 label_idx += 1
-
         # Generate branch target
-        for i in range(len(self.branch_idx)):
-            self.branch_idx[i] = random.randint(1, cfg.max_branch_step)
+        for i in range(len(branch_idx)):
+            branch_idx[i] = random.randint(1, cfg.max_branch_step)
 
-        while(j < len(self.instr_stream.instr_list)):
+        while j < len(self.instr_stream.instr_list):
             if((self.instr_stream.instr_list[j].category == riscv_instr_category_t.BRANCH) and
                     (not self.instr_stream.instr_list[j].branch_assigned) and
                     (not self.instr_stream.instr_list[j].is_illegal_instr)):
-                '''
-                Post process the branch instructions to give a valid local label
-                Here we only allow forward branch to avoid unexpected infinite loop
-                The loop structure will be inserted with a separate routine using
-                reserved loop registers
-                '''
+                # Post process the branch instructions to give a valid local label
+                # Here we only allow forward branch to avoid unexpected infinite loop
+                # The loop structure will be inserted with a separate routine using
+                # reserved loop registers
                 branch_target_label = 0
-                # branch_byte_offset = 0
                 branch_target_label = self.instr_stream.instr_list[j].idx + \
-                    self.branch_idx[branch_cnt]
+                    branch_idx[branch_cnt]
                 if(branch_target_label >= label_idx):
                     branch_target_label = label_idx - 1
                 branch_cnt += 1
-                if(branch_cnt == len(self.branch_idx)):
+                if(branch_cnt == len(branch_idx)):
                     branch_cnt = 0
-                    random.shuffle(self.branch_idx)
+                    random.shuffle(branch_idx)
                 logging.info("Processing branch instruction[%0d]:%0s # %0d -> %0d", j,
                              self.instr_stream.instr_list[j].convert2asm(),
                              self.instr_stream.instr_list[j].idx, branch_target_label)
                 self.instr_stream.instr_list[j].imm_str = "{}f".format(branch_target_label)
                 self.instr_stream.instr_list[j].branch_assigned = 1
                 branch_target[branch_target_label] = 1
-
             # Remove the local label which is not used as branch target
             if(self.instr_stream.instr_list[j].has_label and
                     self.instr_stream.instr_list[j].is_local_numeric_label):
                 idx = int(self.instr_stream.instr_list[j].label)
-                if(not branch_target[idx]):
+                if not branch_target[idx]:
                     self.instr_stream.instr_list[j].has_label = 0
             j += 1
         logging.info("Finished post-processing instructions")
 
+    # Inject a jump instruction stream
+    # This function is called by riscv_asm_program_gen with the target program label
+    # The jump routine is implmented with an atomic instruction stream(riscv_jump_instr). Similar
+    # to load/store instructions, JALR/JAL instructions also need a proper base address and offset
+    # as the jump target.
     def insert_jump_instr(self):
         # TODO riscv_jump_instr class implementation
         """
@@ -194,6 +218,9 @@
         """
         pass
 
+    # Convert the instruction stream to the string format.
+    # Label is attached to the instruction if available, otherwise attach proper space to make
+    # the code indent consistent.
     def generate_instr_stream(self, no_label = 0):
         prefix = ''
         string = ''
@@ -208,15 +235,15 @@
                         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):
+                if self.instr_stream.instr_list[i].has_label:
                     prefix = pkg_ins.format_string(string = '{}:'.format(
                         self.instr_stream.instr_list[i].label), length = pkg_ins.LABEL_STR_LEN)
                 else:
                     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")
+            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:
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 5b957d1..ac2fbdb 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
@@ -1,7 +1,6 @@
 """

 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

@@ -10,6 +9,7 @@
 distributed under the License is distributed on an "AS IS" BASIS,

 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 """

+

 import random

 import logging

 import sys

@@ -20,15 +20,12 @@
 from pygen_src.riscv_instr_gen_config import cfg

 

 

+# Base class for RISC-V instruction stream

+# A instruction stream here is a queue of RISC-V basic instructions.

+# This class also provides some functions to manipulate the instruction stream, like insert a new

+# instruction, mix two instruction streams etc.

 @vsc.randobj

 class riscv_instr_stream:

-    '''

-     Base class for RISC-V instruction stream

-     A instruction stream here is a queue of RISC-V basic instructions.

-     This class also provides some functions to manipulate the instruction stream, like insert a new

-     instruction, mix two instruction streams etc.

-    '''

-

     def __init__(self):

         self.instr_list = []

         self.instr_cnt = 0

@@ -40,6 +37,7 @@
         self.reserved_rd = vsc.list_t(vsc.enum_t(riscv_reg_t))

         self.hart = 0

 

+    # Initialize the instruction stream, create each instruction instance

     def initialize_instr_list(self, instr_cnt):

         self.instr_list.clear()

         self.instr_cnt = instr_cnt

@@ -50,12 +48,11 @@
             instr = riscv_instr()

             self.instr_list.append(instr)

 

+    # Insert an instruction to the existing instruction stream at the given index

+    # When index is -1, the instruction is injected at a random location

     def insert_instr(self, instr, idx = -1):

-        """

-           Insert an instruction to the existing instruction stream at the given index

-           When index is -1, the instruction is injected at a random location

-        """

         current_instr_cnt = len(self.instr_list)

+        # TODO

         if idx == -1:

             idx = random.randint(0, current_instr_cnt - 1)

             while self.instr_list[idx].atomic:

@@ -64,16 +61,14 @@
                     self.instr_list.append(instr)

                     return

         elif idx > current_instr_cnt or idx < 0:

-            logging.error("Cannot insert instr:%0s at idx %0d", instr.convert2asm(), idx)

+            logging.error("Cannot insert instr:{} at idx {}".format(instr.convert2asm(), idx))

             sys.exit(1)

         self.instr_list.insert(idx, instr)

 

+    # Insert an instruction to the existing instruction stream at the given index

+    # When index is -1, the instruction is injected at a random location

+    # When replace is 1, the original instruction at the inserted position will be replaced

     def insert_instr_stream(self, new_instr, idx = -1, replace = 0):

-        """

-            Insert an instruction to the existing instruction stream at the given index

-            When index is -1, the instruction is injected at a random location

-            When replace is 1, the original instruction at the inserted position will be replaced

-        """

         current_instr_cnt = len(self.instr_list)

 

         if current_instr_cnt == 0:

@@ -97,7 +92,7 @@
                     logging.critical("Cannot inject the instruction")

                     sys.exit(1)

         elif idx > current_instr_cnt or idx < 0:

-            logging.error("Cannot insert instr stream at idx %0d", idx)

+            logging.error("Cannot insert instr stream at idx {}".format(idx))

             sys.exit(1)

         # When replace is 1, the original instruction at this index will be removed.

         # The label of the original instruction will be copied to the head

@@ -117,17 +112,15 @@
                 self.instr_list = self.instr_list[0:idx] + new_instr + \

                     self.instr_list[idx:current_instr_cnt]

 

+    # Mix the input instruction stream with the original instruction, the instruction order is

+    # preserved. When 'contained' is set, the original instruction stream will be inside the

+    # new instruction stream with the first and last instruction from the input instruction stream.

+    # new_instr is a list of riscv_instr

     def mix_instr_stream(self, new_instr, contained = 0):

-        """

-        Mix the input instruction stream with the original instruction, the instruction order is

-        preserved. When 'contained' is set, the original instruction stream will be inside the

-        new instruction stream with the first and last instruction from the input instruction

-        stream.

-        new_instr is a list of riscv_instr

-        """

         current_instr_cnt = len(self.instr_list)

         new_instr_cnt = len(new_instr)

         insert_instr_position = [0] * new_instr_cnt

+        # TODO

         if len(insert_instr_position) > 0:

             insert_instr_position.sort()

         for i in range(new_instr_cnt):

@@ -148,16 +141,13 @@
         return s

 

 

+# Generate a random instruction stream based on the configuration

+# There are two ways to use this class to generate instruction stream

+# 1. For short instruction stream, you can call randomize() directly.

+# 2. For long instruction stream (>1K), randomize() all instructions together might take a

+# long time for the constraint solver. In this case, you can call gen_instr to generate

+# instructions one by one. The time only grows linearly with the instruction count

 class riscv_rand_instr_stream(riscv_instr_stream):

-    """

-    Generate a random instruction stream based on the configuration

-    There are two ways to use this class to generate instruction stream

-        1. For short instruction stream, you can call randomize() directly.

-        2. For long instruction stream (>1K), randomize() all instructions together might take a

-           long time for the constraint solver. In this case, you can call gen_instr to generate

-           instructions one by one. The time only grows linearly with the instruction count

-    """

-

     def __init__(self):

         # calling super constructor

         super().__init__()

@@ -196,7 +186,7 @@
                                                                     riscv_reg_t.A5)))

                     with vsc.foreach(self.avail_regs, idx = True) as i:

                         self.avail_regs[i].not_inside(vsc.rangelist(cfg.reserved_regs,

-                                                      self.reserved_rd))

+                                                                    self.reserved_rd))

             except Exception:

                 logging.critical("Cannot randomize avail_regs")

                 sys.exit(1)'''

@@ -209,12 +199,14 @@
             if no_load_store:

                 self.category_dist[riscv_instr_category_t.LOAD.name] = 0

                 self.category_dist[riscv_instr_category_t.STORE.name] = 0

-            logging.info("setup_instruction_dist: %0d", len(self.category_dist))

+            logging.info("setup_instruction_dist: {}".format(len(self.category_dist)))

 

     def gen_instr(self, no_branch = 0, no_load_store = 1, is_debug_program = 0):

         self.setup_allowed_instr(no_branch, no_load_store)

         for i in range(len(self.instr_list)):

             self.instr_list[i] = self.randomize_instr(self.instr_list[i], is_debug_program)

+        # Do not allow branch instruction as the last instruction because there's no

+        # forward branch target

         while self.instr_list[-1].category == riscv_instr_category_t.BRANCH:

             self.instr_list.pop()

             if len(self.instr_list) == 0:

@@ -268,3 +260,11 @@
                     instr.rs1 != cfg.reserved_regs[i]

         # TODO: Add constraint for CSR, floating point register

         return instr

+

+    def get_init_gpr_instr(self, gpr, val):

+        # TODO

+        pass

+

+    def add_init_vector_gpr_instr(self, gpr, val):

+        # TODO

+        pass

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
index 7df1cb7..bf0160e 100644
--- 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
@@ -32,6 +32,7 @@
     SPARSE = auto()
 
 
+# Base class for all load/store instruction stream
 @vsc.randobj
 class riscv_load_store_base_instr_stream(riscv_mem_access_stream):
     def __init__(self):
@@ -213,6 +214,7 @@
             self.load_store_instr.append(instr)
 
 
+# A single load/store instruction
 @vsc.randobj
 class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream):
     def __init__(self):
@@ -224,6 +226,7 @@
         self.num_mixed_instr < 5
 
 
+# Back to back load/store instructions
 @vsc.randobj
 class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream):
     def __init__(self):
@@ -237,6 +240,19 @@
         self.num_mixed_instr == 0
 
 
+# Back to back load/store instructions
+@vsc.randobj
+class riscv_load_store_shared_mem_stream(riscv_load_store_stress_instr_stream):
+    def __init__(self):
+        super().__init__()
+
+    def pre_randomize(self):
+        self.load_store_shared_memory = 1
+        super().pre_randomize()
+
+
+# Random load/store sequence
+# A random mix of load/store instructions and other instructions
 @vsc.randobj
 class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream):
     def __init__(self):
@@ -248,6 +264,7 @@
         self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(10, 30)))
 
 
+# Use a small set of GPR to create various WAW, RAW, WAR hazard scenario
 @vsc.randobj
 class riscv_load_store_hazard_instr_stream(riscv_load_store_base_instr_stream):
     def __init__(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
index 4631a2a..49e7c0c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
@@ -1,7 +1,6 @@
 """
 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
@@ -30,7 +29,7 @@
         super().init_reg(reg_name)
         # ---------------Machine mode register ----------------
         # Machine status Register
-        if(reg_name == privileged_reg_t.MSTATUS):
+        if reg_name == privileged_reg_t.MSTATUS:
             self.privil_level = privileged_level_t.M_LEVEL
             self.add_field("UIE", 1, reg_field_access_t.WARL)
             self.add_field("SIE", 1, reg_field_access_t.WARL)
@@ -51,7 +50,7 @@
             self.add_field("TVM", 1, reg_field_access_t.WARL)
             self.add_field("TW", 1, reg_field_access_t.WARL)
             self.add_field("TSR", 1, reg_field_access_t.WARL)
-            if(rcs.XLEN == 32):
+            if rcs.XLEN == 32:
                 self.add_field("WPRI3", 8, reg_field_access_t.WPRI)
             else:
                 self.add_field("WPRI3", 9, reg_field_access_t.WPRI)
@@ -60,7 +59,7 @@
                 self.add_field("WPRI4", rcs.XLEN - 37, reg_field_access_t.WPRI)
             self.add_field("SD", 1, reg_field_access_t.WARL)
         # Machine interrupt-enable register
-        elif(reg_name == privileged_reg_t.MIE):
+        elif reg_name == privileged_reg_t.MIE:
             self.privil_level = privileged_level_t.M_LEVEL
             self.add_field("USIE", 1, reg_field_access_t.WARL)
             self.add_field("SSIE", 1, reg_field_access_t.WARL)
@@ -75,5 +74,6 @@
             self.add_field("WPEI2", 1, reg_field_access_t.WPRI)
             self.add_field("MEIE", 1, reg_field_access_t.WARL)
             self.add_field("WPRI3", rcs.XLEN - 12, reg_field_access_t.WPRI)
+        # TODO add condition for rest of the modes
         else:
             logging.error("reg %0s is not supported yet", reg_name.name)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
index ce612a1..1fdf1bf 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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 logging
@@ -22,6 +20,7 @@
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
 
+# This class provides some common routines for privileged mode operations
 @vsc.randobj
 class riscv_privileged_common_seq():
     def __init___(self):
@@ -79,8 +78,8 @@
 
     def gen_csr_instr(self, regs, instrs):
         for i in range(len(regs)):
-            instrs.append("li x{}, {}".format(cfg.gpr[0].value, hex(regs[i].get_val())))
-            instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name.value),
+            instrs.append("li x{}, {}".format(cfg.gpr[0], hex(regs[i].get_val())))
+            instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name),
                                                      cfg.gpr[0], regs[i].reg_name.name))
 
     def setup_satp(self, instrs):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
index c573634..a47b205 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
@@ -1,7 +1,6 @@
 """
 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
@@ -9,7 +8,6 @@
 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
@@ -36,11 +34,12 @@
                      riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I)
     '''
 
+    # Convert the instruction to assembly code
     def convert2asm(self, prefix = ""):
         asm_str = pkg_ins.format_string(self.get_instr_name(), pkg_ins.MAX_INSTR_STR_LEN)
+        # instr rd,imm
         asm_str = "{}{}, {}".format(asm_str, self.rd.name, self.get_imm())
-
-        if(self.comment != ""):
+        if self.comment != "":
             asm_str = "{} #{}".format(asm_str, self.comment)
         return asm_str.lower()
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
index 395b2d0..9550119 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
@@ -1,7 +1,6 @@
 """
 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
@@ -21,7 +20,10 @@
 rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
 
 
+# -----------------------------------------------
 # Light weight RISC-V register class library
+# -----------------------------------------------
+
 # Base class for RISC-V register field
 @vsc.randobj
 class riscv_reg_field:
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
index 1f67bcb..65a395e 100644
--- 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
@@ -12,9 +12,8 @@
 
 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.
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 127b085..543f1a9 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
@@ -26,6 +26,10 @@
                                                   riscv_single_load_store_instr_stream)
 
 
+# ----------------------------------------------------------
+# pyflow commmon utility helpers functions
+# ----------------------------------------------------------
+
 def factory(obj_of):
     objs = {
         "riscv_directed_instr_stream": riscv_directed_instr_stream,
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
index d984036..d5d9349 100644
--- 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
@@ -1,7 +1,6 @@
 """
 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
@@ -10,74 +9,109 @@
 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)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+                                       riscv_instr_group_t, mtvec_mode_t,
+                                       privileged_mode_t)
 
 
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
 
-
-
+# XLEN
 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]
-
+# set to BARE if address translation is not supported
 SATP_MODE = satp_mode_t.BARE
 
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
 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]
-
+# Interrupt mode support
 supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
 
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
 max_interrupt_vector_num = 16
 
-support_debug_mode = 0
-
-NUM_HARTS = 2
-
+# Physical memory protection support
 support_pmp = 0
 
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
 
+# Support delegate trap to user mode
 support_umode_trap = 0
 
+# Support sfence.vma instruction
 support_sfence = 0
 
+# Support unaligned load/store
 support_unaligned_load_store = 1
 
+# GPR Setting
 NUM_FLOAT_GPR = 32
-
 NUM_GPR = 32
-
 NUM_VEC_GPR = 32
 
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
 VECTOR_EXTENSION_ENABLE = 0
 
 VLEN = 512
 
+# Maximum size of a single vector element
 ELEN = 32
 
+# Minimum size of a sub-element, which must be at most 8-bits.
 SELEN = 8
 
-#VELEN = 
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
 
-MAX_MUL = 8
+# Maxium LMUL supported by the core
+MAX_LMUL = 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]
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 2
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID,  # Vendor ID
+                   privileged_reg_t.MARCHID,  # Architecture ID
+                   privileged_reg_t.MIMPID,  # Implementation ID
+                   privileged_reg_t.MHARTID,  # Hardware thread ID
+                   privileged_reg_t.MSTATUS,  # Machine status
+                   privileged_reg_t.MISA,  # ISA and extensions
+                   privileged_reg_t.MIE,  # Machine interrupt-enable register
+                   privileged_reg_t.MTVEC,  # Machine trap-handler base address
+                   privileged_reg_t.MCOUNTEREN,  # Machine counter enable
+                   privileged_reg_t.MSCRATCH,  # Scratch register for machine trap handlers
+                   privileged_reg_t.MEPC,  # Machine exception program counter
+                   privileged_reg_t.MCAUSE,  # Machine trap cause
+                   privileged_reg_t.MTVAL,  # Machine bad address or instruction
+                   privileged_reg_t.MIP  # Machine interrupt pending
+                   ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
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 fbcc451..ef9ee53 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
@@ -1,7 +1,6 @@
 """
 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
@@ -10,37 +9,108 @@
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 """
+
+import math
 from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
-                                       riscv_instr_group_t, privileged_mode_t)
+                                       riscv_instr_group_t, mtvec_mode_t,
+                                       privileged_mode_t)
 
 
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
 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]
-
+# set to BARE if address translation is not supported
 SATP_MODE = satp_mode_t.BARE
 
-supported_isa = [riscv_instr_group_t.RV32I]
-
+# Supported Privileged mode
 supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-NUM_HARTS = 1
 
-support_pmp = 0
-
-support_debug_mode = 0
-
+# Unsupported instructions
 unsupported_instr = []
 
+# ISA supported by the processor
+supported_isa = [riscv_instr_group_t.RV32I]
+
+# Interrupt mode support
+supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
+max_interrupt_vector_num = 16
+
+# Physical memory protection support
+support_pmp = 0
+
+# Debug mode support
+support_debug_mode = 0
+
+# Support delegate trap to user mode
 support_umode_trap = 0
 
+# Support sfence.vma instruction
+support_sfence = 0
+
+# Support unaligned load/store
+support_unaligned_load_store = 1
+
 # GPR Setting
 NUM_FLOAT_GPR = 32
 NUM_GPR = 32
 NUM_VEC_GPR = 32
 
-max_interrupt_vector_num = 16
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
+VECTOR_EXTENSION_ENABLE = 0
+
+VLEN = 512
+
+# Maximum size of a single vector element
+ELEN = 32
+
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
+
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
+
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
+
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID,  # Vendor ID
+                   privileged_reg_t.MARCHID,  # Architecture ID
+                   privileged_reg_t.MIMPID,  # Implementation ID
+                   privileged_reg_t.MHARTID,  # Hardware thread ID
+                   privileged_reg_t.MSTATUS,  # Machine status
+                   privileged_reg_t.MISA,  # ISA and extensions
+                   privileged_reg_t.MIE,  # Machine interrupt-enable register
+                   privileged_reg_t.MTVEC,  # Machine trap-handler base address
+                   privileged_reg_t.MCOUNTEREN,  # Machine counter enable
+                   privileged_reg_t.MSCRATCH,  # Scratch register for machine trap handlers
+                   privileged_reg_t.MEPC,  # Machine exception program counter
+                   privileged_reg_t.MCAUSE,  # Machine trap cause
+                   privileged_reg_t.MTVAL,  # Machine bad address or instruction
+                   privileged_reg_t.MIP  # Machine interrupt pending
+                   ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
index ae18332..5de8125 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
@@ -1,7 +1,6 @@
 """
 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
@@ -10,71 +9,111 @@
 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)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+                                       riscv_instr_group_t, mtvec_mode_t,
+                                       privileged_mode_t)
 
 
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
 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]
-
+# set to BARE if address translation is not supported
 SATP_MODE = satp_mode_t.BARE
 
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
 supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
                  riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32F,
                  riscv_instr_group_t.RV32FC, riscv_instr_group_t.RV32D,
                  riscv_instr_group_t.RV32DC, riscv_instr_group_t.RV32A]
 
-supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-
+# Interrupt mode support
 supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
 
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
 max_interrupt_vector_num = 16
 
-support_debug_mode = 0
-
-NUM_HARTS = 1
-
+# Physical memory protection support
 support_pmp = 0
 
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
 
+# Support delegate trap to user mode
 support_umode_trap = 0
 
+# Support sfence.vma instruction
 support_sfence = 0
 
+# Support unaligned load/store
 support_unaligned_load_store = 1
 
+# GPR Setting
 NUM_FLOAT_GPR = 32
-
 NUM_GPR = 32
-
 NUM_VEC_GPR = 32
 
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
 VECTOR_EXTENSION_ENABLE = 0
 
 VLEN = 512
 
+# Maximum size of a single vector element
 ELEN = 32
 
-SELEN = 0
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
 
-MAX_MUL = 8
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
 
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
-                         interrupt_cause_t.M_TIMER_INTR,
-                         interrupt_cause_t.M_EXTERNAL_INTR]
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
 
-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]
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID,  # Vendor ID
+                   privileged_reg_t.MARCHID,  # Architecture ID
+                   privileged_reg_t.MIMPID,  # Implementation ID
+                   privileged_reg_t.MHARTID,  # Hardware thread ID
+                   privileged_reg_t.MSTATUS,  # Machine status
+                   privileged_reg_t.MISA,  # ISA and extensions
+                   privileged_reg_t.MIE,  # Machine interrupt-enable register
+                   privileged_reg_t.MTVEC,  # Machine trap-handler base address
+                   privileged_reg_t.MCOUNTEREN,  # Machine counter enable
+                   privileged_reg_t.MSCRATCH,  # Scratch register for machine trap handlers
+                   privileged_reg_t.MEPC,  # Machine exception program counter
+                   privileged_reg_t.MCAUSE,  # Machine trap cause
+                   privileged_reg_t.MTVAL,  # Machine bad address or instruction
+                   privileged_reg_t.MIP  # Machine interrupt pending
+                   ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
index 7f46476..d91f2ed 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
@@ -1,7 +1,6 @@
 """
 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
@@ -10,44 +9,52 @@
 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)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+                                       riscv_instr_group_t, mtvec_mode_t,
+                                       privileged_mode_t)
 
 
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
 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]
-
+# set to BARE if address translation is not supported
 SATP_MODE = satp_mode_t.BARE
 
-supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
-                 riscv_instr_group_t.RV32C]
-
+# Supported Privileged mode
 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 = 1
-
-support_pmp = 0
-
+# Unsupported instructions
 unsupported_instr = []
 
+# ISA supported by the processor
+supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, riscv_instr_group_t.RV32C]
+
+# Interrupt mode support
+supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
+max_interrupt_vector_num = 16
+
+# Physical memory protection support
+support_pmp = 0
+
+# Debug mode support
+support_debug_mode = 0
+
+# Support delegate trap to user mode
 support_umode_trap = 0
 
+# Support sfence.vma instruction
 support_sfence = 0
 
+# Support unaligned load/store
 support_unaligned_load_store = 1
 
 # GPR Setting
@@ -55,22 +62,55 @@
 NUM_GPR = 32
 NUM_VEC_GPR = 32
 
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
 VECTOR_EXTENSION_ENABLE = 0
 
 VLEN = 512
 
+# Maximum size of a single vector element
 ELEN = 32
 
-SELEN = 0
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
 
-MAX_MUL = 8
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
 
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
-                         interrupt_cause_t.M_TIMER_INTR,
-                         interrupt_cause_t.M_EXTERNAL_INTR]
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
 
-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]
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID,  # Vendor ID
+                   privileged_reg_t.MARCHID,  # Architecture ID
+                   privileged_reg_t.MIMPID,  # Implementation ID
+                   privileged_reg_t.MHARTID,  # Hardware thread ID
+                   privileged_reg_t.MSTATUS,  # Machine status
+                   privileged_reg_t.MISA,  # ISA and extensions
+                   privileged_reg_t.MIE,  # Machine interrupt-enable register
+                   privileged_reg_t.MTVEC,  # Machine trap-handler base address
+                   privileged_reg_t.MCOUNTEREN,  # Machine counter enable
+                   privileged_reg_t.MSCRATCH,  # Scratch register for machine trap handlers
+                   privileged_reg_t.MEPC,  # Machine exception program counter
+                   privileged_reg_t.MCAUSE,  # Machine trap cause
+                   privileged_reg_t.MTVAL,  # Machine bad address or instruction
+                   privileged_reg_t.MIP  # Machine interrupt pending
+                   ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
index 8a11e93..0299170 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
@@ -1,7 +1,6 @@
 """
 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
@@ -10,45 +9,53 @@
 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)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+                                       riscv_instr_group_t, mtvec_mode_t,
+                                       privileged_mode_t)
 
 
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
 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]
-
+# set to BARE if address translation is not supported
 SATP_MODE = satp_mode_t.BARE
 
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
 supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
                  riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32B]
 
-supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-
+# Interrupt mode support
 supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
 
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
 max_interrupt_vector_num = 16
 
-support_debug_mode = 0
-
-NUM_HARTS = 1
-
+# Physical memory protection support
 support_pmp = 0
 
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
 
+# Support delegate trap to user mode
 support_umode_trap = 0
 
+# Support sfence.vma instruction
 support_sfence = 0
 
+# Support unaligned load/store
 support_unaligned_load_store = 1
 
 # GPR Setting
@@ -56,23 +63,55 @@
 NUM_GPR = 32
 NUM_VEC_GPR = 32
 
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
 VECTOR_EXTENSION_ENABLE = 0
 
 VLEN = 512
 
+# Maximum size of a single vector element
 ELEN = 32
 
+# Minimum size of a sub-element, which must be at most 8-bits.
 SELEN = 8
 
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
+
+# Maxium LMUL supported by the core
 MAX_LMUL = 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]
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID,  # Vendor ID
+                   privileged_reg_t.MARCHID,  # Architecture ID
+                   privileged_reg_t.MIMPID,  # Implementation ID
+                   privileged_reg_t.MHARTID,  # Hardware thread ID
+                   privileged_reg_t.MSTATUS,  # Machine status
+                   privileged_reg_t.MISA,  # ISA and extensions
+                   privileged_reg_t.MIE,  # Machine interrupt-enable register
+                   privileged_reg_t.MTVEC,  # Machine trap-handler base address
+                   privileged_reg_t.MCOUNTEREN,  # Machine counter enable
+                   privileged_reg_t.MSCRATCH,  # Scratch register for machine trap handlers
+                   privileged_reg_t.MEPC,  # Machine exception program counter
+                   privileged_reg_t.MCAUSE,  # Machine trap cause
+                   privileged_reg_t.MTVAL,  # Machine bad address or instruction
+                   privileged_reg_t.MIP  # Machine interrupt pending
+                   ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
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 75e29d5..66287da 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
@@ -24,6 +24,7 @@
 from pygen_src.riscv_utils import gen_config_table
 
 
+# Base test
 class riscv_instr_base_test:
     def __init__(self):
         self.start_idx = cfg.argv.start_idx
@@ -41,17 +42,23 @@
         if cfg.asm_test_suffix != "":
             self.asm_file_name = "{}.{}".format(self.asm_file_name,
                                                 cfg.asm_test_suffix)
+        self.asm.get_directed_instr_stream()
         test_name = "{}_{}.S".format(self.asm_file_name,
                                      num + self.start_idx)
-        self.asm.get_directed_instr_stream()
+        self.apply_directed_instr()
+        logging.info("All directed instruction is applied")
         self.asm.gen_program()
         self.asm.gen_test_file(test_name)
+        logging.info("TEST GENERATION DONE")
 
     def randomize_cfg(self):
         cfg.randomize()
         logging.info("riscv_instr_gen_config is randomized")
         gen_config_table()
 
+    def apply_directed_instr(self):
+        pass
+
 
 start_time = time.time()
 riscv_base_test_ins = riscv_instr_base_test()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
index 6d406f9..a1cabab 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
@@ -106,6 +106,11 @@
     def get_coverage_report(self):
         model = vsc.get_coverage_report_model()
         cov_dir = cfg.argv.log_file_name.split("/")[0]
+        file = open('{}/CoverageGroups.txt'.format(cov_dir), 'w')
+        file.write("CoverGroups, CoverPoints and Bins Summary\n")
+        str_report = vsc.get_coverage_report(details=True)
+        file.write("{}\n".format(str_report))
+        file.close()
         file = open('{}/CoverageReport.txt'.format(cov_dir), 'w')
         file.write("Groups Coverage Summary\n")
         file.write("Total groups in report: {}\n".format(
@@ -125,18 +130,6 @@
         pass
 
     def sample(self):
-        binary = vsc.int_t(rcs.XLEN)
-        binary.set_val(get_val(self.trace["binary"], hexa=1))
-        # TODO: Currently handled using string formatting as part select
-        #  isn't yet supported for global vsc variables
-        # width is rcs.XLEN+2 because of 0b in the beginning of binary_bin
-        binary_bin = format(binary.get_val(), '#0{}b'.format(rcs.XLEN + 2))
-        if binary_bin[-2:] != "11":  # TODO: and RV32C in supported_isa
-            # TODO: sample compressed instruction
-            pass
-        if binary_bin[-2:] == "11":
-            # TODO: sampling
-            pass
         processed_instr_name = self.process_instr_name(self.trace["instr"])
         if processed_instr_name in riscv_instr_name_t.__members__:
             instr_name = riscv_instr_name_t[processed_instr_name]
@@ -145,9 +138,10 @@
             # cov_instr is created, time to manually assign attributes
             # TODO: This will get fixed later when we get an inst from template
             instruction.assign_attributes()
-            if instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I",
+            if (instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I",
                                           "RV64M", "RV64C", "RV32F", "RV64F",
-                                          "RV32D", "RV64D", "RV32B", "RV64B"]:
+                                          "RV32D", "RV64D", "RV32B", "RV64B"]) \
+                                       and (instruction.group in rcs.supported_isa):
                 self.assign_trace_info_to_instr(instruction)
                 instruction.pre_sample()
                 self.instr_cg.sample(instruction)
@@ -178,7 +172,7 @@
 
     def process_instr_name(self, instruction):
         instruction = instruction.upper()
-        instruction.replace(".", "_")
+        instruction = instruction.replace(".", "_")
         instruction = self.update_instr_name(instruction)
         return instruction
 
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 352c520..2c61df2 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
@@ -31,13 +31,14 @@
         gen_config_table()
 
     def apply_directed_instr(self):
+        # Mix below directed instruction streams with the random instructions
         self.asm.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 4)
-        self.asm.add_directed_instr_stream("riscv_loop_instr", 3)
+        # self.asm.add_directed_instr_stream("riscv_loop_instr", 3)
         self.asm.add_directed_instr_stream("riscv_jal_instr", 4)
-        self.asm.add_directed_instr_stream("riscv_hazard_instr_stream", 4)
+        # self.asm.add_directed_instr_stream("riscv_hazard_instr_stream", 4)
         self.asm.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 4)
-        self.asm.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4)
-        self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4)
+        # self.asm.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4)
+        # self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4)
 
 
 start_time = time.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 0458b01..c476504 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
@@ -380,11 +380,21 @@
     # Run the instruction generator
     if not argv.co:
         seed_gen = SeedGen(argv.start_seed, argv.seed, argv.seed_yaml)
+        if argv.simulator == 'pyflow':
+            """Default timeout of Pyflow is 20 minutes, if the user
+               doesn't specified their own gen_timeout value from CMD
+            """
+            if argv.gen_timeout == 360:
+                gen_timeout = 1200
+            else:
+                gen_timeout = argv.gen_timeout
+        else:
+            gen_timeout = argv.gen_timeout
         do_simulate(sim_cmd, argv.simulator, test_list, cwd, argv.sim_opts,
                     seed_gen,
                     argv.csr_yaml, argv.isa, argv.end_signature_addr,
                     argv.lsf_cmd,
-                    argv.gen_timeout, argv.log_suffix, argv.batch_size,
+                    gen_timeout, argv.log_suffix, argv.batch_size,
                     output_dir,
                     argv.verbose, check_return_code, argv.debug, argv.target)
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
index 045ef20..e3ca844 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
@@ -157,7 +157,7 @@
                               stderr=subprocess.STDOUT)
         children.append(ps)
     for i in range(len(children)):
-        logging.info("Command progress: {}/{}".format(i, len(children)))
+        logging.info("Command progress: {}/{}".format(i + 1, len(children)))
         logging.debug("Waiting for command: {}".format(cmd_list[i]))
         try:
             output = children[i].communicate(timeout=timeout_s)[0]
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
old mode 100755
new mode 100644
index 22c7b7f..335c5e4
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
@@ -31,7 +31,7 @@
     has_rs3 = 1'b0;
     case (format) inside
       R_FORMAT: begin
-        if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP,
+        if (instr_name inside {BMATFLIP,
                                CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D,
                                CRC32C_D}) begin
           has_rs2 = 1'b0;
@@ -61,21 +61,12 @@
 
     if (format inside {I_FORMAT}) begin
       if (category inside {SHIFT, LOGICAL}) begin
-        if (group == RV64B && !(instr_name inside {SLLIU_W})) begin
-          imm_len = $clog2(XLEN) - 1;
-        end else begin
-          imm_len = $clog2(XLEN);
-        end
+        imm_len = $clog2(XLEN);
       end
-
       // ARITHMETIC RV32B
       if (instr_name inside {SHFLI, UNSHFLI}) begin
         imm_len = $clog2(XLEN) - 1;
       end
-      // ARITHMETIC RV64B
-      if (instr_name inside {ADDIWU}) begin
-        imm_len = 12;
-      end
     end
 
     imm_mask = imm_mask << imm_len;
@@ -117,63 +108,38 @@
 
   function bit [6:0] get_opcode();
     case (instr_name) inside
-      ANDN, ORN, XNOR, GORC, SLO, SRO, ROL, ROR, SBCLR, SBSET, SBINV, SBEXT,
-          GREV: get_opcode = 7'b0110011;
-      SLOI, SROI, RORI, SBCLRI, SBSETI, SBINVI, SBEXTI, GORCI, GREVI, CMIX, CMOV,
-          FSL: get_opcode = 7'b0010011;
-      FSR, FSRI, CLZ, CTZ, PCNT, BMATFLIP, SEXT_B, SEXT_H, CRC32_B, CRC32_H, CRC32_W, CRC32C_B,
-          CRC32C_H: get_opcode = 7'b0010011;
+      GORC, SLO, SRO, GREV, XPERM_N, XPERM_B, XPERM_H, XPERM_W: get_opcode = 7'b0110011;
+      GORCI, SLOI, SROI, GREVI, CMIX, CMOV, FSL: get_opcode = 7'b0010011;
+      FSR, FSRI, BMATFLIP, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H: get_opcode = 7'b0010011;
       CRC32C_W, CRC32_D, CRC32C_D: get_opcode = 7'b0010011;
-      CLMUL, CLMULR, CLMULH, MIN, MAX, MINU, MAXU, SHFL, UNSHFL, BDEP, BEXT, PACK, PACKU, BMATOR,
-          BMATXOR, PACKH, BFP: get_opcode = 7'b0110011;
+      SHFL, UNSHFL, BCOMPRESS, BDECOMPRESS, PACK, PACKU, BMATOR, BMATXOR, PACKH, BFP: get_opcode
+          = 7'b0110011;
       SHFLI, UNSHFLI: get_opcode = 7'b0010011;
-      ADDIWU, SLLIU_W: get_opcode = 7'b0011011;
-      ADDWU, SUBWU, ADDU_W, SUBU_W, SLOW, SROW, ROLW, RORW, SBCLRW, SBSETW, SBINVW, SBEXTW, GORCW,
-          GREVW: get_opcode = 7'b0111011;
-      SLOIW, SROIW, RORIW, SBCLRIW, SBSETIW, SBINVIW, GORCIW, GREVIW: get_opcode = 7'b0011011;
+      SLOW, SROW, GORCW, GREVW: get_opcode = 7'b0111011;
+      SLOIW, SROIW, GORCIW, GREVIW: get_opcode = 7'b0011011;
       FSLW, FSRW: get_opcode = 7'b0111011;
-      FSRIW, CLZW, CTZW, PCNTW: get_opcode = 7'b0011011;
-      CLMULW, CLMULRW, CLMULHW, SHFLW, UNSHFLW, BDEPW, BEXTW, PACKW, PACKUW,
-          BFPW: get_opcode = 7'b0111011;
+      FSRIW: get_opcode = 7'b0011011;
+      SHFLW, UNSHFLW, BCOMPRESSW, BDECOMPRESSW, PACKW, PACKUW, BFPW: get_opcode = 7'b0111011;
       default: get_opcode = super.get_opcode();
     endcase
   endfunction
 
   virtual function bit [2:0] get_func3();
     case (instr_name) inside
-      ANDN: get_func3 = 3'b111;
-      ORN: get_func3 = 3'b110;
-      XNOR: get_func3 = 3'b100;
       GORC: get_func3 = 3'b101;
+      GORCI: get_func3 = 3'b101;
       SLO: get_func3 = 3'b001;
       SRO: get_func3 = 3'b101;
-      ROL: get_func3 = 3'b001;
-      ROR: get_func3 = 3'b101;
-      SBCLR: get_func3 = 3'b001;
-      SBSET: get_func3 = 3'b001;
-      SBINV: get_func3 = 3'b001;
-      SBEXT: get_func3 = 3'b101;
-      GREV: get_func3 = 3'b101;
       SLOI: get_func3 = 3'b001;
       SROI: get_func3 = 3'b101;
-      RORI: get_func3 = 3'b101;
-      SBCLRI: get_func3 = 3'b001;
-      SBSETI: get_func3 = 3'b001;
-      SBINVI: get_func3 = 3'b001;
-      SBEXTI: get_func3 = 3'b101;
-      GORCI: get_func3 = 3'b101;
+      GREV: get_func3 = 3'b101;
       GREVI: get_func3 = 3'b101;
       CMIX: get_func3 = 3'b001;
       CMOV: get_func3 = 3'b101;
       FSL: get_func3 = 3'b001;
       FSR: get_func3 = 3'b101;
       FSRI: get_func3 = 3'b101;
-      CLZ: get_func3 = 3'b001;
-      CTZ: get_func3 = 3'b001;
-      PCNT: get_func3 = 3'b001;
       BMATFLIP: get_func3 = 3'b001;
-      SEXT_B: get_func3 = 3'b001;
-      SEXT_H: get_func3 = 3'b001;
       CRC32_B: get_func3 = 3'b001;
       CRC32_H: get_func3 = 3'b001;
       CRC32_W: get_func3 = 3'b001;
@@ -182,17 +148,10 @@
       CRC32C_W: get_func3 = 3'b001;
       CRC32_D: get_func3 = 3'b001;
       CRC32C_D: get_func3 = 3'b001;
-      CLMUL: get_func3 = 3'b001;
-      CLMULR: get_func3 = 3'b010;
-      CLMULH: get_func3 = 3'b011;
-      MIN: get_func3 = 3'b100;
-      MAX: get_func3 = 3'b101;
-      MINU: get_func3 = 3'b110;
-      MAXU: get_func3 = 3'b111;
       SHFL: get_func3 = 3'b001;
       UNSHFL: get_func3 = 3'b101;
-      BDEP: get_func3 = 3'b110;
-      BEXT: get_func3 = 3'b110;
+      BCOMPRESS: get_func3 = 3'b110;
+      BDECOMPRESS: get_func3 = 3'b110;
       PACK: get_func3 = 3'b100;
       PACKU: get_func3 = 3'b100;
       BMATOR: get_func3 = 3'b011;
@@ -201,46 +160,30 @@
       BFP: get_func3 = 3'b111;
       SHFLI: get_func3 = 3'b001;
       UNSHFLI: get_func3 = 3'b101;
-      ADDIWU: get_func3 = 3'b100;
-      SLLIU_W: get_func3 = 3'b001;
-      ADDWU: get_func3 = 3'b000;
-      SUBWU: get_func3 = 3'b000;
-      ADDU_W: get_func3 = 3'b000;
-      SUBU_W: get_func3 = 3'b000;
       SLOW: get_func3 = 3'b001;
       SROW: get_func3 = 3'b101;
       ROLW: get_func3 = 3'b001;
-      RORW: get_func3 = 3'b101;
-      SBCLRW: get_func3 = 3'b001;
-      SBSETW: get_func3 = 3'b001;
-      SBINVW: get_func3 = 3'b001;
-      SBEXTW: get_func3 = 3'b101;
       GORCW: get_func3 = 3'b101;
       GREVW: get_func3 = 3'b101;
       SLOIW: get_func3 = 3'b001;
       SROIW: get_func3 = 3'b101;
       RORIW: get_func3 = 3'b101;
-      SBCLRIW: get_func3 = 3'b001;
-      SBSETIW: get_func3 = 3'b001;
-      SBINVIW: get_func3 = 3'b001;
       GORCIW: get_func3 = 3'b101;
       GREVIW: get_func3 = 3'b101;
       FSLW: get_func3 = 3'b001;
       FSRW: get_func3 = 3'b101;
       FSRIW: get_func3 = 3'b101;
-      CLZW: get_func3 = 3'b001;
-      CTZW: get_func3 = 3'b001;
-      PCNTW: get_func3 = 3'b001;
-      CLMULW: get_func3 = 3'b001;
-      CLMULRW: get_func3 = 3'b010;
-      CLMULHW: get_func3 = 3'b011;
       SHFLW: get_func3 = 3'b001;
       UNSHFLW: get_func3 = 3'b101;
-      BDEPW: get_func3 = 3'b110;
-      BEXTW: get_func3 = 3'b110;
+      BCOMPRESSW: get_func3 = 3'b110;
+      BDECOMPRESSW: get_func3 = 3'b110;
       PACKW: get_func3 = 3'b100;
       PACKUW: get_func3 = 3'b100;
       BFPW: get_func3 = 3'b111;
+      XPERM_N: get_func3 = 3'b010;
+      XPERM_B: get_func3 = 3'b100;
+      XPERM_H: get_func3 = 3'b110;
+      XPERM_W: get_func3 = 3'b000;
       default: get_func3 = super.get_func3();
     endcase
     ;
@@ -256,17 +199,8 @@
       SRO: get_func7 = 7'b0010000;
       ROL: get_func7 = 7'b0110000;
       ROR: get_func7 = 7'b0110000;
-      SBCLR: get_func7 = 7'b0100100;
-      SBSET: get_func7 = 7'b0010100;
-      SBINV: get_func7 = 7'b0110100;
-      SBEXT: get_func7 = 7'b0100100;
       GREV: get_func7 = 7'b0110100;
-      CLZ: get_func7 = 7'b0110000;
-      CTZ: get_func7 = 7'b0110000;
-      PCNT: get_func7 = 7'b0110000;
       BMATFLIP: get_func7 = 7'b0110000;
-      SEXT_B: get_func7 = 7'b0110000;
-      SEXT_H: get_func7 = 7'b0110000;
       CRC32_B: get_func7 = 7'b0110000;
       CRC32_H: get_func7 = 7'b0110000;
       CRC32_W: get_func7 = 7'b0110000;
@@ -275,58 +209,35 @@
       CRC32C_W: get_func7 = 7'b0110000;
       CRC32_D: get_func7 = 7'b0110000;
       CRC32C_D: get_func7 = 7'b0110000;
-      CLMUL: get_func7 = 7'b0000101;
-      CLMULR: get_func7 = 7'b0000101;
-      CLMULH: get_func7 = 7'b0000101;
-      MIN: get_func7 = 7'b0000101;
-      MAX: get_func7 = 7'b0000101;
-      MINU: get_func7 = 7'b0000101;
-      MAXU: get_func7 = 7'b0000101;
       SHFL: get_func7 = 7'b0000100;
       UNSHFL: get_func7 = 7'b0000100;
-      BDEP: get_func7 = 7'b0100100;
-      BEXT: get_func7 = 7'b0000100;
+      BCOMPRESS: get_func7 = 7'b0000100;
+      BDECOMPRESS: get_func7 = 7'b0100100;
       PACK: get_func7 = 7'b0000100;
       PACKU: get_func7 = 7'b0100100;
       BMATOR: get_func7 = 7'b0000100;
       BMATXOR: get_func7 = 7'b0100100;
       PACKH: get_func7 = 7'b0000100;
       BFP: get_func7 = 7'b0100100;
-      ADDWU: get_func7 = 7'b0000101;
-      SUBWU: get_func7 = 7'b0100101;
-      ADDU_W: get_func7 = 7'b0000100;
-      SUBU_W: get_func7 = 7'b0100100;
       SLOW: get_func7 = 7'b0010000;
       SROW: get_func7 = 7'b0010000;
-      ROLW: get_func7 = 7'b0110000;
-      RORW: get_func7 = 7'b0110000;
-      SBCLRW: get_func7 = 7'b0100100;
-      SBSETW: get_func7 = 7'b0010100;
-      SBINVW: get_func7 = 7'b0110100;
-      SBEXTW: get_func7 = 7'b0100100;
       GORCW: get_func7 = 7'b0010100;
+      GORCIW: get_func7 = 7'b0010100;
       GREVW: get_func7 = 7'b0110100;
+      GREVIW: get_func7 = 7'b0110100;
       SLOIW: get_func7 = 7'b0010000;
       SROIW: get_func7 = 7'b0010000;
-      RORIW: get_func7 = 7'b0110000;
-      SBCLRIW: get_func7 = 7'b0100100;
-      SBSETIW: get_func7 = 7'b0010100;
-      SBINVIW: get_func7 = 7'b0110100;
-      GORCIW: get_func7 = 7'b0010100;
-      GREVIW: get_func7 = 7'b0110100;
-      CLZW: get_func7 = 7'b0110000;
-      CTZW: get_func7 = 7'b0110000;
-      PCNTW: get_func7 = 7'b0110000;
-      CLMULW: get_func7 = 7'b0000101;
-      CLMULRW: get_func7 = 7'b0000101;
-      CLMULHW: get_func7 = 7'b0000101;
       SHFLW: get_func7 = 7'b0000100;
       UNSHFLW: get_func7 = 7'b0000100;
-      BDEPW: get_func7 = 7'b0100100;
-      BEXTW: get_func7 = 7'b0000100;
+      BCOMPRESSW: get_func7 = 7'b0000100;
+      BDECOMPRESSW: get_func7 = 7'b0100100;
       PACKW: get_func7 = 7'b0000100;
       PACKUW: get_func7 = 7'b0100100;
       BFPW: get_func7 = 7'b0100100;
+      XPERM_N: get_func7 = 7'b0010100;
+      XPERM_B: get_func7 = 7'b0010100;
+      XPERM_H: get_func7 = 7'b0010100;
+      XPERM_W: get_func7 = 7'b0010100;
       default: get_func7 = super.get_func7();
     endcase
 
@@ -337,17 +248,9 @@
       SLOI: get_func5 = 5'b00100;
       SROI: get_func5 = 5'b00100;
       RORI: get_func5 = 5'b01100;
-      SBCLRI: get_func5 = 5'b01001;
-      SBSETI: get_func5 = 5'b01001;
-      SBINVI: get_func5 = 5'b01101;
-      SBEXTI: get_func5 = 5'b01001;
       GORCI: get_func5 = 5'b00101;
       GREVI: get_func5 = 5'b01101;
 
-      CLZW: get_func5 = 5'b00000;
-      CTZW: get_func5 = 5'b00001;
-      PCNTW: get_func5 = 5'b00010;
-
       CRC32_B: get_func5 = 5'b10000;
       CRC32_H: get_func5 = 5'b10001;
       CRC32_W: get_func5 = 5'b10010;
@@ -357,12 +260,7 @@
       CRC32_D: get_func5 = 5'b10011;
       CRC32C_D: get_func5 = 5'b11011;
 
-      CLZ: get_func5 = 5'b00000;
-      CTZ: get_func5 = 5'b00001;
-      PCNT: get_func5 = 5'b00010;
       BMATFLIP: get_func5 = 5'b00011;
-      SEXT_B: get_func5 = 5'b00100;
-      SEXT_H: get_func5 = 5'b00101;
       default: `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
     endcase
   endfunction
@@ -385,23 +283,15 @@
     string binary = "";
     case (format)
       R_FORMAT: begin
-        if ((category inside {LOGICAL}) && (group == RV32B)) begin
-          if (instr_name inside {SEXT_B, SEXT_H}) begin
-            binary =
-                $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
-          end
-        end
-
         if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
-          if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CLZ, CTZ,
-                                 PCNT}) begin
+          if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W}) begin
             binary =
                 $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
           end
         end
 
         if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
-          if (instr_name inside {CLZW, CTZW, PCNTW, CRC32_D, CRC32C_D, BMATFLIP}) begin
+          if (instr_name inside {CRC32_D, CRC32C_D, BMATFLIP}) begin
             binary =
                 $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
           end
@@ -413,8 +303,6 @@
           binary = $sformatf("%8h", {get_func5(), imm[6:0], rs1, get_func3(), rd, get_opcode()});
         end else if ((category inside {SHIFT, LOGICAL}) && (group == RV64B)) begin
           binary = $sformatf("%8h", {get_func7(), imm[4:0], rs1, get_func3(), rd, get_opcode()});
-          if (instr_name == SLLIU_W)
-            binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()});
         end
 
         if (instr_name inside {FSRI}) begin
@@ -450,37 +338,19 @@
 
   virtual function bit is_supported(riscv_instr_gen_config cfg);
     return cfg.enable_b_extension && (
-           (ZBB inside {cfg.enable_bitmanip_groups} && instr_name inside {
-               CLZ, CTZ, CLZW, CTZW, PCNT, PCNTW,
-               SLO, SLOI, SLOW, SLOIW,
-               SRO, SROI, SROW, SROIW,
-               MIN, MINU, MAX, MAXU,
-               ADDWU, ADDIWU, SUBWU,
-               ADDU_W, SUBU_W,
-               SLLIU_W,
-               ANDN, ORN,
-               XNOR, PACK, PACKW, PACKU, PACKUW, PACKH,
-               ROL, ROLW, ROR, RORW, RORI, RORIW
-               }) ||
-           (ZBS inside {cfg.enable_bitmanip_groups} && instr_name inside {
-               SBSET, SBSETW, SBSETI, SBSETIW,
-               SBCLR, SBCLRW, SBCLRI, SBCLRIW,
-               SBINV, SBINVW, SBINVI, SBINVIW,
-               SBEXT, SBEXTW, SBEXTI
-               }) ||
            (ZBP inside {cfg.enable_bitmanip_groups} && instr_name inside {
                GREV, GREVW, GREVI, GREVIW,
                GORC, GORCW, GORCI, GORCIW,
-               SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI
+               SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI,
+               XPERM_N, XPERM_B, XPERM_H, XPERM_W,
+               SLO, SLOW, SLOI, SLOIW,
+               SRO, SROW, SROI, SROIW
                }) ||
            (ZBE inside {cfg.enable_bitmanip_groups} && instr_name inside {
-               BEXT, BEXTW,
-               BDEP, BDEPW
+               BCOMPRESS, BCOMPRESSW,
+               BDECOMPRESS, BDECOMPRESSW
                }) ||
            (ZBF inside {cfg.enable_bitmanip_groups} && instr_name inside {BFP, BFPW}) ||
-           (ZBC inside {cfg.enable_bitmanip_groups} && instr_name inside {
-               CLMUL, CLMULW, CLMULH, CLMULHW, CLMULR, CLMULRW
-               }) ||
            (ZBR inside {cfg.enable_bitmanip_groups} && instr_name inside {
                CRC32_B, CRC32_H, CRC32_W, CRC32_D,
                CRC32C_B, CRC32C_H, CRC32C_W, CRC32C_D
@@ -490,10 +360,7 @@
                }) ||
            (ZBT inside {cfg.enable_bitmanip_groups} && instr_name inside {
                CMOV, CMIX,
-               FSL, FSLW, FSR, FSRW, FSRI, FSRIW}) ||
-           // TODO, spec 0.92 doesn't categorize these 2 instr, put them in ZB_TMP #572
-           (ZB_TMP inside {cfg.enable_bitmanip_groups} && instr_name inside {
-               SEXT_B, SEXT_H})
+               FSL, FSLW, FSR, FSRW, FSRI, FSRIW})
            );
   endfunction
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
index 385af7b..04fdcb7 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
@@ -318,11 +318,11 @@
       C_ADD:
         binary = $sformatf("%4h", {get_func3(), 1'b1, rd, rs2, get_c_opcode()});
       C_FSDSP, C_SDSP:
-        binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:3], imm[8:6], rs2, get_c_opcode()});
+        binary = $sformatf("%4h", {get_func3(), imm[5:3], imm[8:6], rs2, get_c_opcode()});
       C_SQSP:
-        binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:4], imm[9:6], rs2, get_c_opcode()});
+        binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[9:6], rs2, get_c_opcode()});
       C_SWSP, C_FSWSP:
-        binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:2], imm[7:6], rs2, get_c_opcode()});
+        binary = $sformatf("%4h", {get_func3(), imm[5:2], imm[7:6], rs2, get_c_opcode()});
       default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
     endcase
     return {prefix, binary};
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
index 6639090..088f389 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
@@ -248,7 +248,7 @@
     if (group inside {RV32F, RV64F}) begin
       fs1_sign = get_fp_operand_sign(fs1_value, 31);
       fs2_sign = get_fp_operand_sign(fs2_value, 31);
-      fs3_sign = get_fp_operand_sign(fs2_value, 31);
+      fs3_sign = get_fp_operand_sign(fs3_value, 31);
       fd_sign = get_fp_operand_sign(fd_value, 31);
     end else if (instr_name == FCVT_S_D) begin
       fs1_sign = get_fp_operand_sign(fs1_value, 63);
@@ -259,7 +259,7 @@
     end else begin
       fs1_sign = get_fp_operand_sign(fs1_value, 63);
       fs2_sign = get_fp_operand_sign(fs2_value, 63);
-      fs3_sign = get_fp_operand_sign(fs2_value, 63);
+      fs3_sign = get_fp_operand_sign(fs3_value, 63);
       fd_sign = get_fp_operand_sign(fd_value, 63);
     end
   endfunction : pre_sample
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
index c444adc..2b2f322 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
@@ -344,7 +344,7 @@
       if(imm_type == UIMM) begin
         imm_len = 5;
       end else begin
-        imm_len = 11;
+        imm_len = 12;
       end
     end
     imm_mask = imm_mask << imm_len;
@@ -580,7 +580,7 @@
         if(instr_name inside {FENCE, FENCE_I})
           binary = $sformatf("%8h", {17'b0, get_func3(), 5'b0, get_opcode()});
         else if(category == CSR)
-          binary = $sformatf("%8h", {csr[10:0], imm[4:0], get_func3(), rd, get_opcode()});
+          binary = $sformatf("%8h", {csr[11:0], imm[4:0], get_func3(), rd, get_opcode()});
         else if(instr_name == ECALL)
           binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()});
         else if(instr_name inside {URET, SRET, MRET})
@@ -604,7 +604,7 @@
       end
       R_FORMAT: begin
         if(category == CSR)
-          binary = $sformatf("%8h", {csr[10:0], rs1, get_func3(), rd, get_opcode()});
+          binary = $sformatf("%8h", {csr[11:0], rs1, get_func3(), rd, get_opcode()});
         else if(instr_name == SFENCE_VMA)
           binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()});
         else
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
new file mode 100644
index 0000000..0600ac4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zba_instr extends riscv_instr;
+  `uvm_object_utils(riscv_zba_instr)
+
+  function new(string name = "");
+    super.new(name);
+  endfunction : new
+
+  function void pre_randomize();
+    super.pre_randomize();
+  endfunction
+
+  virtual function void set_imm_len();
+    if (!(instr_name inside {SLLI_UW})) begin
+      imm_len = $clog2(XLEN) - 1;
+    end else begin
+      imm_len = $clog2(XLEN);
+    end
+    imm_mask = imm_mask << imm_len;
+  endfunction : set_imm_len
+
+  function bit[6:0] get_opcode();
+    case (instr_name) inside
+      SH1ADD, SH2ADD, SH3ADD :          get_opcode = 7'b0110011;
+      SH1ADD_UW, SH2ADD_UW, SH3ADD_UW : get_opcode = 7'b0111011;
+      SLLI_UW :                         get_opcode = 7'b0011011;
+      default :                         get_opcode = super.get_opcode();
+    endcase
+  endfunction : get_opcode
+
+  virtual function bit [2:0] get_func3();
+    case (instr_name) inside
+      ADD_UW    : get_func3 = 3'b000;
+      SH1ADD    : get_func3 = 3'b010;
+      SH2ADD    : get_func3 = 3'b100;
+      SH3ADD    : get_func3 = 3'b110;
+      SH1ADD_UW : get_func3 = 3'b010;
+      SH2ADD_UW : get_func3 = 3'b100;
+      SH3ADD_UW : get_func3 = 3'b110;
+      SLLI_UW   : get_func3 = 3'b001;
+      default   : get_func3 = super.get_func3();
+    endcase
+  endfunction : get_func3
+
+  function bit [6:0] get_func7();
+    case (instr_name) inside
+      ADD_UW    : get_func7 = 7'b0000100;
+      SH1ADD    : get_func7 = 7'b0010000;
+      SH2ADD    : get_func7 = 7'b0010000;
+      SH3ADD    : get_func7 = 7'b0010000;
+      SH1ADD_UW : get_func7 = 7'b0010000;
+      SH2ADD_UW : get_func7 = 7'b0010000;
+      SH3ADD_UW : get_func7 = 7'b0010000;
+      SLLI_UW   : get_func7 = 7'b0010000;
+      default   : get_func7 = super.get_func7();
+    endcase
+  endfunction : get_func7
+
+  virtual function string convert2bin(string prefix = "");
+    string binary = "";
+    if (instr_name inside {SLLI_UW}) begin
+      binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()});
+    end
+    else begin
+      binary = super.convert2bin(prefix);
+    end
+  endfunction : convert2bin
+
+  virtual function bit is_supported(riscv_instr_gen_config cfg);
+    return (cfg.enable_zba_extension &&
+           (RV32ZBA inside { supported_isa } || RV64ZBA inside { supported_isa }) &&
+           instr_name inside {
+             ADD_UW,
+             SH1ADD, SH1ADD_UW,
+             SH2ADD, SH2ADD_UW,
+             SH3ADD, SH3ADD_UW,
+             SLLI_UW
+           });
+  endfunction : is_supported
+
+endclass : riscv_zba_instr
+
+
+
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
new file mode 100644
index 0000000..475671a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbb_instr extends riscv_instr;
+  `uvm_object_utils(riscv_zbb_instr)
+
+  function new(string name = "");
+    super.new(name);
+  endfunction : new
+
+  virtual function void set_rand_mode();
+    super.set_rand_mode();
+    case (format) inside
+      R_FORMAT: begin
+        if (instr_name inside { ZEXT_H }) begin
+          has_rs2 = 1'b0;
+        end
+      end
+
+      I_FORMAT: begin
+        if (instr_name inside { CLZ, CLZW, CTZ, CTZW, CPOP, CPOPW, ORC_B, SEXT_B, SEXT_H, REV8 })
+        begin
+          has_imm = 1'b0;
+        end
+      end
+
+    endcase
+  endfunction : set_rand_mode
+
+  function void pre_randomize();
+    super.pre_randomize();
+  endfunction
+
+  function bit is_rv64();
+    is_rv64 = (group == RV64B);
+  endfunction : is_rv64
+
+  virtual function void set_imm_len();
+    if (format inside {I_FORMAT}) begin
+      if (instr_name inside {RORI}) begin
+        imm_len = $clog2(XLEN);
+      end else begin
+        imm_len = 5;
+      end
+    end
+    imm_mask = imm_mask << imm_len;
+  endfunction : set_imm_len
+
+  virtual function string convert2asm(string prefix = "");
+    string asm_str_final;
+    string asm_str;
+
+    asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN);
+
+    case (format)
+      I_FORMAT : begin // instr rd rs1
+        if (!has_imm) begin
+          asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
+        end
+      end
+
+      R_FORMAT : begin // instr rd rs1
+        if (!has_rs2) begin
+          asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
+        end
+      end
+
+      default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
+    endcase
+
+    if (asm_str_final == "") begin
+      return super.convert2asm(prefix);
+    end
+
+    if (comment != "") begin
+      asm_str_final = { asm_str_final, " #", comment };
+    end
+
+    return asm_str_final.tolower();
+
+  endfunction : convert2asm
+
+  function bit[6:0] get_opcode();
+    case (instr_name) inside
+      ANDN, MAX, MAXU, MIN, MINU,
+      ORN, ROL, ROR, XNOR          : get_opcode = 7'b011_0011;
+      ZEXT_H                       : get_opcode = 7'b011_0011 | (is_rv64() << 3);
+      ROLW, RORW                   : get_opcode = 7'b011_1011;
+      CLZ, CPOP, CTZ, ORC_B,
+      CLZW, CPOPW, CTZW, RORIW     : get_opcode = 7'b001_1011;
+      REV8, RORI, SEXT_B, SEXT_H   : get_opcode = 7'b001_0011;
+      default                      : get_opcode = super.get_opcode();
+    endcase
+  endfunction : get_opcode
+
+  virtual function bit [2:0] get_func3();
+    case (instr_name) inside
+      ANDN    : get_func3 = 3'b111;
+      CLZ     : get_func3 = 3'b001;
+      CLZW    : get_func3 = 3'b001;
+      CPOP    : get_func3 = 3'b001;
+      CPOPW   : get_func3 = 3'b001;
+      CTZ     : get_func3 = 3'b001;
+      CTZW    : get_func3 = 3'b001;
+      MAX     : get_func3 = 3'b110;
+      MAXU    : get_func3 = 3'b111;
+      MIN     : get_func3 = 3'b100;
+      MINU    : get_func3 = 3'b101;
+      ORC_B   : get_func3 = 3'b101;
+      ORN     : get_func3 = 3'b110;
+      REV8    : get_func3 = 3'b101;
+      ROL     : get_func3 = 3'b001;
+      ROLW    : get_func3 = 3'b001;
+      ROR     : get_func3 = 3'b101;
+      RORW    : get_func3 = 3'b101;
+      RORI    : get_func3 = 3'b101;
+      RORIW   : get_func3 = 3'b101;
+      SEXT_B  : get_func3 = 3'b001;
+      SEXT_H  : get_func3 = 3'b001;
+      XNOR    : get_func3 = 3'b100;
+      ZEXT_H  : get_func3 = 3'b100;
+      default : get_func3 = super.get_func3();
+    endcase
+  endfunction : get_func3
+
+  virtual function bit [4:0] get_func5();
+    case (instr_name) inside
+      CLZ     : get_func5 = 5'b0_0000;
+      CLZW    : get_func5 = 5'b0_0000;
+      CPOP    : get_func5 = 5'b0_0010;
+      CPOPW   : get_func5 = 5'b0_0010;
+      CTZ     : get_func5 = 5'b0_0001;
+      CTZW    : get_func5 = 5'b0_0001;
+      ORC_B   : get_func5 = 5'b0_0111;
+      REV8    : get_func5 = 5'b1_1000;
+      SEXT_B  : get_func5 = 5'b0_0100;
+      SEXT_H  : get_func5 = 5'b0_0101;
+    endcase
+  endfunction : get_func5
+
+  virtual function bit [6:0] get_func7();
+    case (instr_name) inside
+      ANDN    : get_func7 = 7'b010_0000;
+      CLZ     : get_func7 = 7'b011_0000;
+      CLZW    : get_func7 = 7'b011_0000;
+      CPOP    : get_func7 = 7'b011_0000;
+      CPOPW   : get_func7 = 7'b011_0000;
+      CTZ     : get_func7 = 7'b011_0000;
+      CTZW    : get_func7 = 7'b011_0000;
+      MAX     : get_func7 = 7'b000_0101;
+      MAXU    : get_func7 = 7'b000_0101;
+      MIN     : get_func7 = 7'b000_0101;
+      MINU    : get_func7 = 7'b000_0101;
+      ORC_B   : get_func7 = 7'b001_0100;
+      ORN     : get_func7 = 7'b010_0000;
+      REV8    : get_func7 = 7'b011_0100 | is_rv64(); // 0110101 64 bit
+      ROL     : get_func7 = 7'b011_0000;
+      ROLW    : get_func7 = 7'b011_0000;
+      ROR     : get_func7 = 7'b011_0000;
+      RORW    : get_func7 = 7'b011_0000;
+      RORI    : get_func7 = 7'b011_0000;
+      RORIW   : get_func7 = 7'b011_0000;
+      SEXT_B  : get_func7 = 7'b011_0000;
+      SEXT_H  : get_func7 = 7'b011_0000;
+      XNOR    : get_func7 = 7'b010_0000;
+      ZEXT_H  : get_func7 = 7'b000_0100;
+      default : get_func7 = super.get_func7();
+    endcase
+  endfunction : get_func7
+
+  virtual function string convert2bin(string prefix = "");
+    string binary = "";
+
+    case (format)
+      R_FORMAT: begin
+        if (instr_name inside { ZEXT_H }) begin
+          binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
+        end
+      end
+
+      I_FORMAT: begin
+        case (instr_name) inside
+          CLZ, CLZW, CPOP, CPOPW, CTZ, CTZW, ORC_B, REV8, SEXT_B, SEXT_H: begin
+            binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd,
+                                       get_opcode()});
+          end
+          RORIW: begin
+            binary = $sformatf("%8h", {get_func7(), imm[5:0], rs1, get_func3(), rd, get_opcode()});
+          end
+          RORI: begin
+            // set bit 0 of funct7 only if rv64 and shamt[MSB] is set
+            binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1,
+                                        get_func3(), rd, get_opcode()});
+          end
+        endcase
+      end
+
+      default: begin
+        if (binary == "") begin
+          binary = super.convert2bin(prefix);
+        end
+      end
+
+    endcase // case (format)
+  endfunction : convert2bin
+
+  virtual function bit is_supported(riscv_instr_gen_config cfg);
+    return (cfg.enable_zbb_extension &&
+           (RV32ZBB inside { supported_isa } || RV64ZBB inside { supported_isa }) &&
+           instr_name inside {
+             ANDN,
+             CLZ, CLZW,
+             CPOP, CPOPW,
+             CTZ, CTZW,
+             MAX, MAXU,
+             MIN, MINU,
+             ORC_B, ORN,
+             REV8,
+             ROL, ROLW,
+             ROR, RORW,
+             RORI, RORIW,
+             SEXT_B, SEXT_H,
+             XNOR,
+             ZEXT_H
+           });
+  endfunction : is_supported
+
+endclass : riscv_zbb_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
new file mode 100644
index 0000000..8bc825e
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbc_instr extends riscv_instr;
+  `uvm_object_utils(riscv_zbc_instr)
+
+  function new(string name = "");
+    super.new(name);
+  endfunction : new
+
+  function void pre_randomize();
+    super.pre_randomize();
+  endfunction : pre_randomize
+
+  function bit[6:0] get_opcode();
+    case (instr_name) inside
+      CLMUL,
+      CLMULH,
+      CLMULR  : get_opcode = 7'b011_0011;
+      default : get_opcode = super.get_opcode();
+    endcase
+  endfunction : get_opcode
+
+  function bit [2:0] get_func3();
+    case (instr_name) inside
+      CLMUL   : get_func3 = 3'b001;
+      CLMULH  : get_func3 = 3'b011;
+      CLMULR  : get_func3 = 3'b010;
+      default : get_func3 = super.get_func3();
+    endcase
+  endfunction : get_func3
+
+  function bit [6:0] get_func7();
+    case (instr_name) inside
+      CLMUL   : get_func7 = 7'b000_0101;
+      CLMULH  : get_func7 = 7'b000_0101;
+      CLMULR  : get_func7 = 7'b000_0101;
+      default : get_func7 = super.get_func7();
+    endcase
+  endfunction : get_func7
+
+  virtual function string convert2bin(string prefix = "");
+    string binary = "";
+    if (instr_name inside {CLMUL, CLMULH, CLMULR}) begin
+      binary = $sformatf("%8h", {get_func7(), rs2, rs1, get_func3(), rd, get_opcode()});
+    end
+    else begin
+      binary = super.convert2bin(prefix);
+    end
+  endfunction : convert2bin
+
+  virtual function bit is_supported(riscv_instr_gen_config cfg);
+    return (cfg.enable_zbc_extension &&
+           (RV32ZBC inside { supported_isa } || RV64ZBC inside { supported_isa }) &&
+            instr_name inside {
+              CLMUL, CLMULH, CLMULR
+            });
+  endfunction : is_supported
+
+endclass : riscv_zbc_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
new file mode 100644
index 0000000..95004ed
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbs_instr extends riscv_instr;
+  `uvm_object_utils(riscv_zbs_instr)
+
+  function new(string name = "");
+    super.new(name);
+  endfunction : new
+
+  function void pre_randomize();
+    super.pre_randomize();
+  endfunction : pre_randomize
+
+  function bit is_rv64();
+    is_rv64 = (group == RV64B);
+  endfunction : is_rv64
+
+  virtual function void set_imm_len();
+    if (format inside {I_FORMAT}) begin
+      if (instr_name inside { BCLRI, BEXTI, BINVI, BSETI }) begin
+        imm_len = $clog2(XLEN);
+      end
+    end
+    imm_mask = imm_mask << imm_len;
+  endfunction : set_imm_len
+
+  function bit [6:0] get_opcode();
+    case (instr_name) inside
+      BCLR,  BEXT,  BINV,  BSET,
+      BCLRI, BEXTI, BINVI, BSETI :  begin
+        get_opcode = 7'b0010011;
+      end
+      default : get_opcode = super.get_opcode();
+    endcase
+  endfunction : get_opcode
+
+  function bit [2:0] get_func3();
+    case (instr_name) inside
+      BCLR    : get_func3 = 3'b001;
+      BCLRI   : get_func3 = 3'b001;
+      BEXT    : get_func3 = 3'b101;
+      BEXTI   : get_func3 = 3'b101;
+      BINV    : get_func3 = 3'b001;
+      BINVI   : get_func3 = 3'b001;
+      BSET    : get_func3 = 3'b001;
+      BSETI   : get_func3 = 3'b001;
+      default : get_func3 = super.get_func3();
+    endcase
+  endfunction : get_func3
+
+  function bit [6:0] get_func7();
+    case (instr_name) inside
+      BCLR    : get_func7 = 7'b0100100;
+      BCLRI   : get_func7 = 7'b0100100;
+      BEXT    : get_func7 = 7'b0100100;
+      BEXTI   : get_func7 = 7'b0100100;
+      BINV    : get_func7 = 7'b0110100;
+      BINVI   : get_func7 = 7'b0110100;
+      BSET    : get_func7 = 7'b0010100;
+      BSETI   : get_func7 = 7'b0010100;
+      default : get_func7 = super.get_func7();
+    endcase
+  endfunction : get_func7
+
+  virtual function string convert2bin(string prefix = "");
+    string binary = "";
+
+    case (format) inside
+      I_FORMAT : begin
+        case (instr_name) inside
+          BCLRI, BEXTI, BINVI, BSETI : begin
+            binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1,
+                                        get_func3(), rd, get_opcode()});
+          end
+        endcase
+      end
+      default : begin
+        if (binary == "") begin
+          return super.convert2bin(prefix);
+        end
+      end
+    endcase
+  endfunction : convert2bin
+
+  virtual function bit is_supported(riscv_instr_gen_config cfg);
+    return (cfg.enable_zbs_extension &&
+           (RV32ZBS inside { supported_isa } || RV64ZBS inside { supported_isa }) &&
+           instr_name inside {
+              BCLR, BEXT, BINV, BSET,
+              BCLRI, BEXTI, BINVI, BSETI
+            });
+  endfunction : is_supported
+
+endclass : riscv_zbs_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
index 984a1d4..4c568cc 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
@@ -15,62 +15,40 @@
  * limitations under the License.
  */
 
+// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+
 // LOGICAL instructions
-`DEFINE_B_INSTR(SEXT_B,  R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(SEXT_H,  R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(ANDN,    R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(ORN ,    R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(XNOR,    R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(GORC,    R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(GORCI,   I_FORMAT, LOGICAL, RV32B, UIMM)
-`DEFINE_B_INSTR(CMIX,   R4_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(CMOV,   R4_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACK,    R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACKU,   R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACKH,   R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(GORC,     R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(GORCI,    I_FORMAT, LOGICAL, RV32B, UIMM)
+`DEFINE_B_INSTR(CMIX,    R4_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(CMOV,    R4_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACK,     R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACKU,    R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACKH,    R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_N,  R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_B,  R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_H,  R_FORMAT, LOGICAL, RV32B)
 // SHIFT intructions
-`DEFINE_B_INSTR(SLO,     R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SRO,     R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(ROL,     R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(ROR,     R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBCLR,   R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBSET,   R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBINV,   R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBEXT,   R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(GREV,    R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(GREVI,   I_FORMAT, SHIFT, RV32B , UIMM)
-`DEFINE_B_INSTR(SLOI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SROI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(RORI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBCLRI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBSETI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBINVI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBEXTI ,   I_FORMAT, SHIFT, RV32B ,UIMM)
+`DEFINE_B_INSTR(SLO,    R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(SRO,    R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(SLOI,   I_FORMAT, SHIFT, RV32B, UIMM)
+`DEFINE_B_INSTR(SROI,   I_FORMAT, SHIFT, RV32B, UIMM)
+`DEFINE_B_INSTR(GREV,   R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(GREVI,  I_FORMAT, SHIFT, RV32B, UIMM)
 `DEFINE_B_INSTR(FSL,   R4_FORMAT, SHIFT, RV32B)
 `DEFINE_B_INSTR(FSR,   R4_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(FSRI,   I_FORMAT, SHIFT, RV32B ,UIMM)
+`DEFINE_B_INSTR(FSRI,   I_FORMAT, SHIFT, RV32B, UIMM)
 // ARITHMETIC intructions
-`DEFINE_B_INSTR(CLZ,    R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CTZ,    R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(PCNT,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_B,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_H,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_W,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_B,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_H,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_W,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMUL,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMULR,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMULH,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MIN,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MAX,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MINU,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MAXU,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(SHFL,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(UNSHFL,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BDEP,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BEXT,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BFP,   R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(SHFLI,   I_FORMAT, ARITHMETIC, RV32B, UIMM)
-`DEFINE_B_INSTR(UNSHFLI,   I_FORMAT, ARITHMETIC, RV32B, UIMM)
-
+`DEFINE_B_INSTR(CRC32_B,     R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32_H,     R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32_W,     R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_B,    R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_H,    R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_W,    R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(SHFL,        R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(UNSHFL,      R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(SHFLI,       I_FORMAT, ARITHMETIC, RV32B, UIMM)
+`DEFINE_B_INSTR(UNSHFLI,     I_FORMAT, ARITHMETIC, RV32B, UIMM)
+`DEFINE_B_INSTR(BCOMPRESS,   R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(BDECOMPRESS, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(BFP,         R_FORMAT, ARITHMETIC, RV32B)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
new file mode 100644
index 0000000..91edfd1
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBA_INSTR(SH1ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
+`DEFINE_ZBA_INSTR(SH2ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
+`DEFINE_ZBA_INSTR(SH3ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
new file mode 100644
index 0000000..afa88d8
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBB_INSTR(ANDN,   R_FORMAT, LOGICAL,    RV32ZBB);
+`DEFINE_ZBB_INSTR(CLZ,    I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(CPOP,   I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(CTZ,    I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MAX,    R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MAXU,   R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MIN,    R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MINU,   R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(ORC_B,  I_FORMAT, LOGICAL,    RV32ZBB);
+`DEFINE_ZBB_INSTR(ORN,    R_FORMAT, LOGICAL,    RV32ZBB);
+`DEFINE_ZBB_INSTR(REV8,   I_FORMAT, SHIFT,      RV32ZBB);
+`DEFINE_ZBB_INSTR(ROL,    R_FORMAT, SHIFT,      RV32ZBB);
+`DEFINE_ZBB_INSTR(ROR,    R_FORMAT, SHIFT,      RV32ZBB);
+`DEFINE_ZBB_INSTR(RORI,   I_FORMAT, SHIFT,      RV32ZBB, UIMM);
+`DEFINE_ZBB_INSTR(SEXT_B, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(SEXT_H, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(XNOR,   R_FORMAT, LOGICAL,    RV32ZBB);
+`DEFINE_ZBB_INSTR(ZEXT_H, R_FORMAT, ARITHMETIC, RV32ZBB);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
new file mode 100644
index 0000000..032e18a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBC_INSTR(CLMUL,  R_FORMAT, ARITHMETIC, RV32ZBC)
+`DEFINE_ZBC_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32ZBC)
+`DEFINE_ZBC_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32ZBC)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
new file mode 100644
index 0000000..9cbc0b2
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBS_INSTR(BCLR,  R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BCLRI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BEXT,  R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BEXTI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BINV,  R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BINVI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BSET,  R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BSETI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
index 9c681c4..7cafd68 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
@@ -15,54 +15,32 @@
  * limitations under the License.
  */
 
-// ARITHMETIC intructions
-`DEFINE_B_INSTR(BMATOR,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BMATXOR,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BMATFLIP,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CRC32_D,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CRC32C_D,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDIWU,   I_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDWU,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SUBWU,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDU_W,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SUBU_W,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLZW,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CTZW,    R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(PCNTW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULRW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULHW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SHFLW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(UNSHFLW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BDEPW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BEXTW,   R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BFPW,   R_FORMAT, ARITHMETIC, RV64B)
+// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
 
+// ARITHMETIC intructions
+`DEFINE_B_INSTR(BMATOR,       R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BMATXOR,      R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BMATFLIP,     R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(CRC32_D,      R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(CRC32C_D,     R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(SHFLW,        R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(UNSHFLW,      R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BCOMPRESSW,   R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BDECOMPRESSW, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BFPW,         R_FORMAT, ARITHMETIC, RV64B)
 // SHIFT intructions
-`DEFINE_B_INSTR(SLLIU_W,    I_FORMAT, SHIFT, RV64B, UIMM)
 `DEFINE_B_INSTR(SLOW,    R_FORMAT, SHIFT, RV64B)
 `DEFINE_B_INSTR(SROW,    R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(ROLW,    R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(RORW,    R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBCLRW,   R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBSETW,   R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBINVW,   R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBEXTW,   R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(GREVW,    R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SLOIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SROIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(RORIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBCLRIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBSETIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBINVIW ,   I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(GREVIW,   I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(SLOIW,   I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(SROIW,   I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(GREVW,   R_FORMAT, SHIFT, RV64B)
+`DEFINE_B_INSTR(GREVIW,  I_FORMAT, SHIFT, RV64B, UIMM)
 `DEFINE_B_INSTR(FSLW,   R4_FORMAT, SHIFT, RV64B)
 `DEFINE_B_INSTR(FSRW,   R4_FORMAT, SHIFT, RV64B)
 `DEFINE_B_INSTR(FSRIW,   I_FORMAT, SHIFT, RV64B, UIMM)
-
 // LOGICAL instructions
-`DEFINE_B_INSTR(GORCW,    R_FORMAT, LOGICAL, RV64B)
-`DEFINE_B_INSTR(GORCIW,   I_FORMAT, LOGICAL, RV64B, UIMM)
-`DEFINE_B_INSTR(PACKW,    R_FORMAT, LOGICAL, RV64B)
-`DEFINE_B_INSTR(PACKUW,   R_FORMAT, LOGICAL, RV64B)
-
+`DEFINE_B_INSTR(GORCW,   R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(GORCIW,  I_FORMAT, LOGICAL, RV64B, UIMM)
+`DEFINE_B_INSTR(PACKW,   R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(PACKUW,  R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(XPERM_W, R_FORMAT, LOGICAL, RV64B)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
new file mode 100644
index 0000000..e354430
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBA_INSTR(ADD_UW,    R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH1ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH2ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH3ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SLLI_UW,   I_FORMAT, SHIFT,      RV64ZBA, UIMM);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
new file mode 100644
index 0000000..e1c278c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBB_INSTR(CLZW,  I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(CPOPW, I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(CTZW,  I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(ROLW,  R_FORMAT, SHIFT,      RV64ZBB);
+`DEFINE_ZBB_INSTR(RORW,  R_FORMAT, SHIFT,      RV64ZBB);
+`DEFINE_ZBB_INSTR(RORIW, I_FORMAT, SHIFT,      RV64ZBB, UIMM);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
index 96cca5f..9822d67 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
@@ -452,6 +452,8 @@
         RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1;
         RVV                  : misa[MISA_EXT_V] = 1'b1;
         RV32X, RV64X         : misa[MISA_EXT_X] = 1'b1;
+        RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS,
+        RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS : ; // No Misa bit for Zb* extensions
         default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported",
                                    supported_isa[i].name()))
       endcase
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
index fc30b41..aee215c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
@@ -105,3 +105,22 @@
   class riscv_``instr_n``_instr extends riscv_b_instr;  \
     `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
 
+//Zba-extension instruction
+`define DEFINE_ZBA_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+  class riscv_``instr_n``_instr extends riscv_zba_instr; \
+    `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbb-extension instruction
+`define DEFINE_ZBB_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+  class riscv_``instr_n``_instr extends riscv_zbb_instr; \
+    `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbc-extension instruction
+`define DEFINE_ZBC_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+  class riscv_``instr_n``_instr extends riscv_zbc_instr; \
+    `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbs-extension instruction
+`define DEFINE_ZBS_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+  class riscv_``instr_n``_instr extends riscv_zbs_instr; \
+    `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
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 91ced68..60ff4b5 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
@@ -181,6 +181,38 @@
     }
   }
 
+  constraint zba_extension_c {
+    if (RV32ZBA inside {supported_isa}) {
+      if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+        !(opcode inside {7'b0110011, 7'b0111011, 7'b0011011});
+      }
+    }
+  }
+
+  constraint zbb_extension_c {
+    if (RV32ZBB inside {supported_isa}) {
+      if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+        !(opcode inside {7'b0110011, 7'b0010011, 7'b0111011, 7'b0011011});
+      }
+    }
+  }
+
+  constraint zbc_extension_c {
+    if (RV32ZBB inside {supported_isa}) {
+      if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+        !(opcode inside {7'b0110011});
+      }
+    }
+  }
+
+  constraint zbs_extension_c {
+    if (RV32ZBS inside {supported_isa}) {
+      if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+        !(opcode inside {7'b0110011, 7'b0010011});
+      }
+    }
+  }
+
   constraint illegal_compressed_op_c {
     if (exception == kIllegalCompressedOpcode) {
       c_op != 2'b01;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
index 33896ad..badc423 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
@@ -34,6 +34,10 @@
 
 `define SAMPLE_F(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_floating_point_instr)
 `define SAMPLE_B(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_b_instr)
+`define SAMPLE_ZBA(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zba_instr)
+`define SAMPLE_ZBB(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbb_instr)
+`define SAMPLE_ZBC(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbc_instr)
+`define SAMPLE_ZBS(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbs_instr)
 
 `define INSTR_CG_BEGIN(INSTR_NAME, INSTR_CLASS = riscv_instr) \
   covergroup ``INSTR_NAME``_cg with function sample(INSTR_CLASS instr);
@@ -377,6 +381,58 @@
     `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
     `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
 
+`define ZBA_I_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rd          : coverpoint instr.rd; \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBA_R_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rs2         : coverpoint instr.rs2; \
+    cp_rd          : coverpoint instr.rd;  \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBB_I_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rd          : coverpoint instr.rd; \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBB_R_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rs2         : coverpoint instr.rs2; \
+    cp_rd          : coverpoint instr.rd;  \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBC_I_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rd          : coverpoint instr.rd; \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBC_R_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rs2         : coverpoint instr.rs2; \
+    cp_rd          : coverpoint instr.rd;  \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBS_I_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rd          : coverpoint instr.rd; \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBS_R_INSTR_CG_BEGIN(INSTR_NAME) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_rs2         : coverpoint instr.rs2; \
+    cp_rd          : coverpoint instr.rd;  \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
 `define B_I_INSTR_CG_BEGIN(INSTR_NAME) \
   `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \
     cp_rs1         : coverpoint instr.rs1; \
@@ -857,43 +913,177 @@
   `FCLASS_INSTR_CG_BEGIN(fclass_d, D)
   `CG_END
 
-  // B extension
+  // B extension instructions ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+  `ZBA_R_INSTR_CG_BEGIN(sh1add)
+  `CG_END
+  `ZBA_R_INSTR_CG_BEGIN(sh2add)
+  `CG_END
+  `ZBA_R_INSTR_CG_BEGIN(sh3add)
+  `CG_END
+  `ZBA_R_INSTR_CG_BEGIN(sh1add_uw)
+  `CG_END
+  `ZBA_R_INSTR_CG_BEGIN(sh2add_uw)
+  `CG_END
+  `ZBA_R_INSTR_CG_BEGIN(sh3add_uw)
+  `CG_END
+
   // Count Leading/Trailing Zeros (clz, ctz)
-  `B_R_INSTR_NO_RS2_CG_BEGIN(clz)
+  `ZBB_I_INSTR_CG_BEGIN(clz)
     `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
   `CG_END
 
-  `B_R_INSTR_NO_RS2_CG_BEGIN(ctz)
+  `ZBB_I_INSTR_CG_BEGIN(ctz)
     `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
   `CG_END
 
-  `B_R_INSTR_NO_RS2_CG_BEGIN(clzw)
-    `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN/2-1)
+  `ZBB_I_INSTR_CG_BEGIN(clzw)
+    `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
   `CG_END
 
-  `B_R_INSTR_NO_RS2_CG_BEGIN(ctzw)
-    `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN/2-1)
+  `ZBB_I_INSTR_CG_BEGIN(ctzw)
+    `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
   `CG_END
 
-  // Count Bits Set (pcnt)
-  `B_R_INSTR_NO_RS2_CG_BEGIN(pcnt)
+  `ZBB_I_INSTR_CG_BEGIN(cpop)
     `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
   `CG_END
 
-  `B_R_INSTR_NO_RS2_CG_BEGIN(pcntw)
-    `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN/2-1)
+  `ZBB_I_INSTR_CG_BEGIN(cpopw)
+    `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
   `CG_END
 
   // Logic-with-negate (andn, orn, xnor)
-  `B_R_INSTR_CG_BEGIN(andn)
+  `ZBB_R_INSTR_CG_BEGIN(andn)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(orn)
+  `ZBB_R_INSTR_CG_BEGIN(orn)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(xnor)
+  `ZBB_R_INSTR_CG_BEGIN(xnor)
   `CG_END
 
+  // Or-combine
+  `ZBB_R_INSTR_CG_BEGIN(orc_b)
+    `CP_VALUE_RANGE(or_combine_mode, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  // Min/max instructions (min, max, minu, maxu)
+  `ZBB_R_INSTR_CG_BEGIN(min)
+    cp_rs1_gt_rs2  : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
+    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
+      bins equal = {1};
+    }
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(max)
+    cp_rs1_gt_rs2  : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
+    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
+      bins equal = {1};
+    }
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(minu)
+    cp_rs1_gt_rs2  : coverpoint (instr.rs1_value > instr.rs2_value);
+    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
+      bins equal = {1};
+    }
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(maxu)
+    cp_rs1_gt_rs2  : coverpoint (instr.rs1_value > instr.rs2_value);
+    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
+      bins equal = {1};
+    }
+  `CG_END
+
+  // Sign-extend instructions (sext.b, sext.h)
+  `ZBB_I_INSTR_CG_BEGIN(sext_b)
+  `CG_END
+
+  `ZBB_I_INSTR_CG_BEGIN(sext_h)
+  `CG_END
+
+  `ZBB_I_INSTR_CG_BEGIN(zext_h)
+  `CG_END
+
+  // Rotate (Left/Right) (rol, ror, rori)
+  `ZBB_R_INSTR_CG_BEGIN(ror)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(rol)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBB_I_INSTR_CG_BEGIN(rori)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(rorw)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(rolw)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
+  `CG_END
+
+  `ZBB_I_INSTR_CG_BEGIN(roriw)
+    `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1)
+  `CG_END
+
+  `ZBB_R_INSTR_CG_BEGIN(rev8)
+  `CG_END
+
+  // Multiplication
+  `ZBC_R_INSTR_CG_BEGIN(clmul)
+  `CG_END
+
+  `ZBC_R_INSTR_CG_BEGIN(clmulh)
+  `CG_END
+
+  `ZBC_R_INSTR_CG_BEGIN(clmulr)
+  `CG_END
+
+  `ZBA_I_INSTR_CG_BEGIN(slli_uw)
+    `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  `ZBA_R_INSTR_CG_BEGIN(add_uw)
+  `CG_END
+
+  `ZBS_R_INSTR_CG_BEGIN(bclr)
+    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_I_INSTR_CG_BEGIN(bclri)
+    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_R_INSTR_CG_BEGIN(bext)
+    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_I_INSTR_CG_BEGIN(bexti)
+    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_R_INSTR_CG_BEGIN(binv)
+    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_I_INSTR_CG_BEGIN(binvi)
+    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_R_INSTR_CG_BEGIN(bset)
+    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+  `CG_END
+
+  `ZBS_I_INSTR_CG_BEGIN(bseti)
+    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+  `CG_END
+
+  // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
   // Pack two words in one register (pack, packu, packh)
   `B_R_INSTR_CG_BEGIN(pack)
   `CG_END
@@ -910,75 +1100,6 @@
   `B_R_INSTR_CG_BEGIN(packuw)
   `CG_END
 
-  // Min/max instructions (min, max, minu, maxu)
-  `B_R_INSTR_CG_BEGIN(min)
-    cp_rs1_gt_rs2  : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
-    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
-      bins equal = {1};
-    }
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(max)
-    cp_rs1_gt_rs2  : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
-    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
-      bins equal = {1};
-    }
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(minu)
-    cp_rs1_gt_rs2  : coverpoint (instr.rs1_value > instr.rs2_value);
-    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
-      bins equal = {1};
-    }
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(maxu)
-    cp_rs1_gt_rs2  : coverpoint (instr.rs1_value > instr.rs2_value);
-    cp_rs1_eq_rs2  : coverpoint (instr.rs1_value == instr.rs2_value) {
-      bins equal = {1};
-    }
-  `CG_END
-
-  // Sign-extend instructions (sext.b, sext.h)
-  `B_R_INSTR_NO_RS2_CG_BEGIN(sext_b)
-  `CG_END
-
-  `B_R_INSTR_NO_RS2_CG_BEGIN(sext_h)
-  `CG_END
-
-  // Single-bit instructions (sbset, sbclr, sbinv, sbext)
-  `B_R_INSTR_CG_BEGIN(sbset)
-    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(sbclr)
-    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(sbinv)
-    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(sbext)
-    `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(sbseti)
-    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(sbclri)
-    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(sbinvi)
-    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(sbexti)
-    `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
-  `CG_END
-
   // Shift Ones (Left/Right) (slo, sloi, sro, sroi)
   `B_R_INSTR_CG_BEGIN(slo)
     `CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1)
@@ -1012,31 +1133,6 @@
     `CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN/2-1)
   `CG_END
 
-  // Rotate (Left/Right) (rol, ror, rori)
-  `B_R_INSTR_CG_BEGIN(ror)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(rol)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(rori)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(rorw)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(rolw)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(roriw)
-    `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1)
-  `CG_END
-
   // Generalized Reverse (grev, grevi, rev)
   `B_R_INSTR_CG_BEGIN(grev)
     `CP_VALUE_RANGE(reverse_mode, instr.rs2_value, 0, XLEN-1)
@@ -1135,34 +1231,16 @@
     `CP_VALUE_RANGE(offset, instr.rs2_value[20:16], 0, XLEN/2-1)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(bext)
+  `B_R_INSTR_CG_BEGIN(bcompress)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(bextw)
+  `B_R_INSTR_CG_BEGIN(bcompressw)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(bdep)
+  `B_R_INSTR_CG_BEGIN(bdecompress)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(bdepw)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmul)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmulh)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmulr)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmulw)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmulhw)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(clmulrw)
+  `B_R_INSTR_CG_BEGIN(bdecompressw)
   `CG_END
 
   `B_R_INSTR_NO_RS2_CG_BEGIN(crc32_b)
@@ -1230,25 +1308,6 @@
     `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN/2-1)
   `CG_END
 
-  `B_R_INSTR_CG_BEGIN(addwu)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(subwu)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(addiwu)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(addu_w)
-  `CG_END
-
-  `B_R_INSTR_CG_BEGIN(subu_w)
-  `CG_END
-
-  `B_I_INSTR_CG_BEGIN(slliu_w)
-    `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
-  `CG_END
-
   // CSR instructions
   `CSR_INSTR_CG_BEGIN(csrrw)
     cp_rs1 : coverpoint instr.rs1;
@@ -1971,103 +2030,120 @@
       fcvt_d_lu_cg = new();
     `CG_SELECTOR_END
 
+    `CG_SELECTOR_BEGIN(RV32ZBA)
+      sh1add_cg = new();
+      sh2add_cg = new();
+      sh3add_cg = new();
+    `CG_SELECTOR_END
+    `CG_SELECTOR_BEGIN(RV32ZBB)
+      andn_cg   = new();
+      clz_cg    = new();
+      cpop_cg   = new();
+      ctz_cg    = new();
+      max_cg    = new();
+      maxu_cg   = new();
+      min_cg    = new();
+      minu_cg   = new();
+      orc_b_cg  = new();
+      orn_cg    = new();
+      rev8_cg   = new();
+      rol_cg    = new();
+      ror_cg    = new();
+      rori_cg   = new();
+      sext_b_cg = new();
+      sext_h_cg = new();
+      xnor_cg   = new();
+      zext_h_cg = new();
+    `CG_SELECTOR_END
+    `CG_SELECTOR_BEGIN(RV32ZBC)
+      clmul_cg  = new();
+      clmulh_cg = new();
+      clmulr_cg = new();
+    `CG_SELECTOR_END
+    `CG_SELECTOR_BEGIN(RV32ZBS)
+      bclr_cg   = new();
+      bclri_cg  = new();
+      bext_cg   = new();
+      bexti_cg  = new();
+      binv_cg   = new();
+      binvi_cg  = new();
+      bset_cg   = new();
+      bseti_cg  = new();
+    `CG_SELECTOR_END
+
     `CG_SELECTOR_BEGIN(RV32B)
-      clz_cg      = new();
-      ctz_cg      = new();
-      pcnt_cg     = new();
-      andn_cg     = new();
-      orn_cg      = new();
-      xnor_cg     = new();
-      pack_cg     = new();
-      packh_cg    = new();
-      min_cg      = new();
-      max_cg      = new();
-      minu_cg     = new();
-      maxu_cg     = new();
-      sext_b_cg   = new();
-      sext_h_cg   = new();
-      sbset_cg    = new();
-      sbclr_cg    = new();
-      sbinv_cg    = new();
-      sbext_cg    = new();
-      sbseti_cg   = new();
-      sbclri_cg   = new();
-      sbinvi_cg   = new();
-      sbexti_cg   = new();
-      slo_cg      = new();
-      sro_cg      = new();
-      sloi_cg     = new();
-      sroi_cg     = new();
-      ror_cg      = new();
-      rol_cg      = new();
-      rori_cg     = new();
-      grev_cg     = new();
-      grevi_cg    = new();
-      shfli_cg    = new();
-      unshfli_cg  = new();
-      shfl_cg     = new();
-      unshfl_cg   = new();
-      gorc_cg     = new();
-      gorci_cg    = new();
-      bfp_cg      = new();
-      bext_cg     = new();
-      bdep_cg     = new();
-      clmul_cg    = new();
-      clmulh_cg   = new();
-      clmulr_cg   = new();
-      crc32_b_cg  = new();
-      crc32_h_cg  = new();
-      crc32_w_cg  = new();
-      crc32c_b_cg = new();
-      crc32c_h_cg = new();
-      crc32c_w_cg = new();
-      cmix_cg     = new();
-      cmov_cg     = new();
-      fsl_cg      = new();
-      fsr_cg      = new();
-      fsri_cg     = new();
+      pack_cg        = new();
+      packh_cg       = new();
+      slo_cg         = new();
+      sro_cg         = new();
+      sloi_cg        = new();
+      sroi_cg        = new();
+      grev_cg        = new();
+      grevi_cg       = new();
+      shfli_cg       = new();
+      unshfli_cg     = new();
+      shfl_cg        = new();
+      unshfl_cg      = new();
+      gorc_cg        = new();
+      gorci_cg       = new();
+      bfp_cg         = new();
+      bcompress_cg   = new();
+      bdecompress_cg = new();
+      crc32_b_cg     = new();
+      crc32_h_cg     = new();
+      crc32_w_cg     = new();
+      crc32c_b_cg    = new();
+      crc32c_h_cg    = new();
+      crc32c_w_cg    = new();
+      cmix_cg        = new();
+      cmov_cg        = new();
+      fsl_cg         = new();
+      fsr_cg         = new();
+      fsri_cg        = new();
+    `CG_SELECTOR_END
+
+    `CG_SELECTOR_BEGIN(RV64ZBA)
+        add_uw_cg          = new();
+        sh1add_uw_cg       = new();
+        sh2add_uw_cg       = new();
+        sh3add_uw_cg       = new();
+        slli_uw_cg         = new();
+    `CG_SELECTOR_END
+    `CG_SELECTOR_BEGIN(RV64ZBB)
+        clzw_cg           = new();
+        cpopw_cg          = new();
+        ctzw_cg           = new();
+        rolw_cg           = new();
+        rorw_cg           = new();
+        roriw_cg          = new();
     `CG_SELECTOR_END
 
     `CG_SELECTOR_BEGIN(RV64B)
-      clzw_cg     = new();
-      ctzw_cg     = new();
-      pcntw_cg    = new();
-      packw_cg    = new();
-      packuw_cg   = new();
-      slow_cg     = new();
-      srow_cg     = new();
-      sloiw_cg    = new();
-      sroiw_cg    = new();
-      rorw_cg     = new();
-      rolw_cg     = new();
-      roriw_cg    = new();
-      grevw_cg    = new();
-      greviw_cg   = new();
-      shflw_cg    = new();
-      unshflw_cg  = new();
-      gorcw_cg    = new();
-      gorciw_cg   = new();
-      bfpw_cg     = new();
-      bextw_cg    = new();
-      bdepw_cg    = new();
-      clmulw_cg   = new();
-      clmulhw_cg  = new();
-      clmulrw_cg  = new();
-      crc32_d_cg  = new();
-      crc32c_d_cg = new();
-      bmator_cg   = new();
-      bmatxor_cg  = new();
-      bmatflip_cg = new();
-      fslw_cg     = new();
-      fsrw_cg     = new();
-      fsriw_cg    = new();
-      addwu_cg    = new();
-      subwu_cg    = new();
-      addiwu_cg   = new();
-      addu_w_cg   = new();
-      subu_w_cg   = new();
-      slliu_w_cg  = new();
+      packw_cg        = new();
+      packuw_cg       = new();
+      slow_cg         = new();
+      srow_cg         = new();
+      sloiw_cg        = new();
+      sroiw_cg        = new();
+      grevw_cg        = new();
+      greviw_cg       = new();
+      shflw_cg        = new();
+      unshflw_cg      = new();
+      gorcw_cg        = new();
+      gorciw_cg       = new();
+      bfpw_cg         = new();
+      bcompressw_cg   = new();
+      bdecompressw_cg = new();
+      crc32_d_cg      = new();
+      crc32c_d_cg     = new();
+      bmator_cg       = new();
+      bmatxor_cg      = new();
+      bmatflip_cg     = new();
+      fslw_cg         = new();
+      fsrw_cg         = new();
+      fsriw_cg        = new();
     `CG_SELECTOR_END
+
     // Ignore the exception which cannot be covered when running with ISS
     if (iss_mode) begin
       int i;
@@ -2284,36 +2360,49 @@
       FLE_D      : `SAMPLE_F(fle_d_cg, instr)
       FCLASS_S   : `SAMPLE_F(fclass_s_cg, instr)
       FCLASS_D   : `SAMPLE_F(fclass_d_cg, instr)
+      // RV32ZBA
+      SH1ADD     : `SAMPLE_ZBA(sh1add_cg, instr)
+      SH2ADD     : `SAMPLE_ZBA(sh2add_cg, instr)
+      SH3ADD     : `SAMPLE_ZBA(sh3add_cg, instr)
+      // RV32ZBB
+      ANDN       : `SAMPLE_ZBB(andn_cg, instr)
+      CLZ        : `SAMPLE_ZBB(clz_cg, instr)
+      CPOP       : `SAMPLE_ZBB(cpop_cg, instr)
+      CTZ        : `SAMPLE_ZBB(ctz_cg, instr)
+      MAX        : `SAMPLE_ZBB(max_cg, instr)
+      MAXU       : `SAMPLE_ZBB(maxu_cg, instr)
+      MIN        : `SAMPLE_ZBB(min_cg, instr)
+      MINU       : `SAMPLE_ZBB(minu_cg, instr)
+      ORC_B      : `SAMPLE_ZBB(orc_b_cg, instr)
+      ORN        : `SAMPLE_ZBB(orn_cg, instr)
+      REV8       : `SAMPLE_ZBB(rev8_cg, instr)
+      ROL        : `SAMPLE_ZBB(rol_cg, instr)
+      ROR        : `SAMPLE_ZBB(ror_cg, instr)
+      RORI       : `SAMPLE_ZBB(rori_cg, instr)
+      SEXT_B     : `SAMPLE_ZBB(sext_b_cg, instr)
+      SEXT_H     : `SAMPLE_ZBB(sext_h_cg, instr)
+      XNOR       : `SAMPLE_ZBB(xnor_cg, instr)
+      ZEXT_H     : `SAMPLE_ZBB(zext_h_cg, instr)
+      // RV32ZBC
+      CLMUL      : `SAMPLE_ZBC(clmul_cg, instr)
+      CLMULH     : `SAMPLE_ZBC(clmulh_cg, instr)
+      CLMULR     : `SAMPLE_ZBC(clmulr_cg, instr)
+      // RV32ZBS
+      BCLR       : `SAMPLE_ZBS(bclr_cg, instr)
+      BCLRI      : `SAMPLE_ZBS(bclri_cg, instr)
+      BEXT       : `SAMPLE_ZBS(bext_cg, instr)
+      BEXTI      : `SAMPLE_ZBS(bexti_cg, instr)
+      BINV       : `SAMPLE_ZBS(binv_cg, instr)
+      BINVI      : `SAMPLE_ZBS(binvi_cg, instr)
+      BSET       : `SAMPLE_ZBS(bset_cg, instr)
+      BSETI      : `SAMPLE_ZBS(bseti_cg, instr)
       // RV32B
-      CLZ        : `SAMPLE_B(clz_cg, instr)
-      CTZ        : `SAMPLE_B(ctz_cg, instr)
-      PCNT       : `SAMPLE_B(pcnt_cg, instr)
-      ANDN       : `SAMPLE_B(andn_cg, instr)
-      ORN        : `SAMPLE_B(orn_cg, instr)
-      XNOR       : `SAMPLE_B(xnor_cg, instr)
       PACK       : `SAMPLE_B(pack_cg, instr)
       PACKH      : `SAMPLE_B(packh_cg, instr)
-      MIN        : `SAMPLE_B(min_cg, instr)
-      MAX        : `SAMPLE_B(max_cg, instr)
-      MINU       : `SAMPLE_B(minu_cg, instr)
-      MAXU       : `SAMPLE_B(maxu_cg, instr)
-      SEXT_B     : `SAMPLE_B(sext_b_cg, instr)
-      SEXT_H     : `SAMPLE_B(sext_h_cg, instr)
-      SBSET      : `SAMPLE_B(sbset_cg, instr)
-      SBCLR      : `SAMPLE_B(sbclr_cg, instr)
-      SBINV      : `SAMPLE_B(sbinv_cg, instr)
-      SBEXT      : `SAMPLE_B(sbext_cg, instr)
-      SBSETI     : `SAMPLE_B(sbseti_cg, instr)
-      SBCLRI     : `SAMPLE_B(sbclri_cg, instr)
-      SBINVI     : `SAMPLE_B(sbinvi_cg, instr)
-      SBEXTI     : `SAMPLE_B(sbexti_cg, instr)
       SLO        : `SAMPLE_B(slo_cg, instr)
       SRO        : `SAMPLE_B(sro_cg, instr)
       SLOI       : `SAMPLE_B(sloi_cg, instr)
       SROI       : `SAMPLE_B(sroi_cg, instr)
-      ROR        : `SAMPLE_B(ror_cg, instr)
-      ROL        : `SAMPLE_B(rol_cg, instr)
-      RORI       : `SAMPLE_B(rori_cg, instr)
       GREV       : `SAMPLE_B(grev_cg, instr)
       GREVI      : `SAMPLE_B(grevi_cg, instr)
       SHFLI      : `SAMPLE_B(shfli_cg, instr)
@@ -2323,11 +2412,8 @@
       GORC       : `SAMPLE_B(gorc_cg, instr)
       GORCI      : `SAMPLE_B(gorci_cg, instr)
       BFP        : `SAMPLE_B(bfp_cg, instr)
-      BEXT       : `SAMPLE_B(bext_cg, instr)
-      BDEP       : `SAMPLE_B(bdep_cg, instr)
-      CLMUL      : `SAMPLE_B(clmul_cg, instr)
-      CLMULH     : `SAMPLE_B(clmulh_cg, instr)
-      CLMULR     : `SAMPLE_B(clmulr_cg, instr)
+      BCOMPRESS  : `SAMPLE_B(bcompress_cg, instr)
+      BDECOMPRESS: `SAMPLE_B(bdecompress_cg, instr)
       CRC32_B    : `SAMPLE_B(crc32_b_cg, instr)
       CRC32_H    : `SAMPLE_B(crc32_h_cg, instr)
       CRC32_W    : `SAMPLE_B(crc32_w_cg, instr)
@@ -2339,45 +2425,43 @@
       FSL        : `SAMPLE_B(fsl_cg, instr)
       FSR        : `SAMPLE_B(fsr_cg, instr)
       FSRI       : `SAMPLE_B(fsri_cg, instr)
+      // RV64ZBA
+      ADD_UW        : `SAMPLE_ZBA(add_uw_cg, instr)
+      SH1ADD_UW     : `SAMPLE_ZBA(sh1add_uw_cg, instr)
+      SH2ADD_UW     : `SAMPLE_ZBA(sh2add_uw_cg, instr)
+      SH3ADD_UW     : `SAMPLE_ZBA(sh3add_uw_cg, instr)
+      SLLI_UW       : `SAMPLE_ZBA(slli_uw_cg, instr)
+      // RV64ZBB
+      CLZW         : `SAMPLE_ZBB(clzw_cg, instr)
+      CPOPW        : `SAMPLE_ZBB(cpopw_cg, instr)
+      CTZW         : `SAMPLE_ZBB(ctzw_cg, instr)
+      ROLW         : `SAMPLE_ZBB(rolw_cg, instr)
+      RORW         : `SAMPLE_ZBB(rorw_cg, instr)
+      RORIW        : `SAMPLE_ZBB(roriw_cg, instr)
       // RV64B
-      CLZW       : `SAMPLE_B(clzw_cg, instr)
-      CTZW       : `SAMPLE_B(ctzw_cg, instr)
-      PCNTW      : `SAMPLE_B(pcntw_cg, instr)
-      PACKW      : `SAMPLE_B(packw_cg, instr)
-      PACKUW     : `SAMPLE_B(packuw_cg, instr)
-      SLOW       : `SAMPLE_B(slow_cg, instr)
-      SROW       : `SAMPLE_B(srow_cg, instr)
-      SLOIW      : `SAMPLE_B(sloiw_cg, instr)
-      SROIW      : `SAMPLE_B(sroiw_cg, instr)
-      RORW       : `SAMPLE_B(rorw_cg, instr)
-      ROLW       : `SAMPLE_B(rolw_cg, instr)
-      RORIW      : `SAMPLE_B(roriw_cg, instr)
-      GREVW      : `SAMPLE_B(grevw_cg, instr)
-      GREVIW     : `SAMPLE_B(greviw_cg, instr)
-      SHFLW      : `SAMPLE_B(shflw_cg, instr)
-      UNSHFLW    : `SAMPLE_B(unshflw_cg, instr)
-      GORCW      : `SAMPLE_B(gorcw_cg, instr)
-      GORCIW     : `SAMPLE_B(gorciw_cg, instr)
-      BFPW       : `SAMPLE_B(bfpw_cg, instr)
-      BEXTW      : `SAMPLE_B(bextw_cg, instr)
-      BDEPW      : `SAMPLE_B(bdepw_cg, instr)
-      CLMULW     : `SAMPLE_B(clmulw_cg, instr)
-      CLMULHW    : `SAMPLE_B(clmulhw_cg, instr)
-      CLMULRW    : `SAMPLE_B(clmulrw_cg, instr)
-      CRC32_D    : `SAMPLE_B(crc32_d_cg, instr)
-      CRC32C_D   : `SAMPLE_B(crc32c_d_cg, instr)
-      BMATOR     : `SAMPLE_B(bmator_cg, instr)
-      BMATXOR    : `SAMPLE_B(bmatxor_cg, instr)
-      BMATFLIP   : `SAMPLE_B(bmatflip_cg, instr)
-      FSLW       : `SAMPLE_B(fslw_cg, instr)
-      FSRW       : `SAMPLE_B(fsrw_cg, instr)
-      FSRIW      : `SAMPLE_B(fsriw_cg, instr)
-      ADDWU      : `SAMPLE_B(addwu_cg, instr)
-      SUBWU      : `SAMPLE_B(subwu_cg, instr)
-      ADDIWU     : `SAMPLE_B(addiwu_cg, instr)
-      ADDU_W     : `SAMPLE_B(addu_w_cg, instr)
-      SUBU_W     : `SAMPLE_B(subu_w_cg, instr)
-      SLLIU_W    : `SAMPLE_B(slliu_w_cg, instr)
+      PACKW        : `SAMPLE_B(packw_cg, instr)
+      PACKUW       : `SAMPLE_B(packuw_cg, instr)
+      SLOW         : `SAMPLE_B(slow_cg, instr)
+      SROW         : `SAMPLE_B(srow_cg, instr)
+      SLOIW        : `SAMPLE_B(sloiw_cg, instr)
+      SROIW        : `SAMPLE_B(sroiw_cg, instr)
+      GREVW        : `SAMPLE_B(grevw_cg, instr)
+      GREVIW       : `SAMPLE_B(greviw_cg, instr)
+      SHFLW        : `SAMPLE_B(shflw_cg, instr)
+      UNSHFLW      : `SAMPLE_B(unshflw_cg, instr)
+      GORCW        : `SAMPLE_B(gorcw_cg, instr)
+      GORCIW       : `SAMPLE_B(gorciw_cg, instr)
+      BFPW         : `SAMPLE_B(bfpw_cg, instr)
+      BCOMPRESSW   : `SAMPLE_B(bcompressw_cg, instr)
+      BDECOMPRESSW : `SAMPLE_B(bdecompressw_cg, instr)
+      CRC32_D      : `SAMPLE_B(crc32_d_cg, instr)
+      CRC32C_D     : `SAMPLE_B(crc32c_d_cg, instr)
+      BMATOR       : `SAMPLE_B(bmator_cg, instr)
+      BMATXOR      : `SAMPLE_B(bmatxor_cg, instr)
+      BMATFLIP     : `SAMPLE_B(bmatflip_cg, instr)
+      FSLW         : `SAMPLE_B(fslw_cg, instr)
+      FSRW         : `SAMPLE_B(fsrw_cg, instr)
+      FSRIW        : `SAMPLE_B(fsriw_cg, instr)
       `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
       default: begin
         if (instr.group == RV32I) begin
@@ -2459,7 +2543,9 @@
         instr = riscv_instr::create_instr(instr_name);
         if ((instr.group inside {supported_isa}) &&
             (instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C,
-                                 RVV, RV64B, RV32B})) begin
+                                 RVV, RV64B, RV32B,
+                                 RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS,
+                                 RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS})) begin
           if (((instr_name inside {URET}) && !support_umode_trap) ||
               ((instr_name inside {SRET, SFENCE_VMA}) &&
               !(SUPERVISOR_MODE inside {supported_privileged_mode})) ||
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
index 4aeb819..9a2fdd1 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
@@ -252,6 +252,12 @@
   bit                    vector_instr_only;
   // Bit manipulation extension support
   bit                    enable_b_extension;
+
+  bit                    enable_zba_extension;
+  bit                    enable_zbb_extension;
+  bit                    enable_zbc_extension;
+  bit                    enable_zbs_extension;
+
   b_ext_group_t          enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT,
                                                      ZB_TMP};
 
@@ -516,6 +522,10 @@
     `uvm_field_int(vector_instr_only, UVM_DEFAULT)
     `uvm_field_int(enable_b_extension, UVM_DEFAULT)
     `uvm_field_array_enum(b_ext_group_t, enable_bitmanip_groups, UVM_DEFAULT)
+    `uvm_field_int(enable_zba_extension, UVM_DEFAULT)
+    `uvm_field_int(enable_zbb_extension, UVM_DEFAULT)
+    `uvm_field_int(enable_zbc_extension, UVM_DEFAULT)
+    `uvm_field_int(enable_zbs_extension, UVM_DEFAULT)
     `uvm_field_int(use_push_data_section, UVM_DEFAULT)
   `uvm_object_utils_end
 
@@ -575,6 +585,10 @@
     get_bool_arg_value("+enable_floating_point=", enable_floating_point);
     get_bool_arg_value("+enable_vector_extension=", enable_vector_extension);
     get_bool_arg_value("+enable_b_extension=", enable_b_extension);
+    get_bool_arg_value("+enable_zba_extension=", enable_zba_extension);
+    get_bool_arg_value("+enable_zbb_extension=", enable_zbb_extension);
+    get_bool_arg_value("+enable_zbc_extension=", enable_zbc_extension);
+    get_bool_arg_value("+enable_zbs_extension=", enable_zbs_extension);
     cmdline_enum_processor #(b_ext_group_t)::get_array_values("+enable_bitmanip_groups=",
                                                               enable_bitmanip_groups);
     if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
@@ -600,6 +614,27 @@
     if (!(RV32C inside {supported_isa})) begin
       disable_compressed_instr = 1;
     end
+
+    if (!((RV32ZBA inside {supported_isa}) ||
+          (RV64ZBA inside {supported_isa}))) begin
+      enable_zba_extension = 0;
+    end
+
+    if (!((RV32ZBB inside {supported_isa}) ||
+          (RV64ZBB inside {supported_isa}))) begin
+      enable_zbb_extension = 0;
+    end
+
+    if (!((RV32ZBC inside {supported_isa}) ||
+          (RV64ZBC inside {supported_isa}))) begin
+      enable_zbc_extension = 0;
+    end
+
+    if (!((RV32ZBS inside {supported_isa}) ||
+          (RV64ZBS inside {supported_isa}))) begin
+      enable_zbs_extension = 0;
+    end
+
     vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg");
     pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg");
     pmp_cfg.rand_mode(pmp_cfg.pmp_randomize);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
index 5376def..0524f66 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
@@ -99,7 +99,15 @@
     RV128C,
     RVV,
     RV32B,
+    RV32ZBA,
+    RV32ZBB,
+    RV32ZBC,
+    RV32ZBS,
     RV64B,
+    RV64ZBA,
+    RV64ZBB,
+    RV64ZBC,
+    RV64ZBS,
     RV32X,
     RV64X
   } riscv_instr_group_t;
@@ -154,108 +162,115 @@
     CSRRWI,
     CSRRSI,
     CSRRCI,
-    // RV32B instructions
+    // RV32ZBA instructions
+    SH1ADD,
+    SH2ADD,
+    SH3ADD,
+    // RV32ZBB instructions
     ANDN,
+    CLZ,
+    CPOP,
+    CTZ,
+    MAX,
+    MAXU,
+    MIN,
+    MINU,
+    ORC_B,
     ORN,
-    XNOR,
-    GORC,
-    SLO,
-    SRO,
+    REV8,
     ROL,
     ROR,
-    SBCLR,
-    SBSET,
-    SBINV,
-    SBEXT,
-    GREV,
-    SLOI,
-    SROI,
     RORI,
-    SBCLRI,
-    SBSETI,
-    SBINVI,
-    SBEXTI,
+    SEXT_B,
+    SEXT_H,
+    XNOR,
+    ZEXT_H,
+    // RV32ZBC instructions
+    CLMUL,
+    CLMULH,
+    CLMULR,
+    // RV32ZBS instructions
+    BCLR,
+    BCLRI,
+    BEXT,
+    BEXTI,
+    BINV,
+    BINVI,
+    BSET,
+    BSETI,
+    // RV32B instructions
+    // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+    GORC,
     GORCI,
-    GREVI,
     CMIX,
     CMOV,
+    PACK,
+    PACKU,
+    PACKH,
+    XPERM_N,
+    XPERM_B,
+    XPERM_H,
+    SLO,
+    SRO,
+    SLOI,
+    SROI,
+    GREV,
+    GREVI,
     FSL,
     FSR,
     FSRI,
-    CLZ,
-    CTZ,
-    PCNT,
-    SEXT_B,
-    SEXT_H,
     CRC32_B,
     CRC32_H,
     CRC32_W,
     CRC32C_B,
     CRC32C_H,
     CRC32C_W,
-    CLMUL,
-    CLMULR,
-    CLMULH,
-    MIN,
-    MAX,
-    MINU,
-    MAXU,
     SHFL,
     UNSHFL,
-    BDEP,
-    BEXT,
-    PACK,
-    PACKU,
-    BMATOR,
-    BMATXOR,
-    PACKH,
-    BFP,
     SHFLI,
     UNSHFLI,
+    BCOMPRESS,
+    BDECOMPRESS,
+    BFP,
+    // RV64ZBA instructions
+    ADD_UW,
+    SH1ADD_UW,
+    SH2ADD_UW,
+    SH3ADD_UW,
+    SLLI_UW,
+    // RV64ZBB instructions
+    CLZW,
+    CPOPW,
+    CTZW,
+    ROLW,
+    RORW,
+    RORIW,
     //RV64B instructions
-    ADDIWU,
-    SLLIU_W,
-    ADDWU,
-    SUBWU,
+    // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+    BMATOR,
+    BMATXOR,
     BMATFLIP,
     CRC32_D,
     CRC32C_D,
-    ADDU_W,
-    SUBU_W,
+    SHFLW,
+    UNSHFLW,
+    BCOMPRESSW,
+    BDECOMPRESSW,
+    BFPW,
     SLOW,
     SROW,
-    ROLW,
-    RORW,
-    SBCLRW,
-    SBSETW,
-    SBINVW,
-    SBEXTW,
-    GORCW,
-    GREVW,
     SLOIW,
     SROIW,
-    RORIW,
-    SBCLRIW,
-    SBSETIW,
-    SBINVIW,
-    GORCIW,
+    GREVW,
     GREVIW,
     FSLW,
     FSRW,
     FSRIW,
-    CLZW,
-    CTZW,
-    PCNTW,
-    CLMULW,
-    CLMULRW,
-    CLMULHW,
-    SHFLW,
-    UNSHFLW,
-    BDEPW,
-    BEXTW,
+    GORCW,
+    GORCIW,
     PACKW,
     PACKUW,
-    BFPW,
+    XPERM_W,
     // RV32M instructions
     MUL,
     MULH,
@@ -1151,6 +1166,7 @@
   } vxrm_t;
 
   typedef enum int {
+    ZBA,
     ZBB,
     ZBS,
     ZBP,
@@ -1178,7 +1194,7 @@
   parameter int DATA_WIDTH  = 32;
 
   // Parameters for output assembly program formatting
-  parameter int MAX_INSTR_STR_LEN = 11;
+  parameter int MAX_INSTR_STR_LEN = 13;
   parameter int LABEL_STR_LEN     = 18;
 
   // Parameter for program generation
@@ -1372,10 +1388,18 @@
   `include "riscv_vector_cfg.sv"
   `include "riscv_pmp_cfg.sv"
   typedef class riscv_instr;
+  typedef class riscv_zba_instr;
+  typedef class riscv_zbb_instr;
+  typedef class riscv_zbc_instr;
+  typedef class riscv_zbs_instr;
   typedef class riscv_b_instr;
   `include "riscv_instr_gen_config.sv"
   `include "isa/riscv_instr.sv"
   `include "isa/riscv_amo_instr.sv"
+  `include "isa/riscv_zba_instr.sv"
+  `include "isa/riscv_zbb_instr.sv"
+  `include "isa/riscv_zbc_instr.sv"
+  `include "isa/riscv_zbs_instr.sv"
   `include "isa/riscv_b_instr.sv"
   `include "isa/riscv_floating_point_instr.sv"
   `include "isa/riscv_vector_instr.sv"
@@ -1388,9 +1412,15 @@
   `include "isa/rv32f_instr.sv"
   `include "isa/rv32i_instr.sv"
   `include "isa/rv32b_instr.sv"
+  `include "isa/rv32zba_instr.sv"
+  `include "isa/rv32zbb_instr.sv"
+  `include "isa/rv32zbc_instr.sv"
+  `include "isa/rv32zbs_instr.sv"
   `include "isa/rv32m_instr.sv"
   `include "isa/rv64a_instr.sv"
   `include "isa/rv64b_instr.sv"
+  `include "isa/rv64zba_instr.sv"
+  `include "isa/rv64zbb_instr.sv"
   `include "isa/rv64c_instr.sv"
   `include "isa/rv64d_instr.sv"
   `include "isa/rv64f_instr.sv"
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
index 91693c0..4784657 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
@@ -89,7 +89,8 @@
     mstatus.set_field("SPP", 0);
     // Enable interrupt
     mstatus.set_field("MPIE", cfg.enable_interrupt);
-    mstatus.set_field("MIE", cfg.enable_interrupt);
+    // MIE is set when returning with mret, avoids trapping before returning
+    mstatus.set_field("MIE", 0);
     mstatus.set_field("SPIE", cfg.enable_interrupt);
     mstatus.set_field("SIE",  cfg.enable_interrupt);
     mstatus.set_field("UPIE", cfg.enable_interrupt);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
index 11048dc..e255cb8 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
@@ -34,24 +34,24 @@
   description: >
     Random test with all useful knobs
   gen_opts: >
-    +instr_cnt=10000
+    +instr_cnt=100000
     +num_of_sub_program=5
     +illegal_instr_ratio=5
     +hint_instr_ratio=5
     +stream_name_0=riscv_load_store_rand_instr_stream
-    +stream_freq_0=4
+    +stream_freq_0=20
     +stream_name_1=riscv_loop_instr
-    +stream_freq_1=4
+    +stream_freq_1=20
     +stream_name_2=riscv_hazard_instr_stream
-    +stream_freq_2=4
+    +stream_freq_2=20
     +stream_name_3=riscv_load_store_hazard_instr_stream
-    +stream_freq_3=4
+    +stream_freq_3=20
     +stream_name_4=riscv_mem_region_stress_test
-    +stream_freq_4=4
+    +stream_freq_4=20
     +stream_name_5=riscv_jal_instr
-    +stream_freq_5=4
+    +stream_freq_5=20
     +stream_name_6=riscv_int_numeric_corner_stream
-    +stream_freq_6=4
+    +stream_freq_6=20
     +dist_control_mode=1
     +dist_shift=10
     +dist_arithmetic=10