Update lowrisc_ibex to lowRISC/ibex@d14312c

Ibex top-level interface has changed, single hart_id replaces
cluster_id/core_id.

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

* Replace cluster_id/core_id with hart_id (lowRISC/ibex#29) (Greg
  Chadwick)
* CSR: Access checks on Debug CSRs (Rahul Behl)
* [RTL] - Add PMP module (Tom Roberts)
* Register file: update comments (Pirmin Vogel)
* Controller: change behavior of DRET instruction (Pirmin Vogel)
* Update interrupt mode, add debug mode WFI test (lowRISC/ibex#268)
  (udinator)
* Lint: Update Verilator waiver file (Philipp Wagner)
* Update google_riscv-dv to 102791d (lowRISC/ibex#266) (taoliug)
* Mention CREDITS.md in license header (Philipp Wagner)
* Replace author credits in files with CREDITS.md (Philipp Wagner)
* Add link to CREDITS.md from README.md (Philipp Wagner)
* Add CREDITS.md file (Philipp Wagner)
* Integrate risc-v stream generator handshake into Ibex sim flow
  (lowRISC/ibex#264) (udinator)
* Update google_riscv-dv to google/riscv-dv@faddfa4 (lowRISC/ibex#263)
  (udinator)
* Correct a typo in doc/verification.rst (Felix Yan)
* Update documentation how to run riscv-compliance (Philipp Wagner)
* CI: Run the compliance tests for all ISA variants (Philipp Wagner)
* Update google_riscv-dv to e81acc9 (lowRISC/ibex#257) (taoliug)
* Make mtvec writable, remove previous workaround (lowRISC/ibex#256)
  (taoliug)
* Test cleanup (lowRISC/ibex#255) (taoliug)
* Update google_riscv-dv to 73274f2 (lowRISC/ibex#254) (taoliug)
* Consolidate some debug generation options, and make the
  signature_addr handshake optional (lowRISC/ibex#253) (udinator)
* Add more debug tests (lowRISC/ibex#251) (udinator)
* src_files.yml: Add ibex_core_tracing.sv (Pirmin Vogel)
* ram_1p.sv: Fix rvalid_o generation (Pirmin Vogel)
* Remove unused signal data_reg_offset (Ivan Ribeiro)
* Add Azure Pipelines build badge to README.md (Philipp Wagner)
* CI: Use Azure Pipelines to run lint and some DV (Philipp Wagner)
* Update google_riscv-dv to google/riscv-dv@7cce16c (lowRISC/ibex#246)
  (udinator)
* ID stage: rework CSR-related pipeline flushes (Pirmin Vogel)
* Adapt Verilator lint waiver (Pirmin Vogel)
* Add basic debug test and modify sim flow (lowRISC/ibex#243)
  (udinator)
* [DV] Enable aligned load/store test (lowRISC/ibex#242) (taoliug)
* Update google_riscv-dv to 63fa0ca (lowRISC/ibex#241) (taoliug)
* Update google_riscv-dv to google/riscv-dv@07599f6 (lowRISC/ibex#240)
  (udinator)
* Fix the verbose logging issue, fix coverage/waveform options
  (lowRISC/ibex#235) (taoliug)
* Update google_riscv-dv to google/riscv-dv@e905e9f (lowRISC/ibex#234)
  (udinator)
* update ibex testbench (lowRISC/ibex#232) (udinator)
* update ibex simulation flow (lowRISC/ibex#233) (udinator)
* [rtl] Add support for instruction fetch errors (Tom Roberts)
diff --git a/hw/ip/rv_core_ibex/dv/tb/core_ibex_tb_top.sv b/hw/ip/rv_core_ibex/dv/tb/core_ibex_tb_top.sv
index f838482..545dd93 100644
--- a/hw/ip/rv_core_ibex/dv/tb/core_ibex_tb_top.sv
+++ b/hw/ip/rv_core_ibex/dv/tb/core_ibex_tb_top.sv
@@ -21,8 +21,7 @@
     .clk_i(clk),
     .rst_ni(rst_n),
     .test_en_i(1'b1),
-    .core_id_i('0),
-    .cluster_id_i('0),
+    .hart_id_i(32'b0),
     .boot_addr_i(`BOOT_ADDR), // align with spike boot address
     .irq_i('0),
     .irq_id_i('0),
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
index 3bba30f..c9660c9 100644
--- a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
@@ -22,9 +22,7 @@
 
   input  logic        test_en_i,     // enable all clock gates for testing
 
-  // Core ID, Cluster ID and boot address are considered more or less static
-  input  logic [ 3:0] core_id_i,
-  input  logic [ 5:0] cluster_id_i,
+  input  logic [31:0] hart_id_i,
   input  logic [31:0] boot_addr_i,
 
   // Instruction memory interface
@@ -105,8 +103,7 @@
 
      .test_en_i,
 
-     .core_id_i,
-     .cluster_id_i,
+     .hart_id_i,
      .boot_addr_i,
 
      .instr_req_o,
@@ -244,8 +241,7 @@
     .rst_ni           ( rst_ni                 ),
 
     .fetch_enable_i   ( fetch_enable_i         ),
-    .core_id_i        ( core_id_i              ),
-    .cluster_id_i     ( cluster_id_i           ),
+    .hart_id_i        ( hart_id_i              ),
 
     .valid_i          ( rvfi_valid             ),
     .pc_i             ( rvfi_pc_rdata          ),
diff --git a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
index da28906..bae971b 100644
--- a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
+++ b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
@@ -116,8 +116,7 @@
     .rst_ni               (ndmreset_n),
     .test_en_i            (1'b0),
     // static pinning
-    .core_id_i            (4'b0000),
-    .cluster_id_i         (6'b000000),
+    .hart_id_i            (32'b0),
     .boot_addr_i          (ADDR_SPACE_ROM),
     // TL-UL buses
     .tl_i_o               (tl_corei_h_h2d),
diff --git a/hw/top_earlgrey/rtl/top_earlgrey.sv b/hw/top_earlgrey/rtl/top_earlgrey.sv
index a64c23f..8128ba7 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey.sv
@@ -128,8 +128,7 @@
     .rst_ni               (ndmreset_n),
     .test_en_i            (1'b0),
     // static pinning
-    .core_id_i            (4'b0000),
-    .cluster_id_i         (6'b000000),
+    .hart_id_i            (32'b0),
     .boot_addr_i          (ADDR_SPACE_ROM),
     // TL-UL buses
     .tl_i_o               (tl_corei_h_h2d),
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_usb.sv b/hw/top_earlgrey/rtl/top_earlgrey_usb.sv
index a9b0b67..fd79548 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_usb.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_usb.sv
@@ -93,8 +93,7 @@
     .rst_ni               (ndmreset_n),
     .test_en_i            (1'b0),
     // static pinning
-    .core_id_i            (4'b0000),
-    .cluster_id_i         (6'b000000),
+    .hart_id_i            (32'b0),
     .boot_addr_i          (ADDR_SPACE_RAM_MAIN + 'h1000),  // no ROM for now, straight out of SRAM
     // TL-UL buses
     .tl_i_o               (tl_h_h2d[TlCorei]),
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index 14d5505..37908b0 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: ca97cfb58ee8fe94382372e6c3c766218a200a24
+    rev: d14312c3cc47a7d4b34943e4febb96312353b2cc
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/CREDITS.md b/hw/vendor/lowrisc_ibex/CREDITS.md
new file mode 100644
index 0000000..2d27294
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/CREDITS.md
@@ -0,0 +1,44 @@
+Credits
+=======
+
+Ibex has originally been developed by the PULP team at ETH Zürich and
+University of Bologna under the name Zero-riscy. In December 2018, Ibex has
+been contributed to lowRISC who is maintaining and advancing the design since
+then.
+
+Throughout the years, Ibex has seen contributions from many people and we at
+lowRISC are very thankful for all of them. This file lists the many people who
+contributed to what is called Ibex today. If you made a contribution to Ibex
+in the form of source code, bug reports, testing, marketing, or any other form,
+please feel free to open a pull request to get your name added to this file.
+
+- Alex Bradbury
+- Andreas Traber
+- Antonio Pullini
+- Eunchan Kim
+- Florian Zaruba
+- Francesco Conti
+- Germain Haugou
+- Igor Loi
+- Ioannis Karageorgos
+- Markus Wegmann
+- Ivan Ribeiro
+- Matthias Baer
+- Michael Gautschi
+- Michael Schaffner
+- Nils Graf
+- Noah Huesser
+- Pasquale Davide Schiavone
+- Philipp Wagner
+- Pirmin Vogel
+- Rahul Behl
+- Rhys Thomas
+- Renzo Andri
+- Robert Schilling
+- Scott Johnson
+- Stefan Wallentowitz
+- Sven Stucki
+- Tao Liu
+- Tobias Wölfel
+- Tom Roberts
+- Udi Jonnalagadda
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index cf5bcf1..c044ef2 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -1,3 +1,5 @@
+[![Build Status](https://dev.azure.com/lowrisc/ibex/_apis/build/status/lowRISC.ibex?branchName=master)](https://dev.azure.com/lowrisc/ibex/_build/latest?definitionId=3&branchName=master)
+
 # Ibex RISC-V Core
 
 Ibex is a small and efficient, 32-bit, in-order RISC-V core with a 2-stage pipeline that implements
@@ -57,6 +59,11 @@
 Unless otherwise noted, everything in this repository is covered by the Apache
 License, Version 2.0 (see LICENSE for full text).
 
+## Credits
+
+Many people have contributed to Ibex through the years. Please have a look at
+the [credits file](CREDITS.md) and the commit history for more information.
+
 ## References
 1. [Schiavone, Pasquale Davide, et al. "Slow and steady wins the race? A comparison of
  ultra-low-power RISC-V cores for Internet-of-Things applications."
diff --git a/hw/vendor/lowrisc_ibex/azure-pipelines.yml b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
new file mode 100644
index 0000000..e95f9f1
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
@@ -0,0 +1,135 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+# Azure Pipelines CI build configuration
+# Documentation at https://aka.ms/yaml
+
+variables:
+  VERILATOR_VERSION: 4.016
+  VERILATOR_PATH: /opt/buildcache/verilator/$(VERILATOR_VERSION)
+  RISCV_TOOLCHAIN_TAR_VERSION: 20190807-1
+
+trigger:
+  batch: true
+  branches:
+# Combine builds on master as long as another build is running
+    include:
+    - master
+
+# Note: All tests run as part of one job to avoid copying intermediate build
+# artifacts around (e.g. Verilator and toolchain builds). Once more builds/tests
+# are added, we need to re-evaluate this decision to parallelize jobs and
+# improve end-to-end CI times.
+
+jobs:
+- job: lint_dv
+  displayName: Run quality checks (Lint and DV)
+  pool:
+    vmImage: "ubuntu-16.04"
+  steps:
+  # Installing six is a workaround for pip dependency resolution: six is already
+  # installed as system package with a version below the required one.
+  # Explicitly installing six through pip gets us a supported version.
+  - bash: |
+      sudo apt-get install -y \
+          python3 \
+          python3-pip \
+          python3-setuptools \
+          srecord \
+          zlib1g-dev \
+          git \
+          make \
+          autoconf \
+          g++ \
+          flex \
+          bison \
+          curl \
+        && sudo pip3 install -U six fusesoc
+    displayName: Install dependencies
+
+  - bash: |
+      set -e
+      if [ ! -d $(VERILATOR_PATH) ]; then
+        echo "Building verilator (no cached build found)"
+        mkdir -p build/verilator
+        cd build/verilator
+        curl -Ls -o verilator.tgz https://www.veripool.org/ftp/verilator-$(VERILATOR_VERSION).tgz
+        tar -xf verilator.tgz
+        cd verilator-$(VERILATOR_VERSION)
+        ./configure --prefix=$(VERILATOR_PATH)
+        make -j$(nproc)
+        mkdir -p $VERILATOR_PATH
+        make install
+      else
+        echo "Re-using cached verilator build"
+      fi
+      echo "##vso[task.setvariable variable=PATH]$VERILATOR_PATH/bin:$PATH"
+    displayName: Build and install Verilator
+
+  - bash: |
+      export TOOLCHAIN_URL=https://github.com/lowRISC/lowrisc-toolchains/releases/download/${RISCV_TOOLCHAIN_TAR_VERSION}/lowrisc-toolchain-gcc-rv32imc-${RISCV_TOOLCHAIN_TAR_VERSION}.tar.xz
+      mkdir -p build/toolchain
+      curl -Ls -o build/toolchain/rv32-toolchain.tar.xz $TOOLCHAIN_URL
+      sudo mkdir -p /tools/riscv && sudo chmod 777 /tools/riscv
+      tar -C /tools/riscv -xf build/toolchain/rv32-toolchain.tar.xz --strip-components=1
+      echo "##vso[task.setvariable variable=PATH]/tools/riscv/bin:$PATH"
+    displayName: Get precompiled RISC-V toolchain
+
+  - bash: |
+      echo $PATH
+      python3 --version
+      echo -n "fusesoc "
+      fusesoc --version
+      verilator --version
+      riscv32-unknown-elf-gcc --version
+    displayName: Display environment
+
+  - bash: |
+      fusesoc --cores-root . run --target=lint lowrisc:ibex:ibex_core
+      if [ $? != 0 ]; then
+        echo -n "##vso[task.logissue type=error]"
+        echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint lowrisc:ibex:ibex_core' to check and fix all errors."
+        exit 1
+      fi
+    displayName: Lint Verilog source files with Verilator
+
+  - bash: |
+      cd build
+      git clone https://github.com/riscv/riscv-compliance.git
+    displayName: Get RISC-V Compliance test suite
+
+  - bash: |
+      # Build simulation model of Ibex
+      fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_riscv_compliance --RV32M=1 --RV32E=0
+      if [ $? != 0 ]; then
+        echo -n "##vso[task.logissue type=error]"
+        echo "Unable to build Verilator model of Ibex for compliance testing."
+        exit 1
+      fi
+
+      # Run compliance test suite
+      export TARGET_SIM=$PWD/build/lowrisc_ibex_ibex_riscv_compliance_0.1/sim-verilator/Vibex_riscv_compliance
+      export RISCV_PREFIX=riscv32-unknown-elf-
+      export RISCV_TARGET=ibex
+      export RISCV_DEVICE=rv32imc
+      fail=0
+      for isa in rv32i rv32im rv32imc; do
+        make -C build/riscv-compliance RISCV_ISA=$isa 2>&1 | tee run.log 
+        if [ ${PIPESTATUS[0]} != 0 ]; then
+          echo -n "##vso[task.logissue type=error]"
+          echo "The RISC-V compliance test suite failed for $isa"
+
+          # There's no easy way to get the test results in machine-readable
+          # form to properly exclude known-failing tests. Going with an
+          # approximate solution for now.
+          if [ $isa == rv32i ] && grep -q 'FAIL: 5/55' run.log; then
+            echo -n "##vso[task.logissue type=error]"
+            echo "Expected failure for rv32i, see lowrisc/ibex#100 more more information."
+          else
+            fail=1
+          fi
+        fi
+      done
+      exit $fail
+    displayName: "Run RISC-V Compliance test for Ibex RV32IMC"
diff --git a/hw/vendor/lowrisc_ibex/doc/cs_registers.rst b/hw/vendor/lowrisc_ibex/doc/cs_registers.rst
index 067607a..9f29a7c 100644
--- a/hw/vendor/lowrisc_ibex/doc/cs_registers.rst
+++ b/hw/vendor/lowrisc_ibex/doc/cs_registers.rst
@@ -34,6 +34,18 @@
 +---------+--------------------+--------+-----------------------------------------------+
 |  0x344  | ``mip``            | R      | Machine Interrupt Pending Register            |
 +---------+--------------------+--------+-----------------------------------------------+
+|  0x3A0  | ``pmpcfg0``        | WARL   | PMP Configuration Register                    |
++---------+--------------------+--------+-----------------------------------------------+
+|     .             .               .                    .                              |
++---------+--------------------+--------+-----------------------------------------------+
+|  0x3A3  | ``pmpcfg3``        | WARL   | PMP Configuration Register                    |
++---------+--------------------+--------+-----------------------------------------------+
+|  0x3B0  | ``pmpaddr0``       | WARL   | PMP Address Register                          |
++---------+--------------------+--------+-----------------------------------------------+
+|     .             .               .                    .                              |
++---------+--------------------+--------+-----------------------------------------------+
+|  0x3BF  | ``pmpaddr15``      | WARL   | PMP Address Register                          |
++---------+--------------------+--------+-----------------------------------------------+
 |  0x7B0  | ``dcsr``           | RW     | Debug Control and Status Register             |
 +---------+--------------------+--------+-----------------------------------------------+
 |  0x7B1  | ``dpc``            | RW     | Debug PC                                      |
@@ -212,6 +224,57 @@
 | 3     | **Machine Software Interrupt Pending (MSIP):** if set, ``irq_software_i`` is pending. |
 +-------+---------------------------------------------------------------------------------------+
 
+PMP Configuration Register (pmpcfgx)
+----------------------------------------
+
+CSR Address: ``0x3A0 - 0x3A3``
+
+Reset Value: ``0x0000_0000``
+
+``pmpcfgx`` are registers to configure PMP regions. Each register configures 4 PMP regions.
+
++---------------------------------------+
+|  31:24  |  23:16  |  15:8   |   7:0   |
++---------------------------------------+
+| pmp3cfg | pmp2cfg | pmp1cfg | pmp0cfg |
++---------------------------------------+
+
+The configuration fields for each region are as follows:
+
++-------+--------------------------+
+| Bit#  |  Definition              |
++-------+--------------------------+
+|    7  | Lock                     |
++-------+--------------------------+
+|  6:5  | Reserved (Read as zero)  |
++-------+--------------------------+
+|  4:3  | Mode                     |
++-------+--------------------------+
+|    2  | Execute permission       |
++-------+--------------------------+
+|    1  | Write permission         |
++-------+--------------------------+
+|    0  | Read permission          |
++-------+--------------------------+
+
+Details of these configuration bits can be found in the RISC-V Privileged Specification, version 1.11 (see Physical Memory Protection CSRs, Section 3.6.1).
+
+Note that the combination of Write permission = 1, Read permission = 0 is reserved, and will be treated by the core as Read/Write permission = 0.
+
+PMP Address Register (pmpaddrx)
+----------------------------------------
+
+CSR Address: ``0x3B0 - 0x3BF``
+
+Reset Value: ``0x0000_0000``
+
+``pmpaddrx`` are registers to set address matching for PMP regions.
+
++----------------+
+|     31:0       |
++----------------+
+| address[33:2]  |
++----------------+
 
 .. _csr-mhartid:
 
diff --git a/hw/vendor/lowrisc_ibex/doc/exception_interrupts.rst b/hw/vendor/lowrisc_ibex/doc/exception_interrupts.rst
index a0e1212..99be67e 100644
--- a/hw/vendor/lowrisc_ibex/doc/exception_interrupts.rst
+++ b/hw/vendor/lowrisc_ibex/doc/exception_interrupts.rst
@@ -70,6 +70,8 @@
 +----------------+---------------------------------------------------------------+
 | Exception Code | Description                                                   |
 +----------------+---------------------------------------------------------------+
+|              1 | Instruction access fault                                      |
++----------------+---------------------------------------------------------------+
 |              2 | Illegal instruction                                           |
 +----------------+---------------------------------------------------------------+
 |              3 | Breakpoint                                                    |
@@ -81,7 +83,7 @@
 |             11 | Environment call from M-mode (ECALL)                          |
 +----------------+---------------------------------------------------------------+
 
-The illegal instruction exception, LSU error exceptions and ECALL instruction exceptions cannot be disabled and are always active.
+The illegal instruction exception, instruction access fault, LSU error exceptions and ECALL instruction exceptions cannot be disabled and are always active.
 
 
 Handling
diff --git a/hw/vendor/lowrisc_ibex/doc/index.rst b/hw/vendor/lowrisc_ibex/doc/index.rst
index 2dfb674..7b241fd 100644
--- a/hw/vendor/lowrisc_ibex/doc/index.rst
+++ b/hw/vendor/lowrisc_ibex/doc/index.rst
@@ -14,6 +14,7 @@
    cs_registers
    performance_counters
    exception_interrupts
+   pmp
    debug
    tracer
    rvfi
diff --git a/hw/vendor/lowrisc_ibex/doc/instruction_fetch.rst b/hw/vendor/lowrisc_ibex/doc/instruction_fetch.rst
index f55bc4d..3c62b85 100644
--- a/hw/vendor/lowrisc_ibex/doc/instruction_fetch.rst
+++ b/hw/vendor/lowrisc_ibex/doc/instruction_fetch.rst
@@ -30,6 +30,8 @@
 +-------------------------+-----------+-----------------------------------------------+
 | ``instr_rdata_i[31:0]`` | input     | Data read from memory                         |
 +-------------------------+-----------+-----------------------------------------------+
+| ``instr_err_i``         | input     | Memory access error                           |
++-------------------------+-----------+-----------------------------------------------+
 
 
 Misaligned Accesses
diff --git a/hw/vendor/lowrisc_ibex/doc/integration.rst b/hw/vendor/lowrisc_ibex/doc/integration.rst
index fb39b59..b737da3 100644
--- a/hw/vendor/lowrisc_ibex/doc/integration.rst
+++ b/hw/vendor/lowrisc_ibex/doc/integration.rst
@@ -12,6 +12,9 @@
 .. code-block:: verilog
 
   ibex_core #(
+      .PMPEnable        (0),
+      .PMPGranularity   (0),
+      .PMPNumRegions    (4),
       .MHPMCounterNum   (0),
       .MHPMCounterWidth (40),
       .RV32E            (0),
@@ -25,8 +28,7 @@
       .test_en_i      (),
 
       // Configuration
-      .core_id_i      (),
-      .cluster_id_i   (),
+      .hart_id_i      (),
       .boot_addr_i    (),
 
       // Instruction memory interface
@@ -35,6 +37,7 @@
       .instr_rvalid_i (),
       .instr_addr_o   (),
       .instr_rdata_i  (),
+      .instr_err_i    (),
 
       // Data memory interface
       .data_req_o     (),
@@ -67,6 +70,12 @@
 +-----------------------+-------------+------------+-----------------------------------------------------------------+
 | Name                  | Type/Range  | Default    | Description                                                     |
 +=======================+=============+============+=================================================================+
+| ``PMPEnable``         | bit         | 0          | Enable PMP support                                              |
++-----------------------+-------------+------------+-----------------------------------------------------------------+
+| ``PMPGranularity``    | int (0..31) | 0          | Minimum granularity of PMP address matching                     |
++-----------------------+-------------+------------+-----------------------------------------------------------------+
+| ``PMPNumRegions``     | int (1..16) | 4          | Number implemented PMP regions (ignored if PMPEnable == 0)      |
++-----------------------+-------------+------------+-----------------------------------------------------------------+
 | ``MHPMCounterNum``    | int (0..8)  | 0          | Number of performance monitor event counters                    |
 +-----------------------+-------------+------------+-----------------------------------------------------------------+
 | ``MHPMCounterWidth``  | int (64..1) | 40         | Bit width of performance monitor event counters                 |
@@ -80,7 +89,6 @@
 | ``DmExceptionAddr``   | int         | 0x1A110808 | Address to jump to when an exception occurs while in debug mode |
 +-----------------------+-------------+------------+-----------------------------------------------------------------+
 
-
 Interfaces
 ----------
 
@@ -93,10 +101,8 @@
 +-------------------------+-------------------------+-----+----------------------------------------+
 | ``test_en_i``           | 1                       | in  | Test input, enables clock              |
 +-------------------------+-------------------------+-----+----------------------------------------+
-| ``core_id_i``           | 4                       | in  | Core ID, usually static, can be read   |
+| ``hart_id_i``           | 32                      | in  | Hart ID, usually static, can be read   |
 |                         |                         |     | from :ref:`csr-mhartid` CSR            |
-+-------------------------+-------------------------+-----+                                        +
-| ``cluster_id_i``        | 6                       | in  |                                        |
 +-------------------------+-------------------------+-----+----------------------------------------+
 | ``boot_addr_i``         | 32                      | in  | First program counter after reset      |
 |                         |                         |     | = ``boot_addr_i`` + 0x80,              |
diff --git a/hw/vendor/lowrisc_ibex/doc/introduction.rst b/hw/vendor/lowrisc_ibex/doc/introduction.rst
index 22ed619..3744422 100644
--- a/hw/vendor/lowrisc_ibex/doc/introduction.rst
+++ b/hw/vendor/lowrisc_ibex/doc/introduction.rst
@@ -82,6 +82,7 @@
 The control and status registers are explained in :ref:`cs-registers`.
 :ref:`performance-counters` gives an overview of the performance monitors and event counters available in Ibex.
 :ref:`exceptions-interrupts` deals with the infrastructure for handling exceptions and interrupts,
+:ref:`pmp` gives a brief overview of PMP support.
 :ref:`debug-support` gives a brief overview on the debug infrastructure.
 :ref:`tracer` gives a brief overview of the tracer module.
 For information regarding formal verification support, check out :ref:`rvfi`.
diff --git a/hw/vendor/lowrisc_ibex/doc/pmp.rst b/hw/vendor/lowrisc_ibex/doc/pmp.rst
new file mode 100644
index 0000000..eaa69b4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/doc/pmp.rst
@@ -0,0 +1,33 @@
+.. _pmp:
+
+Physical Memory Protection (PMP)
+================================
+
+The Physical Memory Protection (PMP) unit implements region-based memory access checking in-accordance with the RISC-V Privileged Specification, version 1.11.
+The following configuration parameters are available to control PMP checking:
+
++----------------+---------------+-------------------------------------------------+
+| Parameter      | Default value | Description                                     |
++================+===============+=================================================+
+| PMPEnable      | 0             | PMP support enabled                             |
++----------------+---------------+-------------------------------------------------+
+| PMPNumRegions  | 4             | Number of implemented regions (1 - 16)          |
++----------------+---------------+-------------------------------------------------+
+| PMPGranularity | 0             | Minimum match granularity 2^G\+2 bytes (0 - 31) |
++----------------+---------------+-------------------------------------------------+
+
+When PMPEnable is zero, the PMP module is not instantiated and all PMP registers read as zero (regardless of the value of PMPNumRegions)
+
+PMP Integration
+---------------
+
+Addresses from the instruction fetch unit and load-store unit are passed to the PMP module for checking, and the output of the PMP check is used to gate the external request.
+To maintain consistency with external errors, the instruction fetch unit and load-store unit progress with their request as if it was granted externally.
+The PMP error is registered and consumed by the core when the data would have been consumed.
+
+PMP Granularity
+---------------
+
+The PMP granularity parameter is used to reduce the size of the address matching comparators by increasing the minimum region size.
+When the granularity is greater than zero, NA4 mode is not available and will be treated as OFF mode.
+
diff --git a/hw/vendor/lowrisc_ibex/doc/verification.rst b/hw/vendor/lowrisc_ibex/doc/verification.rst
index 62d74d2..66cd79b 100644
--- a/hw/vendor/lowrisc_ibex/doc/verification.rst
+++ b/hw/vendor/lowrisc_ibex/doc/verification.rst
@@ -64,7 +64,7 @@
    # Verbose logging
    make ... VERBOSE=1
 
-   # Run multipe tests in parallel through LSF
+   # Run multiple tests in parallel through LSF
    make ... LSF_CMD="bsub -Is"
 
    # Get command reference of the simulation script
diff --git a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/README.md b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/README.md
index 99b89e6..b958e43 100644
--- a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/README.md
+++ b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/README.md
@@ -28,14 +28,16 @@
    pip3 install --user -U fusesoc
    ```
 
-   We recommend installing Verilator from source as versions from Linux distributions are often outdated.
-   See https://www.veripool.org/projects/verilator/wiki/Installing for installation instructions.
+   We recommend installing Verilator from source as versions from Linux
+   distributions are often outdated. See
+   https://www.veripool.org/projects/verilator/wiki/Installing for installation
+   instructions.
 
 1. Build a simulation of Ibex
 
    ```sh
    cd $IBEX_REPO_BASE
-   fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_riscv_compliance --RV32M=0 --RV32E=0
+   fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_riscv_compliance --RV32M=1 --RV32E=0
    ```
 
    You can use the two compile-time options `--RV32M` and `--RV32E` to
@@ -45,31 +47,33 @@
 
 2. Get the RISC-V Compliance test suite
 
-   The compliance test suite currently needs workarounds for Ibex.
-   Get a modified version of it.
+   The upstream RISC-V compliance test suite supports Ibex out of the box.
 
    ```
-   git clone https://github.com/imphil/riscv-compliance.git
+   git clone https://github.com/riscv/riscv-compliance.git
    cd riscv-compliance
-   git checkout ibex
    ```
 
 3. Run the test suite
    ```sh
    cd $RISCV_COMPLIANCE_REPO_BASE
-   export RISCV_TARGET=ibex
-   export RISCV_ISA=rv32i
+   # adjust to match your compiler name
    export RISCV_PREFIX=riscv32-unknown-elf-
+   # give the path to the simulation binary compiled in step 1
    export TARGET_SIM=path/to/your/Vibex_riscv_compliance
-   make clean
-   make
+
+   export RISCV_DEVICE=rv32imc
+   export RISCV_TARGET=ibex
+
+   # Note: rv32imc does not include the I and M extension tests
+   make RISCV_ISA=rv32i && make RISCV_ISA=rv32im && make RISCV_ISA=rv32imc
    ```
 
 Compliance test suite system
 ----------------------------
 
-This directory contains a system designed especially to run the compliance test suite.
-The system consists of
+This directory contains a system designed especially to run the compliance test
+suite. The system consists of
 
 - an Ibex core,
 - a bus,
diff --git a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv
index d8e88a2..58d1ec8 100644
--- a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv
+++ b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv
@@ -110,8 +110,7 @@
 
       .test_en_i             ('b0),
 
-      .core_id_i             (4'b0),
-      .cluster_id_i          (6'b0),
+      .hart_id_i             (32'b0),
       // First instruction executed is at 0x0 + 0x80
       .boot_addr_i           (32'h00000000),
 
@@ -120,6 +119,7 @@
       .instr_rvalid_i        (host_rvalid[CoreI]),
       .instr_addr_o          (host_addr[CoreI]),
       .instr_rdata_i         (host_rdata[CoreI]),
+      .instr_err_i           (host_err[CoreI]),
 
       .data_req_o            (host_req[CoreD]),
       .data_gnt_i            (host_gnt[CoreD]),
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/Makefile b/hw/vendor/lowrisc_ibex/dv/uvm/Makefile
index d02788a..b113a3c 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/Makefile
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/Makefile
@@ -2,35 +2,41 @@
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
 
-DV_DIR     := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-GEN_DIR    := $(realpath ${DV_DIR}/../../vendor/google_riscv-dv)
-TOOLCHAIN  := ${RISCV_TOOLCHAIN}
-OUT        := "${DV_DIR}/out"
+DV_DIR              := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+GEN_DIR             := $(realpath ${DV_DIR}/../../vendor/google_riscv-dv)
+TOOLCHAIN           := ${RISCV_TOOLCHAIN}
+OUT                 := "${DV_DIR}/out"
 # Run time options for the instruction generator
-GEN_OPTS   :=
+GEN_OPTS            :=
 # Run time options for ibex RTL simulation
-SIM_OPTS   :=
+SIM_OPTS            :=
 # Enable waveform dumping
-WAVES      := 1
+WAVES               := 1
 # Enable coverage dump
-COV        := 0
+COV                 := 0
 # RTL simulator
-SIMULATOR  := "vcs"
+SIMULATOR           := "vcs"
 # ISS (spike, ovpsim)
-ISS        := "spike"
+ISS                 := "spike"
 # ISA
-ISA        := "rv32imc"
+ISA                 := "rv32imc"
 # Test name (default: full regression)
-TEST       := "all"
+TEST                := "all"
 # Seed for instruction generator and RTL simulation
-SEED       := -1
+SEED                := -1
 # Verbose logging
-VERBOSE    := 0
+VERBOSE             :=
 # Number of iterations for each test, assign a non-zero value to override the
 # iteration count in the test list
-ITERATIONS := 0
+ITERATIONS          := 0
 # LSF CMD
-LSF_CMD    :=
+LSF_CMD             :=
+# Generator timeout limit in seconds
+TIMEOUT             := 1800
+# Privileged CSR YAML description file
+CSR_FILE            := ${DV_DIR}/riscv_dv_extension/csr_description.yaml
+# Pass/fail signature address at the end of test
+SIGNATURE_ADDR      := 8ffffffc
 
 SHELL=/bin/bash
 
@@ -44,25 +50,36 @@
 	rm -rf ${OUT}
 
 # Common options for all targets
-COMMON_OPTS=--seed=${SEED} \
-            --test=${TEST} \
-            --verbose=${VERBOSE} \
-            --testlist=${DV_DIR}/riscv_dv_extension/testlist.yaml \
-            --iterations=${ITERATIONS}
+COMMON_OPTS:=--seed=${SEED} \
+             --test=${TEST} \
+             --testlist=${DV_DIR}/riscv_dv_extension/testlist.yaml \
+             --iterations=${ITERATIONS}
+
+ifeq ($(VERBOSE), 1)
+	COMMON_OPTS+=--verbose
+endif
+
+# Options used for privileged CSR test generation
+CSR_OPTS=--csr_yaml=${CSR_FILE} \
+         --isa=${ISA} \
+         --end_signature_addr=0x${SIGNATURE_ADDR}
 
 # Generate random instructions
 .SILENT gen:
 	mkdir -p ${OUT}
 	cd ${GEN_DIR}; \
 	python3 ./run.py \
-     --o=${OUT}/instr_gen ${GEN_OPTS} \
+     --output=${OUT}/instr_gen ${GEN_OPTS} \
      --steps=gen \
+     --gen_timeout=${TIMEOUT} \
      --lsf_cmd="${LSF_CMD}" \
      ${COMMON_OPTS} \
+     ${CSR_OPTS} \
      --cmp_opts="+define+RISCV_CORE_SETTING=${DV_DIR}/riscv_dv_extension/ibex_core_setting.sv \
        +define+RISCV_DV_EXT_FILE_LIST=${DV_DIR}/riscv_dv_extension/flist \
        +incdir+${DV_DIR}/riscv_dv_extension/ " \
-     --sim_opts="+uvm_set_type_override=riscv_asm_program_gen,ibex_asm_program_gen";
+     --sim_opts="+uvm_set_type_override=riscv_asm_program_gen,ibex_asm_program_gen \
+                 +signature_addr=${SIGNATURE_ADDR}";
 
 # Compile the generated assmebly programs to ELF/BIN
 gcc_compile:
@@ -71,6 +88,7 @@
      --o=${OUT}/instr_gen ${GEN_OPTS} \
      --steps=gcc_compile \
      ${COMMON_OPTS} \
+     --gcc_opts=-mno-strict-align \
      --isa=${ISA} \
      --mabi=ilp32
 
@@ -103,8 +121,9 @@
      --steps=sim \
      ${COMMON_OPTS} \
      --simulator=${SIMULATOR} \
-     --en_cov=${COV} \
-     --en_wave=${WAVES} \
+     --en_cov ${COV} \
+     --en_wave ${WAVES} \
+     --sim_opts="+signature_addr=0x${SIGNATURE_ADDR}" \
      ${SIM_OPTS}
 
 # Compare the regression result between ISS and RTL sim
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/common/irq_agent/irq_master_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/common/irq_agent/irq_master_driver.sv
index 64e58b3..23ad25a 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/common/irq_agent/irq_master_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/common/irq_agent/irq_master_driver.sv
@@ -52,7 +52,10 @@
     vif.irq_external <= trans.irq_external;
     vif.irq_fast     <= trans.irq_fast;
     vif.irq_nm       <= trans.irq_nm;
-    @(posedge vif.clock);
+    // We hold the interrupt high for two cycles as Ibex is level sensitive,
+    // so this guarantees that Ibex will respond appropriately to the
+    // interrupt
+    repeat (2) @(posedge vif.clock);
     drive_reset_value();
   endtask : drive_seq_item
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/compare b/hw/vendor/lowrisc_ibex/dv/uvm/compare
deleted file mode 100755
index ddcfb95..0000000
--- a/hw/vendor/lowrisc_ibex/dv/uvm/compare
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-
-RUN_DIR="$1"
-report_file="$1/regr.log"
-rm -rf "$report_file"
-script_path="../../vendor/google_riscv-dv"
-
-compare_log () {
-  spike_log="$1"
-  ibex_log="$2"
-  # -----------------------------------------------------------------------------
-  # Convert spike log to standard instruction trace csv
-  # -----------------------------------------------------------------------------
-  # Remove all the init spike boot instructions
-  # 0xffffffff80000080 is the first user instruction
-  sed -i '/0xffffffff80000080/,$!d' "$spike_log"
-  # Remove all instructions after ecall (end of program excecution)
-  sed -i '/ecall/q' "$spike_log"
-  # Convert the spike log to riscv_instr_trace.proto format
-  spike_csv=$(echo "$spike_log" | sed 's/\.log/.csv/g')
-  python $script_path/scripts/spike_log_to_trace_csv.py \
-         --log $spike_log --csv $spike_csv >> $report_file
-
-  # -----------------------------------------------------------------------------
-  # Convert ibex log to standard instruction trace csv
-  # -----------------------------------------------------------------------------
-  # Remove all instructions after ecall (end of program excecution)
-  sed -i '/ecall/q' "$ibex_log"
-  # Convert the spike log to riscv_instr_trace.proto format
-  ibex_csv=$(echo "$ibex_log" | sed 's/\.log/.csv/g')
-  python ./riscv_dv_extension/ibex_log_to_trace_csv.py \
-         --log $ibex_log --csv $ibex_csv >> $report_file
-
-  # -----------------------------------------------------------------------------
-  # Compare the trace log
-  # -----------------------------------------------------------------------------
-  python $script_path/scripts/instr_trace_compare.py $spike_csv $ibex_csv \
-         "spike" "ibex" >> $report_file
-}
-
-echo "compare simulation result under $RUN_DIR"
-while read asm_test; do
-  SRC=$(echo "$asm_test" | sed 's/^.*\///g' | sed 's/\.S>*$//g')
-  echo "Test: $asm_test" >> $report_file
-  compare_log $RUN_DIR/instr_gen/spike_sim/$SRC.S.o.log \
-              $RUN_DIR/rtl_sim/$SRC/trace_core_00_0.log
-done <"$RUN_DIR/asm_test_list"
-
-passed_cnt="$(grep -c PASS $report_file)"
-failed_cnt="$(grep -c FAIL $report_file)"
-echo "$passed_cnt tests PASSED, $failed_cnt tests FAILED" >> $report_file
-
-cat $report_file
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_dut_probe_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_dut_probe_if.sv
index d285b7f..48fa34c 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_dut_probe_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_dut_probe_if.sv
@@ -6,6 +6,10 @@
 interface core_ibex_dut_probe_if(input logic clk);
   logic illegal_instr;
   logic ecall;
+  logic wfi;
+  logic ebreak;
+  logic dret;
+  logic mret;
   logic fetch_enable;
   logic debug_req;
 endinterface
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env.sv b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env.sv
index f2b04f1..58af297 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env.sv
@@ -25,7 +25,7 @@
                           create("data_if_slave_agent", this);
     instr_if_slave_agent = ibex_mem_intf_slave_agent::type_id::
                            create("instr_if_slave_agent", this);
-    if (cfg.enable_irq_seq) begin
+    if (cfg.enable_irq_stress_seq || cfg.enable_irq_single_seq) begin
       irq_agent = irq_master_agent::type_id::create("irq_agent", this);
     end
     // Create virtual sequencer
@@ -36,7 +36,7 @@
     super.connect_phase(phase);
     vseqr.data_if_seqr = data_if_slave_agent.sequencer;
     vseqr.instr_if_seqr = instr_if_slave_agent.sequencer;
-    if (cfg.enable_irq_seq) begin
+    if (cfg.enable_irq_stress_seq || cfg.enable_irq_single_seq) begin
       vseqr.irq_seqr = irq_agent.sequencer;
     end
   endfunction : connect_phase
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env_cfg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env_cfg.sv
index 8c352d8..388bc24 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env_cfg.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_env_cfg.sv
@@ -4,18 +4,33 @@
 
 class core_ibex_env_cfg extends uvm_object;
 
-  bit enable_irq_seq;
-  bit enable_debug_seq;
+  bit       enable_irq_stress_seq;
+  bit       enable_irq_single_seq;
+  bit       enable_debug_stress_seq;
+  bit       enable_debug_single_seq;
+  bit[31:0] max_interval;
+  bit       require_signature_addr;
+  bit[31:0] signature_addr;
 
   `uvm_object_utils_begin(core_ibex_env_cfg)
-    `uvm_field_int(enable_irq_seq,   UVM_DEFAULT)
-    `uvm_field_int(enable_debug_seq, UVM_DEFAULT)
+    `uvm_field_int(enable_irq_stress_seq,   UVM_DEFAULT)
+    `uvm_field_int(enable_irq_single_seq,   UVM_DEFAULT)
+    `uvm_field_int(enable_debug_single_seq, UVM_DEFAULT)
+    `uvm_field_int(enable_debug_stress_seq, UVM_DEFAULT)
+    `uvm_field_int(max_interval, UVM_DEFAULT)
+    `uvm_field_int(require_signature_addr, UVM_DEFAULT)
+    `uvm_field_int(signature_addr, UVM_DEFAULT)
   `uvm_object_utils_end
 
   function new(string name = "");
     super.new(name);
-    void'($value$plusargs("enable_irq_seq=%0d", enable_irq_seq));
-    void'($value$plusargs("enable_debug_seq=%0d", enable_debug_seq));
+    void'($value$plusargs("enable_irq_stress_seq=%0d", enable_irq_stress_seq));
+    void'($value$plusargs("enable_irq_single_seq=%0d", enable_irq_single_seq));
+    void'($value$plusargs("enable_debug_stress_seq=%0d", enable_debug_stress_seq));
+    void'($value$plusargs("enable_debug_single_seq=%0d", enable_debug_single_seq));
+    void'($value$plusargs("max_interval=%0d", max_interval));
+    void'($value$plusargs("require_signature_addr=%0d", require_signature_addr));
+    void'($value$plusargs("signature_addr=%0h", signature_addr));
   endfunction
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_vseqr.sv b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_vseqr.sv
index 068b20a..f3af18e 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_vseqr.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/env/core_ibex_vseqr.sv
@@ -7,9 +7,9 @@
 // ---------------------------------------------
 class core_ibex_vseqr extends uvm_sequencer;
 
-  ibex_mem_intf_slave_sequencer data_if_seqr;
-  ibex_mem_intf_slave_sequencer instr_if_seqr;
-  irq_master_sequencer          irq_seqr;
+  ibex_mem_intf_slave_sequencer                   data_if_seqr;
+  ibex_mem_intf_slave_sequencer                   instr_if_seqr;
+  irq_master_sequencer                            irq_seqr;
 
   `uvm_component_utils(core_ibex_vseqr)
   `uvm_component_new
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/ibex_dv.f b/hw/vendor/lowrisc_ibex/dv/uvm/ibex_dv.f
index 4f260a8..2ee06d2 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/ibex_dv.f
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/ibex_dv.f
@@ -31,6 +31,7 @@
 ${PRJ_DIR}/ibex/rtl/ibex_core_tracing.sv
 
 // Core DV files
+${PRJ_DIR}/ibex/vendor/google_riscv-dv/src/riscv_signature_pkg.sv
 +incdir+${PRJ_DIR}/ibex/dv/uvm/env
 +incdir+${PRJ_DIR}/ibex/dv/uvm/tests
 +incdir+${PRJ_DIR}/ibex/dv/uvm/common/ibex_mem_intf_agent
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/csr_description.yaml b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/csr_description.yaml
new file mode 100644
index 0000000..9e7b0bc
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/csr_description.yaml
@@ -0,0 +1,280 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+#
+#
+# Base CSR template that should be followed when describing all processor supported CSRs to enable correct generation of directed test sequences
+#- csr: CSR_NAME
+#  description: >
+#    BRIEF_DESCRIPTION
+#  address: 0x###
+#  privilege_mode: MODE (D/M/S/H/U)
+#  rv32:
+#    - MSB_FIELD_NAME:
+#      - description: >
+#          BRIEF_DESCRIPTION
+#      - type: TYPE (WPRI/WLRL/WARL)
+#      - reset_val: RESET_VAL
+#      - msb: MSB_POS
+#      - lsb: LSB_POS
+#    - ...
+#    - ...
+#    - LSB_FIELD_NAME:
+#      - description: ...
+#      - type: ...
+#      - ...
+#  rv64:
+#    - MSB_FIELD_NAME:
+#      - description: >
+#          BRIEF_DESCRIPTION
+#      - type: TYPE (WPRI/WLRL/WARL)
+#      - reset_val: RESET_VAL
+#      - msb: MSB_POS
+#      - lsb: LSB_POS
+#    - ...
+#    - ...
+#    - LSB_FIELD_NAME:
+#      - description: ...
+#      - type: ...
+#      - ...
+
+
+# Ibex MISA CSR
+- csr: misa
+  description: >
+    Machine ISA Register
+  address: 0x301
+  privilege_mode: M
+  rv32:
+    - field_name: MXL
+      description: >
+        Encodes native base ISA width
+      type: R
+      reset_val: 1
+      msb: 31
+      lsb: 30
+    - field_name: Extensions
+      description: >
+          Encodes all supported ISA extensions
+      type: R
+      reset_val: 0x1104
+      msb: 25
+      lsb: 0
+
+# TODO(udij) - clarify expected write behavior
+# MHARTID
+#- csr: mhartid
+#  description: >
+#    Contains integer ID of hardware thread running code
+#  address: 0xF14
+#  privilege_mode: M
+#  rv32:
+#    - field_name: cluster_id
+#      description: >
+#        ID of the cluster
+#      type: R
+#      reset_val: 0
+#      msb: 10
+#      lsb: 5
+#    - field_name: core_id
+#      description: >
+#        ID of the core within cluster
+#      type: R
+#      reset_val: 0
+#      msb: 3
+#      lsb: 0
+
+# MSTATUS
+- csr: mstatus
+  descriptipn: >
+    Controls hart's current operating state
+  address: 0x300
+  privilege_mode: M
+  rv32:
+    - field_name: mpp
+      description: >
+        Previous privilege mode
+      type: R
+      reset_val: 0x3
+      msb: 12
+      lsb: 11
+    - field_name: mpie
+      description: >
+        Previous value of interrupt-enable bit
+      type: WARL
+      reset_val: 0
+      msb: 7
+      lsb: 7
+    - field_name: mie
+      description: >
+        M-mode interrupt enable
+      type: WARL
+      reset_val: 0
+      msb: 3
+      lsb: 3
+
+# MIP
+- csr: mip
+  description: >
+    Contains pending interrupt information
+  address: 0x344
+  privilege_mode: M
+  rv32:
+    - field_name: fast
+      description: >
+        platform-specific interrupts
+      type: R
+      reset_val: 0
+      msb: 30
+      lsb: 16
+    - field_name: meip
+      description: >
+        M-mode external interrupts
+      type: R
+      reset_val: 0
+      msb: 11
+      lsb: 11
+    - field_name: mtip
+      description: >
+        M-mode timer interrupts
+      type: R
+      reset_val: 0
+      msb: 7
+      lsb: 7
+    - field_name: msip
+      description: >
+        M-mode software interrupts
+      type: R
+      reset_val: 0
+      msb: 3
+      lsb: 3
+
+# MIE
+- csr: mie
+  description: >
+    Contains interrupt information
+  address: 0x304
+  privilege_mode: M
+  rv32:
+    - field_name: fast
+      description: >
+        platform-specific interrupts
+      type: WARL
+      reset_val: 0
+      msb: 30
+      lsb: 16
+    - field_name: meip
+      description: >
+        M-mode external interrupts
+      type: WARL
+      reset_val: 0
+      msb: 11
+      lsb: 11
+    - field_name: mtip
+      description: >
+        M-mode timer interrupts
+      type: WARL
+      reset_val: 0
+      msb: 7
+      lsb: 7
+    - field_name: msip
+      description: >
+        M-mode software interrupts
+      type: WARL
+      reset_val: 0
+      msb: 3
+      lsb: 3
+
+# MSCRATCH
+- csr: mscratch
+  description: >
+    M-mode scratch register
+  address: 0x340
+  privilege_mode: M
+  rv32:
+    - field_name: mscratch
+      description: >
+        scratch register
+      type: WARL
+      reset_val: 0
+      msb: 31
+      lsb: 0
+
+# MEPC
+- csr: mepc
+  description: >
+    Stores the address of the instruction that was interrupted or caused exception
+  address: 0x341
+  privilege_mode: M
+  rv32:
+    - field_name: mepc
+      description: >
+        M-mode exception PC register
+      type: WARL
+      reset_val: 0
+      msb: 31
+      lsb: 1
+
+# MCAUSE
+- csr: mcause
+  description: >
+    Indicates trap cause
+  address: 0x342
+  privilege_mode: M
+  rv32:
+    - field_name: Interrupt
+      description: >
+        Indicates if trap caused by interrupt
+      type: WARL
+      reset_val: 0
+      msb: 31
+      lsb: 31
+    - field_name: Exception Code
+      type: WLRL
+      reset_val: 0
+      msb: 4
+      lsb: 0
+
+# MTVAL
+- csr: mtval
+  description: >
+    Machine Trap Value register
+  address: 0x343
+  privilege_mode: M
+  rv32:
+    - field_name: mtval
+      description: >
+        Address of faulting instruction
+      type: WARL
+      reset_val: 0
+      msb: 31
+      lsb: 0
+
+# MTVEC
+- csr: mtvec
+  description: >
+    Machine trap vector base address
+  address: 0x305
+  privilege_mode: M
+  rv32:
+    - field_name: base
+      description: >
+        trap vector base address (256 byte aligned)
+      type: WARL
+      reset_val: 0x800000
+      msb: 31
+      lsb: 8
+    - field_name: base_zero_end
+      description: >
+        bottom six bits of base always set to zero
+      type: R
+      reset_val: 0
+      msb: 7
+      lsb: 2
+    - field_name: mode
+      description: >
+        trap handling mode
+      type: R
+      reset_val: 0x1
+      msb: 1
+      lsb: 0
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv
index a3c9da7..1abe405 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv
@@ -21,35 +21,19 @@
     // with ibex.
     cfg.check_misa_init_val = 1'b0;
     cfg.check_xstatus = 1'b0;
-    // The ibex core load the program from 0x80
-    // Some address is reserved for hardware interrupt handling, need to decide if we need to copy
-    // the init program from crt0.S later.
     instr_stream.push_back(".macro init");
     instr_stream.push_back(".endm");
     instr_stream.push_back(".section .text.init");
     instr_stream.push_back(".globl _start");
     instr_stream.push_back(".option norvc");
-    // 0x0 - 0x4F is reserved for trap/interrupt handling
-    repeat (20) begin
-      instr_stream.push_back("j mtvec_handler");
-    end
-    // 0x50 debug mode entry
+    // 0x0 debug mode entry
     instr_stream.push_back("j debug_rom");
-    // 0x54 debug mode exception handler
+    // 0x4 debug mode exception handler
     instr_stream.push_back("j debug_exception");
     // Align the start section to 0x80
     instr_stream.push_back(".align 7");
-    instr_stream.push_back("_start: j _reset_entry");
-    // ibex reserves 0x84-0x8C for trap handling, redirect everything mtvec_handler
-    // 0x84 illegal instruction
-    instr_stream.push_back("j mtvec_handler");
-    // 0x88 ECALL instruction handler
-    instr_stream.push_back("j mtvec_handler");
-    // 0x8C LSU error
-    instr_stream.push_back("j mtvec_handler");
     instr_stream.push_back(".option rvc");
-    // Starting point of the reset entry
-    instr_stream.push_back("_reset_entry:");
+    instr_stream.push_back("_start:");
   endfunction
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_core_setting.sv b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_core_setting.sv
index 38b8412..4f4c598 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_core_setting.sv
@@ -34,6 +34,9 @@
 // ISA supported by the processor
 riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C};
 
+// Interrupt mode support
+mtvec_mode_t supported_interrupt_mode[$] = {VECTORED};
+
 // Debug mode support
 bit support_debug_mode = 1;
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_log_to_trace_csv.py b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_log_to_trace_csv.py
index ac6ced0..5377300 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_log_to_trace_csv.py
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/ibex_log_to_trace_csv.py
@@ -27,6 +27,8 @@
         trace_csv = RiscvInstructiontTraceCsv(csv_fd)
         trace_csv.start_new_trace()
         for line in f:
+            if re.search("ecall", line):
+              break
             # Extract instruction infromation
             m = re.search(r"^\s*(?P<time>\d+)\s+(?P<cycle>\d+) " \
                           "(?P<pc>[0-9a-f]+) (?P<bin>[0-9a-f]+) (?P<instr>.*)" \
@@ -45,6 +47,49 @@
     print("Processed instruction count : %d" % instr_cnt)
 
 
+def check_ibex_uvm_log(uvm_log, core_name, test_name, report, write=True):
+  """Process Ibex UVM simulation log.
+
+  This function will be used when a test disables the normal post_compare step.
+  Process the UVM simulation log produced by the test to check for correctness
+
+  Args:
+    uvm_log: the uvm simulation log
+    core_name: the name of the core
+    test_name: name of the test being checked
+    report: the output report file
+    write: enables writing to the log file
+
+  Returns:
+    A boolean indicating whether the test passed or failed based on the signature
+  """
+  pass_cnt = 0
+  fail_cnt = 0
+  with open(uvm_log, "r") as log:
+    for line in log:
+      if 'RISC-V UVM TEST PASSED' in line:
+        pass_cnt += 1
+        break
+      elif 'RISC-V UVM TEST FAILED' in line:
+        fail_cnt += 1
+        break
+
+  if write:
+    if report:
+      fd = open(report, "a+")
+    else:
+      fd = sys.stdout
+    fd.write("%s uvm log : %s\n" % (core_name, uvm_log))
+    if pass_cnt == 1:
+      fd.write("%s : PASSED\n" % test_name)
+    elif fail_cnt == 1:
+      fd.write("%s : FAILED\n" % test_name)
+    if report:
+      fd.close()
+
+  return pass_cnt == 1
+
+
 def main():
   instr_trace = []
   # Parse input arguments
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist
deleted file mode 100644
index e8423a4..0000000
--- a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-//====================================================================
-// Test name                    : iterations :       options
-//--------------------------------------------------------------------
-riscv_arithmetic_basic_test     :      20    :
-riscv_machine_mode_rand_test    :      20    :
-riscv_privileged_mode_rand_test :      0     :
-riscv_rand_instr_test           :      20    :
-riscv_rand_jump_test            :      20    :
-riscv_mmu_stress_test           :      20    :
-riscv_page_table_exception_test :      0     :
-riscv_no_fence_test             :      10    :
-riscv_sfence_exception_test     :      0     :
-riscv_illegal_instr_test        :      10    :
-riscv_hint_instr_test           :      10    :
-riscv_ebreak_test               :      20    :
-riscv_wfi_test                  :      5     : +enable_interrupt=1
-//--------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist.yaml b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist.yaml
index 80f1e35..7d9c2a1 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/riscv_dv_extension/testlist.yaml
@@ -1,16 +1,6 @@
-# Copyright Google LLC
-#
-# 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.
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
 
 - test: riscv_arithmetic_basic_test
   description: >
@@ -40,7 +30,7 @@
 - test: riscv_rand_instr_test
   description: >
     Random instruction stress test
-  iterations: 20
+  iterations: 10
   gen_test: riscv_instr_base_test
   gen_opts: >
     +instr_cnt=10000
@@ -68,7 +58,7 @@
   description: >
     Test with different patterns of load/store instructions, stress test MMU
     operations.
-  iterations: 20
+  iterations: 10
   gen_test: riscv_instr_base_test
   gen_opts: >
     +instr_cnt=10000
@@ -85,7 +75,7 @@
     instruction and handle corresponding exception properly. An exception
     handling routine is designed to resume execution after illegal
     instruction exception.
-  iterations: 20
+  iterations: 10
   gen_test: riscv_rand_instr_test
   gen_opts: >
     +enable_illegal_instruction=1
@@ -112,43 +102,126 @@
     +no_ebreak=0
   rtl_test: core_ibex_base_test
 
-- test: riscv_ebreak_debug_mode_test
+- test: riscv_debug_basic_test
   description: >
-    Ebreak instruction test with debug mode enabled.
-  iterations: 10
-  gen_test: riscv_rand_instr_test
+    Randomly assert debug_req_i, random instruction sequence in debug_rom section
+  iterations: 5
+  gen_test: riscv_instr_base_test
   gen_opts: >
+    +require_signature_addr=1
+    +gen_debug_section=1
+    +no_ebreak=1
+    +no_branch_jump=1
     +instr_cnt=6000
-    +no_ebreak=0
-  rtl_test: core_ibex_base_test
+    +no_csr_instr=1
+    +no_fence=1
+    +num_of_sub_program=0
+  rtl_test: core_ibex_debug_intr_test
   sim_opts: >
-    +enable_debug_seq=1
-  compare_opts: >
-    +compare_final_value_only=1
+    +require_signature_addr=1
+    +max_interval=1000
+    +enable_debug_stress_seq=1
+  compare_opts:
+    compare_final_value_only: 1
+    verbose: 1
 
-- test: riscv_fast_interrupt_test
+- test: riscv_debug_stress_test
   description: >
-    WFI(wait for interrupt) instruction test. If WFI is supported, processor
-    should halt execution upon decoding WFI instruction and resume execution
-    by interrupt. Otherwise WFI should be executed as NOP instruction.
-    Interrupt handling routine is skipped to allow instruction strace comparison
-    with ISS which is not interrupted during execution.
-  iterations: 2
+    Randomly assert debug_req_i more often, debug_rom is empty, with only a dret instruction
   gen_test: riscv_rand_instr_test
   gen_opts: >
-    +skip_trap_handling=1
-    +no_wfi=0
-  rtl_test: core_ibex_base_test
+    +require_signature_addr=1
+    +no_ebreak=1
+    +instr_cnt=6000
+    +no_csr_instr=1
+    +no_fence=1
+  rtl_test: core_ibex_debug_intr_test
+  iterations: 5
   sim_opts: >
-    +enable_irq_seq=1
+    +max_interval=250
+    +enable_debug_stress_seq=1
+    +require_signature_addr=1
+  compare_opts:
+    compare_final_value_only: 1
+    verbose: 1
 
-- test: riscv_full_interrupt_test
+- test: riscv_debug_branch_jump_test
+  description: >
+    Randomly assert debug_req_i, insert branch instructions and subprograms into debug_rom to make core
+    jump around within the debug_rom
+  iterations: 5
+  gen_test: riscv_rand_instr_test
+  gen_opts: >
+    +require_signature_addr=1
+    +gen_debug_section=1
+    +no_ebreak=1
+    +instr_cnt=6000
+    +no_csr_instr=1
+    +no_fence=1
+    +num_of_sub_program=5
+    +num_debug_sub_program=5
+  rtl_test: core_ibex_debug_intr_test
+  sim_opts: >
+    +require_signature_addr=1
+    +enable_debug_stress_seq=1
+  compare_opts:
+    compare_final_value_only: 1
+    verbose: 1
+
+- test: riscv_debug_wfi_test
+  description: >
+    Assert debug_req while core is in WFI sleep state, should jump to debug mode
+  iterations: 5
+  gen_test: riscv_rand_instr_test
+  gen_opts: >
+    +require_signature_addr=1
+    +gen_debug_section=1
+    +no_ebreak=1
+    +instr_cnt=3000
+    +no_csr_instr=1
+    +no_fence=1
+    +no_wfi=0
+  rtl_test: core_ibex_debug_wfi_test
+  sim_opts: >
+    +require_signature_addr=1
+    +enable_debug_single_seq=1
+  compare_opts:
+    compare_final_value_only: 1
+    verbose: 1
+
+- test: riscv_interrupt_test
   description: >
     Random instruction test with complete interrupt handling
   iterations: 0
   gen_test: riscv_rand_instr_test
-  rtl_test: core_ibex_base_test
+  gen_opts: >
+    +require_signature_addr=1
+  rtl_test: core_ibex_debug_intr_test
   sim_opts: >
-    +enable_irq_seq=1
-  compare_opts: >
-    +compare_final_value_only=1
+    +require_signature_addr=1
+    +enable_irq_stress_seq=1
+  compare_opts:
+    compare_final_value_only: 1
+
+- test: riscv_csr_test
+  description: >
+    Test all CSR instructions on all implemented CSR registers
+  iterations: 5
+  no_iss: 1
+  rtl_test: core_ibex_csr_test
+  no_post_compare: 1
+
+- test: riscv_unaligned_load_store_test
+  description: >
+    Unaligned load/store test, ibex should handle it correctly without raising any exception
+  iterations: 5
+  gen_test: riscv_instr_base_test
+  gen_opts: >
+    +instr_cnt=10000
+    +num_of_sub_program=5
+    +directed_instr_0=riscv_load_store_rand_instr_stream,20
+    +directed_instr_1=riscv_load_store_hazard_instr_stream,20
+    +directed_instr_2=riscv_cache_line_stress_instr_stream,20
+    +directed_instr_3=riscv_multi_page_load_store_instr_stream,20
+    +enable_unaligned_load_store=1
+  rtl_test: core_ibex_base_test
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/sim b/hw/vendor/lowrisc_ibex/dv/uvm/sim
deleted file mode 100755
index 6d6eee8..0000000
--- a/hw/vendor/lowrisc_ibex/dv/uvm/sim
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env bash
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-
-# Script to run the assembly tests generated by the riscv-dv instruction generator.
-
-# Test directory
-RUN_DIR="./"
-
-# Assembly test file name
-TEST=""
-
-# Seed
-RAND_SEED=1
-SEED=""
-
-# Wavform dump options
-WAVES=0
-WAVES_OPTS=""
-
-# Coveragedump options
-COV=0
-COV_OPTS=""
-
-# Process command line options
-while [[ $# -gt 0 ]]
-do
-key="$1"
-case $key in
-    -dir)
-    RUN_DIR="$2"
-    shift
-    ;;
-    -test)
-    TEST="$2"
-    shift
-    ;;
-    -waves)
-    WAVES="$2"
-    shift
-    ;;
-    -cov)
-    COV="$2"
-    shift
-    ;;
-    -seed)
-    SEED="$2"
-    RAND_SEED=0
-    shift
-    ;;
-    *)
-    echo "unknown option $1"
-    exit 1
-    ;;
-esac
-shift
-done
-
-
-# If the test is specified through "-test" option, run a single test rather
-# than all tests under RUN_DIR.
-if [[ $TEST == "" ]]; then
-  find "$RUN_DIR" -name "*.S" > "$RUN_DIR/asm_test_list"
-else
-  echo "$TEST" > "$RUN_DIR/asm_test_list"
-fi
-
-OUT="$RUN_DIR/rtl_sim"
-CWD=`pwd`
-
-# Run each test
-while read asm_test; do
-  OPTS=""
-  SRC=$(echo "$asm_test" | sed 's/^.*\///g' | sed 's/\.S>*$//g')
-  BINFILE="$asm_test.bin"
-  mkdir -p $OUT/$SRC
-  cd $OUT/$SRC
-  if [[ $RAND_SEED == 1 ]]; then
-    SEED=$RANDOM
-  fi
-  if [[ $WAVES == 1 ]]; then
-    WAVES_OPTS="-ucli -do $CWD/vcs.tcl"
-  fi
-  if [[ $COV == 1 ]]; then
-    COV_OPTS="-cm line+tgl+assert+fsm+branch \
-              -cm_dir ${RUN_DIR}/rtl_sim/test.vdb \
-              -cm_log /dev/null \
-              -assert nopostproc \
-              -cm_name test_${SEED}"
-  fi
-  if [[ "$BINFILE" =~ "ebreak" ]]; then
-    OPTS="+enable_debug_seq=1"
-  fi
-  if [[ "$BINFILE" =~ "wfi" ]]; then
-    OPTS="+enable_irq_seq=1"
-  fi
-  CMD="$OUT/vcs_simv +UVM_TESTNAME=core_ibex_base_test \
-       ${WAVES_OPTS} +ntb_random_seed=${SEED} +vcs+lic+wait ${COV_OPTS}\
-       +UVM_MAX_QUIT_COUNT=5 +bin=$BINFILE -l sim.log ${OPTS}"
-  echo "Running simulation for : $CMD"
-  $CMD
-done <"$RUN_DIR/asm_test_list"
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/sim.py b/hw/vendor/lowrisc_ibex/dv/uvm/sim.py
index 67452d5..44558c5 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/sim.py
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/sim.py
@@ -45,7 +45,7 @@
     Processed command
   """
   if enable == "1":
-    return re.sub(keyword, opts, cmd)
+    return re.sub(keyword, opts.rstrip(), cmd)
   else:
     return re.sub(keyword, "", cmd)
 
@@ -83,43 +83,6 @@
   sys.exit(1)
 
 
-def run_cmd(cmd):
-  """Run a command and return output
-
-  Args:
-    cmd : shell command to run
-
-  Returns:
-    command output
-  """
-  try:
-    ps = subprocess.Popen(cmd,
-                          shell=True,
-                          universal_newlines=True,
-                          stdout=subprocess.PIPE,
-                          stderr=subprocess.STDOUT,
-                          executable='/bin/bash')
-  except subprocess.CalledProcessError as exc:
-    print(ps.communicate()[0])
-    sys.exit(1)
-  return ps.communicate()[0]
-
-
-def get_seed(seed):
-  """Get the seed to run the generator
-
-  Args:
-    seed : input seed
-
-  Returns:
-    seed to run instruction generator
-  """
-  if seed >= 0:
-    return seed
-  else:
-    return random.getrandbits(32)
-
-
 def rtl_compile(compile_cmd, test_list, output_dir, lsf_cmd, opts, verbose):
   """Run the instruction generator
 
@@ -165,27 +128,24 @@
   for test in test_list:
     for i in range(test['iterations']):
       rand_seed = get_seed(seed)
+      test_sim_cmd = re.sub("<seed>", str(rand_seed), sim_cmd)
+      if "sim_opts" in test:
+        test_sim_cmd += test['sim_opts']
+      print(test_sim_cmd)
       sim_dir = output_dir + ("/%s.%d" %(test['test'], i))
       run_cmd(("mkdir -p %s" % sim_dir))
       os.chdir(sim_dir)
       if verbose:
         print("Run dir: %s" % sim_dir)
       binary = ("%s/%s.%d.bin" % (bin_dir, test['test'], i))
-      cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
+      cmd = lsf_cmd + " " + test_sim_cmd.rstrip() + \
             (" +UVM_TESTNAME=%s " % test['rtl_test']) + \
             (" +bin=%s " % binary) + \
-            (" +ntb_random_seed=%d " % rand_seed) + \
             (" -l sim.log ")
       print("Running %s with %s" % (test['rtl_test'], binary))
       if verbose:
         print(cmd)
-      try:
-        output = subprocess.check_output(cmd.split(),
-                                         timeout=1000,
-                                         universal_newlines=True)
-      except subprocess.CalledProcessError as exc:
-        print(output)
-        sys.exit(1)
+      output = run_cmd(' '.join(cmd.split()))
       if verbose:
         print(output)
 
@@ -205,19 +165,39 @@
       elf = ("%s/asm_tests/%s.%d.o" % (output_dir, test['test'], i))
       print("Comparing %s/DUT sim result : %s" % (iss, elf))
       run_cmd(("echo 'Test binary: %s' >> %s" % (elf, report)))
+      uvm_log = ("%s/rtl_sim/%s.%d/sim.log" % (output_dir, test['test'], i))
       rtl_log = ("%s/rtl_sim/%s.%d/trace_core_00_0.log" % (output_dir, test['test'], i))
       rtl_csv = ("%s/rtl_sim/%s.%d/trace_core_00_0.csv" % (output_dir, test['test'], i))
-      process_ibex_sim_log(rtl_log, rtl_csv)
-      iss_log = ("%s/instr_gen/%s_sim/%s.%d.log" % (output_dir, iss, test['test'], i))
-      iss_csv = ("%s/instr_gen/%s_sim/%s.%d.csv" % (output_dir, iss, test['test'], i))
-      if iss == "spike":
-        process_spike_sim_log(iss_log, iss_csv)
-      elif iss == "ovpsim":
-        process_ovpsim_sim_log(iss_log, iss_csv)
+      test_name = "%s.%d" % (test['test'], i)
+      if 'no_post_compare' in test and test['no_post_compare'] == 1:
+        check_ibex_uvm_log(uvm_log, "ibex", test_name, report)
       else:
-        print("Unsupported ISS" % iss)
-        sys.exit(1)
-      compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report)
+        process_ibex_sim_log(rtl_log, rtl_csv)
+        iss_log = ("%s/instr_gen/%s_sim/%s.%d.log" % (output_dir, iss, test['test'], i))
+        iss_csv = ("%s/instr_gen/%s_sim/%s.%d.csv" % (output_dir, iss, test['test'], i))
+        if iss == "spike":
+          process_spike_sim_log(iss_log, iss_csv)
+        elif iss == "ovpsim":
+          process_ovpsim_sim_log(iss_log, iss_csv)
+        else:
+          print("Unsupported ISS" % iss)
+          sys.exit(1)
+        uvm_result = check_ibex_uvm_log(uvm_log, "ibex", test_name, report, False)
+        if not uvm_result:
+          check_ibex_uvm_log(uvm_log, "ibex", test_name, report)
+        else:
+          if 'compare_opts' in test:
+            compare_opts = test.get('compare_opts')
+            in_order_mode = compare_opts.get('in_order_mode', 1)
+            coalescing_limit = compare_opts.get('coalescing_limit', 0)
+            verbose = compare_opts.get('verbose', 0)
+            mismatch = compare_opts.get('mismatch_print_limit', 5)
+            compare_final = compare_opts.get('compare_final_value_only', 0)
+            compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report,
+                              in_order_mode, coalescing_limit, verbose,
+                              mismatch, compare_final)
+          else:
+            compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report)
   passed_cnt = run_cmd("grep PASSED %s | wc -l" % report).strip()
   failed_cnt = run_cmd("grep FAILED %s | wc -l" % report).strip()
   summary = ("%s PASSED, %s FAILED" % (passed_cnt, failed_cnt))
@@ -245,7 +225,7 @@
                     help="RTL simulator setting YAML")
 parser.add_argument("--iss", type=str, default="spike",
                     help="Instruction set simulator")
-parser.add_argument("--verbose", type=int, default=0,
+parser.add_argument("-v", "--verbose", dest="verbose", action="store_true",
                     help="Verbose logging")
 parser.add_argument("--cmp_opts", type=str, default="",
                     help="Compile options for the generator")
@@ -262,6 +242,7 @@
                           command is not specified")
 
 args = parser.parse_args()
+parser.set_defaults(verbose=False)
 cwd = os.path.dirname(os.path.realpath(__file__))
 
 # Create the output directory
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tb/core_ibex_tb_top.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tb/core_ibex_tb_top.sv
index 1eaab87..251ea86 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/tb/core_ibex_tb_top.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tb/core_ibex_tb_top.sv
@@ -18,14 +18,12 @@
   core_ibex_dut_probe_if dut_if(.clk(clk));
 
   // TODO(taliu) Resolve the tied-off ports
-  ibex_core_tracing #(.DmHaltAddr(`BOOT_ADDR + 'h50),
-                      .DmExceptionAddr(`BOOT_ADDR + 'h54)
-  ) dut (
+  ibex_core_tracing #(.DmHaltAddr(`BOOT_ADDR + 'h0),
+                      .DmExceptionAddr(`BOOT_ADDR + 'h4)) dut (
     .clk_i(clk),
     .rst_ni(rst_n),
     .test_en_i(1'b1),
-    .core_id_i('0),
-    .cluster_id_i('0),
+    .hart_id_i(32'b0),
     .boot_addr_i(`BOOT_ADDR), // align with spike boot address
     .debug_req_i(debug_req),
     .irq_software_i(irq_if.irq_software),
@@ -64,12 +62,17 @@
     force dut.instr_rvalid_i    = instr_mem_vif.rvalid;
     force instr_mem_vif.addr    = dut.instr_addr_o;
     force dut.instr_rdata_i     = instr_mem_vif.rdata;
+    force dut.instr_err_i       = 0; // TODO(taliu) Support interface error
     // IRQ interface
     force irq_vif.clock         = clk;
     force irq_vif.reset         = ~rst_n;
   end
 
-  assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
+  assign dut_if.ecall   = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
+  assign dut_if.wfi     = dut.u_ibex_core.id_stage_i.wfi_insn_dec;
+  assign dut_if.ebreak  = dut.u_ibex_core.id_stage_i.ebrk_insn;
+  assign dut_if.dret    = dut.u_ibex_core.id_stage_i.dret_insn_dec;
+  assign dut_if.mret    = dut.u_ibex_core.id_stage_i.mret_insn_dec;
 
 
   initial begin
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_base_test.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_base_test.sv
index 8e41f25..75d5d58 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_base_test.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_base_test.sv
@@ -4,21 +4,30 @@
 
 class core_ibex_base_test extends uvm_test;
 
-  core_ibex_env                   env;
-  core_ibex_env_cfg               cfg;
-  virtual clk_if                  clk_vif;
-  virtual core_ibex_dut_probe_if  dut_vif;
-  mem_model_pkg::mem_model        mem;
-  core_ibex_vseq                  vseq;
-  bit                             enable_irq_seq;
-  bit                             enable_debug_seq;
-  irq_seq                         irq_seq_h;
-  int unsigned                    timeout_in_cycles = 2000000;
+  core_ibex_env                                   env;
+  core_ibex_env_cfg                               cfg;
+  virtual clk_if                                  clk_vif;
+  virtual core_ibex_dut_probe_if                  dut_vif;
+  mem_model_pkg::mem_model                        mem;
+  core_ibex_vseq                                  vseq;
+  irq_seq                                         irq_seq_h;
+  int unsigned                                    timeout_in_cycles = 3000000;
+  // If no signature_addr handshake functionality is desired between the
+  // testbench and the generated code, the test will wait for the specified
+  // number of cycles before starting stimulus sequences (irq and debug)
+  int unsigned                                    stimulus_delay = 800;
+  bit[ibex_mem_intf_agent_pkg::DATA_WIDTH]        signature_data_q[$];
+  bit[ibex_mem_intf_agent_pkg::DATA_WIDTH]        signature_data;
+  uvm_tlm_analysis_fifo #(ibex_mem_intf_seq_item) item_collected_port;
 
   `uvm_component_utils(core_ibex_base_test)
 
   function new(string name="", uvm_component parent=null);
+    core_ibex_report_server ibex_report_server;
     super.new(name, parent);
+    ibex_report_server = new();
+    uvm_report_server::set_server(ibex_report_server);
+    item_collected_port = new("item_collected_port_test", this);
   endfunction
 
   virtual function void build_phase(uvm_phase phase);
@@ -40,18 +49,30 @@
     vseq.cfg = cfg;
   endfunction
 
+  virtual function void connect_phase(uvm_phase phase);
+    super.connect_phase(phase);
+    env.data_if_slave_agent.monitor.item_collected_port.connect(this.item_collected_port.analysis_export);
+  endfunction
+
   virtual task run_phase(uvm_phase phase);
     phase.raise_objection(this);
     dut_vif.fetch_enable = 1'b0;
     clk_vif.wait_clks(100);
     load_binary_to_mem();
     dut_vif.fetch_enable = 1'b1;
-    vseq.start(env.vseqr);
+    send_stimulus();
     wait_for_test_done();
-    vseq.stop();
     phase.drop_objection(this);
   endtask
 
+  virtual function void report_phase(uvm_phase phase);
+    super.report_phase(phase);
+  endfunction
+
+  virtual task send_stimulus();
+    vseq.start(env.vseqr);
+  endtask
+
   function void load_binary_to_mem();
     string      bin;
     bit [7:0]   r8;
@@ -80,6 +101,7 @@
     fork
       begin
         wait (dut_vif.ecall === 1'b1);
+        vseq.stop();
         `uvm_info(`gfn, "ECALL instruction is detected, test done", UVM_LOW)
         // De-assert fetch enable to finish the test
         dut_vif.fetch_enable = 1'b0;
@@ -93,4 +115,71 @@
     join_any
   endtask
 
+
+  virtual task wait_for_mem_txn(input bit[ibex_mem_intf_agent_pkg::ADDR_WIDTH-1:0] ref_addr,
+                                input signature_type_t ref_type);
+    ibex_mem_intf_seq_item mem_txn;
+    forever begin
+      // The first write to this address is guaranteed to contain the
+      // signature type in bits [7:0]
+      item_collected_port.get(mem_txn);
+      if (mem_txn.addr == ref_addr && mem_txn.data[7:0] === ref_type && mem_txn.read_write == WRITE) begin
+        signature_data = mem_txn.data;
+        case (ref_type)
+          // The very first write to the signature address in every test is
+          // guaranteed to be a write of CORE_STATUS, indicating the
+          // INITIALIZED state
+          CORE_STATUS: begin
+            signature_data_q.push_back(signature_data >> 8);
+          end
+          TEST_RESULT: begin
+            signature_data_q.push_back(signature_data >> 8);
+          end
+          // The next 32 writes to the address are guaranteed to be a dump of
+          // all GPRs
+          WRITE_GPR: begin
+            for(int i = 0; i < 32; i++) begin
+              do begin
+                item_collected_port.get(mem_txn);
+              end while(!(mem_txn.addr == ref_addr && mem_txn.read_write == WRITE));
+              signature_data_q.push_back(mem_txn.data);
+            end
+          end
+          // The next write to this address is guaranteed to be the data held
+          // in the CSR
+          WRITE_CSR: begin
+            signature_data_q.push_back(signature_data >> 8);
+            do begin
+              item_collected_port.get(mem_txn);
+            end while (!(mem_txn.addr == ref_addr && mem_txn.read_write == WRITE));
+            signature_data_q.push_back(mem_txn.data);
+          end
+          default: begin
+            `uvm_fatal(`gfn, $sformatf("The data 0x%0h written to the signature address is formatted incorrectly.", signature_data))
+          end
+        endcase
+        return;
+      end
+    end
+  endtask
+
+  // API of various tasks wrapping wait_for_mem_txn, for various common
+  // functionalities that might be needed for verification purposes.
+  // Will be expanded as needed.
+
+  virtual task check_next_core_status(core_status_t core_status, error_msg="");
+    wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
+    signature_data = signature_data_q.pop_front();
+    if (signature_data != core_status) begin
+      `uvm_error(`gfn, error_msg)
+    end
+  endtask
+
+  virtual task wait_for_core_status(core_status_t core_status);
+    do begin
+      wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
+      signature_data = signature_data_q.pop_front();
+    end while (signature_data != core_status);
+  endtask
+
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_report_server.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_report_server.sv
new file mode 100644
index 0000000..a8db720
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_report_server.sv
@@ -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
+
+class core_ibex_report_server extends uvm_default_report_server;
+
+  function new(string name = "");
+    super.new(name);
+  endfunction
+
+  function void report_summarize(UVM_FILE file = 0);
+    int error_count;
+    error_count = get_severity_count(UVM_WARNING);
+    error_count = get_severity_count(UVM_ERROR) + error_count;
+    error_count = get_severity_count(UVM_FATAL) + error_count;
+
+    if (error_count == 0) begin
+      $display("\n--- RISC-V UVM TEST PASSED ---\n");
+    end else begin
+      $display("\n--- RISC-V UVM TEST FAILED ---\n");
+    end
+    super.report_summarize(file);
+  endfunction
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_seq_lib.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_seq_lib.sv
index 2035a43..0170a47 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_seq_lib.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_seq_lib.sv
@@ -9,7 +9,7 @@
   rand int unsigned  delay;
   int unsigned       num_of_iterations; // 0: infinite until stopped
   int unsigned       iteration_cnt;
-  int unsigned       max_interval = 1000;
+  int unsigned       max_interval;
   int unsigned       max_delay = 500;
   virtual clk_if     clk_vif;
   bit                stop_seq;
@@ -98,7 +98,7 @@
   virtual task send_req();
     `uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
     dut_vif.debug_req <= 1'b1;
-    clk_vif.wait_clks($urandom_range(1, 20));
+    clk_vif.wait_clks($urandom_range(10, 30));
     dut_vif.debug_req <= 1'b0;
   endtask
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_lib.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_lib.sv
new file mode 100644
index 0000000..34bd049
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_lib.sv
@@ -0,0 +1,124 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// CSR test class
+class core_ibex_csr_test extends core_ibex_base_test;
+
+  `uvm_component_utils(core_ibex_csr_test)
+  `uvm_component_new
+
+  virtual task wait_for_test_done();
+    bit result;
+    fork
+    begin
+      wait_for_mem_txn(cfg.signature_addr, TEST_RESULT);
+      result = signature_data_q.pop_front();
+      if (result == TEST_PASS) begin
+        `uvm_info(`gfn, "CSR test completed successfully!", UVM_LOW)
+      end else if (result == TEST_FAIL) begin
+        `uvm_error(`gfn, "CSR TEST_FAILED!")
+      end else begin
+        `uvm_fatal(`gfn, "CSR test values are not configured properly")
+      end
+    end
+    begin
+      clk_vif.wait_clks(timeout_in_cycles);
+      `uvm_fatal(`gfn, "TEST TIMEOUT!!")
+    end
+    join_any
+  endtask
+
+endclass
+
+// Debug test class
+class core_ibex_debug_intr_test extends core_ibex_base_test;
+
+  `uvm_component_utils(core_ibex_debug_intr_test)
+  `uvm_component_new
+
+  virtual task send_stimulus();
+    fork
+      begin
+        vseq.start(env.vseqr);
+      end
+      begin
+        if (cfg.require_signature_addr) begin
+          wait_for_core_status(INITIALIZED);
+        end else begin
+          // If no signature_addr functionality is desired, then the test will
+          // simply wait for an adequate number of cycles
+          clk_vif.wait_clks(stimulus_delay);
+        end
+        fork
+          begin
+            if (cfg.enable_irq_stress_seq) begin
+              vseq.start_irq_stress_seq();
+            end
+          end
+          begin
+            if (cfg.enable_debug_stress_seq) begin
+              vseq.start_debug_stress_seq();
+            end
+          end
+        join_none
+      end
+    join_none
+  endtask
+
+endclass
+
+// Debug WFI test class
+class core_ibex_debug_wfi_test extends core_ibex_base_test;
+
+  `uvm_component_utils(core_ibex_debug_wfi_test)
+  `uvm_component_new
+
+  virtual task send_stimulus();
+    fork
+      begin
+        vseq.start(env.vseqr);
+      end
+      begin
+        if (!cfg.require_signature_addr) begin
+          clk_vif.wait_clks(stimulus_delay);
+          fork
+            begin
+              if (cfg.enable_irq_stress_seq) begin
+                vseq.start_irq_stress_seq();
+              end
+            end
+            begin
+              if (cfg.enable_debug_stress_seq) begin
+                vseq.start_debug_stress_seq();
+              end
+            end
+          join_none
+        end else begin
+          // Wait for core initialization before starting the wfi stimulus
+          // loop - first write to signature address is guaranteed to be core
+          // initialization info
+          check_next_core_status(INITIALIZED, "Core initialization handshake failure");
+          // TODO(udi) - need to check that no other instruction fetches occur
+          // after the WFI is detected, and before any stimulus is sent to the
+          // core
+          forever begin
+            wait (dut_vif.wfi === 1'b1);
+            clk_vif.wait_clks($urandom_range(100));
+            vseq.start_debug_single_seq();
+            // After assserting this signal, core should wake up and jump into
+            // debug mode from WFI state - next handshake should
+            // be a notification that the core is now in debug mode
+            check_next_core_status(IN_DEBUG_MODE, "Core did not jump into debug mode from WFI state");
+            // We don't want to trigger debug stimulus for any WFI
+            // instructions encountered inside the debug rom - those should
+            // act as NOP instructions - so we wait until hitting the end of
+            // the debug rom
+            wait (dut_vif.dret === 1'b1);
+          end
+        end
+      end
+    join_none
+  endtask
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_pkg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_pkg.sv
index c1a83a6..b6a8d4f 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_test_pkg.sv
@@ -11,9 +11,12 @@
   import core_ibex_env_pkg::*;
   import ibex_mem_intf_agent_pkg::*;
   import irq_agent_pkg::*;
+  import riscv_signature_pkg::*;
 
+  `include "core_ibex_report_server.sv"
   `include "core_ibex_seq_lib.sv"
   `include "core_ibex_vseq.sv"
   `include "core_ibex_base_test.sv"
+  `include "core_ibex_test_lib.sv"
 
 endpackage
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_vseq.sv
index 440a918..9d22c70 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_vseq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/tests/core_ibex_vseq.sv
@@ -8,12 +8,15 @@
 
 class core_ibex_vseq extends uvm_sequence;
 
-  ibex_mem_intf_slave_seq    instr_intf_seq;
-  ibex_mem_intf_slave_seq    data_intf_seq;
-  mem_model_pkg::mem_model   mem;
-  irq_seq                    irq_seq_h;
-  debug_seq                  debug_seq_h;
-  core_ibex_env_cfg          cfg;
+  ibex_mem_intf_slave_seq                       instr_intf_seq;
+  ibex_mem_intf_slave_seq                       data_intf_seq;
+  mem_model_pkg::mem_model                      mem;
+  irq_seq                                       irq_seq_stress_h;
+  irq_seq                                       irq_seq_single_h;
+  debug_seq                                     debug_seq_stress_h;
+  debug_seq                                     debug_seq_single_h;
+  core_ibex_env_cfg                             cfg;
+  bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0]  data;
 
   `uvm_object_utils(core_ibex_vseq)
   `uvm_declare_p_sequencer(core_ibex_vseqr)
@@ -22,30 +25,69 @@
   virtual task body();
     instr_intf_seq = ibex_mem_intf_slave_seq::type_id::create("instr_intf_seq");
     data_intf_seq  = ibex_mem_intf_slave_seq::type_id::create("data_intf_seq");
+    if (cfg.enable_irq_stress_seq) begin
+      irq_seq_stress_h = irq_seq::type_id::create("irq_seq_stress_h");
+      irq_seq_stress_h.max_interval = cfg.max_interval;
+    end
+    if (cfg.enable_irq_single_seq) begin
+      irq_seq_single_h = irq_seq::type_id::create("irq_seq_single_h");
+      irq_seq_single_h.num_of_iterations = 1;
+      irq_seq_single_h.max_interval = 1;
+      irq_seq_single_h.max_delay = 1;
+      irq_seq_single_h.interval.rand_mode(0);
+      irq_seq_single_h.interval = 0;
+    end
+    if (cfg.enable_debug_stress_seq) begin
+      debug_seq_stress_h = debug_seq::type_id::create("debug_seq_stress_h");
+      debug_seq_stress_h.max_interval = cfg.max_interval;
+    end
+    if (cfg.enable_debug_single_seq) begin
+      debug_seq_single_h = debug_seq::type_id::create("debug_seq_single_h");
+      debug_seq_single_h.num_of_iterations = 1;
+      debug_seq_single_h.max_interval = 1;
+      debug_seq_single_h.max_delay = 1;
+      debug_seq_single_h.interval.rand_mode(0);
+      debug_seq_single_h.interval = 0;
+    end
     instr_intf_seq.m_mem = mem;
     data_intf_seq.m_mem  = mem;
-
     fork
       instr_intf_seq.start(p_sequencer.instr_if_seqr);
       data_intf_seq.start(p_sequencer.data_if_seqr);
-      if (cfg.enable_irq_seq) begin
-        irq_seq_h = irq_seq::type_id::create("irq_seq_h");
-        irq_seq_h.start(p_sequencer.irq_seqr);
-      end
-      if (cfg.enable_debug_seq) begin
-        debug_seq_h = debug_seq::type_id::create("debug_seq_h");
-        debug_seq_h.start(null);
-      end
     join_none
   endtask
 
   virtual task stop();
-    if (cfg.enable_irq_seq) begin
-      irq_seq_h.stop();
+    if (cfg.enable_irq_stress_seq) begin
+      irq_seq_stress_h.stop();
     end
-    if (cfg.enable_debug_seq) begin
-      debug_seq_h.stop();
+    if (cfg.enable_irq_single_seq) begin
+      irq_seq_single_h.stop();
     end
+    if (cfg.enable_debug_stress_seq) begin
+      debug_seq_stress_h.stop();
+    end
+    if (cfg.enable_debug_single_seq) begin
+      debug_seq_single_h.stop();
+    end
+  endtask
+
+  // Helper tasks to allow the test fine grained control to start sequences
+  // through the vseq - necessary for testing directed stimulus scenarios
+  virtual task start_debug_stress_seq();
+    debug_seq_stress_h.start(null);
+  endtask
+
+  virtual task start_debug_single_seq();
+    debug_seq_single_h.start(null);
+  endtask
+
+  virtual task start_irq_stress_seq();
+    irq_seq_stress_h.start(p_sequencer.irq_seqr);
+  endtask
+
+  virtual task start_irq_single_seq();
+    irq_seq_single_h.start(p_sequencer.irq_seqr);
   endtask
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/yaml/rtl_simulation.yaml b/hw/vendor/lowrisc_ibex/dv/uvm/yaml/rtl_simulation.yaml
index be7f0e5..ea7037f 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/yaml/rtl_simulation.yaml
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/yaml/rtl_simulation.yaml
@@ -36,6 +36,7 @@
   sim:
     cmd: >
       <out>/vcs_simv +vcs+lic+wait <sim_opts> <wave_opts> <cov_opts>
+        +ntb_random_seed=<seed>
     cov_opts: >
       -cm line+tgl+assert+fsm+branch
       -cm_dir <out>/test.vdb
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/ram_1p.sv b/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/ram_1p.sv
index 98b56c1..eaf131c 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/ram_1p.sv
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/ram_1p.sv
@@ -42,7 +42,7 @@
     if (!rst_ni) begin
       rvalid_o <= '0;
     end else begin
-      rvalid_o <= req_i && ~write_i;
+      rvalid_o <= req_i;
     end
   end
 
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/top_artya7_100.sv b/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/top_artya7_100.sv
index e212bf7..8391f68 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/top_artya7_100.sv
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7-100/rtl/top_artya7_100.sv
@@ -48,8 +48,7 @@
 
      .test_en_i             ('b0),
 
-     .core_id_i             (4'b0),
-     .cluster_id_i          (6'b0),
+     .hart_id_i             (32'b0),
      // First instruction executed is at 0x0 + 0x80
      .boot_addr_i           (32'h00000000),
 
@@ -58,6 +57,7 @@
      .instr_rvalid_i        (instr_rvalid),
      .instr_addr_o          (instr_addr),
      .instr_rdata_i         (instr_rdata),
+     .instr_err_i           ('b0),
 
      .data_req_o            (data_req),
      .data_gnt_i            (data_gnt),
diff --git a/hw/vendor/lowrisc_ibex/examples/sim/tb/ibex_tracing_tb.sv b/hw/vendor/lowrisc_ibex/examples/sim/tb/ibex_tracing_tb.sv
index 48345a0..42b2b7b 100644
--- a/hw/vendor/lowrisc_ibex/examples/sim/tb/ibex_tracing_tb.sv
+++ b/hw/vendor/lowrisc_ibex/examples/sim/tb/ibex_tracing_tb.sv
@@ -77,8 +77,7 @@
     .test_en_i              (1'b0),
 
     // Core ID, Cluster ID and boot address are considered more or less static
-    .core_id_i              (4'b0),
-    .cluster_id_i           (6'b0),
+    .hart_id_i              (32'b0),
     .boot_addr_i            (32'b0),
 
     // Instruction memory interface
@@ -87,6 +86,7 @@
     .instr_rvalid_i         (instr_rvalid),
     .instr_addr_o           (),
     .instr_rdata_i          (instr_rdata),
+    .instr_err_i            (1'b0),
 
     // Data memory interface
     .data_req_o             (),
diff --git a/hw/vendor/lowrisc_ibex/ibex_core.core b/hw/vendor/lowrisc_ibex/ibex_core.core
index 016a118..48c0e9a 100644
--- a/hw/vendor/lowrisc_ibex/ibex_core.core
+++ b/hw/vendor/lowrisc_ibex/ibex_core.core
@@ -21,6 +21,7 @@
       - rtl/ibex_multdiv_fast.sv
       - rtl/ibex_multdiv_slow.sv
       - rtl/ibex_prefetch_buffer.sv
+      - rtl/ibex_pmp.sv
       # XXX: Figure out the best way to switch these two implementations
       # dynamically on the target.
 #      - rtl/ibex_register_file_latch.sv # ASIC
diff --git a/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt b/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
index 286fd2d..4df10e5 100644
--- a/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
+++ b/hw/vendor/lowrisc_ibex/lint/verilator_waiver.vlt
@@ -24,34 +24,54 @@
 
 // Bits of signal are not used: fetch_addr_n[0]
 // cleaner to write all bits even if not all are used
-lint_off -msg UNUSED -file "*/rtl/ibex_if_stage.sv" -lines 94
+lint_off -msg UNUSED -file "*/rtl/ibex_if_stage.sv" -lines 80
 
 // Bits of signal are not used: shift_right_result_ext[32]
 // cleaner to write all bits even if not all are used
-lint_off -msg UNUSED -file "*/rtl/ibex_alu.sv" -lines 122
+lint_off -msg UNUSED -file "*/rtl/ibex_alu.sv" -lines 107
 
 // Bits of signal are not used: alu_adder_ext_i[0]
 // Bottom bit is round, not needed
-lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 35
+lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 23
 
 // Bits of signal are not used: mac_res_ext[34]
 // cleaner to write all bits even if not all are used
-lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 60
+lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 48
 
 // Bits of signal are not used: res_adder_h[32]
 // cleaner to write all bits even if not all are used
-lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 80
+lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 68
 
 // Signal is not used: test_en_i
 // testability signal
-lint_off -msg UNUSED -file "*/rtl/ibex_register_file_ff.sv" -lines 38
+lint_off -msg UNUSED -file "*/rtl/ibex_register_file_ff.sv" -lines 21
+
+// Signal is not used: clk_i
+// leaving clk and reset connected in-case we want to add assertions
+lint_off -msg UNUSED -file "*/rtl/ibex_pmp.sv" -lines 15
+
+// Signal is not used: rst_ni
+// leaving clk and reset connected in-case we want to add assertions
+lint_off -msg UNUSED -file "*/rtl/ibex_pmp.sv" -lines 16
+
+// Signal is not used: csr_pmp_addr
+// Signal not connected when PMP is not configured
+lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 186
+
+// Signal is not used: csr_pmp_cfg
+// Signal not connected when PMP is not configured
+lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 187
+
+// Signal is not used: priv_mode
+// Signal not connected when PMP is not configured
+lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 199
 
 // Signal unoptimizable: Feedback to clock or circular logic:
 // ibex_core.id_stage_i.controller_i.ctrl_fsm_cs
 // Issue lowrisc/ibex#211
-lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 112
+lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 98
 
 // Signal unoptimizable: Feedback to clock or circular logic:
 // ibex_core.cs_registers_i.mie_q
 // Issue lowrisc/ibex#212
-lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 157
+lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 149
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
index ebab401..83268db 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
@@ -1,23 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-//                                                                            //
-// Engineer:       Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    ALU                                                        //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Arithmetic logic unit of the pipelined processor.          //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Arithmetic logic unit
  */
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
index 31c31d5..feb5a65 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
@@ -1,21 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-//                                                                            //
-// Engineer:       Sven Stucki - svstucki@student.ethz.ch                     //
-//                                                                            //
-// Design Name:    Compressed instruction decoder                             //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Decodes RISC-V compressed instructions into their RV32     //
-//                 equivalent. This module is fully combinatorial.            //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Compressed instruction decoder
  *
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index 464d6a1..d61c3fd 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -1,25 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Matthias Baer - baermatt@student.ethz.ch                   //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Andreas Traber - atraber@student.ethz.ch                   //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Main controller                                            //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Main controller of the processor                           //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Main controller of the processor
  */
@@ -38,13 +21,15 @@
     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_status_i,          // decoder has CSR status instr
+    input  logic                  csr_pipe_flush_i,      // do CSR-related pipeline flush
 
     // from IF-ID pipeline stage
     input  logic                  instr_valid_i,         // instr from IF-ID reg is valid
     input  logic [31:0]           instr_i,               // instr from IF-ID reg, for mtval
     input  logic [15:0]           instr_compressed_i,    // instr from IF-ID reg, for mtval
     input  logic                  instr_is_compressed_i, // instr from IF-ID reg is compressed
+    input  logic                  instr_fetch_err_i,     // instr from IF-ID reg has error
+    input  logic [31:0]           pc_id_i,               // instr from IF-ID reg address
 
     // to IF-ID pipeline stage
     output logic                  instr_valid_clear_o,   // kill instr in IF-ID reg
@@ -80,6 +65,7 @@
     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,
 
@@ -119,6 +105,8 @@
   logic stall;
   logic halt_if;
   logic halt_id;
+  logic illegal_dret;
+  logic illegal_insn;
   logic exc_req;
   logic exc_req_lsu;
   logic special_req;
@@ -134,8 +122,8 @@
   // glitches
   always_ff @(negedge clk_i) begin
     // print warning in case of decoding errors
-    if ((ctrl_fsm_cs == DECODE) && instr_valid_i && illegal_insn_i) begin
-      $display("%t: Illegal instruction (core %0d) at PC 0x%h: 0x%h", $time, ibex_core.core_id_i,
+    if ((ctrl_fsm_cs == DECODE) && instr_valid_i && illegal_insn) begin
+      $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, ibex_core.hart_id_i,
                ibex_id_stage.pc_id_i, ibex_id_stage.instr_rdata_i);
     end
   end
@@ -149,14 +137,19 @@
   assign load_err_d  = load_err_i;
   assign store_err_d = store_err_i;
 
+  // "Executing DRET outside of Debug Mode causes an illegal instruction exception."
+  // [Debug Spec v0.13.2, p.41]
+  assign illegal_dret = dret_insn_i & ~debug_mode_q;
+  assign illegal_insn = illegal_insn_i | illegal_dret;
+
   // exception requests
-  assign exc_req     = ecall_insn_i | ebrk_insn_i | illegal_insn_i;
+  assign exc_req     = ecall_insn_i | ebrk_insn_i | illegal_insn | instr_fetch_err_i;
 
   // LSU exception requests
   assign exc_req_lsu = store_err_i | load_err_i;
 
   // special requests: special instructions, pipeline flushes, exceptions...
-  assign special_req = mret_insn_i | dret_insn_i | wfi_insn_i | csr_status_i |
+  assign special_req = mret_insn_i | dret_insn_i | wfi_insn_i | csr_pipe_flush_i |
       exc_req | exc_req_lsu;
 
   ////////////////
@@ -453,7 +446,11 @@
           csr_save_cause_o = 1'b1;
 
           // set exception registers, priorities according to Table 3.7 of Privileged Spec v1.11
-          if (illegal_insn_i) begin
+          if (instr_fetch_err_i) begin
+            exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
+            csr_mtval_o = pc_id_i;
+
+          end else if (illegal_insn) begin
             exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
             csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
 
@@ -506,7 +503,7 @@
           end
 
         end else begin
-          // special instructions
+          // special instructions and pipeline flushes
           if (mret_insn_i) begin
             pc_mux_o              = PC_ERET;
             pc_set_o              = 1'b1;
@@ -520,6 +517,9 @@
             debug_mode_d          = 1'b0;
           end else if (wfi_insn_i) begin
             ctrl_fsm_ns           = WAIT_SLEEP;
+          end else if (csr_pipe_flush_i && handle_irq) begin
+            // start handling IRQs when doing CSR-related pipeline flushes
+            ctrl_fsm_ns           = IRQ_TAKEN;
           end
         end // exc_req
 
@@ -538,6 +538,9 @@
     endcase
   end
 
+  // signal to CSR when in debug mode
+  assign debug_mode_o = debug_mode_q;
+
   ///////////////////
   // Stall control //
   ///////////////////
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 98da120..be613b9 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -1,26 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Matthias Baer - baermatt@student.ethz.ch                   //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Andreas Traber - atraber@student.ethz.ch                   //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Top level module                                           //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Top level module of the RISC-V core.                       //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 `ifdef RISCV_FORMAL
   `define RVFI
 `endif
@@ -29,6 +11,9 @@
  * Top level module of the ibex RISC-V core
  */
 module ibex_core #(
+    parameter bit          PMPEnable        = 0,
+    parameter int unsigned PMPGranularity   = 0,
+    parameter int unsigned PMPNumRegions    = 4,
     parameter int unsigned MHPMCounterNum   = 0,
     parameter int unsigned MHPMCounterWidth = 40,
     parameter bit RV32E                     = 0,
@@ -42,9 +27,7 @@
 
     input  logic        test_en_i,     // enable all clock gates for testing
 
-    // Core ID, Cluster ID and boot address are considered more or less static
-    input  logic [ 3:0] core_id_i,
-    input  logic [ 5:0] cluster_id_i,
+    input  logic [31:0] hart_id_i,
     input  logic [31:0] boot_addr_i,
 
     // Instruction memory interface
@@ -53,6 +36,7 @@
     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,
@@ -109,12 +93,15 @@
 
   import ibex_pkg::*;
 
+  localparam int unsigned PMP_NUM_CHAN = 2;
+
   // IF/ID signals
   logic        instr_valid_id;
   logic        instr_new_id;
   logic [31:0] instr_rdata_id;         // Instruction sampled inside IF stage
   logic [15:0] instr_rdata_c_id;       // Compressed instruction sampled inside IF stage
   logic        instr_is_compressed_id;
+  logic        instr_fetch_err;        // Bus error on instr fetch
   logic        illegal_c_insn_id;      // Illegal compressed instruction sent to ID stage
   logic [31:0] pc_if;                  // Program counter in IF stage
   logic [31:0] pc_id;                  // Program counter in ID stage
@@ -173,7 +160,6 @@
   logic        data_we_ex;
   logic [1:0]  data_type_ex;
   logic        data_sign_ext_ex;
-  logic [1:0]  data_reg_offset_ex;
   logic        data_req_ex;
   logic [31:0] data_wdata_ex;
   logic [31:0] regfile_wdata_lsu;
@@ -196,6 +182,13 @@
   logic        csr_mstatus_mie;
   logic [31:0] csr_mepc, csr_depc;
 
+  // PMP signals
+  logic [33:0] csr_pmp_addr [PMPNumRegions];
+  pmp_cfg_t    csr_pmp_cfg  [PMPNumRegions];
+  logic        pmp_req_err  [PMP_NUM_CHAN];
+  logic        instr_req_out;
+  logic        data_req_out;
+
   logic        csr_save_if;
   logic        csr_save_id;
   logic        csr_restore_mret_id;
@@ -203,8 +196,10 @@
   logic        csr_mtvec_init;
   logic [31:0] csr_mtvec;
   logic [31:0] csr_mtval;
+  priv_lvl_e   priv_mode;
 
   // debug mode and dcsr configuration
+  logic        debug_mode;
   dbg_cause_e  debug_cause;
   logic        debug_csr_save;
   logic        debug_single_step;
@@ -304,11 +299,13 @@
       .req_i                    ( instr_req_int          ), // instruction request control
 
       // instruction cache interface
-      .instr_req_o              ( instr_req_o            ),
+      .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]     ),
 
       // outputs to ID stage
       .instr_valid_id_o         ( instr_valid_id         ),
@@ -316,6 +313,7 @@
       .instr_rdata_id_o         ( instr_rdata_id         ),
       .instr_rdata_c_id_o       ( instr_rdata_c_id       ),
       .instr_is_compressed_id_o ( instr_is_compressed_id ),
+      .instr_fetch_err_o        ( instr_fetch_err        ),
       .illegal_c_insn_id_o      ( illegal_c_insn_id      ),
       .pc_if_o                  ( pc_if                  ),
       .pc_id_o                  ( pc_id                  ),
@@ -343,6 +341,8 @@
       .perf_imiss_o             ( perf_imiss             )
   );
 
+  // Qualify the instruction request with PMP error
+  assign instr_req_o = instr_req_out & ~pmp_req_err[PMP_I];
 
   //////////////
   // ID stage //
@@ -382,6 +382,7 @@
       .exc_pc_mux_o                 ( exc_pc_mux_id          ),
       .exc_cause_o                  ( exc_cause              ),
 
+      .instr_fetch_err_i            ( instr_fetch_err        ),
       .illegal_c_insn_i             ( illegal_c_insn_id      ),
 
       .pc_id_i                      ( pc_id                  ),
@@ -416,7 +417,6 @@
       .data_we_ex_o                 ( data_we_ex             ), // to load store unit
       .data_type_ex_o               ( data_type_ex           ), // to load store unit
       .data_sign_ext_ex_o           ( data_sign_ext_ex       ), // to load store unit
-      .data_reg_offset_ex_o         ( data_reg_offset_ex     ), // to load store unit
       .data_wdata_ex_o              ( data_wdata_ex          ), // to load store unit
 
       .lsu_addr_incr_req_i          ( lsu_addr_incr_req      ),
@@ -435,6 +435,7 @@
       .irq_nm_i                     ( irq_nm_i               ),
 
       // 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            ),
@@ -500,15 +501,18 @@
   // Load/store unit //
   /////////////////////
 
+  assign data_req_o = data_req_out & ~pmp_req_err[PMP_D];
+
   ibex_load_store_unit  load_store_unit_i (
       .clk_i                 ( clk                 ),
       .rst_ni                ( rst_ni              ),
 
       // data interface
-      .data_req_o            ( data_req_o          ),
+      .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           ),
@@ -520,7 +524,6 @@
       .data_we_ex_i          ( data_we_ex          ),
       .data_type_ex_i        ( data_type_ex        ),
       .data_wdata_ex_i       ( data_wdata_ex       ),
-      .data_reg_offset_ex_i  ( data_reg_offset_ex  ),
       .data_sign_ext_ex_i    ( data_sign_ext_ex    ),
 
       .data_rdata_ex_o       ( regfile_wdata_lsu   ),
@@ -553,15 +556,17 @@
   ibex_cs_registers #(
       .MHPMCounterNum   ( MHPMCounterNum   ),
       .MHPMCounterWidth ( MHPMCounterWidth ),
+      .PMPGranularity   ( PMPGranularity   ),
+      .PMPNumRegions    ( PMPNumRegions    ),
       .RV32E            ( RV32E            ),
       .RV32M            ( RV32M            )
   ) cs_registers_i (
       .clk_i                   ( clk                    ),
       .rst_ni                  ( rst_ni                 ),
 
-      // Core and Cluster ID from outside
-      .core_id_i               ( core_id_i              ),
-      .cluster_id_i            ( cluster_id_i           ),
+      // Hart ID from outside
+      .hart_id_i               ( hart_id_i              ),
+      .priv_mode_o             ( priv_mode              ),
 
       // mtvec
       .csr_mtvec_o             ( csr_mtvec              ),
@@ -588,8 +593,13 @@
       .csr_mstatus_mie_o       ( csr_mstatus_mie        ),
       .csr_mepc_o              ( csr_mepc               ),
 
+      // PMP
+      .csr_pmp_cfg_o           ( csr_pmp_cfg            ),
+      .csr_pmp_addr_o          ( csr_pmp_addr           ),
+
       // 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      ),
@@ -621,6 +631,36 @@
       .lsu_busy_i              ( lsu_busy               )
   );
 
+  if (PMPEnable) begin : g_pmp
+    logic [33:0] pmp_req_addr [PMP_NUM_CHAN];
+    pmp_req_e    pmp_req_type [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_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;
+
+    ibex_pmp #(
+        .PMPGranularity        ( PMPGranularity ),
+        .PMPNumChan            ( PMP_NUM_CHAN   ),
+        .PMPNumRegions         ( PMPNumRegions  )
+    ) pmp_i (
+        .clk_i                 ( clk            ),
+        .rst_ni                ( rst_ni         ),
+        // Interface to CSRs
+        .csr_pmp_cfg_i         ( csr_pmp_cfg    ),
+        .csr_pmp_addr_i        ( csr_pmp_addr   ),
+        .priv_mode_i           ( priv_mode      ),
+        // 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
+    assign pmp_req_err[PMP_I] = 1'b0;
+    assign pmp_req_err[PMP_D] = 1'b0;
+  end
+
 `ifdef RVFI
   always_ff @(posedge clk or negedge rst_ni) begin
     if (!rst_ni) begin
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
index 48f3d3b..63c100f 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
@@ -20,9 +20,7 @@
 
     input  logic        test_en_i,     // enable all clock gates for testing
 
-    // Core ID, Cluster ID and boot address are considered more or less static
-    input  logic [ 3:0] core_id_i,
-    input  logic [ 5:0] cluster_id_i,
+    input  logic [31:0] hart_id_i,
     input  logic [31:0] boot_addr_i,
 
     // Instruction memory interface
@@ -31,6 +29,7 @@
     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,
@@ -100,8 +99,7 @@
 
     .test_en_i,
 
-    .core_id_i,
-    .cluster_id_i,
+    .hart_id_i,
     .boot_addr_i,
 
     .instr_req_o,
@@ -109,6 +107,7 @@
     .instr_rvalid_i,
     .instr_addr_o,
     .instr_rdata_i,
+    .instr_err_i,
 
     .data_req_o,
     .data_gnt_i,
@@ -160,8 +159,7 @@
       .rst_ni           ( rst_ni                 ),
 
       .fetch_enable_i   ( fetch_enable_i         ),
-      .core_id_i        ( core_id_i              ),
-      .cluster_id_i     ( cluster_id_i           ),
+      .hart_id_i        ( hart_id_i              ),
 
       .valid_i          ( rvfi_valid             ),
       .pc_i             ( rvfi_pc_rdata          ),
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index a7adcaf..f65ab51 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -1,24 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Sven Stucki - svstucki@student.ethz.ch                     //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Control and Status Registers                               //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Control and Status Registers (CSRs) following the RISC-V   //
-//                 Privileged Specification, draft version 1.11               //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Control and Status Registers
  *
@@ -28,6 +12,9 @@
 module ibex_cs_registers #(
     parameter int unsigned MHPMCounterNum   = 8,
     parameter int unsigned MHPMCounterWidth = 40,
+    parameter bit          PMPEnable        = 0,
+    parameter int unsigned PMPGranularity   = 0,
+    parameter int unsigned PMPNumRegions    = 4,
     parameter bit RV32E                     = 0,
     parameter bit RV32M                     = 0
 ) (
@@ -35,9 +22,9 @@
     input  logic                 clk_i,
     input  logic                 rst_ni,
 
-    // Core and Cluster ID
-    input  logic  [3:0]          core_id_i,
-    input  logic  [5:0]          cluster_id_i,
+    // Hart ID
+    input  logic [31:0]          hart_id_i,
+    output ibex_pkg::priv_lvl_e  priv_mode_o,
 
     // mtvec
     output logic [31:0]          csr_mtvec_o,
@@ -64,7 +51,12 @@
     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],
+
     // 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,
@@ -172,6 +164,10 @@
   logic [31:0] mstack_epc_q, mstack_epc_d;
   logic  [5:0] mstack_cause_q, mstack_cause_d;
 
+  // PMP Signals
+  logic [31:0]                 pmp_addr_rdata  [PMP_MAX_REGIONS];
+  logic [PMP_CFG_W-1:0]        pmp_cfg_rdata   [PMP_MAX_REGIONS];
+
   // Hardware performance monitor signals
   logic [31:0] mcountinhibit_d, mcountinhibit_q, mcountinhibit;
   logic [31:0] mcountinhibit_force;
@@ -225,7 +221,7 @@
 
     unique case (csr_addr_i)
       // mhartid: unique hardware thread id
-      CSR_MHARTID: csr_rdata_int = {21'b0, cluster_id_i[5:0], 1'b0, core_id_i[3:0]};
+      CSR_MHARTID: csr_rdata_int = hart_id_i;
 
       // mstatus: always M-mode, contains IE bit
       CSR_MSTATUS: begin
@@ -270,10 +266,48 @@
         csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mip.irq_fast;
       end
 
-      CSR_DCSR:      csr_rdata_int = dcsr_q;
-      CSR_DPC:       csr_rdata_int = depc_q;
-      CSR_DSCRATCH0: csr_rdata_int = dscratch0_q;
-      CSR_DSCRATCH1: csr_rdata_int = dscratch1_q;
+      // PMP registers
+      CSR_PMPCFG0:   csr_rdata_int = {pmp_cfg_rdata[3],  pmp_cfg_rdata[2],
+                                      pmp_cfg_rdata[1],  pmp_cfg_rdata[0]};
+      CSR_PMPCFG1:   csr_rdata_int = {pmp_cfg_rdata[7],  pmp_cfg_rdata[6],
+                                      pmp_cfg_rdata[5],  pmp_cfg_rdata[4]};
+      CSR_PMPCFG2:   csr_rdata_int = {pmp_cfg_rdata[11], pmp_cfg_rdata[10],
+                                      pmp_cfg_rdata[9],  pmp_cfg_rdata[8]};
+      CSR_PMPCFG3:   csr_rdata_int = {pmp_cfg_rdata[15], pmp_cfg_rdata[14],
+                                      pmp_cfg_rdata[13], pmp_cfg_rdata[12]};
+      CSR_PMPADDR0:  csr_rdata_int = pmp_addr_rdata[0];
+      CSR_PMPADDR1:  csr_rdata_int = pmp_addr_rdata[1];
+      CSR_PMPADDR2:  csr_rdata_int = pmp_addr_rdata[2];
+      CSR_PMPADDR3:  csr_rdata_int = pmp_addr_rdata[3];
+      CSR_PMPADDR4:  csr_rdata_int = pmp_addr_rdata[4];
+      CSR_PMPADDR5:  csr_rdata_int = pmp_addr_rdata[5];
+      CSR_PMPADDR6:  csr_rdata_int = pmp_addr_rdata[6];
+      CSR_PMPADDR7:  csr_rdata_int = pmp_addr_rdata[7];
+      CSR_PMPADDR8:  csr_rdata_int = pmp_addr_rdata[8];
+      CSR_PMPADDR9:  csr_rdata_int = pmp_addr_rdata[9];
+      CSR_PMPADDR10: csr_rdata_int = pmp_addr_rdata[10];
+      CSR_PMPADDR11: csr_rdata_int = pmp_addr_rdata[11];
+      CSR_PMPADDR12: csr_rdata_int = pmp_addr_rdata[12];
+      CSR_PMPADDR13: csr_rdata_int = pmp_addr_rdata[13];
+      CSR_PMPADDR14: csr_rdata_int = pmp_addr_rdata[14];
+      CSR_PMPADDR15: csr_rdata_int = pmp_addr_rdata[15];
+
+      CSR_DCSR: begin
+        csr_rdata_int = dcsr_q;
+        illegal_csr = ~debug_mode_i;
+      end
+      CSR_DPC: begin
+        csr_rdata_int = depc_q;
+        illegal_csr = ~debug_mode_i;
+      end
+      CSR_DSCRATCH0: begin
+        csr_rdata_int = dscratch0_q;
+        illegal_csr = ~debug_mode_i;
+      end
+      CSR_DSCRATCH1: begin
+        csr_rdata_int = dscratch1_q;
+        illegal_csr = ~debug_mode_i;
+      end
 
       // machine counter/timers
       CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit;
@@ -527,7 +561,7 @@
   end
 
   // only write CSRs during one clock cycle
-  assign csr_we_int  = csr_wreq & instr_new_id_i;
+  assign csr_we_int  = csr_wreq & ~illegal_csr_priv & instr_new_id_i;
 
   assign csr_rdata_o = csr_rdata_int;
 
@@ -600,6 +634,131 @@
     end
   end
 
+  assign priv_mode_o = mstatus_q.mpp;
+
+  // -----------------
+  // PMP registers
+  // -----------------
+
+  if (PMPEnable) begin : g_pmp_registers
+    pmp_cfg_t                    pmp_cfg         [PMPNumRegions];
+    pmp_cfg_t                    pmp_cfg_wdata   [PMPNumRegions];
+    logic [31:0]                 pmp_addr        [PMPNumRegions];
+    logic [PMPNumRegions-1:0]    pmp_cfg_we;
+    logic [PMPNumRegions-1:0]    pmp_addr_we;
+
+    // Expanded / qualified register read data
+    for (genvar i = 0; i < PMP_MAX_REGIONS; i++) begin : g_exp_rd_data
+      if (i < PMPNumRegions) begin : g_implemented_regions
+        // Add in zero padding for reserved fields
+        assign pmp_cfg_rdata[i] = {pmp_cfg[i].lock, 2'b00, pmp_cfg[i].mode,
+                                   pmp_cfg[i].exec, pmp_cfg[i].write, pmp_cfg[i].read};
+
+        // Address field read data depends on the current programmed mode and the granularity
+        // See RISC-V Privileged Specification, version 1.11, Section 3.6.1
+        if (PMPGranularity == 0) begin : g_pmp_g0
+          // If G == 0, read data is unmodified
+          assign pmp_addr_rdata[i] = pmp_addr[i];
+
+        end else if (PMPGranularity == 1) begin : g_pmp_g1
+          // If G == 1, bit [G-1] reads as zero in TOR or OFF mode
+          always_comb begin
+            pmp_addr_rdata[i] = pmp_addr[i];
+            if ((pmp_cfg[i].mode == PMP_MODE_OFF) || (pmp_cfg[i].mode == PMP_MODE_TOR)) begin
+              pmp_addr_rdata[i][PMPGranularity-1:0] = '0;
+            end
+          end
+
+        end else begin
+          // For G >= 2, bits are masked to one or zero depending on the mode
+          always_comb begin
+            pmp_addr_rdata[i] = pmp_addr[i];
+            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
+              pmp_addr_rdata[i][PMPGranularity-1:0] = '0;
+            end else if (pmp_cfg[i].mode == PMP_MODE_NAPOT) begin
+              // In NAPOT mode, bits [G-2:0] must read as one
+              pmp_addr_rdata[i][PMPGranularity-2:0] = '1;
+            end
+          end
+        end
+
+      end else begin : g_other_regions
+        // Non-implemented regions read as zero
+        assign pmp_cfg_rdata[i]  = '0;
+        assign pmp_addr_rdata[i] = '0;
+      end
+    end
+
+    // Write data calculation
+    for (genvar i = 0; i < PMPNumRegions; i++) begin : g_pmp_csrs
+      // -------------------------
+      // Instantiate cfg registers
+      // -------------------------
+      assign pmp_cfg_we[i] = csr_we_int & ~pmp_cfg[i].lock &
+                             (csr_addr == (CSR_OFF_PMP_CFG + (i[11:0] >> 2)));
+
+      // Select the correct WDATA (each CSR contains 4 CFG fields, each with 2 RES bits)
+      assign pmp_cfg_wdata[i].lock  = csr_wdata_int[(i%4)*PMP_CFG_W+7];
+      // NA4 mode is not selectable when G > 0, mode is treated as OFF
+      always_comb begin
+        unique case (csr_wdata_int[(i%4)*PMP_CFG_W+3+:2])
+          2'b00   : pmp_cfg_wdata[i].mode = PMP_MODE_OFF;
+          2'b01   : pmp_cfg_wdata[i].mode = PMP_MODE_TOR;
+          2'b10   : pmp_cfg_wdata[i].mode = (PMPGranularity == 0) ? PMP_MODE_NA4:
+                                                                    PMP_MODE_OFF;
+          2'b11   : pmp_cfg_wdata[i].mode = PMP_MODE_NAPOT;
+          default : pmp_cfg_wdata[i].mode = pmp_cfg_mode_e'('X);
+        endcase
+      end
+      assign pmp_cfg_wdata[i].exec  = csr_wdata_int[(i%4)*PMP_CFG_W+2];
+      // W = 1, R = 0 is a reserved combination. For now, we force W to 0 if R == 0
+      assign pmp_cfg_wdata[i].write = &csr_wdata_int[(i%4)*PMP_CFG_W+:2];
+      assign pmp_cfg_wdata[i].read  = csr_wdata_int[(i%4)*PMP_CFG_W];
+
+      always_ff @(posedge clk_i or negedge rst_ni) begin
+        if (!rst_ni) begin
+          pmp_cfg[i] <= pmp_cfg_t'('b0);
+        end else if (pmp_cfg_we[i]) begin
+          pmp_cfg[i] <= pmp_cfg_wdata[i];
+        end
+      end
+
+      // --------------------------
+      // Instantiate addr registers
+      // --------------------------
+      if (i < PMPNumRegions - 1) begin : g_lower
+        assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
+                                (pmp_cfg[i+1].mode != PMP_MODE_TOR) &
+                                (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0]));
+      end else begin : g_upper
+        assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
+                                (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0]));
+      end
+
+      always_ff @(posedge clk_i or negedge rst_ni) begin
+        if (!rst_ni) begin
+          pmp_addr[i] <= 'b0;
+        end else if (pmp_addr_we[i]) begin
+          pmp_addr[i] <= csr_wdata_int;
+        end
+      end
+      assign csr_pmp_cfg_o[i]  = pmp_cfg[i];
+      assign csr_pmp_addr_o[i] = {pmp_addr[i],2'b00};
+    end
+
+  end else begin : g_no_pmp_tieoffs
+    // Generate tieoffs when PMP is not configured
+    for (genvar i = 0; i < PMP_MAX_REGIONS; i++) begin : g_rdata
+      assign pmp_addr_rdata[i] = '0;
+      assign pmp_cfg_rdata[i]  = '0;
+    end
+    for (genvar i = 0; i < PMPNumRegions; i++) begin : g_outputs
+      assign csr_pmp_cfg_o[i]  = pmp_cfg_t'('0);
+      assign csr_pmp_addr_o[i] = '0;
+    end
+  end
+
   //////////////////////////
   //  Performance monitor //
   //////////////////////////
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
index d472c50..72f483d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
@@ -1,26 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer        Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Matthias Baer - baermatt@student.ethz.ch                   //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                                                                            //
-// Design Name:    Decoder                                                    //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Decoder                                                    //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 // Source/Destination register instruction index
 `define REG_S1 19:15
 `define REG_S2 24:20
@@ -82,7 +64,7 @@
     // CSRs
     output logic                 csr_access_o,          // access to CSR
     output ibex_pkg::csr_op_e    csr_op_o,              // operation to perform on CSR
-    output logic                 csr_status_o,          // access to xstatus CSR
+    output logic                 csr_pipe_flush_o,      // CSR-related pipeline flush
 
     // LSU
     output logic                 data_req_o,            // start transaction to data memory
@@ -91,7 +73,6 @@
                                                         // word or word
     output logic                 data_sign_extension_o, // sign extension for data read from
                                                         // memory
-    output logic [1:0]           data_reg_offset_o,     // register byte offset for stores
 
     // jump/branches
     output logic                 jump_in_dec_o,         // jump is being calculated in ALU
@@ -159,6 +140,32 @@
     end
   end
 
+  /////////////////////////////////
+  // CSR-related pipline flushes //
+  /////////////////////////////////
+  always_comb begin : csr_pipeline_flushes
+    csr_pipe_flush_o = 1'b0;
+
+    // A pipeline flush is needed to let the controller react after modifying certain CSRs:
+    // - When enabling interrupts, pending IRQs become visible to the controller only during
+    //   the next cycle. If during that cycle the core disables interrupts again, it does not
+    //   see any pending IRQs and consequently does not start to handle interrupts.
+    // - When modifying debug CSRs - TODO: Check if this is really needed
+    if (csr_access_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin
+      if (csr_num_e'(instr[31:20]) == CSR_MSTATUS   ||
+          csr_num_e'(instr[31:20]) == CSR_MIE) begin
+        csr_pipe_flush_o = 1'b1;
+      end
+    end else if (csr_access_o == 1'b1 && csr_op_o != CSR_OP_READ) begin
+      if (csr_num_e'(instr[31:20]) == CSR_DCSR      ||
+          csr_num_e'(instr[31:20]) == CSR_DPC       ||
+          csr_num_e'(instr[31:20]) == CSR_DSCRATCH0 ||
+          csr_num_e'(instr[31:20]) == CSR_DSCRATCH1) begin
+        csr_pipe_flush_o = 1'b1;
+      end
+    end
+  end
+
   /////////////
   // Decoder //
   /////////////
@@ -183,14 +190,12 @@
     regfile_we                  = 1'b0;
 
     csr_access_o                = 1'b0;
-    csr_status_o                = 1'b0;
     csr_illegal                 = 1'b0;
     csr_op                      = CSR_OP_READ;
 
     data_we_o                   = 1'b0;
     data_type_o                 = 2'b00;
     data_sign_extension_o       = 1'b0;
-    data_reg_offset_o           = 2'b00;
     data_req_o                  = 1'b0;
 
     illegal_insn                = 1'b0;
@@ -555,17 +560,6 @@
             default: csr_illegal = 1'b1;
           endcase
 
-          if (!csr_illegal) begin
-            // flush pipeline on access to mstatus or debug CSRs
-            if (csr_num_e'(instr[31:20]) == CSR_MSTATUS   ||
-                csr_num_e'(instr[31:20]) == CSR_DCSR      ||
-                csr_num_e'(instr[31:20]) == CSR_DPC       ||
-                csr_num_e'(instr[31:20]) == CSR_DSCRATCH0 ||
-                csr_num_e'(instr[31:20]) == CSR_DSCRATCH1) begin
-              csr_status_o = 1'b1;
-            end
-          end
-
           illegal_insn = csr_illegal;
         end
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
index f12a75f..54041a3 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
@@ -1,26 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Renzo Andri - andrire@student.ethz.ch                      //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Execute stage                                              //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Execution block: Hosts ALU and MUL/DIV unit                //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Execution stage
  *
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
index ba32767..1a2d5d1 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
@@ -1,18 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                                                                            //
-// Design Name:    Fetch Fifo for 32 bit memory interface                     //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Fetch fifo                                                 //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Fetch Fifo for 32 bit memory interface
  *
@@ -30,6 +20,7 @@
     // input port
     input  logic [31:0] in_addr_i,
     input  logic [31:0] in_rdata_i,
+    input  logic        in_err_i,
     input  logic        in_valid_i,
     output logic        in_ready_o,
 
@@ -39,6 +30,7 @@
     input  logic        out_ready_i,
     output logic [31:0] out_rdata_o,
     output logic [31:0] out_addr_o,
+    output logic        out_err_o,
 
     output logic        out_valid_stored_o // same as out_valid_o, except that if something is
                                            // incoming now it is not included. This signal is
@@ -50,10 +42,12 @@
   // index 0 is used for output
   logic [DEPTH-1:0] [31:0]  addr_n,    addr_int,    addr_q;
   logic [DEPTH-1:0] [31:0]  rdata_n,   rdata_int,   rdata_q;
+  logic [DEPTH-1:0]         err_n,     err_int,     err_q;
   logic [DEPTH-1:0]         valid_n,   valid_int,   valid_q;
 
   logic             [31:2]  addr_next;
   logic             [31:0]  rdata, rdata_unaligned;
+  logic                     err,   err_unaligned;
   logic                     valid, valid_unaligned;
 
   logic                     aligned_is_compressed, unaligned_is_compressed;
@@ -65,12 +59,22 @@
 
 
   assign rdata = valid_q[0] ? rdata_q[0] : in_rdata_i;
+  assign err   = valid_q[0] ? err_q[0]   : in_err_i;
   assign valid = valid_q[0] | in_valid_i;
 
   assign rdata_unaligned = valid_q[1] ? {rdata_q[1][15:0], rdata[31:16]} :
                                         {in_rdata_i[15:0], rdata[31:16]};
-  // it is implied that rdata_valid_q[0] is set
-  assign valid_unaligned = valid_q[1] | (valid_q[0] & in_valid_i);
+  // If entry[1] is valid, an error can come from entry[0] or entry[1], unless the
+  // instruction in entry[0] is compressed (entry[1] is a new instruction)
+  // If entry[1] is not valid, and entry[0] is, an error can come from entry[0] or the incoming
+  // data, unless the instruction in entry[0] is compressed
+  // If entry[0] is not valid, the error must come from the incoming data
+  assign err_unaligned   = valid_q[1] ? ((err_q[1] & ~unaligned_is_compressed) | err_q[0]) :
+                                        ((valid_q[0] & err_q[0]) |
+                                         (in_err_i & (~valid_q[0] | ~unaligned_is_compressed)));
+  // An uncompressed unaligned instruction is only valid if both parts are available
+  assign valid_unaligned = valid_q[1] ? 1'b1 :
+                                        (valid_q[0] & in_valid_i);
 
   assign unaligned_is_compressed    = rdata[17:16] != 2'b11;
   assign aligned_is_compressed      = rdata[ 1: 0] != 2'b11;
@@ -87,6 +91,7 @@
     if (out_addr_o[1]) begin
       // unaligned case
       out_rdata_o = rdata_unaligned;
+      out_err_o   = err_unaligned;
 
       if (unaligned_is_compressed) begin
         out_valid_o = valid;
@@ -96,6 +101,7 @@
     end else begin
       // aligned case
       out_rdata_o = rdata;
+      out_err_o   = err;
       out_valid_o = valid;
     end
   end
@@ -134,12 +140,14 @@
   always_comb begin
     addr_int    = addr_q;
     rdata_int   = rdata_q;
+    err_int     = err_q;
     valid_int   = valid_q;
     if (in_valid_i) begin
       for (int j = 0; j < DEPTH; j++) begin
         if (!valid_q[j]) begin
           addr_int[j]  = in_addr_i;
           rdata_int[j] = in_rdata_i;
+          err_int[j]   = in_err_i;
           valid_int[j] = 1'b1;
           break;
         end
@@ -153,6 +161,7 @@
   always_comb begin
     addr_n     = addr_int;
     rdata_n    = rdata_int;
+    err_n      = err_int;
     valid_n    = valid_int;
 
     if (out_ready_i && out_valid_o) begin
@@ -165,6 +174,7 @@
         end
 
         rdata_n  = {32'b0, rdata_int[DEPTH-1:1]};
+        err_n    = {1'b0,  err_int[DEPTH-1:1]};
         valid_n  = {1'b0,  valid_int[DEPTH-1:1]};
       end else if (aligned_is_compressed) begin
         // just increase address, do not move to next entry in FIFO
@@ -173,6 +183,7 @@
         // move to next entry in FIFO
         addr_n[0] = {addr_next[31:2], 2'b00};
         rdata_n   = {32'b0, rdata_int[DEPTH-1:1]};
+        err_n     = {1'b0,  err_int[DEPTH-1:1]};
         valid_n   = {1'b0,  valid_int[DEPTH-1:1]};
       end
     end
@@ -186,6 +197,7 @@
     if (!rst_ni) begin
       addr_q    <= '{default: '0};
       rdata_q   <= '{default: '0};
+      err_q     <= '0;
       valid_q   <= '0;
     end else begin
       // on a clear signal from outside we invalidate the content of the FIFO
@@ -195,6 +207,7 @@
       end else begin
         addr_q    <= addr_n;
         rdata_q   <= rdata_n;
+        err_q     <= err_n;
         valid_q   <= valid_n;
       end
     end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index e6e36c4..45f2446 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -1,26 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Renzo Andri - andrire@student.ethz.ch                      //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Andreas Traber - atraber@student.ethz.ch                   //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Instruction Decode Stage                                   //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Decode stage of the core. It decodes the instructions      //
-//                 and hosts the register file.                               //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 `ifdef RISCV_FORMAL
   `define RVFI
 `endif
@@ -65,6 +47,7 @@
     output ibex_pkg::exc_cause_e  exc_cause_o,
 
     input  logic                  illegal_c_insn_i,
+    input  logic                  instr_fetch_err_i,
 
     input  logic [31:0]           pc_id_i,
 
@@ -99,7 +82,6 @@
     output logic                  data_we_ex_o,
     output logic [1:0]            data_type_ex_o,
     output logic                  data_sign_ext_ex_o,
-    output logic [1:0]            data_reg_offset_ex_o,
     output logic [31:0]           data_wdata_ex_o,
 
     input  logic                  lsu_addr_incr_req_i,
@@ -118,6 +100,7 @@
     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,
@@ -214,11 +197,10 @@
   logic        data_we_id;
   logic [1:0]  data_type_id;
   logic        data_sign_ext_id;
-  logic [1:0]  data_reg_offset_id;
   logic        data_req_id, data_req_dec;
 
   // CSR control
-  logic        csr_status;
+  logic        csr_pipe_flush;
 
   logic [31:0] alu_operand_a;
   logic [31:0] alu_operand_b;
@@ -377,14 +359,13 @@
       // CSRs
       .csr_access_o                    ( csr_access_o         ),
       .csr_op_o                        ( csr_op_o             ),
-      .csr_status_o                    ( csr_status           ),
+      .csr_pipe_flush_o                ( csr_pipe_flush       ),
 
       // LSU
       .data_req_o                      ( data_req_dec         ),
       .data_we_o                       ( data_we_id           ),
       .data_type_o                     ( data_type_id         ),
       .data_sign_extension_o           ( data_sign_ext_id     ),
-      .data_reg_offset_o               ( data_reg_offset_id   ),
 
       // jump/branches
       .jump_in_dec_o                   ( jump_in_dec          ),
@@ -412,13 +393,15 @@
       .dret_insn_i                    ( dret_insn_dec          ),
       .wfi_insn_i                     ( wfi_insn_dec           ),
       .ebrk_insn_i                    ( ebrk_insn              ),
-      .csr_status_i                   ( csr_status             ),
+      .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_fetch_err_i              ( instr_fetch_err_i      ),
+      .pc_id_i                        ( pc_id_i                ),
 
       // to IF-ID pipeline
       .instr_valid_clear_o            ( instr_valid_clear_o    ),
@@ -457,6 +440,7 @@
       .csr_mtval_o                    ( csr_mtval_o            ),
 
       // 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            ),
@@ -499,7 +483,6 @@
   assign data_type_ex_o              = data_type_id;
   assign data_sign_ext_ex_o          = data_sign_ext_id;
   assign data_wdata_ex_o             = regfile_rdata_b;
-  assign data_reg_offset_ex_o        = data_reg_offset_id;
 
   assign alu_operator_ex_o           = alu_operator;
   assign alu_operand_a_ex_o          = alu_operand_a;
@@ -630,7 +613,8 @@
 
   // the instruction delivered to the ID stage should always be valid
   assert property (
-    @(posedge clk_i) (instr_valid_i & (~illegal_c_insn_i)) |-> (!$isunknown(instr_rdata_i)) ) else
+    @(posedge clk_i) (instr_valid_i & ~(illegal_c_insn_i | instr_fetch_err_i)) |->
+        (!$isunknown(instr_rdata_i)) ) else
       $display("Instruction is valid, but has at least one X");
 
   // make sure multicycles enable signals are unique
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index 62cf845..a1fa6d4 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -1,25 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Renzo Andri - andrire@student.ethz.ch                      //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Igor Loi - igor.loi@unibo.it                               //
-//                 Andreas Traber - atraber@student.ethz.ch                   //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                                                                            //
-// Design Name:    Instruction Fetch Stage                                    //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Instruction fetch unit: Selection of the next PC, and      //
-//                 buffering (sampling) of the read instruction               //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Instruction Fetch Stage
  *
@@ -42,6 +25,8 @@
     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,
 
     // output of ID stage
     output logic                  instr_valid_id_o,         // instr in IF-ID is valid
@@ -52,6 +37,7 @@
                                                             // 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_fetch_err_o,        // bus error on fetch
     output logic                  illegal_c_insn_id_o,      // compressed decoder thinks this
                                                             // is an invalid instr
     output logic [31:0]           pc_if_o,
@@ -97,6 +83,7 @@
   logic              fetch_ready;
   logic       [31:0] fetch_rdata;
   logic       [31:0] fetch_addr;
+  logic              fetch_err;
 
   logic       [31:0] exc_pc;
 
@@ -155,6 +142,7 @@
       .valid_o           ( fetch_valid                 ),
       .rdata_o           ( fetch_rdata                 ),
       .addr_o            ( fetch_addr                  ),
+      .err_o             ( fetch_err                   ),
 
       // goes to instruction memory / instruction cache
       .instr_req_o       ( instr_req_o                 ),
@@ -162,6 +150,8 @@
       .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   ( instr_pmp_err_i             ),
 
       // Prefetch Buffer Status
       .busy_o            ( prefetch_busy               )
@@ -241,6 +231,7 @@
       instr_new_id_o             <= 1'b0;
       instr_valid_id_o           <= 1'b0;
       instr_rdata_id_o           <= '0;
+      instr_fetch_err_o          <= '0;
       instr_rdata_c_id_o         <= '0;
       instr_is_compressed_id_o   <= 1'b0;
       illegal_c_insn_id_o        <= 1'b0;
@@ -250,6 +241,7 @@
       if (if_id_pipe_reg_we) begin
         instr_valid_id_o         <= 1'b1;
         instr_rdata_id_o         <= instr_decompressed;
+        instr_fetch_err_o        <= fetch_err;
         instr_rdata_c_id_o       <= fetch_rdata[15:0];
         instr_is_compressed_id_o <= instr_is_compressed_int;
         illegal_c_insn_id_o      <= illegal_c_insn;
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 2741a85..8abcd95 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
@@ -1,25 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Igor Loi - igor.loi@unibo.it                               //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    Load Store Unit                                            //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Load Store Unit, used to eliminate multiple access during  //
-//                 processor stalls, and to align bytes and halfwords         //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Load Store Unit
  *
@@ -35,6 +18,7 @@
     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,
@@ -46,7 +30,6 @@
     input  logic         data_we_ex_i,         // write enable                     -> from ID/EX
     input  logic [1:0]   data_type_ex_i,       // data type: word, half word, byte -> from ID/EX
     input  logic [31:0]  data_wdata_ex_i,      // data to write to memory          -> from ID/EX
-    input  logic [1:0]   data_reg_offset_ex_i, // register byte offset for stores  -> from ID/EX
     input  logic         data_sign_ext_ex_i,   // sign extension                   -> from ID/EX
 
     output logic [31:0]  data_rdata_ex_o,      // requested data                   -> to ID/EX
@@ -59,7 +42,7 @@
     output logic [31:0]  addr_last_o,          // address of last transaction      -> to controller
                                                // -> mtval
                                                // -> AGU for misaligned accesses
-    output logic         data_valid_o,         // LSU has completed transaction    -> to 
+    output logic         data_valid_o,         // LSU has completed transaction    -> to
 
     // exception signals
     output logic         load_err_o,
@@ -72,6 +55,7 @@
   logic [31:0]  data_addr_w_aligned;
   logic [31:0]  addr_last_q, addr_last_d;
 
+  logic         data_update;
   logic [31:0]  rdata_q, rdata_d;
   logic [1:0]   rdata_offset_q, rdata_offset_d;
   logic [1:0]   data_type_q, data_type_d;
@@ -92,6 +76,8 @@
   logic         split_misaligned_access;
   logic         handle_misaligned_q, handle_misaligned_d; // high after receiving grant for first
                                                           // part of a misaligned access
+  logic         pmp_err_q;
+  logic         data_or_pmp_err;
 
   typedef enum logic [2:0]  {
     IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID
@@ -161,9 +147,8 @@
   /////////////////////
 
   // prepare data to be written to the memory
-  // we handle misaligned accesses, half word and byte accesses and
-  // register offsets here
-  assign wdata_offset = data_addr[1:0] - data_reg_offset_ex_i[1:0];
+  // we handle misaligned accesses, half word and byte accesses here
+  assign wdata_offset = data_addr[1:0];
   always_comb begin
     unique case (wdata_offset)
       2'b00:   data_wdata =  data_wdata_ex_i[31:0];
@@ -187,10 +172,16 @@
   end
 
   // update control signals for next read data upon receiving grant
-  assign rdata_offset_d  = data_gnt_i ? data_addr[1:0]     : rdata_offset_q;
-  assign data_type_d     = data_gnt_i ? data_type_ex_i     : data_type_q;
-  assign data_sign_ext_d = data_gnt_i ? data_sign_ext_ex_i : data_sign_ext_q;
-  assign data_we_d       = data_gnt_i ? data_we_ex_i       : data_we_q;
+  // This must also be set for a pmp error (which might not actually be granted) to force
+  // data_we_q to update in order to signal the correct exception type (load or store)
+  // Note that we can use the registered pmp_err_q here since we will always take an
+  // extra cycle to progress to the RVALID state
+  assign data_update = data_gnt_i | pmp_err_q;
+
+  assign rdata_offset_d  = data_update ? data_addr[1:0]     : rdata_offset_q;
+  assign data_type_d     = data_update ? data_type_ex_i     : data_type_q;
+  assign data_sign_ext_d = data_update ? data_sign_ext_ex_i : data_sign_ext_q;
+  assign data_we_d       = data_update ? data_we_ex_i       : data_we_q;
 
   // registers for rdata alignment and sign-extension
   always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -329,6 +320,7 @@
     data_valid_o        = 1'b0;
     addr_incr_req_o     = 1'b0;
     handle_misaligned_d = handle_misaligned_q;
+    data_or_pmp_err     = 1'b0;
 
     unique case (ls_fsm_cs)
 
@@ -346,7 +338,7 @@
 
       WAIT_GNT_MIS: begin
         data_req_o = 1'b1;
-        if (data_gnt_i) begin
+        if (data_gnt_i || pmp_err_q) begin
           handle_misaligned_d = 1'b1;
           ls_fsm_ns           = WAIT_RVALID_MIS;
         end
@@ -355,11 +347,14 @@
       WAIT_RVALID_MIS: begin
         // tell ID/EX stage to update the address
         addr_incr_req_o = 1'b1;
-        if (data_rvalid_i) begin
-          // first part rvalid is received
-          if (data_err_i) begin
+        // first part rvalid is received, or gets a pmp error
+        // pmp_err_i will hold stable until the address is updated, and
+        // therefore pmp_err_q is valid in both WAIT_GNT_MIS and WAIT_RVALID_MIS states
+        if (data_rvalid_i || pmp_err_q) begin
+          if (pmp_err_q || data_err_i) begin
             // first part created an error, abort transaction
             data_valid_o        = 1'b1;
+            data_or_pmp_err     = 1'b1;
             handle_misaligned_d = 1'b0;
             ls_fsm_ns           = IDLE;
           end else begin
@@ -383,15 +378,18 @@
         // tell ID/EX stage to update the address
         addr_incr_req_o = handle_misaligned_q;
         data_req_o      = 1'b1;
-        if (data_gnt_i) begin
+        if (data_gnt_i || pmp_err_q) begin
           ls_fsm_ns = WAIT_RVALID;
         end
       end
 
       WAIT_RVALID: begin
         data_req_o = 1'b0;
-        if (data_rvalid_i) begin
+        // pmp_err_i will hold stable until the address is updated, and
+        // therefore pmp_err_q is valid in both WAIT_GNT and WAIT_RVALID states
+        if (data_rvalid_i || pmp_err_q) begin
           data_valid_o        = 1'b1;
+          data_or_pmp_err     = data_err_i | pmp_err_q;
           handle_misaligned_d = 1'b0;
           ls_fsm_ns           = IDLE;
         end else begin
@@ -421,10 +419,12 @@
       ls_fsm_cs           <= IDLE;
       addr_last_q         <= '0;
       handle_misaligned_q <= '0;
+      pmp_err_q           <= '0;
     end else begin
       ls_fsm_cs           <= ls_fsm_ns;
       addr_last_q         <= addr_last_d;
       handle_misaligned_q <= handle_misaligned_d;
+      pmp_err_q           <= data_pmp_err_i;
     end
   end
 
@@ -447,10 +447,9 @@
   // output to ID stage: mtval + AGU for misaligned transactions
   assign addr_last_o   = addr_last_q;
 
-  // to know what kind of error to signal, we need to know the type of the transaction to which
-  // the outsanding rvalid belongs.
-  assign load_err_o    = data_err_i & data_rvalid_i & ~data_we_q;
-  assign store_err_o   = data_err_i & data_rvalid_i &  data_we_q;
+  // Signal a load or store error depending on the transaction type outstanding
+  assign load_err_o    = data_or_pmp_err & ~data_we_q;
+  assign store_err_o   = data_or_pmp_err &  data_we_q;
 
   assign busy_o = (ls_fsm_cs == WAIT_RVALID) | (data_req_o == 1'b1);
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
index 34074b1..4be3bf2 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
@@ -1,20 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-//                                                                            //
-// Design Name:    Fast Multiplier and Division                               //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    16x16 kernel multiplier and Long Division                  //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 `define OP_L 15:0
 `define OP_H 31:16
 
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
index dddaa8d..1f58eab 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
@@ -1,20 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-//                                                                            //
-// Design Name:    Slow Multiplier and Division                               //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Baugh-Wooley multiplier and Long Division                  //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Slow Multiplier and Division
  *
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
index cf92a97..8df2f46 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
@@ -1,23 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2017 ETH Zurich and University of Bologna.
+// Copyright 2017 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Matthias Baer - baermatt@student.ethz.ch                   //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                                                                            //
-//                                                                            //
-// Design Name:    RISC-V processor core                                      //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Defines for various constants used by the processor core.  //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * Package with constants used by Ibex
  */
@@ -190,6 +175,7 @@
   // 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},
@@ -206,6 +192,36 @@
   DBG_CAUSE_STEP    = 3'h4
 } dbg_cause_e;
 
+// PMP constants
+parameter int unsigned PMP_MAX_REGIONS      = 16;
+parameter int unsigned PMP_CFG_W            = 8;
+
+// PMP acces type
+parameter int unsigned PMP_I = 0;
+parameter int unsigned PMP_D = 1;
+
+typedef enum logic [1:0] {
+  PMP_ACC_EXEC    = 2'b00,
+  PMP_ACC_WRITE   = 2'b01,
+  PMP_ACC_READ    = 2'b10
+} pmp_req_e;
+
+// 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;
+
+typedef struct packed {
+  logic          lock;
+  pmp_cfg_mode_e mode;
+  logic          exec;
+  logic          write;
+  logic          read;
+} pmp_cfg_t;
+
 // CSRs
 typedef enum logic[11:0] {
   // Machine information
@@ -224,6 +240,28 @@
   CSR_MTVAL     = 12'h343,
   CSR_MIP       = 12'h344,
 
+  // 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,
@@ -240,6 +278,10 @@
   CSR_MINSTRETH          = 12'hB82
 } csr_num_e;
 
+// 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 mhpmcounter-related offsets and mask
 parameter logic [11:0] CSR_OFF_MCOUNTER_SETUP = 12'h320; // mcounter_setup @ 12'h323 - 12'h33F
 parameter logic [11:0] CSR_OFF_MCOUNTER       = 12'hB00; // mcounter       @ 12'hB03 - 12'hB1F
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
new file mode 100644
index 0000000..e54edab
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
@@ -0,0 +1,113 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// 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
+) (
+    // 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::priv_lvl_e     priv_mode_i,    // Current priv mode, assumed to
+                                                    // be the same for all channels
+    // 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]
+
+);
+
+  import ibex_pkg::*; 
+
+  // Access Checking Signals
+  logic [33:0]                                region_start_addr [PMPNumRegions];
+  logic [33:PMPGranularity+2]                 region_addr_mask  [PMPNumRegions];
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   region_match_high;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   region_match_low;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   region_match_both;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   region_match_partial;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   region_perm_check;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   machine_access_fault;
+  logic [PMPNumChan-1:0][PMPNumRegions-1:0]   user_access_allowed;
+  logic [PMPNumChan-1:0]                      access_fault;
+
+
+  // ---------------
+  // Access checking
+  // ---------------
+
+  for (genvar r = 0; r < PMPNumRegions; r++) begin : g_addr_exp
+    // Start address for TOR matching
+    if (r == 0) begin : g_entry0
+      assign region_start_addr[r] = (csr_pmp_cfg_i[r].mode == PMP_MODE_TOR) ? 34'h000000000 :
+                                                                              csr_pmp_addr_i[r];
+    end else begin : g_oth
+      assign region_start_addr[r] = (csr_pmp_cfg_i[r].mode == PMP_MODE_TOR) ? csr_pmp_addr_i[r-1] :
+                                                                              csr_pmp_addr_i[r];
+    end
+    // Address mask for NA matching
+    for (genvar b = PMPGranularity+2; b < 34; b++) begin : g_bitmask
+      if (b == PMPGranularity+2) begin : g_bit0
+        // Always mask bit (G+2) for NAPOT
+        assign region_addr_mask[r][b] = (csr_pmp_cfg_i[r].mode != PMP_MODE_NAPOT);
+      end else begin : g_others
+        // We will mask this bit if it is within the programmed granule
+        // i.e. addr = yyyy 0111
+        //                  ^
+        //                  | This bit pos is the top of the mask, all lower bits set
+        // thus mask = 1111 0000
+        assign region_addr_mask[r][b] = (csr_pmp_cfg_i[r].mode != PMP_MODE_NAPOT) |
+                                        ~&csr_pmp_addr_i[r][b-1:PMPGranularity+2];
+      end
+    end
+  end
+
+  for (genvar c = 0; c < PMPNumChan; c++) begin : g_access_check
+    for (genvar r = 0; r < PMPNumRegions; r++) begin : g_regions
+      // TOR Region high/low matching is reused for all match types
+      assign region_match_low[c][r]     = (pmp_req_addr_i[c][33:PMPGranularity+2] >=
+                                           // Comparators are sized according to granularity
+                                           (region_start_addr[r][33:PMPGranularity+2] &
+                                            region_addr_mask[r]));
+      assign region_match_high[c][r]    = (pmp_req_addr_i[c][33:PMPGranularity+2] <=
+                                           (csr_pmp_addr_i[r][33:PMPGranularity+2] &
+                                            region_addr_mask[r]));
+      assign region_match_both[c][r]    = region_match_low[c][r] & region_match_high[c][r] &
+                                          (csr_pmp_cfg_i[r].mode != PMP_MODE_OFF);
+      assign region_match_partial[c][r] = (region_match_low[c][r] ^ region_match_high[c][r]) &
+                                          (csr_pmp_cfg_i[r].mode != PMP_MODE_OFF);
+      // Check specific required permissions
+      assign region_perm_check[c][r] =
+          ((pmp_req_type_i[c] == PMP_ACC_EXEC)  & csr_pmp_cfg_i[r].exec) |
+          ((pmp_req_type_i[c] == PMP_ACC_WRITE) & csr_pmp_cfg_i[r].write) |
+          ((pmp_req_type_i[c] == PMP_ACC_READ)  & csr_pmp_cfg_i[r].read);
+      // In machine mode, any match to a locked region without sufficient permissions is a fault
+      assign machine_access_fault[c][r] = region_match_both[c][r] & csr_pmp_cfg_i[r].lock &
+                                          ~region_perm_check[c][r];
+      if (r == 0) begin : g_region0
+        // In any other mode, any access should fault unless is matches a region
+        assign user_access_allowed[c][r]  = region_match_both[c][r] & region_perm_check[c][r];
+      end else begin : g_oth_regions
+        assign user_access_allowed[c][r]  = region_match_both[c][r] & region_perm_check[c][r] &
+        // any higher priority (lower region number) partial match should also cause a fault
+                                            ~|region_match_partial[c][r-1:0];
+      end
+    end
+    assign access_fault[c] = (priv_mode_i == PRIV_LVL_M) ? |machine_access_fault[c] :
+                                                           ~|user_access_allowed[c];
+
+    assign pmp_req_err_o[c] = access_fault[c];
+  end
+
+endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
index bef2d17..cda0bb7 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
@@ -1,19 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                                                                            //
-// Design Name:    Prefetcher Buffer for 32 bit memory interface              //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Prefetch Buffer that caches instructions. This cuts overly //
-//                 long critical paths to the instruction cache               //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
 /**
  * Prefetcher Buffer for 32 bit memory interface
  *
@@ -34,6 +23,7 @@
     output logic        valid_o,
     output logic [31:0] rdata_o,
     output logic [31:0] addr_o,
+    output logic        err_o,
 
 
     // goes to instruction memory / instruction cache
@@ -41,6 +31,8 @@
     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
@@ -56,6 +48,8 @@
   logic [31:0] instr_addr_q, fetch_addr;
   logic [31:0] instr_addr, instr_addr_w_aligned;
   logic        addr_valid;
+  logic        pmp_err_q;
+  logic        instr_or_pmp_err;
 
   logic        fifo_valid;
   logic        fifo_ready;
@@ -71,6 +65,10 @@
   // 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 | pmp_err_q;
+
   ibex_fetch_fifo fifo_i (
       .clk_i                 ( clk_i             ),
       .rst_ni                ( rst_ni            ),
@@ -79,6 +77,7 @@
 
       .in_addr_i             ( instr_addr_q      ),
       .in_rdata_i            ( instr_rdata_i     ),
+      .in_err_i              ( instr_or_pmp_err  ),
       .in_valid_i            ( fifo_valid        ),
       .in_ready_o            ( fifo_ready        ),
 
@@ -87,6 +86,7 @@
       .out_ready_i           ( ready_i           ),
       .out_rdata_o           ( rdata_o           ),
       .out_addr_o            ( addr_o            ),
+      .out_err_o             ( err_o             ),
 
       .out_valid_stored_o    (                   )
   );
@@ -141,7 +141,10 @@
         end
 
         //~> granted request or not
-        pf_fsm_ns = instr_gnt_i ? WAIT_RVALID : WAIT_GNT;
+        // If the instruction generated a PMP error, we may or may not
+        // get granted (the external valid is suppressed by the error)
+        // but we proceed to WAIT_RVALID to push the error to the fifo
+        pf_fsm_ns = (instr_gnt_i || pmp_err_q) ? WAIT_RVALID : WAIT_GNT;
       end // case: WAIT_GNT
 
       // we wait for rvalid, after that we are ready to serve a new request
@@ -155,7 +158,8 @@
         if (req_i && (fifo_ready || branch_i)) begin
           // prepare for next request
 
-          if (instr_rvalid_i) begin
+          // Fake the rvalid for PMP errors to push the error to the fifo
+          if (instr_rvalid_i || pmp_err_q) begin
             instr_req_o = 1'b1;
             fifo_valid  = 1'b1;
             addr_valid  = 1'b1;
@@ -173,7 +177,8 @@
         end else begin
           // just wait for rvalid and go back to IDLE, no new request
 
-          if (instr_rvalid_i) begin
+          // Fake the rvalid for PMP errors to push the error to the fifo
+          if (instr_rvalid_i || pmp_err_q) begin
             fifo_valid = 1'b1;
             pf_fsm_ns  = IDLE;
           end
@@ -214,11 +219,13 @@
     if (!rst_ni) begin
       pf_fsm_cs      <= IDLE;
       instr_addr_q   <= '0;
+      pmp_err_q      <= '0;
     end else begin
       pf_fsm_cs      <= pf_fsm_ns;
 
       if (addr_valid) begin
         instr_addr_q <= instr_addr;
+        pmp_err_q    <= instr_pmp_err_i;
       end
     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 07907ec..4dcfaeb 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -1,25 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Francesco Conti - f.conti@unibo.it                         //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                                                                            //
-// Design Name:    RISC-V register file                                       //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Register file with 31 or 15x 32 bit wide registers.        //
-//                 Register 0 is fixed to 0. This register file is based on   //
-//                 flip flops. Use this register file when targeting FPGA     //
-//                 synthesis or Verilator simulation.                         //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * RISC-V register file
  *
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 06d6aec..a5ec550 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -1,28 +1,8 @@
 // Copyright lowRISC contributors.
-// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Antonio Pullini - pullinia@iis.ee.ethz.ch                  //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Sven Stucki - svstucki@student.ethz.ch                     //
-//                 Markus Wegmann - markus.wegmann@technokrat.ch              //
-//                                                                            //
-// Design Name:    RISC-V register file                                       //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Register file with 31 or 15x 32 bit wide registers.        //
-//                 Register 0 is fixed to 0. This register file is based on   //
-//                 latches and is thus smaller than the flip-flop based RF.   //
-//                 It requires a target technology-specific clock gating      //
-//                 cell. Use this register file when targeting ASIC           //
-//                 synthesis or event-based simulators.                       //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 /**
  * RISC-V register file
  *
@@ -66,7 +46,7 @@
   logic [NUM_WORDS-1:1] mem_clocks;
   logic [DataWidth-1:0] wdata_a_q;
 
-  // Write port W1
+  // internal addresses
   logic [ADDR_WIDTH-1:0] raddr_a_int, raddr_b_int, waddr_a_int;
 
   assign raddr_a_int = raddr_a_i[ADDR_WIDTH-1:0];
@@ -75,24 +55,25 @@
 
   logic clk_int;
 
-  //////////////////////////////////////
-  // READ: Read address decoder (RAD) //
-  //////////////////////////////////////
+  //////////
+  // READ //
+  //////////
   assign rdata_a_o = mem[raddr_a_int];
   assign rdata_b_o = mem[raddr_b_int];
 
-  ///////////////////////////////
-  // WRITE: SAMPLE INPUT DATA //
-  ///////////////////////////////
-
+  ///////////
+  // WRITE //
+  ///////////
+  // Global clock gating
   prim_clock_gating cg_we_global (
-      .clk_i     ( clk_i           ),
-      .en_i      ( we_a_i          ),
-      .test_en_i ( test_en_i       ),
-      .clk_o     ( clk_int         )
+      .clk_i     ( clk_i     ),
+      .en_i      ( we_a_i    ),
+      .test_en_i ( test_en_i ),
+      .clk_o     ( clk_int   )
   );
 
-  // use clk_int here, since otherwise we don't want to write anything anyway
+  // Sample input data
+  // 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;
@@ -103,9 +84,7 @@
     end
   end
 
-  ///////////////////////////////////////////////////////////////
-  // WRITE: Write Address Decoder (WAD), combinatorial process //
-  ///////////////////////////////////////////////////////////////
+  // Write address decoding
   always_comb begin : wad
     for (int i = 1; i < NUM_WORDS; i++) begin : wad_word_iter
       if (we_a_i && (waddr_a_int == i)) begin
@@ -116,9 +95,7 @@
     end
   end
 
-  //////////////////////////////////////////////////////////////////////////
-  // WRITE: Clock gating (if integrated clock-gating cells are available) //
-  //////////////////////////////////////////////////////////////////////////
+  // Individual clock gating (if integrated clock-gating cells are available)
   for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_cg_word_iter
     prim_clock_gating cg_i (
         .clk_i     ( clk_int           ),
@@ -128,19 +105,11 @@
     );
   end
 
-  ////////////////////////////
-  // WRITE: Write operation //
-  ////////////////////////////
-  // Generate M = WORDS sequential processes, each of which describes one
-  // word of the memory. The processes are synchronized with the clocks
-  // ClocksxC(i), i = 0, 1, ..., M-1
-  // Use active low, i.e. transparent on low latches as storage elements
-  // Data is sampled on rising clock edge
-
+  // Actual write operation:
+  // Generate the sequential process for the NUM_WORDS words of the memory.
+  // The process is synchronized with the clocks mem_clocks[k], k = 1, ..., NUM_WORDS-1.
   always_latch begin : latch_wdata
-    // Note: The assignment has to be done inside this process or Modelsim complains about it
     mem[0] = '0;
-
     for (int k = 1; k < NUM_WORDS; k++) begin : latch_wdata_word_iter
       if (mem_clocks[k]) begin
         mem[k] = wdata_a_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
index 7bc2b88..2048d46 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
@@ -3,20 +3,6 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-////////////////////////////////////////////////////////////////////////////////
-// Engineer:       Andreas Traber - atraber@iis.ee.ethz.ch                    //
-//                                                                            //
-// Additional contributions by:                                               //
-//                 Davide Schiavone - pschiavo@iis.ee.ethz.ch                 //
-//                                                                            //
-// Design Name:    RISC-V Tracer                                              //
-// Project Name:   ibex                                                       //
-// Language:       SystemVerilog                                              //
-//                                                                            //
-// Description:    Traces the executed instructions                           //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
 // Source/Destination register instruction index
 `define REG_S1 19:15
 `define REG_S2 24:20
@@ -37,8 +23,7 @@
     input  logic                      rst_ni,
 
     input  logic                      fetch_enable_i,
-    input  logic [3:0]                core_id_i,
-    input  logic [5:0]                cluster_id_i,
+    input  logic [31:0]               hart_id_i,
 
     input  logic                      valid_i,
     input  logic [31:0]               pc_i,
@@ -304,7 +289,7 @@
   initial begin
     wait(rst_ni == 1'b1);
     wait(fetch_enable_i == 1'b1);
-    $sformat(fn, "trace_core_%h_%h.log", cluster_id_i, core_id_i);
+    $sformat(fn, "trace_core_%h.log", hart_id_i);
     $display("[TRACER] Output filename is: %s", fn);
     f = $fopen(fn, "w");
     $fwrite(f, "                Time          Cycles PC       Instr    Mnemonic\n");
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
index d0c1f25..88a159d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
@@ -1,5 +1,5 @@
 // Copyright lowRISC contributors.
-// Copyright 2017 ETH Zurich and University of Bologna.
+// Copyright 2017 ETH Zurich and University of Bologna, see also CREDITS.md.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
diff --git a/hw/vendor/lowrisc_ibex/src_files.yml b/hw/vendor/lowrisc_ibex/src_files.yml
index 4edd591..67513ea 100644
--- a/hw/vendor/lowrisc_ibex/src_files.yml
+++ b/hw/vendor/lowrisc_ibex/src_files.yml
@@ -17,6 +17,7 @@
     rtl/ibex_multdiv_fast.sv,
     rtl/ibex_prefetch_buffer.sv,
     rtl/ibex_fetch_fifo.sv,
+    rtl/ibex_pmp.sv,
     rtl/ibex_core.sv,
   ]
 ibex_vip_rtl:
@@ -29,6 +30,7 @@
     rtl/ibex_pkg.sv,
     rtl/ibex_tracer_pkg.sv,
     rtl/ibex_tracer.sv,
+    rtl/ibex_core_tracing.sv,
   ]
 ibex_regfile_rtl:
   targets: [
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 fccdd5f..b4e5d34 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: a07e0a726edf0230314c08d31546eecbed23054b
+    rev: 102791dbb7eb992d3bc22336d2e4e5f0d688e761
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
index b770311..4075aac 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
@@ -2,3 +2,4 @@
 *.bin
 out_*/
 work/
+*.pyc
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
index 44fd621..58d642f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
@@ -3,7 +3,7 @@
 RISCV-DV is a SV/UVM based open-source instruction generator for RISC-V
 processor verification. It currently supports the following features:
 
-- Supported instruction set: RV32IMC, RV64IMC
+- Supported instruction set: RV32IMAC, RV64IMAC
 - Supported privileged mode: machine mode, supervisor mode, user mode
 - Page table randomization and exception
 - Privileged CSR setup randomization
@@ -15,6 +15,10 @@
 - Supports mixing directed instructions with random instruction stream
 - Supports co-simulation with multiple ISS : spike, riscv-ovpsim
 
+A CSR test generation script written in Python is also provided, to generate a
+directed test suite that stresses all CSR instructions on all of the CSRs that
+the core implements.
+
 ## Getting Started
 
 ### Prerequisites
@@ -24,9 +28,26 @@
 Synopsys VCS, Cadence Incisive/Xcelium, and Mentor Questa simulators. Please
 make sure the EDA tool environment is properly setup before running the generator.
 
+To be able to run the CSR generation script, the open-source `bitstring`
+Python library is required ([bitstring](https://github.com/scott-griffiths/bitstring)).
+To install this library, either clone the repository and run the `setup.py`
+setup script, or run only one of the below commands:
+```
+1) sudo apt-get install python3-bitstring (or your OS-specific package manager)
+2) pip install bitstring
+```
+
 ### Running the generator
 
-A simple script "run" is provided for you to run a single test or a regression.
+
+A simple script "run.py" is provided for you to run a single test or a regression.
+
+You can use --help to get the complete command reference:
+
+```
+python3 run.py --help
+```
+
 Here is the command to run a single test:
 
 ```
@@ -35,9 +56,9 @@
 You can specify the simulator by "-simulator" option
 
 ```
-python3 run.py --test=riscv_arithmetic_basic_test --simulator=irun
-python3 run.py --test=riscv_arithmetic_basic_test --simulator=vcs
-python3 run.py --test=riscv_arithmetic_basic_test --simulator=questa
+python3 run.py --test riscv_arithmetic_basic_test --simulator ius
+python3 run.py --test riscv_arithmetic_basic_test --simulator vcs
+python3 run.py --test riscv_arithmetic_basic_test --simulator questa
 ```
 The complete test list can be found in [yaml/testlist.yaml](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml). To run a full
 regression, simply use below command
@@ -55,20 +76,45 @@
 Here's a few more examples of the run command:
 
 ```
-// Get the complete command reference info
-python3 run.py --help
-
 // Run a single test 10 times
-python3 run.py --test=riscv_page_table_exception_test --iterations=10
+python3 run.py --test riscv_page_table_exception_test --iterations 10
+
+// Run a test with verbose logging
+python3 run.py --test riscv_page_table_exception_test --verbose
 
 // Run a test with a specified seed
-python3 run.py --test=riscv_page_table_exception_test --seed=123
+python3 run.py --test riscv_page_table_exception_test --seed 123
 
 // Skip the generation, run ISS simulation with previously generated program
-python3 run.py --test=riscv_page_table_exception_test --steps=iss_sim
+python3 run.py --test riscv_page_table_exception_test --steps iss_sim
+
+// Run the generator only, do not compile and simluation with ISS
+python3 run.py --test riscv_page_table_exception_test --steps gen
+
+// Compile the generator only, do not simulate
+python3 run.py --test riscv_page_table_exception_test --co
+
 ....
 ```
 
+### Privileged CSR Test Generation
+
+
+The CSR generation script is located at
+[scripts/gen_csr_test.py](https://github.com/google/riscv-dv/blob/master/scripts/gen_csr_test.py).
+The CSR test code that this script generates will execute every CSR instruction
+on every processor implemented CSR, writing values to the CSR and then using a
+prediction function to calculate a reference value that will be written into
+another GPR. The reference value will then be compared to the value actually
+stored in the CSR to determine whether to jump to the failure condition or
+continue executing, allowing it to be completely self checking. This script has
+been integrated with run.py. If you want to run it separately, you can get the
+command reference with --help:
+
+```
+python3 scripts/gen_csr_test.py --help
+```
+
 ## Configuration
 
 ### Setup regression test list
@@ -76,15 +122,17 @@
 [Test list in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml)
 
 ```
-# test         : Assembly test name
-# description  : Description of this test
-# gen_opts     : Instruction generator options
-# iterations   : Number of iterations of this test
-# gen_test     : Test name used by the instruction generator
-# rtl_test     : RTL simulation test name
-# cmp_opts     : Compile options passed to the instruction generator
-# sim_opts     : Simulation options passed to the instruction generator
-# compare_opts : Options for the RTL & ISS trace comparison
+# test            : Assembly test name
+# description     : Description of this test
+# gen_opts        : Instruction generator options
+# iterations      : Number of iterations of this test
+# no_iss          : Enable/disable ISS simulation (Optional)
+# gen_test        : Test name used by the instruction generator
+# rtl_test        : RTL simulation test name
+# cmp_opts        : Compile options passed to the instruction generator
+# sim_opts        : Simulation options passed to the instruction generator
+# no_post_compare : Enable/disable log comparison (Optional)
+# compare_opts    : Options for the RTL & ISS trace comparison
 
 - test: riscv_arithmetic_basic_test
   description: >
@@ -102,6 +150,11 @@
 
 ```
 
+Note: To automatically generate CSR tests without having to explicitly run the
+script, include `riscv_csr_test` in the testlist as shown in the example YAML
+file above.
+
+
 ### Configure the generator to match your processor features
 
 The default configuration of the instruction generator is for RV64IMC RISC-V
@@ -133,23 +186,76 @@
 
 ### Runtime options of the generator
 
-| Option   |      Description      | default |
-|----------|:-------------:|:------:|
-| num_of_tests |  Number of assembly tests to be generated | 1 |
-| num_of_sub_program |    Number of sub-program in one test    | 5 |
-| instr_cnt | Instruction count per test  | 200 | 
-| enable_page_table_exception | Enable page table exception  | 0 |
-| no_ebreak |  Disable ebreak instruction  | 1 |
-| no_wfi | Disable WFI instruction  | 1 |
-| no_branch_jump | Disable branch/jump instruction   | 0 |
-| no_load_store | Disable load/store instruction  | 0 |
-| no_csr_instr | Disable CSR instruction | 0 |
-| no_fence | Disable fence instruction  | 0 |
-| enable_illegal_instruction | Enable illegal instructions  | 0 |
-| enable_hint_instruction |  Enable HINT instruction  | 0 |
-| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode  | m |
-| no_directed_instr | Disable directed instruction stream  | 0 |
-| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 |
+| Option                      | Description                                       | Default |
+|:---------------------------:|:-------------------------------------------------:|:-------:|
+| num_of_tests                | Number of assembly tests to be generated          | 1       |
+| num_of_sub_program          | Number of sub-program in one test                 | 5       |
+| instr_cnt                   | Instruction count per test                        | 200     |
+| enable_page_table_exception | Enable page table exception                       | 0       |
+| no_ebreak                   | Disable ebreak instruction                        | 1       |
+| no_wfi                      | Disable WFI instruction                           | 1       |
+| no_branch_jump              | Disable branch/jump instruction                   | 0       |
+| no_load_store               | Disable load/store instruction                    | 0       |
+| no_csr_instr                | Disable CSR instruction                           | 0       |
+| no_fence                    | Disable fence instruction                         | 0       |
+| enable_illegal_instruction  | Enable illegal instructions                       | 0       |
+| enable_hint_instruction     | Enable HINT instruction                           | 0       |
+| boot_mode                   | m:Machine mode, s:Supervisor mode, u:User mode    | m       |
+| no_directed_instr           | Disable directed instruction stream               | 0       |
+| require_signature_addr      | Set to 1 if test needs to talk to testbench       | 0       |
+| signature_addr              | Write to this addr to send data to testbench      | 0       |
+| enable_interrupt            | Enable MStatus.MIE, used in interrupt test        | 0       |
+| gen_debug_section           | Disables randomized debug_rom section             | 0       |
+| num_debug_sub_program       | Number of debug sub-programs in test              | 0       |
+
+
+### Setup Privileged CSR description
+
+This YAML description file of all CSRs is only required for the privileged CSR
+test. All other standard tests do not use this description.
+
+[CSR descriptions in YAML
+format](https://github.com/google/riscv-dv/blob/master/yaml/csr_template.yaml)
+
+```
+- csr: CSR_NAME
+  description: >
+    BRIEF_DESCRIPTION
+  address: 0x###
+  privilege_mode: MODE (D/M/S/H/U)
+  rv32:
+    - MSB_FIELD_NAME:
+      - description: >
+          BRIEF_DESCRIPTION
+      - type: TYPE (WPRI/WLRL/WARL/R)
+      - reset_val: RESET_VAL
+      - msb: MSB_POS
+      - lsb: LSB_POS
+    - ...
+    - ...
+    - LSB_FIELD_NAME:
+      - description: ...
+      - type: ...
+      - ...
+  rv64:
+    - MSB_FIELD_NAME:
+      - description: >
+          BRIEF_DESCRIPTION
+      - type: TYPE (WPRI/WLRL/WARL/R)
+      - reset_val: RESET_VAL
+      - msb: MSB_POS
+      - lsb: LSB_POS
+    - ...
+    - ...
+    - LSB_FIELD_NAME:
+      - description: ...
+      - type: ...
+      - ...
+```
+
+To specify what ISA width should be generated in the test, simply include the
+matching rv32/rv64/rv128 entry and fill in the appropriate CSR field entries.
+
 
 ### Adding new instruction stream and test
 
@@ -163,28 +269,39 @@
 +directed_instr_5=riscv_multi_page_load_store_instr_stream,4
 ```
 
-## Run ISS(Instruction Set Simulator) simulation
+## Compile generated programs with GCC
 
-The default ISS is spike. Thanks for the great support from Imperas Software Ltd.,
-we have added the support for [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim).
+- Install [riscv-gcc](https://github.com/riscv/riscv-gcc) toolchain
+- Set environment variable RISCV_GCC to the directory of the RISC-V gcc
+  executable. (example: <install_dir>/bin/riscv32-unknown-elf-gcc)
 
-- spike setup
+## Run ISS (Instruction Set Simulator) simulation
+
+Currently three ISS are supported, the default ISS is spike. You can install any
+one of below to run ISS simulation.
+
+- [spike](https://github.com/riscv/riscv-isa-sim#) setup
   - Follow the [steps](https://github.com/riscv/riscv-isa-sim#build-steps) to build spike
      - Make sure RISCV_ENABLE_COMMITLOG is defined in [config.h.in](https://github.com/riscv/riscv-isa-sim/blob/master/config.h.in)
   - Set environment variable SPIKE_PATH to the directory of the spike binary
 - [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim) setup
   - Download the riscv-ovpsim binary
   - Set environment variable OVPSIM_PATH to the directory of the ovpsim binary
-
+- [sail-riscv](https://github.com/rems-project/sail-riscv) setup
+  - Follow the [steps](https://github.com/rems-project/sail-riscv/blob/master/README.md) to install sail-riscv
+  - Set environment variable SAIL_RISCV to the sail-riscv binary
 
 You can use -iss to run with different ISS.
 
 ```
 // Run ISS with spike
-python3 run.py --test=riscv_page_table_exception_test --iss=spike
+python3 run.py --test riscv_page_table_exception_test --iss spike
 
 // Run ISS with riscv-ovpsim
-python3 run.py --test=riscv_rand_instr_test --iss=ovpsim
+python3 run.py --test riscv_rand_instr_test --iss ovpsim
+
+// Run ISS with sail-riscv
+python3 run.py --test riscv_rand_instr_test --iss sail
 ```
 
 To run with ISS simulation for RV32IMC, you can specify ISA and ABI from command
@@ -192,7 +309,7 @@
 
 ```
 // Run a full regression with RV32IMC
-python3 run.py --isa=rv32imc --mabi=ilp32
+python3 run.py --isa rv32imc --mabi ilp32
 ```
 
 We have added a flow to run ISS simulation with both spike and riscv-ovpsim,
@@ -202,6 +319,7 @@
 
 ```
 python3 run.py --test=riscv_rand_instr_test --iss=spike,ovpsim
+python3 run.py --test=riscv_rand_instr_test --iss=spike,sail
 ```
 
 ### Integrate a new ISS
@@ -218,13 +336,13 @@
 Simulate with the new ISS
 
 ```
-python3 run.py --test=riscv_page_table_exception_test --iss=new_iss_name
+python3 run.py --test riscv_page_table_exception_test --iss new_iss_name
 ```
 
 ## End-to-end RTL and ISS co-simulation flow
 
 We have collaborated with LowRISC to apply this flow for [IBEX RISC-V core
-verification](https://github.com/lowRISC/ibex/tree/master/dv/uvm). You can use
+verification](https://github.com/lowRISC/ibex/blob/master/doc/verification.rst). You can use
 it as a reference to setup end-to-end co-simulation flow. It's also a good
 reference for [customizing the generator](https://github.com/lowRISC/ibex/tree/master/dv/uvm/riscv_dv_extension) without getting impacted by upstream
 changes.
@@ -252,73 +370,6 @@
 -   Coverage model.
 -   Debug mode support
 
-### DEPRECATED simulation flow
-
-Note: The flow mentioned below will soon be deprecated. Please switch to new
-flow.
-
-A simple script "run" is provided for you to run a single test or a regression.
-Here is the command to run a single test:
-
-```
-./run -test riscv_instr_base_test
-```
-You can specify the simulator by "-tool" option
-
-```
-./run -test riscv_instr_base_test -tool irun
-./run -test riscv_instr_base_test -tool vcs
-./run -test riscv_instr_base_test -tool questa
-```
-The complete test list can be found in testlist. To run a full regression, you
-can just specify the test name to "all".
-
-```
-./run -test all
-```
-The script will run each test in the test list sequentially with the iteration
-count specified in the "testlist". All the generated RISC-V assembly will be
-listed when the regression is done. If it is successful, you should see the
-following output:
-
-```
-===========================================================
-                Generated RISC-V assembly tests
- ----------------------------------------------------------
-./out_2018-11-20/asm_tests/riscv_arithmetic_basic_test.0.S
-./out_2018-11-20/asm_tests/riscv_machine_mode_rand_test.0.S
-./out_2018-11-20/asm_tests/riscv_mmu_stress_test.0.S
-./out_2018-11-20/asm_tests/riscv_mmu_stress_test.1.S
-./out_2018-11-20/asm_tests/riscv_no_fence_test.0.S
-./out_2018-11-20/asm_tests/riscv_page_table_exception_test.0.S
-./out_2018-11-20/asm_tests/riscv_page_table_exception_test.1.S
-./out_2018-11-20/asm_tests/riscv_privileged_mode_rand_test.0.S
-./out_2018-11-20/asm_tests/riscv_privileged_mode_rand_test.1.S
-./out_2018-11-20/asm_tests/riscv_rand_instr_test.0.S
-./out_2018-11-20/asm_tests/riscv_rand_instr_test.1.S
-./out_2018-11-20/asm_tests/riscv_rand_jump_test.0.S
-./out_2018-11-20/asm_tests/riscv_sfence_exception_test.0.S
-```
-
-Here's a few more examples of the run command:
-
-```
-// Run a single test 10 times
-./run -test riscv_page_table_exception_test -n 10
-
-// Run a test with a specified seed
-./run -test riscv_page_table_exception_test -seed 123
-
-// Run a test with addtional runtime options, separated with comma
-./run -test riscv_rand_instr_test -runo +instr_cnt=10000,+no_fence=1
-
-// Two steps compile and simulation (Avoid multiple compilation)
-./run -co # compile only
-# Generate multiple tests
-./run -so -test riscv_rand_instr_test -n 10
-./run -so -test riscv_mmu_stress_test -n 20
-....
-```
 ## Disclaimer
 
 This is not an officially supported Google product.
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/files.f b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/files.f
index bfd9b7a..8722407 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/files.f
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/files.f
@@ -17,6 +17,7 @@
 +incdir+./test
 
 // SOURCES
+./src/riscv_signature_pkg.sv
 ./src/riscv_instr_pkg.sv
 ./test/riscv_instr_test_pkg.sv
 ./test/riscv_instr_gen_tb_top.sv
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_cmp b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_cmp
deleted file mode 100755
index 18f915e..0000000
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_cmp
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-# Copyright 2018 Google LLC
-#
-# 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.
-
-spike_log="$1"
-ovpsim_log="$2"
-report_file="$3"
-
-# -----------------------------------------------------------------------------
-# Convert spike log to standard instruction trace csv
-# -----------------------------------------------------------------------------
-# Convert the spike log to riscv_instr_trace.proto format
-spike_csv=$(echo "$spike_log" | sed 's/\.log/.csv/g')
-python scripts/spike_log_to_trace_csv.py --log $spike_log \
-                                         --csv $spike_csv --xlen 64
-
-# -----------------------------------------------------------------------------
-# Convert ovpsim log to standard instruction trace csv
-# -----------------------------------------------------------------------------
-# Convert the spike log to riscv_instr_trace.proto format
-ovpsim_csv=$(echo "$ovpsim_log" | sed 's/\.log/.csv/g')
-python scripts/ovpsim_log_to_trace_csv.py --log $ovpsim_log --csv $ovpsim_csv
-
-# -----------------------------------------------------------------------------
-# Compare the trace log
-# -----------------------------------------------------------------------------
-python scripts/instr_trace_compare.py $spike_csv $ovpsim_csv \
-                                      spike ovpsim >> $report_file
-echo >> $report_file
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_sim b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_sim
deleted file mode 100755
index 22baa05..0000000
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/iss_sim
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/bin/bash
-# Copyright 2018 Google LLC
-#
-# 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.
-
-# Environment variable for the path of RISC-V GCC toolchain
-# You can install the toolchain from https://github.com/riscv/riscv-gcc
-# RISCV_TOOLCHAIN="XXX"
-
-# GCC compile options
-ABI="lp64"
-ISA="rv64imc"
-
-DATE=`date +%Y-%m-%d`
-
-# Instruction set simulator
-ISS="spike" # other options: ovpsim, all
-
-# riscv-ovpsim options
-OVPSIM_VARIANT="RV64GC"
-
-# Binary of RISC-V ovpsim ISS
-# https://github.com/riscv/riscv-ovpsim
-RISCV_OVPSIM="${OVPSIM_PATH}/riscvOVPsim.exe"
-
-# Directory of assemble tests
-SRC_DIR="./out_${DATE}/asm_tests"
-
-# Assembly test file name
-TEST=""
-
-# Regression report file name
-REPORT="$SRC_DIR/regression_report.log"
-
-# Clean the result of the previous runs
-CLEAN=1
-
-if [[ -z $RISCV_TOOLCHAIN ]]; then
-  echo "ERROR: Please define RISCV_TOOLCHAIN environment variable first"
-  exit 1
-fi
-
-# Process command line options
-while [[ $# -gt 0 ]]
-do
-key="$1"
-  case $key in
-    -iss)
-    ISS="$2"
-    shift
-    ;;
-    -dir)
-    SRC_DIR="$2"
-    shift
-    ;;
-    -toolchain)
-    RISCV_TOOLCHAIN="$2"
-    shift
-    ;;
-    -isa)
-    ISA="$2"
-    shift
-    ;;
-    -abi)
-    ABI="$2"
-    shift
-    ;;
-    -test)
-    TEST="$2"
-    shift
-    ;;
-    -report)
-    REPORT="$2"
-    shift
-    ;;
-    -noclean)
-    CLEAN=0
-    shift
-    ;;
-    *)
-    echo "unknown option $1"
-    return
-    ;;
-esac
-shift
-done
-
-RISCV_GCC="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-gcc"
-RISCV_OBJCOPY="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-objcopy"
-RISCV_SPIKE="$RISCV_TOOLCHAIN/bin/spike"
-
-mkdir -p "$SRC_DIR"
-
-# If the test is specified through "-test" option, run a single test rather
-# than all tests under SRC_DIR.
-if [[ $TEST == "" ]]; then
-  find "$SRC_DIR" -name "*.S" > "$SRC_DIR/asm_test_list"
-else
-  echo "$TEST" > "$SRC_DIR/asm_test_list"
-fi
-
-if [[ $ISA =~ 32 ]]; then
-  OVPSIM_VARIANT="RV32GC"
-fi
-
-# Clean up previous running result
-if [[ $CLEAN == 1 ]]; then
-  rm -rf "$REPORT"
-  if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then
-    rm -rf "$SRC_DIR/spike_sim"
-  fi
-  if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then
-    rm -rf "$SRC_DIR/riscv_ovpsim"
-  fi
-fi
-
-# GCC compile
-while read asm_test; do
-  # Generate binary for RTL simulation
-  SRC="$asm_test"
-  OBJFILE="$asm_test.o"
-  BINFILE="$asm_test.bin"
-  GCC_CMD="$RISCV_GCC -march=$ISA -mabi=$ABI -static -mcmodel=medany \
-           -fvisibility=hidden -nostdlib \
-           -nostartfiles -I$RISCV_TESTS/env/p \
-           -Tscripts/link.ld $SRC -o $OBJFILE"
-  echo "riscv_gcc compiling : $SRC"
-  $($GCC_CMD)
-  echo "Convert $OBJFILE to $BINFILE"
-  # Convert the ELF to plain binary
-  # You can load this binary to your RTL simulation
-  "$RISCV_OBJCOPY" -O binary "$OBJFILE" "$BINFILE"
-done <"$SRC_DIR/asm_test_list"
-
-if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then
-  mkdir -p "$SRC_DIR/riscv_ovpsim"
-fi
-if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then
-  mkdir -p "$SRC_DIR/spike_sim"
-fi
-
-# Run ISS simulation
-while read asm_test; do
-  ELF="${asm_test}.o"
-  TEST_NAME=$(echo "$ELF" | sed 's/^.*\///g')
-  # Spike sim
-  if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then
-    echo "Running spike: $TEST_NAME"
-    SPIKE_LOG="$SRC_DIR/spike_sim/$TEST_NAME.log"
-    SPIKE_CMD="timeout 60s $RISCV_SPIKE --isa=$ISA -l $ELF &> $SPIKE_LOG"
-    $($SPIKE_CMD &> $SPIKE_LOG)
-  fi
-  # riscv_ovpsim sim
-  if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then
-    if [[ -z $OVPSIM_PATH ]]; then
-      echo "ERROR: Please define OVPSIM_PATH environment variable first"
-      exit 1
-    fi
-    OVPSIM_LOG="$SRC_DIR/riscv_ovpsim/$TEST_NAME.log"
-    echo "Running ovpsim: $TEST_NAME"
-    RISCV_OVPSIM_CMD="$RISCV_OVPSIM --variant $OVPSIM_VARIANT \
-                      --override riscvOVPsim/cpu/PMP_registers=0 \
-                      --override riscvOVPsim/cpu/simulateexceptions=T \
-                      --trace --tracechange --traceshowicount --program $ELF \
-                      --finishafter 500000"
-    $($RISCV_OVPSIM_CMD &> $OVPSIM_LOG)
-  fi
-  if [[ "$ISS" == "all" ]]; then
-    echo "Rerun command: ./iss_sim -test $asm_test -iss all" >> "$REPORT"
-    echo "spike  : $SPIKE_LOG" >> "$REPORT"
-    echo "ovpsim : $OVPSIM_LOG" >> "$REPORT"
-    ./iss_cmp "$SPIKE_LOG" "$OVPSIM_LOG" "$REPORT"
-    tail -1 "$REPORT"
-    echo "" >> "$REPORT"
-  fi
-done <"$SRC_DIR/asm_test_list"
-
-if [[ "$ISS" == "all" ]]; then
-  echo "Full regression report is saved to $REPORT"
-  cat "$REPORT"
-fi
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run
deleted file mode 100755
index 23980f2..0000000
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/bin/bash
-# Copyright 2018 Google LLC
-#
-# 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.
-
-
-# This is simple run script to run a dedicated test or a regression
-#
-# Usage:
-# Run a single test with irun
-# ./run -tool irun -test riscv_instr_base_test
-#
-# Run regression with vcs
-# ./run -test all
-#
-# Change output directory
-# ./run -out my_output_dir
-
-DATE=`date +%Y-%m-%d`
-
-# RTL simulator, supports vcs, irun, and questa
-SIMULATOR="vcs"
-
-# random seed
-SEED=`date +%s`
-
-# Test name, "all" means run all tests in the testlist
-TEST="riscv_instr_base_test"
-
-# Number of assembly programs to be generated for this test
-# This option only apply to single test mode. For the regression mode, the number is specified in
-# the testlist
-NUM_TESTS=1
-
-# Simulation output directory
-OUT="./out_${DATE}"
-
-# Simulation only
-SIM_ONLY=0
-
-# Compile only
-CMP_ONLY=0
-
-# Compile/run time options
-SIM_OPTS=""
-CMP_OPTS=""
-
-# Verbose logging, by default disable detail logging
-VERBOSE=0
-
-# Submit to LSF
-LSF_CMD="bsub"
-LSF_OPTS=""
-LSF=0
-LSF_TIMEOUT=100
-
-# Testlist for regression
-TEST_LIST=testlist
-
-# Process command line options
-while [[ $# -gt 0 ]]
-do
-key="$1"
-case $key in
-    -tool)
-    SIMULATOR="$2"
-    shift
-    ;;
-    -test)
-    TEST="$2"
-    shift
-    ;;
-    -n)
-    NUM_TESTS="$2"
-    shift
-    ;;
-    -seed)
-    SEED="$2"
-    shift
-    ;;
-    -sim_opts)
-    SIM_OPTS="$2"
-    shift
-    ;;
-    -cmp_opts)
-    CMP_OPTS="$2"
-    shift
-    ;;
-    -testlist)
-    TEST_LIST="$2"
-    shift
-    ;;
-    -timeout)
-    LSF_TIMEOUT="$2"
-    shift
-    ;;
-    -so)
-    SIM_ONLY=1
-    ;;
-    -verbose)
-    VERBOSE=1
-    ;;
-    -co)
-    CMP_ONLY=1
-    ;;
-    -lsf)
-    LSF=1
-    ;;
-    -lsf_opts)
-    LSF_OPTS="$2"
-    shift
-    ;;
-    -o)
-    OUT="$2"
-    shift
-    ;;
-    *)
-    echo "unknown option $1"
-    exit 1
-    ;;
-esac
-shift
-done
-
-if [[ $LSF == 0 ]]; then
-  LSF_CMD=""
-fi
-
-OUT=`realpath ${OUT}`
-
-# Generate compile and simulation commands
-if [[ "$SIMULATOR" == "vcs" ]]; then
-
-  function run_compile {
-    vcs -file ./vcs.compile.option.f \
-        -f ./files.f -full64 \
-        -l $OUT/compile.log  \
-        -Mdir=$OUT/vcs_simv.csrc \
-        -o $OUT/vcs_simv ${CMP_OPTS}
-  }
-
-  SIM_CMD="$OUT/vcs_simv +vcs+lic+wait +UVM_TESTNAME="
-  SIM_SEED="+ntb_random_seed="
-
-elif [[ "$SIMULATOR" == "irun" ]]; then
-
-  function run_compile {
-    irun -64bit \
-         -access +rwc \
-         -f ./files.f \
-         -q -sv -uvm  \
-         -vlog_ext +.vh -I. \
-         -uvmhome CDNS-1.2 \
-         -elaborate \
-         -l ${OUT}/compile.log ${CMP_OPTS}
-    }
-
-  SIM_CMD="irun -R +UVM_TESTNAME="
-  SIM_SEED="-svseed "
-
-elif [[ "$SIMULATOR" == "questa" ]]; then
-#Questa requires mapping libraries to compile correctly
-  function run_compile {
-      vmap mtiUvm $QUESTA_HOME/questasim/uvm-1.2
-      vlog -64 \
-           -access=rwc \
-           -f ./files.f \
-           -sv \
-           -mfcu -cuname design_cuname \
-           +define+UVM_REGEX_NO_DPI \
-           -writetoplevels ${OUT}/top.list \
-           -l ${OUT}/compile.log ${CMP_OPTS}
-      vopt -64 -debug \
-           +designfile -f ${OUT}/top.list \
-           -l ${OUT}/optimize.log ${CMP_OPTS} \
-           -o design_opt
-    }
-
-  SIM_CMD="vsim -64 -c  -do questa_sim.tcl design_opt  +UVM_TESTNAME="
-  SIM_SEED="-sv_seed "
-
-else
-  echo "unsupported simulator $SIMULATOR"
-  exit 1
-fi
-
-# Clean up previous runs
-if [[ $SIM_ONLY == 0 ]]; then
-  rm -rf ${OUT}
-else
-  rm -rf ${OUT}/asm_tests
-fi
-
-mkdir -p ${OUT}
-mkdir -p ${OUT}/asm_tests
-
-# Compilation
-if [[ $SIM_ONLY == 0 ]]; then
-  echo "Building RISC-V instruction generator..."
-  if [[ $VERBOSE == 1 ]]; then
-    run_compile
-  else
-    run_compile > /dev/null
-  fi
-  echo "Building RISC-V instruction generator...done"
-fi
-
-# Skip simulation if compilation only flag is set
-if [[ $CMP_ONLY == 1 ]]; then
-  exit 0
-fi
-
-# Run sim
-if [[ ${TEST} == "all" ]]; then
-  echo "Running regression with testlist: $TEST_LIST"
-  LOG_LIST="${OUT}/sim_log.list"
-  PROGRAM_CNT=0
-  cat "$TEST_LIST"
-  rm -rf "$LOG_LIST"
-  while read line; do
-    if ! [[ $line =~ ^\/\/ ]]; then
-      if [[ $line =~([a-z0-9_-]*)([[:space:]]*)\:([[:space:]]*)([0-9]*)([[:space:]]*)\:(.*$) ]]; then
-        SEED=`date +%s`
-        TEST=${BASH_REMATCH[1]}
-        ITERATION=${BASH_REMATCH[4]}
-        TEST_OPTS=${BASH_REMATCH[6]}
-        if [[ ${ITERATION} != "0" ]]; then
-          echo "Running ${TEST} to generate ${ITERATION} tests"
-          CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
-               ${SIM_SEED}${SEED} ${TEST_OPTS} ${SIM_OPTS} \
-               -l ${OUT}/sim_${TEST}.log +num_of_tests=${ITERATION}"
-          ((PROGRAM_CNT+=$ITERATION))
-          echo "${OUT}/sim_${TEST}.log" >> ${LOG_LIST}
-          if [[ $VERBOSE == 1 ]]; then
-            ${LSF_CMD} ${LSF_OPTS} ${CMD}
-          else
-            ${LSF_CMD} ${LSF_OPTS} ${CMD} > /dev/null
-          fi
-        fi
-      fi
-    fi
-  done < $TEST_LIST
-  # Wait util all tests are generated
-  if [[ $LSF == 1 ]]; then
-    TIMEOUT_CNT=0
-    TOTAL_CNT=`wc -l < ${LOG_LIST}`
-    echo "Waiting for ${TOTAL_CNT} tests to complete, ${PROGRAM_CNT} programs to generate."
-    while [[ 1 ]]; do
-      COMPLETED_CNT=0
-      while read log; do
-        if [[ -f "$log" ]]; then
-          if grep -q "TEST GENERATION DONE" $log; then
-            ((COMPLETED_CNT+=1))
-          else
-            if [[ $VERBOSE == 1 ]]; then
-              echo "$log is not completed"
-            fi
-          fi
-        else
-          if [[ $VERBOSE == 1 ]]; then
-            echo "$log is not completed"
-          fi
-        fi
-      done < ${LOG_LIST}
-      GENERATED_CNT=`find ${OUT}/asm_tests/ -name "*.S" | wc -l`
-      echo "[$TIMEOUT_CNT] Progress > Test:${COMPLETED_CNT}/${TOTAL_CNT} Program:${GENERATED_CNT}/${PROGRAM_CNT}"
-      if [[ "$COMPLETED_CNT" == "$TOTAL_CNT" ]]; then
-        break
-      else
-        if [[ "$TIMEOUT_CNT" == "$LSF_TIMEOUT" ]]; then
-          echo "Generator timeout after $LSF_TIMEOUT * 10 seconds"
-          break
-        else
-          sleep 10
-        fi
-      fi
-      ((TIMEOUT_CNT+=1))
-    done
-  fi
-else
-  echo "Running test ${TEST} to generate ${NUM_TESTS} tests"
-  CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
-                    ${SIM_SEED}${SEED} \
-                    -l ${OUT}/sim_${TEST}.log \
-                    +num_of_tests=${NUM_TESTS} ${SIM_OPTS}"
-  if [[ $VERBOSE == 1 ]]; then
-    ${CMD}
-  else
-    ${CMD} > /dev/null
-  fi
-fi
-
-
-# List all generated assembly tests
-echo "==========================================================="
-echo "                Generated RISC-V assembly tests"
-echo " ----------------------------------------------------------"
-find $OUT/asm_tests -name "*.S" | sort -k11
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 fe32c7f..0da97d8 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
@@ -21,12 +21,17 @@
 import subprocess
 import re
 import sys
+import logging
 
+from datetime import date
 from scripts.lib import *
 from scripts.spike_log_to_trace_csv import *
 from scripts.ovpsim_log_to_trace_csv import *
+from scripts.sail_log_to_trace_csv import *
 from scripts.instr_trace_compare import *
 
+LOGGER = logging.getLogger()
+
 def get_generator_cmd(simulator, simulator_yaml):
   """ Setup the compile and simulation command for the generator
 
@@ -38,16 +43,16 @@
     compile_cmd    : RTL simulator command to compile the instruction generator
     sim_cmd        : RTL simulator command to run the instruction generator
   """
-  print("Processing simulator setup file : %s" % simulator_yaml)
+  logging.info("Processing simulator setup file : %s" % simulator_yaml)
   yaml_data = read_yaml(simulator_yaml)
   # Search for matched simulator
   for entry in yaml_data:
     if entry['tool'] == simulator:
-      print ("Found matching simulator: %s" % entry['tool'])
+      logging.info("Found matching simulator: %s" % entry['tool'])
       compile_cmd = entry['compile_cmd']
       sim_cmd = entry['sim_cmd']
       return compile_cmd, sim_cmd
-  print ("Cannot find RTL simulator %0s" % simulator)
+  logging.error("Cannot find RTL simulator %0s" % simulator)
   sys.exit(1)
 
 
@@ -62,12 +67,12 @@
   Returns:
     cmd        : ISS run command
   """
-  print("Processing ISS setup file : %s" % iss_yaml)
+  logging.info("Processing ISS setup file : %s" % iss_yaml)
   yaml_data = read_yaml(iss_yaml)
   # Search for matched ISS
   for entry in yaml_data:
     if entry['iss'] == iss:
-      print ("Found matching ISS: %s" % entry['iss'])
+      logging.info("Found matching ISS: %s" % entry['iss'])
       cmd = entry['cmd'].rstrip()
       cmd = re.sub("\<path_var\>", get_env_var(entry['path_var']), cmd)
       if iss == "ovpsim":
@@ -75,7 +80,7 @@
       else:
         cmd = re.sub("\<variant\>", isa, cmd)
       return cmd
-  print ("Cannot find ISS %0s" % iss)
+  logging.error("Cannot find ISS %0s" % iss)
   sys.exit(1)
 
 
@@ -95,68 +100,89 @@
   return cmd
 
 
-def gen(test_list, simulator, simulator_yaml, output_dir, sim_only,
-        compile_only, lsf_cmd, seed, cwd, cmp_opts, sim_opts, timeout_s, verbose):
+def gen(test_list, csr_file, end_signature_addr, isa, simulator,
+        simulator_yaml, output_dir, sim_only, compile_only, lsf_cmd, seed,
+        cwd, cmp_opts, sim_opts, timeout_s):
   """Run the instruction generator
 
   Args:
-    test_list      : List of assembly programs to be compiled
-    simulator      : RTL simulator used to run instruction generator
-    simulator_yaml : RTL simulator configuration file in YAML format
-    output_dir     : Output directory of the ELF files
-    sim_only       : Simulation only
-    compile_only   : Compile the generator only
-    lsf_cmd        : LSF command used to run the instruction generator
-    seed           : Seed to the instruction generator
-    cmp_opts       : Compile options for the generator
-    sim_opts       : Simulation options for the generator
-    timeout_s      : Timeout limit in seconds
-    verbose        : Verbose logging
+    test_list             : List of assembly programs to be compiled
+    csr_file              : YAML file containing description of all CSRs
+    end_signature_addr    : Address that tests will write pass/fail signature to at end of test
+    isa                   : Processor supported ISA subset
+    simulator             : RTL simulator used to run instruction generator
+    simulator_yaml        : RTL simulator configuration file in YAML format
+    output_dir            : Output directory of the ELF files
+    sim_only              : Simulation only
+    compile_only          : Compile the generator only
+    lsf_cmd               : LSF command used to run the instruction generator
+    seed                  : Seed to the instruction generator
+    cmp_opts              : Compile options for the generator
+    sim_opts              : Simulation options for the generator
+    timeout_s             : Timeout limit in seconds
   """
+  # Mutually exclusive options between compile_only and sim_only
+  if compile_only and sim_only:
+    logging.error("argument -co is not allowed with argument -so")
   # Setup the compile and simulation command for the generator
   compile_cmd = []
   sim_cmd = ""
   compile_cmd, sim_cmd = get_generator_cmd(simulator, simulator_yaml);
+  if len(test_list) == 0:
+    return
   # Compile the instruction generator
   if not sim_only:
-    print ("Building RISC-V instruction generator")
-    for cmd in compile_cmd:
-      cmd = re.sub("<out>", os.path.abspath(output_dir), cmd)
-      cmd = re.sub("<cwd>", cwd, cmd)
-      cmd = re.sub("<cmp_opts>", cmp_opts, cmd)
-      if verbose:
-        print("Compile command: %s" % cmd)
-      output = run_cmd(cmd)
-      if verbose:
-        print(output)
+    if (not((len(test_list) == 1) and (test_list[0]['test'] == 'riscv_csr_test'))):
+      logging.info("Building RISC-V instruction generator")
+      for cmd in compile_cmd:
+        cmd = re.sub("<out>", os.path.abspath(output_dir), cmd)
+        cmd = re.sub("<cwd>", cwd, cmd)
+        cmd = re.sub("<cmp_opts>", cmp_opts, cmd)
+        logging.debug("Compile command: %s" % cmd)
+        logging.debug(run_cmd(cmd))
   # Run the instruction generator
   if not compile_only:
     cmd_list = []
     sim_cmd = re.sub("<out>", os.path.abspath(output_dir), sim_cmd)
     sim_cmd = re.sub("<cwd>", cwd, sim_cmd)
     sim_cmd = re.sub("<sim_opts>", sim_opts, sim_cmd)
-    print ("Running RISC-V instruction generator")
+    logging.info("Running RISC-V instruction generator")
     for test in test_list:
-      if test['iterations'] > 0:
-        rand_seed = get_seed(seed)
-        cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
-              (" +UVM_TESTNAME=%s " % test['gen_test']) + \
-              (" +num_of_tests=%d " % test['iterations']) + \
-              (" +asm_file_name=%s/asm_tests/%s " % (output_dir, test['test'])) + \
-              (" -l %s/sim_%s.log " % (output_dir, test['test']))
-        cmd = re.sub("<seed>", str(rand_seed), cmd)
-        if "gen_opts" in test:
-          cmd += test['gen_opts']
-        print("Generating %d %s" % (test['iterations'], test['test']))
+      iterations = test['iterations']
+      if iterations > 0:
+        """
+        If we are running a CSR test, need to call a separate python script
+        to generate directed CSR test code, located at scripts/gen_csr_test.py.
+        """
+        if test['test'] == 'riscv_csr_test':
+          cmd = "python3 scripts/gen_csr_test.py" + \
+                (" --csr_file %s" % csr_file) + \
+                (" --xlen %s" % re.search(r"(?P<xlen>[0-9]+)", isa).group("xlen")) + \
+                (" --iterations %i" % iterations) + \
+                (" --out %s/asm_tests" % output_dir) + \
+                (" --end_signature_addr %s" % end_signature_addr)
+        else:
+          rand_seed = get_seed(seed)
+          cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
+                (" +UVM_TESTNAME=%s " % test['gen_test']) + \
+                (" +num_of_tests=%i " % iterations) + \
+                (" +asm_file_name=%s/asm_tests/%s " % (output_dir, test['test'])) + \
+                (" -l %s/sim_%s.log " % (output_dir, test['test']))
+          cmd = re.sub("<seed>", str(rand_seed), cmd)
+          if "gen_opts" in test:
+            cmd += test['gen_opts']
+        if not re.search("c", isa):
+          cmd += "+disable_comparessed_instr=1";
+        logging.info("Generating %d %s" % (iterations, test['test']))
         if lsf_cmd:
           cmd_list.append(cmd)
         else:
-          run_cmd(cmd, verbose, timeout_s)
+          run_cmd(cmd, timeout_s)
     if lsf_cmd:
-      run_parallel_cmd(cmd_list, verbose, timeout_s)
+      run_parallel_cmd(cmd_list, timeout_s)
 
 
-def gcc_compile(test_list, output_dir, isa, mabi, verbose):
+def gcc_compile(test_list, output_dir, isa, mabi, opts):
   """Use riscv gcc toolchain to compile the assembly program
 
   Args:
@@ -164,7 +190,6 @@
     output_dir : Output directory of the ELF files
     isa        : ISA variant passed to GCC
     mabi       : MABI variant passed to GCC
-    verbose    : Verbose logging
   """
   for test in test_list:
     for i in range(0, test['iterations']):
@@ -173,26 +198,31 @@
       elf = prefix + ".o"
       binary = prefix + ".bin"
       # gcc comilation
-      cmd = ("%s -march=%s -mabi=%s -static -mcmodel=medany \
+      cmd = ("%s -static -mcmodel=medany \
              -fvisibility=hidden -nostdlib \
-             -nostartfiles \
-             -Tscripts/link.ld %s -o %s" % \
-             (get_env_var("RISCV_GCC") ,isa, mabi, asm, elf))
-      print("Compiling %s" % asm)
-      if verbose:
-        print(cmd)
+             -nostartfiles %s \
+             -Tscripts/link.ld %s -o %s " % \
+             (get_env_var("RISCV_GCC"), asm, opts, elf))
+      if 'gcc_opts' in test:
+        cmd += test['gcc_opts']
+      # If march/mabi is not defined in the test gcc_opts, use the default
+      # setting from the command line.
+      if not re.search('march', cmd):
+        cmd += (" -march=%s" % isa)
+      if not re.search('mabi', cmd):
+        cmd += (" -mabi=%s" % mabi)
+      logging.info("Compiling %s" % asm)
+      logging.debug(cmd)
       output = subprocess.check_output(cmd.split())
-      if verbose:
-        print(output)
+      logging.debug(output)
       # Convert the ELF to plain binary, used in RTL sim
-      print ("Converting to %s" % binary)
+      logging.info("Converting to %s" % binary)
       cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY"), elf, binary))
       output = subprocess.check_output(cmd.split())
-      if verbose:
-        print(output)
+      logging.debug(output)
 
 
-def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, timeout_s, verbose):
+def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, timeout_s):
   """Run ISS simulation with the generated test program
 
   Args:
@@ -202,26 +232,27 @@
     iss_yaml   : ISS configuration file in YAML format
     isa        : ISA variant passed to the ISS
     timeout_s  : Timeout limit in seconds
-    verbose    : Verbose logging
   """
   for iss in iss_list.split(","):
     log_dir = ("%s/%s_sim" % (output_dir, iss))
     base_cmd = parse_iss_yaml(iss, iss_yaml, isa)
-    print ("%s sim log dir: %s" % (iss, log_dir))
+    logging.info("%s sim log dir: %s" % (iss, log_dir))
     subprocess.run(["mkdir", "-p", log_dir])
     for test in test_list:
-      for i in range(0, test['iterations']):
-        prefix = ("%s/asm_tests/%s.%d" % (output_dir, test['test'], i))
-        elf = prefix + ".o"
-        log = ("%s/%s.%d.log" % (log_dir, test['test'], i))
-        cmd = get_iss_cmd(base_cmd, elf, log)
-        print ("Running ISS simulation: %s" % elf)
-        run_cmd(cmd, 0, timeout_s)
-        if verbose:
-          print (cmd)
+      if 'no_iss' in test and test['no_iss'] == 1:
+        continue
+      else:
+        for i in range(0, test['iterations']):
+          prefix = ("%s/asm_tests/%s.%d" % (output_dir, test['test'], i))
+          elf = prefix + ".o"
+          log = ("%s/%s.%d.log" % (log_dir, test['test'], i))
+          cmd = get_iss_cmd(base_cmd, elf, log)
+          logging.info("Running ISS simulation: %s" % elf)
+          run_cmd(cmd, timeout_s)
+          logging.debug(cmd)
 
 
-def iss_cmp(test_list, iss, output_dir, isa, verbose):
+def iss_cmp(test_list, iss, output_dir, isa):
   """Compare ISS simulation reult
 
   Args:
@@ -229,7 +260,6 @@
     iss            : List of instruction set simulators
     output_dir     : Output directory of the ELF files
     isa            : ISA
-    verbose        : Verbose logging
   """
   iss_list = iss.split(",")
   if len(iss_list) != 2:
@@ -239,8 +269,8 @@
   for test in test_list:
     for i in range(0, test['iterations']):
       elf = ("%s/asm_tests/%s.%d.o" % (output_dir, test['test'], i))
-      print("Comparing ISS sim result %s/%s : %s" %
-            (iss_list[0], iss_list[1], elf))
+      logging.info("Comparing ISS sim result %s/%s : %s" %
+                  (iss_list[0], iss_list[1], elf))
       csv_list = []
       run_cmd(("echo 'Test binary: %s' >> %s" % (elf, report)))
       for iss in iss_list:
@@ -251,100 +281,153 @@
           process_spike_sim_log(log, csv)
         elif iss == "ovpsim":
           process_ovpsim_sim_log(log, csv)
+        elif iss == "sail":
+          process_sail_sim_log(log, csv)
         else:
-          print("Unsupported ISS" % iss)
+          logging.error("Unsupported ISS" % iss)
           sys.exit(1)
       compare_trace_csv(csv_list[0], csv_list[1], iss_list[0], iss_list[1], report)
   passed_cnt = run_cmd("grep PASSED %s | wc -l" % report).strip()
   failed_cnt = run_cmd("grep FAILED %s | wc -l" % report).strip()
   summary = ("%s PASSED, %s FAILED" % (passed_cnt, failed_cnt))
-  print(summary)
+  logging.info(summary)
   run_cmd(("echo %s >> %s" % (summary, report)))
-  print("ISS regression report is saved to %s" % report)
+  logging.info("ISS regression report is saved to %s" % report)
 
 
-# Parse input arguments
-parser = argparse.ArgumentParser()
+def setup_parser():
+  """Create a command line parser.
 
-parser.add_argument("--o", type=str, default="./out",
-                    help="Output directory name")
-parser.add_argument("--testlist", type=str, default="",
-                    help="Regression testlist")
-parser.add_argument("--isa", type=str, default="rv64imc",
-                    help="RISC-V ISA subset")
-parser.add_argument("--mabi", type=str, default="lp64",
-                    help="mabi used for compilation, lp32 or lp64")
-parser.add_argument("--test", type=str, default="all",
-                    help="Test name, 'all' means all tests in the list")
-parser.add_argument("--seed", type=int, default=-1,
-                    help="Randomization seed, default -1 means random seed")
-parser.add_argument("--iterations", type=int, default=0,
-                    help="Override the iteration count in the test list")
-parser.add_argument("--simulator", type=str, default="vcs",
-                    help="Simulator used to run the generator, default VCS")
-parser.add_argument("--simulator_yaml", type=str, default="",
-                    help="RTL simulator setting YAML")
-parser.add_argument("--iss", type=str, default="spike",
-                    help="RISC-V instruction set simulator: spike, ovpsim")
-parser.add_argument("--iss_yaml", type=str, default="",
-                    help="ISS setting YAML")
-parser.add_argument("--verbose", type=int, default=0,
-                    help="Verbose logging")
-parser.add_argument("--co", type=int, default=0,
-                    help="Compile the generator only")
-parser.add_argument("--so", type=int, default=0,
-                    help="Simulate the generator only")
-parser.add_argument("--cmp_opts", type=str, default="",
-                    help="Compile options for the generator")
-parser.add_argument("--sim_opts", type=str, default="",
-                    help="Simulation options for the generator")
-parser.add_argument("--steps", type=str, default="all",
-                    help="Run steps: gen,gcc_compile,iss_sim,iss_cmp")
-parser.add_argument("--lsf_cmd", type=str, default="",
-                    help="LSF command. Run in local sequentially if lsf \
-                          command is not specified")
-parser.add_argument("--gen_timeout", type=int, default=360,
-                    help="Generator timeout limit in seconds")
-parser.add_argument("--iss_timeout", type=int, default=50,
-                    help="ISS sim timeout limit in seconds")
+  Returns: The created parser.
+  """
+  # Parse input arguments
+  parser = argparse.ArgumentParser()
 
-args = parser.parse_args()
-cwd = os.path.dirname(os.path.realpath(__file__))
+  parser.add_argument("-o", "--output", type=str,
+                      help="Output directory name", dest="o")
+  parser.add_argument("-tl", "--testlist", type=str, default="",
+                      help="Regression testlist", dest="testlist")
+  parser.add_argument("-tn", "--test", type=str, default="all",
+                      help="Test name, 'all' means all tests in the list", dest="test")
+  parser.add_argument("--seed", type=int, default=-1,
+                      help="Randomization seed, default -1 means random seed")
+  parser.add_argument("-i", "--iterations", type=int, default=0,
+                      help="Override the iteration count in the test list", dest="iterations")
+  parser.add_argument("-si", "--simulator", type=str, default="vcs",
+                      help="Simulator used to run the generator, default VCS", dest="simulator")
+  parser.add_argument("--iss", type=str, default="spike",
+                      help="RISC-V instruction set simulator: spike,ovpsim,sail")
+  parser.add_argument("-v", "--verbose", dest="verbose", action="store_true",
+                      help="Verbose logging")
+  parser.add_argument("--co", dest="co", action="store_true",
+                      help="Compile the generator only")
+  parser.add_argument("--so", dest="so", action="store_true",
+                      help="Simulate the generator only")
+  parser.add_argument("--cmp_opts", type=str, default="",
+                      help="Compile options for the generator")
+  parser.add_argument("--sim_opts", type=str, default="",
+                      help="Simulation options for the generator")
+  parser.add_argument("--gcc_opts", type=str, default="",
+                      help="GCC compile options")
+  parser.add_argument("-s", "--steps", type=str, default="all",
+                      help="Run steps: gen,gcc_compile,iss_sim,iss_cmp", dest="steps")
+  parser.add_argument("--lsf_cmd", type=str, default="",
+                      help="LSF command. Run in local sequentially if lsf \
+                            command is not specified")
+  parser.add_argument("--isa", type=str, default="rv64gc",
+                      help="RISC-V ISA subset")
+  parser.add_argument("-m", "--mabi", type=str, default="lp64",
+                      help="mabi used for compilation, lp32 or lp64", dest="mabi")
+  parser.add_argument("--gen_timeout", type=int, default=360,
+                      help="Generator timeout limit in seconds")
+  parser.add_argument("--end_signature_addr", type=str, default="0",
+                      help="Address that privileged CSR test writes to at EOT")
+  parser.add_argument("--iss_timeout", type=int, default=50,
+                      help="ISS sim timeout limit in seconds")
+  parser.add_argument("--iss_yaml", type=str, default="",
+                      help="ISS setting YAML")
+  parser.add_argument("--simulator_yaml", type=str, default="",
+                      help="RTL simulator setting YAML")
+  parser.add_argument("--csr_yaml", type=str, default="",
+                      help="CSR description file")
 
-if not args.iss_yaml:
-  args.iss_yaml = cwd + "/yaml/iss.yaml"
+  parser.set_defaults(co=False)
+  parser.set_defaults(so=False)
+  parser.set_defaults(verbose=False)
 
-if not args.simulator_yaml:
-  args.simulator_yaml = cwd + "/yaml/simulator.yaml"
+  return parser
 
-if not args.testlist:
-  args.testlist = cwd + "/yaml/testlist.yaml"
 
-# Create output directory
-subprocess.run(["mkdir", "-p", args.o])
-subprocess.run(["mkdir", "-p", ("%s/asm_tests" % args.o)])
+def setup_logging(verbose):
+  """Setup the root logger.
 
-# Process regression test list
-matched_list = []
-process_regression_list(args.testlist, args.test, args.iterations, matched_list)
-if len(matched_list) == 0:
-  sys.exit("Cannot find %s in %s" % (args.test, args.testlist))
+  Args:
+    verbose: Verbose logging
+  """
+  if verbose:
+    logging.basicConfig(format="%(asctime)s %(filename)s:%(lineno)-5s %(levelname)-8s %(message)s",
+                        datefmt='%a, %d %b %Y %H:%M:%S',
+                        level=logging.DEBUG)
+  else:
+    logging.basicConfig(format="%(asctime)s %(levelname)-8s %(message)s",
+                        datefmt='%a, %d %b %Y %H:%M:%S',
+                        level=logging.INFO)
 
-# Run instruction generator
-if args.steps == "all" or re.match("gen", args.steps):
-  gen(matched_list, args.simulator, args.simulator_yaml, args.o,
-      args.so, args.co, args.lsf_cmd, args.seed, cwd,
-      args.cmp_opts, args.sim_opts, args.gen_timeout, args.verbose)
 
-# Compile the assembly program to ELF, convert to plain binary
-if args.steps == "all" or re.match("gcc_compile", args.steps):
-  gcc_compile(matched_list, args.o, args.isa, args.mabi, args.verbose)
+def main():
+  """This is the main entry point."""
 
-# Run ISS simulation
-if args.steps == "all" or re.match("iss_sim", args.steps):
-  iss_sim(matched_list, args.o, args.iss, args.iss_yaml,
-          args.isa, args.iss_timeout, args.verbose)
+  parser = setup_parser()
+  args = parser.parse_args()
+  cwd = os.path.dirname(os.path.realpath(__file__))
+  setup_logging(args.verbose)
 
-# Compare ISS simulation result
-if args.steps == "all" or re.match("iss_cmp", args.steps):
-  iss_cmp(matched_list, args.iss, args.o, args.isa, args.verbose)
+  if not args.csr_yaml:
+    args.csr_yaml = cwd + "/yaml/csr_template.yaml"
+
+  if not args.iss_yaml:
+    args.iss_yaml = cwd + "/yaml/iss.yaml"
+
+  if not args.simulator_yaml:
+    args.simulator_yaml = cwd + "/yaml/simulator.yaml"
+
+  if not args.testlist:
+    args.testlist = cwd + "/yaml/testlist.yaml"
+
+  # Create output directory
+  if args.o is None:
+    output_dir = "out_" + str(date.today())
+  else:
+    output_dir = args.o
+  subprocess.run(["mkdir", "-p", output_dir])
+  subprocess.run(["mkdir", "-p", ("%s/asm_tests" % output_dir)])
+
+  # Process regression test list
+  matched_list = []
+  process_regression_list(args.testlist, args.test, args.iterations, matched_list)
+  if len(matched_list) == 0:
+    sys.exit("Cannot find %s in %s" % (args.test, args.testlist))
+
+  # Run instruction generator
+  if args.steps == "all" or re.match("gen", args.steps):
+    gen(matched_list, args.csr_yaml, args.end_signature_addr, args.isa,
+        args.simulator, args.simulator_yaml, output_dir, args.so,
+        args.co, args.lsf_cmd, args.seed, cwd, args.cmp_opts,
+        args.sim_opts, args.gen_timeout)
+
+  if not args.co:
+    # Compile the assembly program to ELF, convert to plain binary
+    if args.steps == "all" or re.match("gcc_compile", args.steps):
+      gcc_compile(matched_list, output_dir, args.isa, args.mabi, args.gcc_opts)
+
+    # Run ISS simulation
+    if args.steps == "all" or re.match("iss_sim", args.steps):
+      iss_sim(matched_list, output_dir, args.iss, args.iss_yaml,
+              args.isa, args.iss_timeout)
+
+    # Compare ISS simulation result
+    if args.steps == "all" or re.match("iss_cmp", args.steps):
+      iss_cmp(matched_list, args.iss, output_dir, args.isa)
+
+if __name__ == "__main__":
+  main()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/gen_csr_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/gen_csr_test.py
index b2915b9..a1604cf 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/gen_csr_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/gen_csr_test.py
@@ -31,8 +31,21 @@
 import yaml
 import argparse
 import random
-from bitstring import BitArray as bitarray
+import copy
 
+try:
+  from bitstring import BitArray as bitarray
+except ImportError as e:
+  logging.error("Please install bitstring package: sudo apt-get install python3-bitstring")
+  sys.exit(1)
+
+"""
+Defines the test's success/failure values, one of which will be written to
+the chosen signature address to indicate the test's result.
+"""
+TEST_RESULT = 1
+TEST_PASS   = 0
+TEST_FAIL   = 1
 
 def get_csr_map(csr_file, xlen):
   """
@@ -44,7 +57,7 @@
 
   Returns:
     A dictionary contining mappings for each CSR, of the form:
-    { csr_name : [csr_val_bitarray, csr_mask_bitarray] }
+    { csr_name : [csr_address, csr_val_bitarray, csr_write_mask_bitarray, csr_read_mask_bitarray] }
   """
   rv_string = "rv{}".format(str(xlen))
   csrs = {}
@@ -52,23 +65,28 @@
     csr_description = yaml.safe_load(c)
     for csr_dict in csr_description:
       csr_name = csr_dict.get("csr")
+      csr_address = csr_dict.get("address")
       assert(rv_string in csr_dict), "The {} CSR must be configured for rv{}".format(csr_name, str(rv))
       csr_value = bitarray(uintbe=0, length=xlen)
-      csr_mask = bitarray(uintbe=0, length=xlen)
+      csr_write_mask = []
+      csr_read_mask = bitarray(uintbe=0, length=xlen)
       csr_field_list = csr_dict.get(rv_string)
       for csr_field_detail_dict in csr_field_list:
         field_type = csr_field_detail_dict.get("type")
         field_val = csr_field_detail_dict.get("reset_val")
         field_msb = csr_field_detail_dict.get("msb")
         field_lsb = csr_field_detail_dict.get("lsb")
-        field_size = field_msb - field_lsb
+        field_size = field_msb - field_lsb + 1
         if field_type != "WPRI":
-          val_size = field_msb - field_lsb + 1
-          val_bitarray = bitarray(uint=field_val, length=val_size)
-          mask_bitarray = bitarray(uint=1, length=1) * val_size
+          val_bitarray = bitarray(uint=field_val, length=field_size)
+          mask_bitarray = bitarray(uint=1, length=1) * field_size
+          start_pos = xlen - 1 - field_msb
+          end_pos = xlen - 1 - field_lsb
+          csr_read_mask.overwrite(mask_bitarray, xlen - 1 - field_msb)
           csr_value.overwrite(val_bitarray, xlen - 1 - field_msb)
-          csr_mask.overwrite(mask_bitarray, xlen - 1 - field_msb)
-      csrs.update({csr_name : [csr_value, csr_mask]})
+          access = True if field_type == "R" else False
+          csr_write_mask.append([mask_bitarray, (start_pos, end_pos), access])
+      csrs.update({csr_name : [csr_address, csr_value, csr_write_mask, csr_read_mask]})
   return csrs
 
 
@@ -102,38 +120,46 @@
     return val
 
 
-def csr_write(val, csr_val, csr_mask):
+def csr_write(val, csr_val, csr_write_mask):
   """
   Performs a CSR write.
 
   Args:
     val: A bitarray containing the value to be written.
     csr_val: A bitarray containing the current CSR value.
-    csr_mask: A bitarray containing the CSR's mask.
+    csr_write_mask: A bitarray containing the CSR's mask.
   """
-  if val.len != csr_mask.len:
-    csr_val.overwrite(val & csr_mask, 0)
+  for bitslice in csr_write_mask:
+    read_only = bitslice[2]
+    start_index = bitslice[1][0]
+    end_index = bitslice[1][1]
+    length = end_index - start_index + 1
+    mask_val = bitslice[0]
+    # only write if not read only
+    if not read_only:
+      val_slice = val[start_index:end_index+1]
+      csr_val.overwrite(mask_val & val_slice, start_index)
 
 
 """
 CSR Read:
   Reads the given CSR, after applying the bitmask
 """
-def csr_read(csr_val, csr_mask):
+def csr_read(csr_val, csr_read_mask):
   """
   Performs a CSR read.
 
   Args:
     csr_val: A bitarray containing the current CSR value.
-    csr_mask: A bitarray containing the CSR's mask.
+    csr_read_mask: A bitarray containing the CSR's read mask.
 
   Returns:
-    A bitarray of the logical AND of csr_val and csr_mask.
+    A bitarray of the logical AND of csr_val and csr_read_mask.
   """
-  return csr_val & csr_mask
+  return csr_val & csr_read_mask
 
 
-def predict_csr_val(csr_op, rs1_val, csr_val, csr_mask):
+def predict_csr_val(csr_op, rs1_val, csr_val, csr_write_mask, csr_read_mask):
   """
   Predicts the CSR reference value, based on the current CSR operation.
 
@@ -141,7 +167,8 @@
     csr_op: A string of the CSR operation being performed.
     rs1_val: A bitarray containing the value to be written to the CSR.
     csr_val: A bitarray containing the current value of the CSR.
-    csr_mask: A bitarray containing the CSR's mask.
+    csr_write_mask: A bitarray containing the CSR's write mask.
+    csr_read_mask: A bitarray containing the CSR's read mask
 
   Returns:
     A hexadecimal string of the predicted CSR value.
@@ -150,68 +177,97 @@
   # create a zero bitarray to zero extend immediates
   zero = bitarray(uint=0, length=csr_val.len - 5)
   if csr_op == 'csrrw':
-    prediction = csr_read(csr_val, csr_mask)
-    csr_write(rs1_val, csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
+    csr_write(rs1_val, csr_val, csr_write_mask)
   elif csr_op == 'csrrs':
-    prediction = csr_read(csr_val, csr_mask)
-    csr_write(rs1_val | prediction, csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
+    csr_write(rs1_val | prediction, csr_val, csr_write_mask)
   elif csr_op == 'csrrc':
-    prediction = csr_read(csr_val, csr_mask)
-    csr_write((~rs1_val) & prediction, csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
+    csr_write((~rs1_val) & prediction, csr_val, csr_write_mask)
   elif csr_op == 'csrrwi':
-    prediction = csr_read(csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
     zero.append(rs1_val[-5:])
-    csr_write(zero, csr_val, csr_mask)
+    csr_write(zero, csr_val, csr_write_mask)
   elif csr_op == 'csrrsi':
-    prediction = csr_read(csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
     zero.append(rs1_val[-5:])
-    csr_write(zero | prediction, csr_val, csr_mask)
+    csr_write(zero | prediction, csr_val, csr_write_mask)
   elif csr_op == 'csrrci':
-    prediction = csr_read(csr_val, csr_mask)
+    prediction = csr_read(csr_val, csr_read_mask)
     zero.append(rs1_val[-5:])
-    csr_write((~zero) & prediction, csr_val, csr_mask)
+    csr_write((~zero) & prediction, csr_val, csr_write_mask)
   return f"0x{prediction.hex}"
 
 
-def gen_csr_test_fail(test_file):
+def gen_setup(test_file):
+  """
+  Generates the setup code for the CSR test.
+
+  Args:
+    test_file: the file containing the generated assembly code.
+  """
+  test_file.write(f".macro init\n")
+  test_file.write(f".endm\n")
+  test_file.write(f".section .text.init\n")
+  test_file.write(f".globl _start\n")
+  test_file.write(f".option norvc\n")
+  for i in range(32):
+    test_file.write(f"j csr_fail\n")
+  test_file.write(f"_start:\n")
+
+
+def gen_csr_test_fail(test_file, end_addr):
   """
   Generates code to handle a test failure.
   This code consists of writing 1 to the GP register in an infinite loop.
   The testbench will poll this register at the end of the test to detect failure.
 
   Args:
-    The file containing the generated assembly test code.
+    test_file: the file containing the generated assembly test code.
+    end_addr: address that should be written to at end of test
   """
   test_file.write(f"csr_fail:\n")
-  test_file.write(f"\tli gp, 1\n")
+  test_file.write(f"\tli x1, {TEST_FAIL}\n")
+  test_file.write(f"\tslli x1, x1, 8\n")
+  test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n")
+  test_file.write(f"\tli x2, {end_addr}\n")
+  test_file.write(f"\tsw x1, 0(x2)\n")
   test_file.write(f"\tj csr_fail\n")
 
 
-def gen_csr_test_pass(test_file):
+def gen_csr_test_pass(test_file, end_addr):
   """
   Generates code to handle test success.
   This code consists of writing 2 to the GP register in an infinite loop.
   The testbench will poll this register at the end of the test to detect success.
 
   Args:
-    The file containing the generated assembly test code.
+    test_file: the file containing the generated assembly test code.
+    end_addr: address that should be written to at end of test
   """
   test_file.write(f"csr_pass:\n")
-  test_file.write(f"\tli gp, 1\n")
+  test_file.write(f"\tli x1, {TEST_PASS}\n")
+  test_file.write(f"\tslli x1, x1, 8\n")
+  test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n")
+  test_file.write(f"\tli x2, {end_addr}\n")
+  test_file.write(f"\tsw x1, 0(x2)\n")
   test_file.write(f"\tj csr_pass\n")
 
 
-def gen_csr_instr(csr_map, csr_instructions, xlen, iterations, out):
+def gen_csr_instr(original_csr_map, csr_instructions, xlen,
+                  iterations, out, end_signature_addr):
   """
   Uses the information in the map produced by get_csr_map() to generate
   test CSR instructions operating on the generated random values.
 
   Args:
-    csr_map: The dictionary containing CSR mappings generated by get_csr_map()
+    original_csr_map: The dictionary containing CSR mappings generated by get_csr_map()
     csr_instructions: A list of all supported CSR instructions in string form.
     xlen: The RISC-V ISA bit length.
     iterations: Indicates how many randomized test files will be generated.
     out: A string containing the directory path that the tests will be generated in.
+    end_signature_addr: The address the test should write to upon terminating
 
   Returns:
     No explicit return value, but will write the randomized assembly test code
@@ -220,13 +276,14 @@
   for i in range(iterations):
     # pick two GPRs at random to act as source and destination registers
     # for CSR operations
-    source_reg, dest_reg = [f"x{i}" for i in random.sample(range(5, 15), 2)]
+    csr_map = copy.deepcopy(original_csr_map)
+    source_reg, dest_reg = [f"x{i}" for i in random.sample(range(1, 16), 2)]
     csr_list = list(csr_map.keys())
     with open(f"{out}/riscv_csr_test.{i}.S", "w") as csr_test_file:
-      csr_test_file.write(f"csr_test:\n")
+      gen_setup(csr_test_file)
       for csr in csr_list:
-        last_csr = csr
-        csr_val, csr_mask = csr_map.get(csr)
+        csr_address, csr_val, csr_write_mask, csr_read_mask = csr_map.get(csr)
+        csr_test_file.write(f"\t# {csr}\n")
         for op in csr_instructions:
           for i in range(3):
             # hex string
@@ -235,11 +292,16 @@
             first_li = ""
             if op[-1] == "i":
               imm = rand_rs1_val[-5:]
-              csr_inst = f"\t{op} {dest_reg}, {csr}, 0b{imm.bin}\n"
+              csr_inst = f"\t{op} {dest_reg}, {csr_address}, 0b{imm.bin}\n"
+              imm_val = bitarray(uint=0, length=xlen-5)
+              imm_val.append(imm)
+              predict_li = (f"\tli {source_reg}, "
+                f"{predict_csr_val(op, imm_val, csr_val, csr_write_mask, csr_read_mask)}\n")
             else:
               first_li = f"\tli {source_reg}, 0x{rand_rs1_val.hex}\n"
-              csr_inst = f"\t{op} {dest_reg}, {csr}, {source_reg}\n"
-              predict_li = f"\tli {source_reg}, {predict_csr_val(op, rand_rs1_val, csr_val, csr_mask)}\n"
+              csr_inst = f"\t{op} {dest_reg}, {csr_address}, {source_reg}\n"
+              predict_li = (f"\tli {source_reg}, "
+                f"{predict_csr_val(op, rand_rs1_val, csr_val, csr_write_mask, csr_read_mask)}\n")
             branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
             csr_test_file.write(first_li)
             csr_test_file.write(csr_inst)
@@ -250,25 +312,32 @@
             been written to the CSR has not been tested.
             """
             if csr == csr_list[-1] and op == csr_instructions[-1] and i == 2:
-              final_csr_read = f"\tcsrr {dest_reg}, {csr_list[-1]}\n"
+              final_csr_read = f"\tcsrr {dest_reg}, {csr_address}\n"
               csrrs_read_mask = bitarray(uint=0, length=xlen)
-              final_li = f"\tli {source_reg}, {predict_csr_val('csrrs', csrrs_read_mask, csr_val, csr_mask)}\n"
+              final_li = (f"\tli {source_reg}, "
+                f"{predict_csr_val('csrrs', csrrs_read_mask, csr_val, csr_write_mask, csr_read_mask)}\n")
               final_branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
               csr_test_file.write(final_csr_read)
               csr_test_file.write(final_li)
               csr_test_file.write(final_branch_check)
-      gen_csr_test_pass(csr_test_file)
-      gen_csr_test_fail(csr_test_file)
+      gen_csr_test_pass(csr_test_file, end_signature_addr)
+      gen_csr_test_fail(csr_test_file, end_signature_addr)
 
 
 """
 Define command line arguments.
 """
 parser = argparse.ArgumentParser()
-parser.add_argument("--csr_file", type=str, help="The YAML file contating descriptions of all processor supported CSRs")
-parser.add_argument("--xlen", type=int, default=32, help="Specify the ISA width, e.g. 32 or 64 or 128")
-parser.add_argument("--num_test", type=int, default=1, help="Specify how many tests to be generated")
-parser.add_argument("--out", type=str, default="./", help="Specify output directory")
+parser.add_argument("--csr_file", type=str, default="yaml/csr_template.yaml",
+        help="The YAML file contating descriptions of all processor supported CSRs")
+parser.add_argument("--xlen", type=int, default=32,
+        help="Specify the ISA width, e.g. 32 or 64 or 128")
+parser.add_argument("--iterations", type=int, default=1,
+        help="Specify how many tests to be generated")
+parser.add_argument("--out", type=str, default="./",
+        help="Specify output directory")
+parser.add_argument("--end_signature_addr", type=str, default="0",
+        help="Address that should be written to at end of this test")
 args = parser.parse_args()
 
 
@@ -277,4 +346,6 @@
 """
 csr_ops = ['csrrw', 'csrrs', 'csrrc', 'csrrwi', 'csrrsi', 'csrrci']
 
-gen_csr_instr(get_csr_map(args.csr_file, args.xlen), csr_ops, args.xlen, args.num_test, args.out)
+gen_csr_instr(get_csr_map(args.csr_file, args.xlen),
+              csr_ops, args.xlen, args.iterations, args.out,
+              args.end_signature_addr)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/instr_trace_compare.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/instr_trace_compare.py
index 870c554..ead4f5c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/instr_trace_compare.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/instr_trace_compare.py
@@ -32,6 +32,10 @@
   matched_cnt = 0
   mismatch_cnt = 0
 
+  # ensure that in order mode is disabled if necessary
+  if compare_final_value_only:
+    in_order_mode = 0
+
   if log:
     fd = open(log, 'a+')
   else:
@@ -56,6 +60,8 @@
       gpr_val_2 = {}
       for trace in instr_trace_1:
         trace_1_index += 1
+        if trace.rd == "":
+          continue
         # Check if there's a GPR change caused by this instruction
         gpr_state_change_1 = check_update_gpr(trace.rd, trace.rd_val, gpr_val_1)
         if gpr_state_change_1 == 0:
@@ -63,10 +69,11 @@
         # Move forward the other trace until a GPR update happens
         gpr_state_change_2 = 0
         while (gpr_state_change_2 == 0 and trace_2_index < len(instr_trace_2)):
-          gpr_state_change_2 = check_update_gpr(
-                               instr_trace_2[trace_2_index].rd,
-                               instr_trace_2[trace_2_index].rd_val,
-                               gpr_val_2)
+          if instr_trace_2[trace_2_index].rd != "":
+            gpr_state_change_2 = check_update_gpr(
+                                 instr_trace_2[trace_2_index].rd,
+                                 instr_trace_2[trace_2_index].rd_val,
+                                 gpr_val_2)
           trace_2_index += 1
         # Check if the GPR update is the same between trace 1 and 2
         if gpr_state_change_2 == 0:
@@ -131,8 +138,8 @@
           for trace_1_index in range(0, len(gpr_trace_1[gpr])-1):
             if (trace_2_index == len(gpr_trace_2[gpr])):
               break
-            if long(gpr_trace_1[gpr][trace_1_index].rd_val, 16) != \
-               long(gpr_trace_2[gpr][trace_2_index].rd_val, 16):
+            if int(gpr_trace_1[gpr][trace_1_index].rd_val, 16) != \
+               int(gpr_trace_2[gpr][trace_2_index].rd_val, 16):
               if coalesced_updates >= coalescing_limit:
                 coalesced_updates = 0
                 mismatch_cnt += 1
@@ -163,8 +170,8 @@
           mismatch_cnt += 1
           fd.write("Zero GPR[%s] updates observed: %s:%d, %s:%d\n" % (gpr,
                    name1, len(gpr_trace_1[gpr]), name2, len(gpr_trace_2[gpr])))
-        elif long(gpr_trace_1[gpr][-1].rd_val, 16) != \
-             long(gpr_trace_2[gpr][-1].rd_val, 16):
+        elif int(gpr_trace_1[gpr][-1].rd_val, 16) != \
+             int(gpr_trace_2[gpr][-1].rd_val, 16):
           mismatch_cnt += 1
           if mismatch_cnt <= mismatch_print_limit:
             fd.write("Mismatch final value:\n")
@@ -183,12 +190,13 @@
 def parse_gpr_update_from_trace(trace_csv, gpr_trace):
   prev_val = {}
   for trace in trace_csv:
-    if not (trace.rd in prev_val):
-      gpr_trace[trace.rd] = []
-      gpr_trace[trace.rd].append(trace)
-    elif prev_val[trace.rd] != trace.rd_val:
-      gpr_trace[trace.rd].append(trace)
-    prev_val[trace.rd] = trace.rd_val
+    if trace.rd != "":
+      if not (trace.rd in prev_val):
+        gpr_trace[trace.rd] = []
+        gpr_trace[trace.rd].append(trace)
+      elif prev_val[trace.rd] != trace.rd_val:
+        gpr_trace[trace.rd].append(trace)
+      prev_val[trace.rd] = trace.rd_val
 
 
 def check_update_gpr(rd, rd_val, gpr):
@@ -206,10 +214,10 @@
 def main():
   # Parse input arguments
   parser = argparse.ArgumentParser()
-  parser.add_argument("csv_file_1", type=str, help="Instruction trace 1 CSV")
-  parser.add_argument("csv_file_2", type=str, help="Instruction trace 2 CSV")
-  parser.add_argument("csv_name_1", type=str, help="Instruction trace 1 name")
-  parser.add_argument("csv_name_2", type=str, help="Instruction trace 2 name")
+  parser.add_argument("--csv_file_1", type=str, help="Instruction trace 1 CSV")
+  parser.add_argument("--csv_file_2", type=str, help="Instruction trace 2 CSV")
+  parser.add_argument("--csv_name_1", type=str, help="Instruction trace 1 name")
+  parser.add_argument("--csv_name_2", type=str, help="Instruction trace 2 name")
   # optional arguments
   parser.add_argument("--log", type=str, default="",
                       help="Log file")
@@ -228,9 +236,6 @@
 
   args = parser.parse_args()
 
-  if args.compare_final_value_only:
-    args.in_order_mode = 0
-
   # Compare trace CSV
   compare_trace_csv(args.csv_file_1, args.csv_file_2,
                     args.csv_name_1, args.csv_name_2, args.log,
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 ae7c54b..1037680 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
@@ -22,6 +22,7 @@
 import subprocess
 import time
 import yaml
+import logging
 
 def read_yaml(yaml_file):
   """ Read YAML file to a dictionary
@@ -36,7 +37,7 @@
     try:
       yaml_data = yaml.safe_load(f)
     except yaml.YAMLError as exc:
-      print(exc)
+      logging.error(exc)
       sys.exit(1)
   return yaml_data
 
@@ -53,7 +54,7 @@
   try:
     val = os.environ[var]
   except KeyError:
-    print ("Please set the environment variable %0s" % var)
+    logging.warning("Please set the environment variable %0s" % var)
     sys.exit(1)
   return val
 
@@ -73,7 +74,7 @@
     return random.getrandbits(32)
 
 
-def run_cmd(cmd, verbose = 0, timeout_s = 999):
+def run_cmd(cmd, timeout_s = 999):
   """Run a command and return output
 
   Args:
@@ -89,20 +90,19 @@
                           stdout=subprocess.PIPE,
                           stderr=subprocess.STDOUT)
   except subprocess.CalledProcessError as exc:
-    print(ps.communicate()[0])
+    logging.error(ps.communicate()[0])
     sys.exit(1)
   try:
     output = ps.communicate(timeout = timeout_s)[0]
   except subprocess.TimeoutExpired:
-    print("Timeout[%ds]: %s" % (timeout_s, cmd))
+    logging.error("Timeout[%ds]: %s" % (timeout_s, cmd))
     output = ""
     ps.kill()
-  if verbose:
-    print(output)
+  logging.debug(output)
   return output
 
 
-def run_parallel_cmd(cmd_list, verbose = 0, timeout_s = 999):
+def run_parallel_cmd(cmd_list, timeout_s = 999):
   """Run a list of commands in parallel
 
   Args:
@@ -120,18 +120,16 @@
                           stderr=subprocess.STDOUT)
     children.append(ps)
   for i in range(len(children)):
-    print("Command progress: %d/%d" % (i, len(children)))
-    if verbose:
-      print("Waiting for command: %s" % cmd_list[i])
+    logging.info("Command progress: %d/%d" % (i, len(children)))
+    logging.debug("Waiting for command: %s" % cmd_list[i])
     try:
       output = children[i].communicate(timeout = timeout_s)[0]
     except subprocess.TimeoutExpired:
-      print("Timeout[%ds]: %s" % (timeout_s, cmd))
+      logging.error("Timeout[%ds]: %s" % (timeout_s, cmd))
       children[i].kill()
     # Restore stty setting otherwise the terminal may go crazy
     os.system("stty sane")
-    if verbose:
-      print(output)
+    logging.debug(output)
 
 
 def process_regression_list(testlist, test, iterations, matched_list):
@@ -145,13 +143,13 @@
   Returns:
     matched_list : A list of matched tests
   """
-  print("Processing regression test list : %s, test: %s" % (testlist, test))
+  logging.info("Processing regression test list : %s, test: %s" % (testlist, test))
   yaml_data = read_yaml(testlist)
   for entry in yaml_data:
     if (entry['test'] == test) or (test == "all"):
-      if iterations > 0:
+      if (iterations > 0 and  entry['iterations'] > 0):
         entry['iterations'] = iterations
       if entry['iterations'] > 0:
-        print ("Found matched tests: %s, iterations:%0d" %
-               (entry['test'], entry['iterations']))
+        logging.info("Found matched tests: %s, iterations:%0d" %
+                    (entry['test'], entry['iterations']))
         matched_list.append(entry)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py
index 1c0874e..3733b14 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py
@@ -18,6 +18,7 @@
 import re
 import os
 import argparse
+import logging
 
 from riscv_trace_csv import *
 
@@ -27,7 +28,7 @@
   Extract instruction and affected register information from ovpsim simulation
   log and save to a list.
   """
-  print("Processing ovpsim log : %s" % ovpsim_log)
+  logging.info("Processing ovpsim log : %s" % ovpsim_log)
   instr_cnt = 0
   trace_instr = ""
   trace_bin = ""
@@ -66,7 +67,7 @@
           rv_instr_trace.binary = trace_bin
           rv_instr_trace.addr = trace_addr
           trace_csv.write_trace_entry(rv_instr_trace)
-  print("Processed instruction count : %d" % instr_cnt)
+  logging.info("Processed instruction count : %d" % instr_cnt)
 
 
 def main():
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/riscv_trace_csv.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/riscv_trace_csv.py
index 329f642..4dfd104 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/riscv_trace_csv.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/riscv_trace_csv.py
@@ -32,6 +32,7 @@
     self.addr = ""
     self.binary = ""
     self.instr_str = ""
+    self.instr = ""
     self.privileged_mode = ""
 
   def get_trace_string(self):
@@ -47,6 +48,7 @@
 
   def __init__(self, csv_fd):
     self.csv_fd = csv_fd
+    self.gpr = {}
 
 
   def start_new_trace(self):
@@ -72,11 +74,19 @@
 
   def write_trace_entry(self, entry):
     """Write a new trace entry to CSV"""
-    self.csv_writer.writerow({'str'    : entry.instr_str,
-                              'rd'     : entry.rd,
-                              'rd_val' : entry.rd_val,
-                              'binary' : entry.binary,
-                              'addr'   : entry.addr})
+    self.gpr[entry.rd] = entry.rd_val
+    self.csv_writer.writerow({'str'     : entry.instr_str,
+                              'rd'      : entry.rd,
+                              'rd_val'  : entry.rd_val,
+                              'rs1'     : entry.rs1,
+                              'rs1_val' : entry.rs1_val,
+                              'rs2'     : entry.rs2,
+                              'rs2_val' : entry.rs2_val,
+                              'addr'    : entry.addr,
+                              'instr'   : entry.instr,
+                              'imm'     : entry.imm,
+                              'binary'  : entry.binary,
+                              'addr'    : entry.addr})
 
 
 def gpr_to_abi(gpr):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py
new file mode 100644
index 0000000..061da71
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py
@@ -0,0 +1,97 @@
+"""
+Copyright 2019 Google LLC
+
+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.
+
+Convert sail sim log to standard riscv instruction trace format
+"""
+
+import argparse
+import os
+import re
+import sys
+import logging
+
+sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
+
+from riscv_trace_csv import *
+
+START_RE = re.compile(r"\[4\] \[M\]: 0x.*00001010")
+END_RE   = re.compile(r"ecall")
+INSTR_RE = re.compile(r"\[[0-9].*\] \[(?P<pri>.)\]: 0x(?P<addr>[A-F0-9]+?)"
+                       " \(0x(?P<bin>[A-F0-9]+?)\) (?P<instr>.+?$)")
+RD_RE    = re.compile(r"x(?P<reg>[0-9]+?) <- 0x(?P<val>[A-F0-9]*)")
+
+def process_sail_sim_log(sail_log, csv):
+  """Process SAIL RISCV simulation log.
+
+  Extract instruction and affected register information from sail simulation
+  log and save to a list.
+  """
+  logging.info("Processing sail log : %s" % sail_log)
+  instr_cnt = 0
+  sail_instr = ""
+
+  with open(sail_log, "r") as f, open(csv, "w") as csv_fd:
+    search_start = 0
+    instr_start = 0
+    trace_csv = RiscvInstructiontTraceCsv(csv_fd)
+    trace_csv.start_new_trace()
+    instr = None
+    for line in f:
+      # Extract instruction infromation
+      m = START_RE.search(line)
+      if m:
+        search_start = 1
+        continue
+      m = END_RE.search(line)
+      if m:
+        break
+      if search_start:
+        instr = INSTR_RE.search(line)
+        if instr:
+          instr_start = 1
+          pri = instr.group("pri")
+          addr = instr.group("addr").lower()
+          binary = instr.group("bin").lower()
+          instr_str = instr.group("instr")
+          continue
+        if instr_start:
+          m = RD_RE.search(line)
+          if m:
+            # Write the extracted instruction to a csvcol buffer file
+            instr_cnt += 1
+            rv_instr_trace = RiscvInstructiontTraceEntry()
+            rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg"))
+            rv_instr_trace.rd_val = m.group("val").lower()
+            rv_instr_trace.privileged_mode = pri
+            rv_instr_trace.addr = addr
+            rv_instr_trace.binary = binary
+            rv_instr_trace.instr_str = instr_str
+            trace_csv.write_trace_entry(rv_instr_trace)
+            instr_start = 0
+  logging.info("Processed instruction count : %d" % instr_cnt)
+
+
+def main():
+  instr_trace = []
+  # Parse input arguments
+  parser = argparse.ArgumentParser()
+  parser.add_argument("--log", type=str, help="Input sail simulation log")
+  parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
+  args = parser.parse_args()
+  # Process sail log
+  process_sail_sim_log(args.log, args.csv)
+
+if __name__ == "__main__":
+  main()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py
index f42c43b..45a23f8 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py
@@ -20,6 +20,7 @@
 import os
 import re
 import sys
+import logging
 
 sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
 
@@ -31,10 +32,18 @@
   Extract instruction and affected register information from spike simulation
   log and save to a list.
   """
-  print("Processing spike log : %s" % spike_log)
+  logging.info("Processing spike log : %s" % spike_log)
   instr_cnt = 0
   spike_instr = ""
 
+  RD_RE    = re.compile(r"(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
+                      "\((?P<bin>.*?)\) x\s*(?P<reg>\d*?) 0x(?P<val>.*)")
+  CORE_RE  = re.compile(r"core.*0x(?P<addr>[a-f0-9]+?) \(0x(?P<bin>.*?)\) (?P<instr>.*?)$")
+  INSTR_RE = re.compile(r"(?P<instr>[a-z\.]+?)(\s+?)(?P<operand>.*)")
+  GPR_RE   = re.compile(r"^[a-z][0-9a-z]$")
+  CSR_RE   = re.compile(r"csr")
+  ILLE_RE  = re.compile(r"trap_illegal_instruction")
+
   # Remove all the init spike boot instructions
   cmd = ("sed -i '/core.*0x0000000000001010/,$!d' %s" % spike_log)
   os.system(cmd)
@@ -42,30 +51,65 @@
   cmd = ("sed -i '/ecall/q' %s" % spike_log)
   os.system(cmd)
 
+  gpr = {}
+  gpr["zero"] = 0
+
   with open(spike_log, "r") as f, open(csv, "w") as csv_fd:
     trace_csv = RiscvInstructiontTraceCsv(csv_fd)
     trace_csv.start_new_trace()
     for line in f:
       # Extract instruction infromation
-      m = re.search(r"core(.*)\) (.*)", line)
+      m = CORE_RE.search(line)
       if m:
-        spike_instr = m.group(2)
-      else:
-        # Extract register value information
-        m = re.search(r"(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
-                       "\((?P<bin>.*?)\) x\s*(?P<reg>\d*?) 0x(?P<val>.*)", line)
-        if m:
-          # Write the extracted instruction to a csvcol buffer file
-          instr_cnt += 1
-          rv_instr_trace = RiscvInstructiontTraceEntry()
-          rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg"))
-          rv_instr_trace.rd_val = m.group("val")
-          rv_instr_trace.privileged_mode = m.group("pri")
-          rv_instr_trace.addr = m.group("addr")
-          rv_instr_trace.binary = m.group("bin")
-          rv_instr_trace.instr_str = spike_instr
+        spike_instr = m.group("instr")
+        rv_instr_trace = RiscvInstructiontTraceEntry()
+        rv_instr_trace.instr_str = spike_instr
+        rv_instr_trace.addr = m.group("addr")
+        rv_instr_trace.binary = m.group("bin")
+        if spike_instr == "wfi":
           trace_csv.write_trace_entry(rv_instr_trace)
-  print("Processed instruction count : %d" % instr_cnt)
+          continue
+        nextline = f.readline()
+        if nextline != "":
+          if ILLE_RE.search(nextline):
+            continue
+          m = RD_RE.search(nextline)
+          if m:
+            # Extract RD information
+            instr_cnt += 1
+            rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg"))
+            rv_instr_trace.rd_val = m.group("val")
+            rv_instr_trace.privileged_mode = m.group("pri")
+            gpr[rv_instr_trace.rd] = rv_instr_trace.rd_val
+          s = INSTR_RE.search(spike_instr)
+          if s:
+            rv_instr_trace.instr = s.group("instr")
+            operand_str = s.group("operand").replace(" ", "")
+            if operand_str != "" :
+              operands = operand_str.split(",")
+              if CSR_RE.search(s.group("instr")):
+                # CSR instruction
+                operand = operands[-1]
+                if GPR_RE.search(operand) or operand == "zero":
+                  rv_instr_trace.rs1 = operand
+                  rv_instr_trace.rs1_val = gpr[operand]
+                else:
+                  rv_instr_trace.imm = operand
+              else:
+                # Non CSR instruction
+                for i in range(1, len(operands)):
+                  operand = operands[i]
+                  if GPR_RE.search(operand) or operand == "zero":
+                    if i == 1:
+                      rv_instr_trace.rs1 = operand
+                      rv_instr_trace.rs1_val = gpr[operand]
+                    else:
+                      rv_instr_trace.rs2 = operands[i]
+                      rv_instr_trace.rs2_val = gpr[operand]
+                  else:
+                    rv_instr_trace.imm = operand
+          trace_csv.write_trace_entry(rv_instr_trace)
+  logging.info("Processed instruction count : %d" % instr_cnt)
 
 
 def main():
@@ -78,5 +122,6 @@
   # Process spike log
   process_spike_sim_log(args.log, args.csv)
 
+
 if __name__ == "__main__":
   main()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/setting/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/setting/riscv_core_setting.sv
index a893983..5ca55e0 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/setting/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/setting/riscv_core_setting.sv
@@ -30,7 +30,10 @@
 riscv_instr_name_t unsupported_instr[];
 
 // ISA supported by the processor
-riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C};
+riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C, RV32A, RV64A};
+
+// Interrupt mode support
+mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
 
 // Debug mode support
 bit support_debug_mode = 0;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv
new file mode 100644
index 0000000..f16fe58
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * 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.
+ */
+
+// Base class for AMO instruction stream
+class riscv_amo_base_instr_stream extends riscv_directed_instr_stream;
+
+  rand int unsigned  num_amo;
+  rand int unsigned  num_mixed_instr;
+  rand int           base;
+  rand riscv_reg_t   rs1_reg;
+  riscv_reg_t        reserved_rd[$];
+  rand int unsigned  data_page_id;
+
+  // User can specify a small group of available registers to generate various hazard condition
+  rand riscv_reg_t   avail_regs[];
+
+  `uvm_object_utils(riscv_amo_base_instr_stream)
+
+  constraint rs1_c {
+    !(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
+  }
+
+  constraint addr_range_c {
+    data_page_id < max_data_page_id;
+    base inside {[0 : max_load_store_offset-1]};
+  }
+
+  constraint aligned_amo_c {
+    if (XLEN == 32) {
+      base % 4 == 0;
+    } else {
+      base % 8 == 0;
+    }
+  }
+
+  function new(string name = "");
+    super.new(name);
+    instr_list.rand_mode(0);
+  endfunction
+
+  function void post_randomize();
+    gen_amo_instr();
+    // rs1 cannot be modified by other instructions
+    if(!(rs1_reg inside {reserved_rd})) begin
+      reserved_rd.push_back(rs1_reg);
+    end
+    add_mixed_instr();
+    add_rs1_init_la_instr();
+    super.post_randomize();
+  endfunction
+
+  // Use "la" instruction to initialize the base regiseter
+  virtual function void add_rs1_init_la_instr();
+    riscv_pseudo_instr la_instr;
+    la_instr = riscv_pseudo_instr::type_id::create("la_instr");
+    `DV_CHECK_RANDOMIZE_WITH_FATAL(la_instr,
+                                   pseudo_instr_name == LA;
+                                   rd == rs1_reg;,
+                                   "Cannot randomize la_instr")
+    if(access_u_mode_mem) begin
+      la_instr.imm_str = $sformatf("data_page_%0d+%0d", data_page_id, base);
+    end else begin
+      la_instr.imm_str = $sformatf("kernel_data_page_%0d+%0d", data_page_id, base);
+    end
+    instr_list.push_front(la_instr);
+  endfunction
+
+  // AMO instruction generation
+  virtual function void gen_amo_instr();
+  endfunction
+
+  // Insert some other instructions to mix with load/store instruction
+  virtual function void add_mixed_instr();
+    riscv_rand_instr rand_instr;
+    for(int i = 0; i < num_mixed_instr; i ++) begin
+      rand_instr = riscv_rand_instr::type_id::create("rand_instr");
+      rand_instr.cfg = cfg;
+      rand_instr.reserved_rd = reserved_rd;
+      `DV_CHECK_RANDOMIZE_WITH_FATAL(rand_instr,
+        if(avail_regs.size() > 0) {
+          rs1 inside {avail_regs};
+          rd inside {avail_regs};
+        }
+        !(category inside {LOAD, STORE, BRANCH, JUMP});,
+        "Cannot randomize instruction")
+      insert_instr(rand_instr);
+    end
+  endfunction
+
+endclass
+
+// A pair of LR/SC instruction
+class riscv_lr_sc_instr_stream extends riscv_amo_base_instr_stream;
+
+  riscv_rand_instr lr_instr;
+  riscv_rand_instr sc_instr;
+
+  constraint legal_c {
+    num_amo == 1;
+    num_mixed_instr inside {[0:15]};
+  }
+
+  `uvm_object_utils(riscv_lr_sc_instr_stream)
+
+  function new(string name = "");
+    super.new(name);
+    lr_instr = riscv_rand_instr::type_id::create("lr_instr");
+    sc_instr = riscv_rand_instr::type_id::create("sc_instr");
+  endfunction
+
+  virtual function void gen_amo_instr();
+    lr_instr.cfg = cfg;
+    sc_instr.cfg = cfg;
+    lr_instr.disable_a_extension_c.constraint_mode(0);
+    sc_instr.disable_a_extension_c.constraint_mode(0);
+    `DV_CHECK_RANDOMIZE_WITH_FATAL(lr_instr,
+                                   rs1 == rs1_reg;
+                                   rd != rs1_reg;
+                                   instr_name inside {LR_W, LR_D};)
+    `DV_CHECK_RANDOMIZE_WITH_FATAL(sc_instr,
+                                   rs1 == rs1_reg;
+                                   rd != rs1_reg;
+                                   instr_name inside {SC_W, SC_D};)
+    instr_list.push_front(lr_instr);
+    instr_list.push_front(sc_instr);
+  endfunction
+
+endclass
+
+class riscv_amo_instr_stream extends riscv_amo_base_instr_stream;
+
+  riscv_rand_instr amo_instr[];
+
+  constraint reasonable_c {
+    solve num_amo before num_mixed_instr;
+    num_amo inside {[1:10]};
+    num_mixed_instr inside {[0:2*num_amo]};
+  }
+
+  `uvm_object_utils(riscv_amo_instr_stream)
+  `uvm_object_new
+
+  virtual function void gen_amo_instr();
+    amo_instr = new[num_amo];
+    foreach (amo_instr[i]) begin
+      amo_instr[i] = riscv_rand_instr::type_id::create($sformatf("amo_instr_%0d", i));
+      amo_instr[i].cfg = cfg;
+      amo_instr[i].disable_a_extension_c.constraint_mode(0);
+      `DV_CHECK_RANDOMIZE_WITH_FATAL(amo_instr[i],
+                                     rs1 == rs1_reg;
+                                     rd != rs1_reg;
+                                     category == AMO;)
+      instr_list.push_front(amo_instr[i]);
+    end
+  endfunction
+
+endclass
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 f11e5eb..9011cb9 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
@@ -31,6 +31,8 @@
    riscv_instr_sequence                sub_program[];
    // Program in binary format, stored in the data section, used to inject illegal/HINT instruction
    riscv_instr_sequence                bin_program;
+   riscv_instr_sequence                debug_program;
+   riscv_instr_sequence                debug_sub_program[];
    string                              instr_binary[$];
    // Kernel programs
    // These programs are called in the interrupt/exception handling routine based on the privileged
@@ -68,6 +70,7 @@
     gen_program_header();
     // Initialize general purpose registers
     init_gpr();
+    setup_misa();
     // Create all page tables
     create_page_table();
     // Setup privileged mode registers and enter target privileged mode
@@ -78,6 +81,7 @@
     if(cfg.enable_illegal_instruction || cfg.enable_hint_instruction) begin
       bin_program = riscv_instr_sequence::type_id::create("bin_program");
       bin_program.instr_cnt = cfg.bin_program_instr_cnt;
+      bin_program.is_debug_program = 0;
       bin_program.label_name = bin_program.get_name();
       bin_program.cfg = cfg;
       if (cfg.enable_illegal_instruction) begin
@@ -87,32 +91,18 @@
         bin_program.hint_instr_pct = $urandom_range(5, 20);
       end
       `DV_CHECK_RANDOMIZE_FATAL(bin_program)
-      bin_program.gen_instr(.is_main_program(0), .enable_hint_instr(cfg.enable_hint_instruction));
+      bin_program.gen_instr(.is_main_program(0));
       bin_program.post_process_instr();
       bin_program.generate_binary_stream(instr_binary);
     end
     // Init section
     gen_init_section();
     // Generate sub program
-    if(cfg.num_of_sub_program > 0) begin
-      sub_program = new[cfg.num_of_sub_program];
-      foreach(sub_program[i]) begin
-        sub_program[i] = riscv_instr_sequence::type_id::create($sformatf("sub_%0d",i+1));
-        sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i];
-        generate_directed_instr_stream(.label(sub_program[i].get_name()),
-                                       .original_instr_cnt(sub_program[i].instr_cnt),
-                                       .min_insert_cnt(0),
-                                       .instr_stream(sub_program[i].directed_instr));
-        sub_program[i].label_name = sub_program[i].get_name();
-        sub_program[i].cfg = cfg;
-        `DV_CHECK_RANDOMIZE_FATAL(sub_program[i])
-        sub_program[i].gen_instr(0);
-        sub_program_name.push_back(sub_program[i].label_name);
-      end
-    end
+    gen_sub_program(sub_program, sub_program_name, cfg.num_of_sub_program);
     // Generate main program
     main_program = riscv_instr_sequence::type_id::create("main_program");
     main_program.instr_cnt = cfg.main_program_instr_cnt;
+    main_program.is_debug_program = 0;
     main_program.label_name = "_main";
     generate_directed_instr_stream(.label("main"),
                                    .original_instr_cnt(main_program.instr_cnt),
@@ -122,30 +112,7 @@
     `DV_CHECK_RANDOMIZE_FATAL(main_program)
     main_program.gen_instr(1);
     // Setup jump instruction among main program and sub programs
-    if(cfg.num_of_sub_program != 0) begin
-      callstack_gen = riscv_callstack_gen::type_id::create("callstack_gen");
-      callstack_gen.init(cfg.num_of_sub_program+1);
-      `uvm_info(get_full_name(), "Randomizing call stack", UVM_LOW)
-      if(callstack_gen.randomize()) begin
-        program_id_t pid;
-        int idx;
-        // Insert the jump instruction based on the call stack
-        foreach(callstack_gen.program_h[i]) begin
-          foreach(callstack_gen.program_h[i].sub_program_id[j]) begin
-            idx++;
-            pid = callstack_gen.program_h[i].sub_program_id[j] - 1;
-            `uvm_info(get_full_name(), $sformatf(
-                      "Gen jump instr %0d -> sub[%0d] %0d", i, j, pid+1), UVM_HIGH)
-            if(i == 0)
-              main_program.insert_jump_instr(sub_program_name[pid], idx);
-            else
-              sub_program[i-1].insert_jump_instr(sub_program_name[pid], idx);
-          end
-        end
-      end else begin
-        `uvm_fatal(get_full_name(), "Failed to generate callstack")
-      end
-    end
+    gen_callstack(main_program, sub_program, sub_program_name, cfg.num_of_sub_program);
     if (bin_program != null) begin
       main_program.insert_jump_instr("sub_bin", 0);
     end
@@ -155,12 +122,7 @@
     // Test done section
     gen_test_done();
     // Shuffle the sub programs and insert to the instruction stream
-    sub_program.shuffle();
-    foreach(sub_program[i]) begin
-      sub_program[i].post_process_instr();
-      sub_program[i].generate_instr_stream();
-      instr_stream = {instr_stream, sub_program[i].instr_string_list};
-    end
+    insert_sub_program(sub_program, instr_stream);
     // Reserve some space to copy instruction from data section
     if (instr_binary.size() > 0) begin
       instr_stream.push_back(".align 2");
@@ -174,8 +136,10 @@
     gen_privileged_mode_switch_routine();
     // Program end
     gen_program_end();
-    // Generate debug mode section
-    gen_debug_mode_section();
+    // Generate debug rom section
+    gen_debug_rom();
+    // Generate debug mode exception handler
+    gen_debug_exception_handler();
     // Starting point of data section
     gen_data_page_begin();
     // Generate the sub program in binary format
@@ -199,13 +163,17 @@
   virtual function void gen_kernel_sections();
     instr_stream.push_back("_kernel_start: .align 12");
     // Kernel programs
-    smode_accessible_umode_program = riscv_instr_sequence::type_id::
-                                     create("smode_accessible_umode_program");
+    if (cfg.init_privileged_mode != MACHINE_MODE) begin
+      smode_accessible_umode_program = riscv_instr_sequence::type_id::
+                                       create("smode_accessible_umode_program");
+      gen_kernel_program(smode_accessible_umode_program);
+    end
     smode_program = riscv_instr_sequence::type_id::create("smode_program");
-    gen_kernel_program(smode_accessible_umode_program);
     gen_kernel_program(smode_program);
-    smode_ls_umem_program = riscv_instr_sequence::type_id::create("smode_ls_umem_program");
-    gen_kernel_program(smode_ls_umem_program);
+    if (cfg.init_privileged_mode != MACHINE_MODE) begin
+      smode_ls_umem_program = riscv_instr_sequence::type_id::create("smode_ls_umem_program");
+      gen_kernel_program(smode_ls_umem_program);
+    end
     // All trap/interrupt handling is in the kernel region
     // Trap/interrupt delegation to user mode is not supported now
     // Trap handler
@@ -234,6 +202,7 @@
                                    .instr_stream(seq.directed_instr),
                                    .access_u_mode_mem(1'b0));
     seq.label_name = seq.get_name();
+    seq.is_debug_program = 0;
     seq.cfg = cfg;
     `DV_CHECK_RANDOMIZE_FATAL(seq)
     seq.gen_instr(0);
@@ -243,6 +212,80 @@
   endfunction
 
   //---------------------------------------------------------------------------------------
+  // Generate any subprograms and set up the callstack
+  //---------------------------------------------------------------------------------------
+
+  virtual function void gen_sub_program(ref riscv_instr_sequence sub_program[],
+                                        ref string sub_program_name[$],
+                                        input int num_sub_program,
+                                        bit is_debug = 1'b0,
+                                        string prefix = "sub");
+    if(num_sub_program > 0) begin
+      sub_program = new[num_sub_program];
+      foreach(sub_program[i]) begin
+        sub_program[i] = riscv_instr_sequence::type_id::create($sformatf("%s_%0d",prefix,i+1));
+        `uvm_info(`gfn, $sformatf("sub program name: %s", prefix), UVM_LOW)
+        sub_program[i].is_debug_program = is_debug;
+        if (is_debug) begin
+          sub_program[i].instr_cnt = cfg.debug_sub_program_instr_cnt[i];
+        end else begin
+          sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i];
+        end
+        generate_directed_instr_stream(.label(sub_program[i].get_name()),
+                                       .original_instr_cnt(sub_program[i].instr_cnt),
+                                       .min_insert_cnt(0),
+                                       .instr_stream(sub_program[i].directed_instr));
+        sub_program[i].label_name = sub_program[i].get_name();
+        sub_program[i].cfg = cfg;
+        `DV_CHECK_RANDOMIZE_FATAL(sub_program[i])
+        sub_program[i].gen_instr(0);
+        sub_program_name.push_back(sub_program[i].label_name);
+      end
+    end
+  endfunction
+
+  virtual function void gen_callstack(riscv_instr_sequence main_program,
+                                      ref riscv_instr_sequence sub_program[],
+                                      ref string sub_program_name[$],
+                                      input int num_sub_program);
+    if(num_sub_program != 0) begin
+      callstack_gen = riscv_callstack_gen::type_id::create("callstack_gen");
+      callstack_gen.init(num_sub_program+1);
+      `uvm_info(get_full_name(), "Randomizing call stack", UVM_LOW)
+      if(callstack_gen.randomize()) begin
+        program_id_t pid;
+        int idx;
+        // Insert the jump instruction based on the call stack
+        foreach(callstack_gen.program_h[i]) begin
+          foreach(callstack_gen.program_h[i].sub_program_id[j]) begin
+            idx++;
+            pid = callstack_gen.program_h[i].sub_program_id[j] - 1;
+            `uvm_info(get_full_name(), $sformatf(
+                      "Gen jump instr %0d -> sub[%0d] %0d", i, j, pid+1), UVM_HIGH)
+            if(i == 0)
+              main_program.insert_jump_instr(sub_program_name[pid], idx);
+            else
+              sub_program[i-1].insert_jump_instr(sub_program_name[pid], idx);
+          end
+        end
+      end else begin
+        `uvm_fatal(get_full_name(), "Failed to generate callstack")
+      end
+    end
+    `uvm_info(get_full_name(), "Randomizing call stack..done", UVM_LOW)
+  endfunction
+
+  virtual function void insert_sub_program(ref riscv_instr_sequence sub_program[],
+                                           ref string instr_list[$]);
+    sub_program.shuffle();
+    foreach(sub_program[i]) begin
+      sub_program[i].post_process_instr();
+      sub_program[i].generate_instr_stream();
+      instr_list = {instr_list, sub_program[i].instr_string_list};
+    end
+  endfunction
+
+  //---------------------------------------------------------------------------------------
   // Major sections - init, stack, data, test_done etc.
   //---------------------------------------------------------------------------------------
 
@@ -314,8 +357,8 @@
     instr_stream.push_back(str);
     // Init stack pointer to point to the end of the user stack
     str = {indent, "la sp, _user_stack_end"};
-    setup_misa();
     instr_stream.push_back(str);
+    core_is_initialized();
     // Copy the instruction from data section to instruction section
     if (instr_binary.size() > 0) begin
       instr_stream.push_back({indent, "la x31, instr_bin"});
@@ -342,6 +385,7 @@
         RV32C, RV64C, RV128C : misa[MISA_EXT_C] = 1'b1;
         RV32I, RV64I, RV128I : misa[MISA_EXT_I] = 1'b1;
         RV32M, RV64M         : misa[MISA_EXT_M] = 1'b1;
+        RV32A, RV64A         : misa[MISA_EXT_A] = 1'b1;
         default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported", supported_isa[i].name()))
       endcase
     end
@@ -352,6 +396,19 @@
     instr_stream.push_back({indent, "csrw misa, x15"});
   endfunction
 
+  // Write to the signature_addr with values to indicate to the core testbench
+  // that is safe to start sending interrupt and debug stimulus
+  virtual function void core_is_initialized();
+    if (cfg.require_signature_addr) begin
+      if (cfg.signature_addr != 32'hdead_beef) begin
+        string str;
+        gen_signature_handshake(instr_stream, CORE_STATUS, INITIALIZED);
+      end else begin
+        `uvm_fatal(`gfn, "The signature_addr is not properly configured!")
+      end
+    end
+  endfunction
+
   // Initialize general purpose registers with random value
   virtual function void init_gpr();
     string str;
@@ -520,9 +577,9 @@
         USER_MODE:       trap_vec_reg = UTVEC;
       endcase
       // Skip utvec init if trap delegation to u_mode is not supported
-      // TODO: For now the default mode is direct mode, needs to support vector mode
-      if((riscv_instr_pkg::supported_privileged_mode[i] == USER_MODE) && !riscv_instr_pkg::support_umode_trap) continue;
-      if(riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue;
+      if ((riscv_instr_pkg::supported_privileged_mode[i] == USER_MODE) &&
+          !riscv_instr_pkg::support_umode_trap) continue;
+      if (riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue;
       tvec_name = trap_vec_reg.name();
       instr = {instr, $sformatf("la a0, %0s_handler", tvec_name.tolower())};
       if(SATP_MODE != BARE && riscv_instr_pkg::supported_privileged_mode[i] != MACHINE_MODE) begin
@@ -533,6 +590,7 @@
                  $sformatf("slli a0, a0, %0d", XLEN - 20),
                  $sformatf("srli a0, a0, %0d", XLEN - 20)};
       end
+      instr = {instr, $sformatf("ori a0, a0, %0d", cfg.mtvec_mode)};
       instr = {instr, $sformatf("csrw 0x%0x, a0 # %0s", trap_vec_reg, trap_vec_reg.name())};
     end
     gen_section("trap_vec_init", instr);
@@ -566,10 +624,11 @@
     // 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.
+    gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION);
     if(page_table_list != null) begin
       page_table_list.gen_page_fault_handling_routine(instr);
     end else begin
-      instr = {"nop"};
+      instr.push_back("nop");
     end
     gen_section("pt_fault_handler", instr);
   endfunction
@@ -584,21 +643,37 @@
     bit is_interrupt = 'b1;
     string tvec_name;
     string instr[$];
-    // Push user mode GPR to kernel stack before executing exception handling, this is to avoid
-    // exception handling routine modify user program state unexpectedly
-    push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr);
-    // Checking xStatus can be optional if ISS (like spike) has different implementation of certain
-    // fields compared with the RTL processor.
-    if (cfg.check_xstatus) begin
-      instr = {instr, $sformatf("csrr x15, 0x%0x # %0s", status, status.name())};
+    if (cfg.mtvec_mode == VECTORED) begin
+      gen_interrupt_vector_table(mode, status, cause, scratch, instr);
+    end else begin
+      // Push user mode GPR to kernel stack before executing exception handling, this is to avoid
+      // exception handling routine modify user program state unexpectedly
+      push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr);
+      // Checking xStatus can be optional if ISS (like spike) has different implementation of certain
+      // fields compared with the RTL processor.
+      if (cfg.check_xstatus) begin
+        instr = {instr, $sformatf("csrr x15, 0x%0x # %0s", status, status.name())};
+      end
+      instr = {instr,
+               // 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]
+               $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()),
+               $sformatf("srli a1, a1, %0d", XLEN-1),
+               $sformatf("bne a1, x0, %0smode_intr_handler", mode)};
     end
+    // The trap handler will occupy one 4KB page, it will be allocated one entry in the page table
+    // with a specific privileged mode.
+    instr_stream.push_back(".align 12");
+    tvec_name = tvec.name();
+    gen_section($sformatf("%0s_handler", tvec_name.tolower()), instr);
+    // Exception handler
+    instr = {};
+    if (cfg.mtvec_mode == VECTORED) begin
+      push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr);
+    end
+    gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION);
     instr = {instr,
-             // 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]
-             $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()),
-             $sformatf("srli a1, a1, %0d", XLEN-1),
-             $sformatf("bne a1, x0, %0smode_intr_handler", mode),
              // 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).
@@ -634,13 +709,42 @@
              $sformatf("csrr x30, 0x%0x # %0s", tval, tval.name()),
              "1: jal x1, test_done "
            };
+    gen_section($sformatf("%0smode_exception_handler", mode), instr);
+  endfunction
 
-    // The trap handler will occupy one 4KB page, it will be allocated one entry in the page table
-    // with a specific privileged mode.
-    instr_stream.push_back(".align 12");
-    tvec_name = tvec.name();
-    gen_section($sformatf("%0s_handler", tvec_name.tolower()), instr);
+  // Generate for interrupt vector table
+  virtual function void gen_interrupt_vector_table(string           mode,
+                                                   privileged_reg_t status,
+                                                   privileged_reg_t cause,
+                                                   privileged_reg_t scratch,
+                                                   ref string       instr[$]);
 
+    // In vector mode, the BASE address is shared between interrupt 0 and exception handling.
+    // When vectored interrupts are enabled, interrupt cause 0, which corresponds to user-mode
+    // software interrupts, are vectored to the same location as synchronous exceptions. This
+    // ambiguity does not arise in practice, since user-mode software interrupts are either
+    // disabled or delegated
+    instr = {instr, ".option norvc;",
+                    $sformatf("j %0smode_exception_handler", mode)};
+    // Redirect the interrupt to the corresponding interrupt handler
+    for (int i = 1; i < 16; i++) begin
+      instr.push_back($sformatf("j %0smode_intr_vector_%0d", mode, i));
+    end
+    instr = {instr, ".option rvc;"};
+    for (int i = 1; i < 16; i++) begin
+      string intr_handler[$];
+      push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, intr_handler);
+      gen_signature_handshake(intr_handler, CORE_STATUS, HANDLING_IRQ);
+      intr_handler = {intr_handler,
+               $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()),
+               // Terminate the test if xCause[31] != 0 (indicating exception)
+               $sformatf("bltz a1, 1f"),
+               // TODO(taliu) write xCause to the signature address
+               // Jump to commmon interrupt handling routine
+               $sformatf("j %0smode_intr_handler", mode),
+               "1: j test_done"};
+      gen_section($sformatf("%0smode_intr_vector_%0d", mode, i), intr_handler);
+    end
   endfunction
 
   // ECALL trap handler
@@ -665,10 +769,12 @@
   // TODO: Support random operations in debug mode
   // TODO: Support ebreak exception delegation
   virtual function void gen_ebreak_handler();
-    string instr[$] = {
-           "csrr  x31, mepc",
-           "addi  x31, x31, 4",
-           "csrw  mepc, x31"
+    string instr[$];
+    gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION);
+    instr = {instr,
+            "csrr  x31, mepc",
+            "addi  x31, x31, 4",
+            "csrw  mepc, x31"
     };
     pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, instr);
     instr.push_back("mret");
@@ -682,10 +788,12 @@
   // 4 and resumes execution. The way that the illegal instruction is injected guarantees that
   // PC + 4 is a valid instruction boundary.
   virtual function void gen_illegal_instr_handler();
-    string instr[$] = {
-           "csrr  x31, mepc",
-           "addi  x31, x31, 4",
-           "csrw  mepc, x31"
+    string instr[$];
+    gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION);
+    instr = {instr,
+            "csrr  x31, mepc",
+            "addi  x31, x31, 4",
+            "csrw  mepc, x31"
     };
     pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, instr);
     instr.push_back("mret");
@@ -792,6 +900,14 @@
   // Helper functions
   //---------------------------------------------------------------------------------------
 
+  // Format a code section, without generating it
+  virtual function void format_section(ref string instr[$]);
+    string prefix = format_string(" ", LABEL_STR_LEN);
+    foreach(instr[i]) begin
+      instr[i] = {prefix, instr[i]};
+    end
+  endfunction
+
   // Generate a code section
   virtual function void gen_section(string label, string instr[$]);
     string str;
@@ -821,6 +937,88 @@
     `uvm_info(get_full_name(), $sformatf("%0s is generated", test_name), UVM_LOW)
   endfunction
 
+  // Helper function to generate the proper sequence of handshake instructions
+  // to signal the testbench (see riscv_signature_pkg.sv)
+  function void gen_signature_handshake(ref string instr[$],
+                                        input signature_type_t signature_type,
+                                        core_status_t core_status = INITIALIZED,
+                                        test_result_t test_result = TEST_FAIL,
+                                        privileged_reg_t csr = MSCRATCH);
+    if (cfg.require_signature_addr) begin
+      string str;
+      str = $sformatf("li x%0d, 0x%0h", cfg.signature_addr_reg, cfg.signature_addr);
+      instr.push_back(str);
+      case (signature_type)
+        // A single data word is written to the signature address.
+        // Bits [7:0] contain the signature_type of CORE_STATUS, and the upper
+        // XLEN-8 bits contain the core_status_t data.
+        CORE_STATUS: begin
+          str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, core_status);
+          instr.push_back(str);
+          str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg);
+          instr.push_back(str);
+          str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg,
+                          cfg.signature_data_reg, signature_type);
+          instr.push_back(str);
+          str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg);
+          instr.push_back(str);
+        end
+        // A single data word is written to the signature address.
+        // Bits [7:0] contain the signature_type of TEST_RESULT, and the upper
+        // XLEN-8 bits contain the test_result_t data.
+        TEST_RESULT: begin
+          str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, test_result);
+          instr.push_back(str);
+          str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg);
+          instr.push_back(str);
+          str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg,
+                          cfg.signature_data_reg, signature_type);
+          instr.push_back(str);
+          str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg);
+          instr.push_back(str);
+        end
+        // The first write to the signature address contains just the
+        // signature_type of WRITE_GPR.
+        // It is followed by 32 consecutive writes to the signature address,
+        // each writing the data contained in one GPR, starting from x0 as the
+        // first write, and ending with x31 as the 32nd write.
+        WRITE_GPR: begin
+          str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, signature_type);
+          instr.push_back(str);
+          str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg);
+          instr.push_back(str);
+          for(int i = 0; i < 32; i++) begin
+            str = $sformatf("sw x%0x, 0(x%0d)", i, cfg.signature_addr_reg);
+            instr.push_back(str);
+          end
+        end
+        // The first write to the signature address contains the
+        // signature_type of WRITE_CSR in bits [7:0], and the CSR address in
+        // the upper XLEN-8 bits.
+        // It is followed by a second write to the signature address,
+        // containing the data stored in the specified CSR.
+        WRITE_CSR: begin
+          str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, csr);
+          instr.push_back(str);
+          str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg);
+          instr.push_back(str);
+          str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg,
+                          cfg.signature_data_reg, signature_type);
+          instr.push_back(str);
+          str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg);
+          instr.push_back(str);
+          str = $sformatf("csrr x%0d, 0x%0h", cfg.signature_data_reg, csr);
+          instr.push_back(str);
+          str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg);
+          instr.push_back(str);
+        end
+        default: begin
+          `uvm_fatal(`gfn, "signature_type is not defined")
+        end
+      endcase
+    end
+ endfunction
+
   //---------------------------------------------------------------------------------------
   // Inject directed instruction stream
   //---------------------------------------------------------------------------------------
@@ -913,11 +1111,49 @@
 
   // Generate the program in the debug ROM
   // Processor will fetch instruction from here upon receiving debug request from debug module
-  virtual function void gen_debug_mode_section();
-    string instr[];
+  virtual function void gen_debug_rom();
+    string push_gpr[$];
+    string pop_gpr[$];
+    string instr[$];
+    string dret;
+    string debug_sub_program_name[$] = {};
     if (riscv_instr_pkg::support_debug_mode) begin
-      instr = {"dret"};
+      // Signal that the core entered the debug rom regardless of whether the
+      // main debug rom program has been generated
+      gen_signature_handshake(instr, CORE_STATUS, IN_DEBUG_MODE);
+      format_section(instr);
+      // The main debug rom
+      if (cfg.gen_debug_section) begin
+        gen_sub_program(debug_sub_program, debug_sub_program_name,
+                        cfg.num_debug_sub_program, 1'b1, "debug_sub");
+        debug_program = riscv_instr_sequence::type_id::create("debug_program");
+        debug_program.instr_cnt = cfg.debug_program_instr_cnt;
+        debug_program.is_debug_program = 1;
+        debug_program.cfg = cfg;
+        `DV_CHECK_RANDOMIZE_FATAL(debug_program)
+        debug_program.gen_instr(.is_main_program(1'b1), .no_branch(1'b0));
+        gen_callstack(debug_program, debug_sub_program, debug_sub_program_name,
+                      cfg.num_debug_sub_program);
+        debug_program.post_process_instr();
+        debug_program.generate_instr_stream(.no_label(1'b1));
+        // Need to save off GPRs to avoid modifying program flow
+        push_gpr_to_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, push_gpr);
+        format_section(push_gpr);
+        pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, pop_gpr);
+        format_section(pop_gpr);
+        instr = {push_gpr, instr, debug_program.instr_string_list, pop_gpr};
+        insert_sub_program(debug_sub_program, instr_stream);
+      end
+      dret = {format_string(" ", LABEL_STR_LEN), "dret"};
+      instr = {instr, dret};
       gen_section("debug_rom", instr);
+    end
+  endfunction
+
+  // Generate exception handling routine for debug ROM
+  virtual function void gen_debug_exception_handler();
+    if (riscv_instr_pkg::support_debug_mode) begin
+      string instr[];
       instr = {"dret"};
       gen_section("debug_exception", instr);
     end
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv
index 4b4ec70..bd86547 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv
@@ -93,7 +93,8 @@
   rand riscv_instr_base    jump;
   rand riscv_instr_base    addi;
   rand riscv_pseudo_instr  la;
-  rand riscv_instr_base    branch;
+  rand riscv_rand_instr    branch;
+  rand int                 imm;
   rand bit                 enable_branch;
   rand int                 mixed_instr_cnt;
   riscv_instr_base         stack_exit_instr[];
@@ -110,6 +111,7 @@
     addi.rd  == la.rd;
     // Avoid using negative offset -1024
     addi.imm != 'hFFFF_FC00;
+    addi.imm != 1024;
     jump.imm == ~addi.imm + 1;
     jump.rs1 == addi.rd;
     addi.instr_name == ADDI;
@@ -125,10 +127,14 @@
     jump = riscv_instr_base::type_id::create("jump");
     la = riscv_pseudo_instr::type_id::create("la");
     addi = riscv_instr_base::type_id::create("addi");
-    branch = riscv_instr_base::type_id::create("branch");
+    branch = riscv_rand_instr::type_id::create("branch");
     instr_list.rand_mode(0);
   endfunction
 
+  function void pre_randomize();
+    branch.cfg = cfg;
+  endfunction
+
   function void post_randomize();
     riscv_instr_base instr[];
     // Generate some random instructions to mix with jump instructions
@@ -171,7 +177,7 @@
   int                      num_of_redudant_instr;
   riscv_instr_base         push_stack_instr[];
   riscv_reg_t              saved_regs[];
-  rand riscv_instr_base    branch_instr;
+  rand riscv_rand_instr    branch_instr;
   rand bit                 enable_branch;
   string                   push_start_label;
 
@@ -179,7 +185,6 @@
 
   function new(string name = "");
     super.new(name);
-    branch_instr = riscv_instr_base::type_id::create("branch_instr");
   endfunction
 
   function void init();
@@ -225,6 +230,8 @@
     end
     if(enable_branch) begin
       // Cover jal -> branch scenario, the branch is added before push stack operation
+      branch_instr = riscv_rand_instr::type_id::create("branch_instr");
+      branch_instr.cfg = cfg;
       `DV_CHECK_RANDOMIZE_WITH_FATAL(branch_instr,
                                      category == BRANCH;)
       branch_instr.imm_str = push_start_label;
@@ -330,9 +337,7 @@
     backward_branch_instr_stream.initialize_instr_list(branch_instr_stream_len);
   endfunction
 
-  virtual function void gen_instr(bit no_branch = 1'b0,
-                                  bit no_load_store = 1'b1,
-                                  bit enable_hint_instr = 1'b0);
+  virtual function void gen_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1);
     int branch_offset;
     super.gen_instr(1'b1);
     forward_branch_instr_stream.gen_instr();
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 03b354b..2cd25c6 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
@@ -125,14 +125,25 @@
     }
   }
 
+  // TODO: Enable atomic instruction
+  constraint no_atomic_c {
+    opcode != 7'b0101111;
+  }
+
   constraint illegal_func3_c {
     solve opcode before func3;
     if (!compressed) {
       if (exception == kIllegalFunc3) {
         (opcode == 7'b1100111) -> (func3 != 3'b000);
         (opcode == 7'b1100011) -> (func3 inside {3'b010, 3'b011});
-        (opcode == 7'b0000011) -> (func3 == 3'b111);
-        (opcode == 7'b0100011) -> (func3 >= 3'b011);
+
+        if (XLEN == 32) {
+          (opcode == 7'b0100011) -> (func3 >= 3'b011);
+          (opcode == 7'b0000011) -> (func3 inside {3'b011, 3'b111});
+        } else {
+          (opcode == 7'b0100011) -> (func3 > 3'b011);
+          (opcode == 7'b0000011) -> (func3 == 3'b111);
+        }
         (opcode == 7'b0001111) -> (!(func3 inside {3'b000, 3'b001}));
         (opcode == 7'b1110011) -> (func3 == 3'b100);
         (opcode == 7'b0011011) -> (!(func3 inside {3'b000, 3'b001, 3'b101}));
@@ -142,8 +153,13 @@
       } else {
         (opcode == 7'b1100111) -> (func3 == 3'b000);
         (opcode == 7'b1100011) -> (!(func3 inside {3'b010, 3'b011}));
-        (opcode == 7'b0000011) -> (func3 != 3'b111);
-        (opcode == 7'b0100011) -> (func3 < 3'b011);
+        if (XLEN == 32) {
+          (opcode == 7'b0100011) -> (func3 < 3'b011);
+          (opcode == 7'b0000011) -> !(func3 inside {3'b011, 3'b111});
+        } else {
+          (opcode == 7'b0100011) -> (func3 <= 3'b011);
+          (opcode == 7'b0000011) -> (func3 != 3'b111);
+        }
         (opcode == 7'b0001111) -> (func3 inside {3'b000, 3'b001});
         (opcode == 7'b1110011) -> (func3 != 3'b100);
         (opcode == 7'b0011011) -> (func3 inside {3'b000, 3'b001, 3'b101});
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_base.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_base.sv
index d371fcf..9f9bf87 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_base.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_base.sv
@@ -18,7 +18,6 @@
 
   rand riscv_instr_group_t      group;
   rand riscv_instr_format_t     format;
-  rand bit [3:0]                latency;
   rand riscv_instr_cateogry_t   category;
   rand riscv_instr_name_t       instr_name;
   rand bit [11:0]               csr;
@@ -30,6 +29,8 @@
   rand imm_t                    imm_type;
   rand bit [4:0]                imm_len;
   rand bit                      is_pseudo_instr;
+  rand bit                      aq;
+  rand bit                      rl;
   bit                           is_branch_target;
   bit                           has_label = 1'b1;
   bit                           atomic = 0;
@@ -38,27 +39,20 @@
   bit                           is_compressed;
   bit                           is_illegal_instr;
   bit                           is_hint_instr;
-
+  bit                           has_imm;
+  bit                           has_rs1;
+  bit                           has_rs2;
+  bit                           has_rd;
+  bit [31:0]                    imm_mask = '1;
   string                        imm_str;
   string                        comment;
   string                        label;
   bit                           is_local_numeric_label;
   int                           idx = -1;
 
-  `uvm_object_utils_begin(riscv_instr_base)
-    `uvm_field_enum(riscv_instr_group_t, group, UVM_DEFAULT)
-    `uvm_field_enum(riscv_instr_format_t, format, UVM_DEFAULT)
-    `uvm_field_enum(riscv_instr_cateogry_t, category, UVM_DEFAULT)
-    `uvm_field_enum(riscv_instr_name_t, instr_name, UVM_DEFAULT)
-    `uvm_field_enum(riscv_reg_t, rs2, UVM_DEFAULT)
-    `uvm_field_enum(riscv_reg_t, rs1, UVM_DEFAULT)
-    `uvm_field_enum(riscv_reg_t, rd, UVM_DEFAULT)
-    `uvm_field_int(imm, UVM_DEFAULT)
-    `uvm_field_enum(imm_t, imm_type, UVM_DEFAULT)
-  `uvm_object_utils_end
+  `uvm_object_utils(riscv_instr_base)
 
   constraint default_c {
-    soft latency == 1;
     soft is_pseudo_instr == 0;
     instr_name != INVALID_INSTR;
   }
@@ -106,6 +100,10 @@
     }
   }
 
+  constraint aq_rl_c {
+    aq && rl == 0;
+  }
+
   // Avoid generating HINT or illegal instruction by default as it's not supported by the compiler
   constraint no_hint_illegal_instr_c {
     if (instr_name inside {C_ADDI, C_ADDIW, C_LI, C_LUI, C_SLLI, C_SLLI64,
@@ -176,6 +174,20 @@
     }
   }
 
+  constraint rvc_csr_c {
+    //  Registers specified by the three-bit rs1’, rs2’, and rd’ fields of the CIW, CL, CS,
+    //  and CB formats
+    if(format inside {CIW_FORMAT, CL_FORMAT, CS_FORMAT, CB_FORMAT}) {
+      rs1 inside {[S0:A5]};
+      rs2 inside {[S0:A5]};
+      rd  inside {[S0:A5]};
+    }
+    // C_ADDI16SP is only valid when rd == SP
+    if(instr_name == C_ADDI16SP) {
+      rd == SP;
+    }
+  }
+
   ////////////  RV32I instructions  //////////////
   // LOAD instructions
   `add_instr(LB,     I_FORMAT, LOAD, RV32I)
@@ -232,7 +244,7 @@
   `add_instr(URET,    I_FORMAT, SYSTEM, RV32I)
   `add_instr(SRET,    I_FORMAT, SYSTEM, RV32I)
   `add_instr(MRET,    I_FORMAT, SYSTEM, RV32I)
-  `add_instr(WFI,     I_FORMAT, SYSTEM, RV32I)
+  `add_instr(WFI,     I_FORMAT, INTERRUPT, RV32I)
   // CSR instructions
   `add_instr(CSRRW,  R_FORMAT, CSR, RV32I, UIMM)
   `add_instr(CSRRS,  R_FORMAT, CSR, RV32I, UIMM)
@@ -366,29 +378,123 @@
   `add_instr(C_FLDSP, CI_FORMAT, LOAD, RV32DC, UIMM)
   `add_instr(C_FSDSP, CSS_FORMAT, STORE, RV32DC, UIMM)
 
+  // RV32A
+  `add_instr(LR_W,      R_FORMAT, LOAD, RV32A)
+  `add_instr(SC_W,      R_FORMAT, STORE, RV32A)
+  `add_instr(AMOSWAP_W, R_FORMAT, AMO, RV32A)
+  `add_instr(AMOADD_W,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOAND_W,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOOR_W,   R_FORMAT, AMO, RV32A)
+  `add_instr(AMOXOR_W,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMIN_W,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMAX_W,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMINU_W, R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMAXU_W, R_FORMAT, AMO, RV32A)
+
+  // RV64A
+  `add_instr(LR_D,      R_FORMAT, LOAD, RV32A)
+  `add_instr(SC_D,      R_FORMAT, STORE, RV32A)
+  `add_instr(AMOSWAP_D, R_FORMAT, AMO, RV32A)
+  `add_instr(AMOADD_D,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOAND_D,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOOR_D,   R_FORMAT, AMO, RV32A)
+  `add_instr(AMOXOR_D,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMIN_D,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMAX_D,  R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMINU_D, R_FORMAT, AMO, RV32A)
+  `add_instr(AMOMAXU_D, R_FORMAT, AMO, RV32A)
+
   // Supervisor Instructions
   `add_instr(SFENCE_VMA, R_FORMAT,SYNCH,RV32I)
 
   function void post_randomize();
+    if (group inside {RV32C, RV64C, RV128C, RV32DC, RV32FC}) begin
+      is_compressed = 1'b1;
+    end
+    if (!(format inside {R_FORMAT, CR_FORMAT})) begin
+      imm_mask = '1;
+      imm_mask = imm_mask << imm_len;
+      has_imm = 1'b1;
+      mask_imm();
+      if (imm_str == "") begin
+        update_imm_str();
+      end
+    end
+    if (format inside {R_FORMAT, S_FORMAT, B_FORMAT, CSS_FORMAT, CS_FORMAT}) begin
+      has_rs2 = 1'b1;
+    end
+    if (!(format inside {J_FORMAT, U_FORMAT, CJ_FORMAT, CSS_FORMAT})) begin
+      has_rs1 = 1'b1;
+    end
+    if (!(format inside {CJ_FORMAT, CB_FORMAT, CS_FORMAT, CSS_FORMAT, B_FORMAT, S_FORMAT})) begin
+      has_rd = 1'b1;
+    end
+  endfunction
+
+  function void mask_imm();
     // Process the immediate value and sign extension
-    bit [31:0] imm_mask = '1;
-    imm_mask = imm_mask << imm_len;
-    if(imm_type inside {UIMM, NZUIMM}) begin
+    if (imm_type inside {UIMM, NZUIMM}) begin
       imm = imm & ~imm_mask;
     end else begin
-      if(imm[imm_len-1])
+      if (imm[imm_len-1]) begin
         imm = imm | imm_mask;
-      else
+      end else begin
         imm = imm & ~imm_mask;
+      end
     end
     // Give a random value if imm is zero after masking unexpectedly
     if((imm_type inside {NZIMM, NZUIMM}) && (imm == '0)) begin
       imm = $urandom_range(2 ** (imm_len-1) - 1, 1);
     end
-    if (group inside {RV32C, RV64C, RV128C, RV32DC, RV32FC})
-      is_compressed = 1'b1;
-    if(imm_str == "")
-      imm_str = $sformatf("%0d", $signed(imm));
+  endfunction
+
+  function void gen_rand_imm();
+    if (!randomize(imm)) begin
+      `uvm_fatal(`gfn, "Cannot randomize imm")
+    end
+    mask_imm();
+    update_imm_str();
+  endfunction
+
+  function void update_imm_str();
+    imm_str = $sformatf("%0d", $signed(imm));
+  endfunction
+
+  function void set_imm(int imm);
+    this.imm = imm;
+    mask_imm();
+    update_imm_str();
+  endfunction
+
+  function riscv_reg_t gen_rand_gpr(riscv_reg_t included_reg[] = {},
+                                    riscv_reg_t excluded_reg[] = {});
+    riscv_reg_t gpr;
+    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(gpr,
+                                       if (is_compressed) {
+                                         gpr inside {[S0:A5]};
+                                       }
+                                       if (excluded_reg.size() != 0) {
+                                         !(gpr inside {excluded_reg});
+                                       }
+                                       if (included_reg.size() != 0) {
+                                         gpr inside {included_reg};
+                                       })
+    return gpr;
+  endfunction
+
+  function void gen_rand_csr(bit illegal_csr_instr = 0,
+                             privileged_mode_t privileged_mode = MACHINE_MODE);
+    if (illegal_csr_instr) begin
+      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(csr, !(csr inside {implemented_csr});)
+    end else begin
+      // Use scratch register to avoid the side effect of modifying other privileged mode CSR.
+      if (privileged_mode == MACHINE_MODE)
+        csr = MSCRATCH;
+      else if (privileged_mode == SUPERVISOR_MODE)
+        csr = SSCRATCH;
+      else
+        csr = USCRATCH;
+    end
   endfunction
 
   function new(string name = "");
@@ -408,7 +514,7 @@
   virtual function string convert2asm(string prefix = "");
     string asm_str;
     asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN);
-    if(category != SYSTEM) begin
+    if((category != SYSTEM) && !(group inside {RV32A, RV64A})) begin
       case(format)
         J_FORMAT, U_FORMAT : // instr rd,imm
           asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), get_imm());
@@ -431,12 +537,13 @@
           else
             asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rs1.name(), rs2.name(), get_imm());
         R_FORMAT: // instr rd,rs1,rs2
-          if(category == CSR)
+          if(category == CSR) begin
             asm_str = $sformatf("%0s%0s, 0x%0x, %0s", asm_str, rd.name(), csr, rs1.name());
-          else if(instr_name == SFENCE_VMA)
+          end else if(instr_name == SFENCE_VMA) begin
             asm_str = "sfence.vma x0, x0"; // TODO: Support all possible sfence
-          else
+          end else begin
             asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
+          end
         CI_FORMAT, CIW_FORMAT:
           if(instr_name == C_NOP)
             asm_str = "c.nop";
@@ -458,6 +565,12 @@
         CJ_FORMAT:
           asm_str = $sformatf("%0s%0s", asm_str, get_imm());
       endcase
+    end else if (group inside {RV32A, RV64A}) begin
+      if (instr_name inside {LR_W, LR_D}) begin
+        asm_str = $sformatf("%0s %0s, (%0s)", asm_str, rd.name(), rs1.name());
+      end else begin
+        asm_str = $sformatf("%0s %0s, %0s, (%0s)", asm_str, rd.name(), rs2.name(), rs1.name());
+      end
     end else begin
       // For EBREAK,C.EBREAK, making sure pc+4 is a valid instruction boundary
       // This is needed to resume execution from epc+4 after ebreak handling
@@ -835,6 +948,14 @@
     get_instr_name = instr_name.name();
     if(get_instr_name.substr(0, 1) == "C_") begin
       get_instr_name = {"c.", get_instr_name.substr(2, get_instr_name.len() - 1)};
+    end else if (group == RV32A) begin
+      get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".w"};
+      get_instr_name = aq ? {get_instr_name, ".aq"} :
+                       rl ? {get_instr_name, ".rl"} : get_instr_name;
+    end else if (group == RV64A) begin
+      get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".d"};
+      get_instr_name = aq ? {get_instr_name, ".aq"} :
+                       rl ? {get_instr_name, ".rl"} : get_instr_name;
     end
     return get_instr_name;
   endfunction
@@ -856,6 +977,30 @@
     end
   endfunction
 
+  // Copy the rand fields of the base instruction
+  virtual function void copy_base_instr(riscv_instr_base obj);
+    this.group           = obj.group;
+    this.format          = obj.format;
+    this.category        = obj.category;
+    this.instr_name      = obj.instr_name;
+    this.rs2             = obj.rs2;
+    this.rs1             = obj.rs1;
+    this.rd              = obj.rd;
+    this.imm             = obj.imm;
+    this.imm_type        = obj.imm_type;
+    this.imm_len         = obj.imm_len;
+    this.imm_mask        = obj.imm_mask;
+    this.imm_str         = obj.imm_str;
+    this.is_pseudo_instr = obj.is_pseudo_instr;
+    this.aq              = obj.aq;
+    this.rl              = obj.rl;
+    this.is_compressed   = obj.is_compressed;
+    this.has_imm         = obj.has_imm;
+    this.has_rs1         = obj.has_rs1;
+    this.has_rs2         = obj.has_rs2;
+    this.has_rd          = obj.has_rd;
+  endfunction
+
 endclass
 
 // Psuedo instructions are used to simplify assembly program writing
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 ead5225..7ce2bc9 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
@@ -30,6 +30,12 @@
   // Instruction count of each sub-program
   rand int               sub_program_instr_cnt[];
 
+  // Instruction count of the debug rom
+  rand int               debug_program_instr_cnt;
+
+  // Instruction count of debug sub-programs
+  rand int               debug_sub_program_instr_cnt[];
+
   // Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
   rand data_pattern_t    data_page_pattern;
 
@@ -52,6 +58,7 @@
   rand bit               mstatus_mxr;
   rand bit               mstatus_sum;
   rand bit               mstatus_tvm;
+  rand mtvec_mode_t      mtvec_mode;
 
   // Enable sfence.vma instruction
   rand bit               enable_sfence;
@@ -63,6 +70,14 @@
   bit                    check_xstatus = 1'b1;
 
   //-----------------------------------------------------------------------------
+  // Instruction list based on the config, generate by build_instruction_template
+  //-----------------------------------------------------------------------------
+  riscv_instr_base       instr_template[riscv_instr_name_t];
+  riscv_instr_name_t     basic_instr[$];
+  riscv_instr_name_t     instr_group[riscv_instr_cateogry_t][$];
+  riscv_instr_name_t     instr_category[riscv_instr_cateogry_t][$];
+
+  //-----------------------------------------------------------------------------
   // Command line options or control knobs
   //-----------------------------------------------------------------------------
   // Main options for RISC-V assembly program generation
@@ -79,6 +94,7 @@
   bit                    no_ebreak = 1;    // No ebreak instruction
   bit                    no_fence;         // No fence instruction
   bit                    no_wfi = 1;       // No WFI instruction
+  bit                    enable_unaligned_load_store;
   bit                    enable_illegal_instruction;
   bit                    enable_hint_instruction;
   int                    bin_program_instr_cnt = 200;
@@ -101,6 +117,20 @@
   bit                    force_m_delegation = 0;
   bit                    force_s_delegation = 0;
   bit                    support_supervisor_mode;
+  // "Memory mapped" address that when written to will indicate some event to
+  // the testbench - testbench will take action based on the value written
+  int                    signature_addr = 32'hdead_beef;
+  bit                    require_signature_addr = 1'b0;
+  rand riscv_reg_t       signature_addr_reg;
+  rand riscv_reg_t       signature_data_reg;
+  bit                    gen_debug_section = 1'b0;
+  // 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.
+  bit                    empty_debug_section = 1'b0;
+  // Number of sub programs in the debug rom
+  int                    num_debug_sub_program = 0;
   // Stack space allocated to each program, need to be enough to store necessary context
   // Example: RA, SP, T0, loop registers
   int                    min_stack_len_per_program = 10 * (XLEN/8);
@@ -122,10 +152,21 @@
 
   constraint default_c {
     sub_program_instr_cnt.size() == num_of_sub_program;
-    main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt;
-    main_program_instr_cnt inside {[1 : instr_cnt]};
+    debug_sub_program_instr_cnt.size() == num_debug_sub_program;
+    if (riscv_instr_pkg::support_debug_mode) {
+      main_program_instr_cnt + sub_program_instr_cnt.sum()
+                             + debug_program_instr_cnt
+                             + debug_sub_program_instr_cnt.sum() == instr_cnt;
+      debug_program_instr_cnt inside {[100 : 300]};
+      foreach(debug_sub_program_instr_cnt[i]) {
+        debug_sub_program_instr_cnt[i] inside {[100 : 300]};
+      }
+    } else {
+      main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt;
+    }
+    main_program_instr_cnt inside {[10 : instr_cnt]};
     foreach(sub_program_instr_cnt[i]) {
-      sub_program_instr_cnt[i] inside {[1 : instr_cnt]};
+      sub_program_instr_cnt[i] inside {[10 : instr_cnt]};
     }
     // Disable sfence if the program is not boot to supervisor mode
     // If sfence exception is allowed, we can enable sfence instruction in any priviledged mode.
@@ -154,6 +195,10 @@
     }
   }
 
+  constraint mtvec_c {
+    mtvec_mode inside {supported_interrupt_mode};
+  }
+
   constraint mstatus_c {
     // This is default disabled at setup phase. It can be enabled in the exception and interrupt
     // handling routine
@@ -210,6 +255,9 @@
     foreach(loop_regs[i]) {
       !(loop_regs[i] inside {default_reserved_regs});
     }
+    !(signature_addr_reg inside {ZERO, default_reserved_regs, loop_regs});
+    !(signature_data_reg inside {ZERO, default_reserved_regs, loop_regs});
+    signature_addr_reg != signature_data_reg;
   }
 
   constraint legal_loop_regs_c {
@@ -249,10 +297,17 @@
     get_bool_arg_value("+no_directed_instr=", no_directed_instr);
     get_bool_arg_value("+no_fence=", no_fence);
     get_bool_arg_value("+no_delegation=", no_delegation);
+    get_bool_arg_value("+enable_unaligned_load_store=", enable_unaligned_load_store);
     get_bool_arg_value("+enable_illegal_instruction=", enable_illegal_instruction);
     get_bool_arg_value("+enable_hint_instruction=", enable_hint_instruction);
     get_bool_arg_value("+force_m_delegation=", force_m_delegation);
     get_bool_arg_value("+force_s_delegation=", force_s_delegation);
+    get_bool_arg_value("+require_signature_addr=", require_signature_addr);
+    if (this.require_signature_addr) begin
+      get_hex_arg_value("+signature_addr=", signature_addr);
+    end
+    get_bool_arg_value("+gen_debug_section=", gen_debug_section);
+    get_int_arg_value("+num_debug_sub_program=", num_debug_sub_program);
     if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
       `uvm_info(get_full_name(), $sformatf(
                 "Got boot mode option - %0s", boot_mode_opts), UVM_LOW)
@@ -276,7 +331,8 @@
       uvm_split_string(s, ",", cmdline_march_list);
       riscv_instr_pkg::supported_isa.delete();
       foreach(cmdline_march_list[i]) begin
-        if(uvm_enum_wrapper#(riscv_instr_group_t)::from_name(cmdline_march_list[i], march)) begin
+        if(uvm_enum_wrapper#(riscv_instr_group_t)::from_name(
+           cmdline_march_list[i].toupper(), march)) begin
           riscv_instr_pkg::supported_isa.push_back(march);
         end else begin
           `uvm_fatal(get_full_name(), $sformatf(
@@ -361,15 +417,80 @@
   // Get an integer argument from comand line
   function void get_int_arg_value(string cmdline_str, ref int val);
     string s;
-    if(inst.get_arg_value(cmdline_str, s))
+    if(inst.get_arg_value(cmdline_str, s)) begin
       val = s.atoi();
+    end
   endfunction
 
   // Get a bool argument from comand line
   function void get_bool_arg_value(string cmdline_str, ref bit val);
     string s;
-    if(inst.get_arg_value(cmdline_str, s))
+    if(inst.get_arg_value(cmdline_str, s)) begin
       val = s.atobin();
+    end
+  endfunction
+
+  // Get a hex argument from command line
+  function void get_hex_arg_value(string cmdline_str, ref int val);
+    string s;
+    if(inst.get_arg_value(cmdline_str, s)) begin
+      val = s.atohex();
+    end
+  endfunction
+
+  // Build instruction template
+  virtual function void build_instruction_template();
+    riscv_instr_name_t instr_name;
+    riscv_instr_name_t excluded_instr[$];
+    get_excluded_instr(excluded_instr);
+    instr_name = instr_name.first;
+    do begin
+      riscv_instr_base instr;
+      if (!(instr_name inside {unsupported_instr, excluded_instr})) begin
+        instr = riscv_instr_base::type_id::create("instr");
+        `DV_CHECK_RANDOMIZE_WITH_FATAL(instr, instr_name == local::instr_name;)
+        if (instr.group inside {supported_isa}) begin
+          `uvm_info(`gfn, $sformatf("Adding [%s] %s to the list",
+                          instr.group.name(), instr.instr_name.name()), UVM_HIGH)
+          if (instr.category inside {SHIFT, ARITHMETIC, LOGICAL, COMPARE}) begin
+            basic_instr.push_back(instr_name);
+          end
+          instr_group[instr.group].push_back(instr_name);
+          instr_category[instr.category].push_back(instr_name);
+          instr_template[instr_name] = instr;
+        end
+      end
+      instr_name = instr_name.next;
+    end
+    while (instr_name != instr_name.first);
+    if (no_ebreak == 0) begin
+      basic_instr = {basic_instr, EBREAK};
+    end
+    if (no_fence == 0) begin
+      basic_instr = {basic_instr, instr_category[SYNCH]};
+    end
+    // TODO: Support CSR instruction in other mode
+    if ((no_csr_instr == 0) && (init_privileged_mode == MACHINE_MODE)) begin
+      basic_instr = {basic_instr, instr_category[CSR]};
+    end
+    if (no_wfi == 0) begin
+      basic_instr = {basic_instr, WFI};
+    end
+  endfunction
+
+  virtual function void get_excluded_instr(ref riscv_instr_name_t excluded[$]);
+    excluded = {excluded, INVALID_INSTR};
+    // Below instrutions will modify stack pointer, not allowed in normal instruction stream.
+    // It can be used in stack operation instruction stream.
+    excluded = {excluded, C_SWSP, C_SDSP, C_ADDI16SP};
+    if (!enable_sfence) begin
+      excluded = {excluded, SFENCE_VMA};
+    end
+    if (no_fence) begin
+      excluded = {excluded, FENCE, FENCEI, SFENCE_VMA};
+    end
+    // TODO: Support C_ADDI4SPN
+    excluded = {excluded, C_ADDI4SPN};
   endfunction
 
 endclass
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 6b035a2..d76ae8a 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
@@ -17,6 +17,7 @@
 package riscv_instr_pkg;
 
   import uvm_pkg::*;
+  import riscv_signature_pkg::*;
 
   `include "uvm_macros.svh"
   `include "dv_defines.svh"
@@ -33,6 +34,11 @@
     SV64 = 4'b1011
   } satp_mode_t;
 
+  typedef enum bit [1:0] {
+    DIRECT   = 2'b00,
+    VECTORED = 2'b01
+  } mtvec_mode_t;
+
   typedef enum bit [2:0] {
     IMM,    // Signed immediate
     UIMM,   // Unsigned immediate
@@ -230,6 +236,30 @@
     C_FSD,
     C_FLDSP,
     C_FSDSP,
+    // RV32A
+    LR_W,
+    SC_W,
+    AMOSWAP_W,
+    AMOADD_W,
+    AMOAND_W,
+    AMOOR_W,
+    AMOXOR_W,
+    AMOMIN_W,
+    AMOMAX_W,
+    AMOMINU_W,
+    AMOMAXU_W,
+    // RV64A
+    LR_D,
+    SC_D,
+    AMOSWAP_D,
+    AMOADD_D,
+    AMOAND_D,
+    AMOOR_D,
+    AMOXOR_D,
+    AMOMIN_D,
+    AMOMAX_D,
+    AMOMINU_D,
+    AMOMAXU_D,
     // Supervisor instruction
     MRET,
     URET,
@@ -310,7 +340,8 @@
     CSR,
     CHANGELEVEL,
     TRAP,
-    INTERRUPT
+    INTERRUPT,
+    AMO
   } riscv_instr_cateogry_t;
 
   typedef bit [11:0] riscv_csr_t;
@@ -729,7 +760,7 @@
     // need to use the virtual address to access the kernel stack.
     if((status == MSTATUS) && (SATP_MODE != BARE)) begin
       // We temporarily use tp to check mstatus to avoid changing other GPR. The value of sp has
-      // been saved to xStatus and can be restored later.
+      // been saved to xScratch and can be restored later.
       if(mprv) begin
         instr.push_back($sformatf("csrr tp, 0x%0x // MSTATUS", status));
         instr.push_back("srli tp, tp, 11");  // Move MPP to bit 0
@@ -769,6 +800,7 @@
     end
   endfunction
 
+  `include "riscv_instr_base.sv"
   `include "riscv_instr_gen_config.sv"
   `include "riscv_illegal_instr.sv"
   `include "riscv_reg.sv"
@@ -779,13 +811,13 @@
   `include "riscv_page_table_list.sv"
   `include "riscv_privileged_common_seq.sv"
   `include "riscv_callstack_gen.sv"
-  `include "riscv_instr_base.sv"
   `include "riscv_data_page_gen.sv"
   `include "riscv_rand_instr.sv"
   `include "riscv_instr_stream.sv"
   `include "riscv_loop_instr.sv"
   `include "riscv_directed_instr_lib.sv"
   `include "riscv_load_store_instr_lib.sv"
+  `include "riscv_amo_instr_lib.sv"
   `include "riscv_instr_sequence.sv"
   `include "riscv_asm_program_gen.sv"
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
index cd7fac9..b29be22 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
@@ -40,6 +40,7 @@
   riscv_pop_stack_instr    instr_stack_exit;     // Stack pop instructions for sub-programs
   riscv_rand_instr_stream  instr_stream;         // Main instruction streams
   bit                      is_main_program;      // Type of this sequence (main or sub program)
+  bit                      is_debug_program;     // Indicates whether sequence is debug program
   string                   label_name;           // Label of the sequence (program name)
   riscv_instr_gen_config   cfg;                  // Configuration class handle
   string                   instr_string_list[$]; // Save the instruction list in string format
@@ -47,7 +48,6 @@
   riscv_instr_stream       directed_instr[];     // List of all directed instruction stream
   riscv_illegal_instr      illegal_instr;        // Illegal instruction generator
   int                      illegal_instr_pct;    // Percentage of illegal instruction
-  bit                      enable_hint_instr;    // Enable HINT instruction
   int                      hint_instr_pct;       // Percentage of HINT instruction
 
   `uvm_object_utils(riscv_instr_sequence)
@@ -70,7 +70,7 @@
   // 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.
-  virtual function void gen_instr(bit is_main_program, bit enable_hint_instr = 1'b0);
+  virtual function void gen_instr(bit is_main_program, bit no_branch = 1'b0);
     this.is_main_program = is_main_program;
     instr_stream.cfg = cfg;
     instr_stream.initialize_instr_list(instr_cnt);
@@ -78,7 +78,7 @@
                                instr_stream.instr_list.size()), UVM_LOW)
     // Do not generate load/store instruction here
     // The load/store instruction will be inserted as directed instruction stream
-    instr_stream.gen_instr(.no_load_store(1'b1), .enable_hint_instr(enable_hint_instr));
+    instr_stream.gen_instr(.no_branch(no_branch), .no_load_store(1'b1));
     if(!is_main_program) begin
       gen_stack_enter_instr();
       gen_stack_exit_instr();
@@ -91,6 +91,7 @@
   // pointer(SP) is reduced by the amount the stack space allocated to this program.
   function void gen_stack_enter_instr();
     bit allow_branch = ((illegal_instr_pct > 0) || (hint_instr_pct > 0)) ? 1'b0 : 1'b1;
+    allow_branch &= !cfg.no_branch_jump;
     `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(program_stack_len,
       program_stack_len inside {[cfg.min_stack_len_per_program : cfg.max_stack_len_per_program]};
       // Keep stack len word aligned to avoid unaligned load/store
@@ -234,21 +235,25 @@
         jump_instr.jump.rd == RA;
       },
       "Cannot randomize jump_instr")
-    `uvm_info(get_full_name(), $sformatf("%0s -> %0s",
-              jump_instr.jump.instr_name.name(), label_name), UVM_HIGH)
     instr_stream.insert_instr_stream(jump_instr.instr_list);
+    `uvm_info(get_full_name(), $sformatf("%0s -> %0s...done",
+              jump_instr.jump.instr_name.name(), label_name), UVM_LOW)
   endfunction
 
   // 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.
-  function void generate_instr_stream();
+  function void generate_instr_stream(bit no_label = 1'b0);
     string prefix, str;
     int i;
     instr_string_list = {};
     for(i = 0; i < instr_stream.instr_list.size(); i++) begin
       if(i == 0) begin
-        prefix = format_string($sformatf("%0s:", label_name), LABEL_STR_LEN);
+        if (no_label) begin
+          prefix = format_string(" ", LABEL_STR_LEN);
+        end else begin
+          prefix = format_string($sformatf("%0s:", label_name), LABEL_STR_LEN);
+        end
         instr_stream.instr_list[i].has_label = 1'b1;
       end else begin
         if(instr_stream.instr_list[i].has_label) begin
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
index 77c2141..3441c7b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
@@ -23,6 +23,8 @@
   rand riscv_instr_base instr_list[$];
   int unsigned          instr_cnt;
   string                label = "";
+  // User can specify a small group of available registers to generate various hazard condition
+  rand riscv_reg_t      avail_regs[];
 
   `uvm_object_utils(riscv_instr_stream)
   `uvm_object_new
@@ -64,11 +66,27 @@
   function void insert_instr_stream(riscv_instr_base new_instr[], int idx = -1, bit replace = 1'b0);
     int current_instr_cnt = instr_list.size();
     int new_instr_cnt = new_instr.size();
+    if(current_instr_cnt == 0) begin
+      instr_list = new_instr;
+      return;
+    end
     if(idx == -1) begin
       idx = $urandom_range(0, current_instr_cnt-1);
-      while(instr_list[idx].atomic) begin
+      repeat(10) begin
+       if (instr_list[idx].atomic) break;
        idx = $urandom_range(0, current_instr_cnt-1);
       end
+      if (instr_list[idx].atomic) begin
+        foreach (instr_list[i]) begin
+          if (!instr_list[i].atomic) begin
+            idx = i;
+            break;
+          end
+        end
+        if (instr_list[idx].atomic) begin
+          `uvm_fatal(`gfn, $sformatf("Cannot inject the instruction"))
+        end
+      end
     end else if((idx > current_instr_cnt) || (idx < 0)) begin
       `uvm_error(`gfn, $sformatf("Cannot insert instr stream at idx %0d", idx))
     end
@@ -129,10 +147,11 @@
   bit                     access_u_mode_mem = 1'b1;
   int                     max_load_store_offset;
   int                     max_data_page_id;
+  riscv_instr_name_t      allowed_instr[$];
 
   // Some additional reserved registers that should not be used as rd register
   // by this instruction stream
-  riscv_reg_t reserved_rd[];
+  riscv_reg_t             reserved_rd[];
 
   constraint avoid_reserved_rd_c {
     if(reserved_rd.size() > 0) {
@@ -146,14 +165,9 @@
   `uvm_object_new
 
   virtual function void create_instr_instance();
-    riscv_rand_instr instr;
-    if(cfg == null) begin
-      `uvm_fatal(get_full_name(), "cfg object is null")
-    end
+    riscv_instr_base instr;
     for(int i = 0; i < instr_cnt; i++) begin
-      instr = riscv_rand_instr::type_id::create($sformatf("instr_%0d", i));
-      instr.cfg = cfg;
-      instr.reserved_rd = reserved_rd;
+      instr = riscv_instr_base::type_id::create($sformatf("instr_%0d", i));
       instr_list.push_back(instr);
     end
   endfunction
@@ -168,18 +182,69 @@
     end
   endfunction
 
-  virtual function void gen_instr(bit no_branch = 1'b0,
-                                  bit no_load_store = 1'b1,
-                                  bit enable_hint_instr = 1'b0);
+  virtual function setup_allowed_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1);
+    allowed_instr = cfg.basic_instr;
+    if (no_branch == 0) begin
+      allowed_instr = {allowed_instr, cfg.instr_category[BRANCH]};
+    end
+    if (no_load_store == 0) begin
+      allowed_instr = {allowed_instr, cfg.instr_category[LOAD], cfg.instr_category[STORE]};
+    end
+  endfunction
+
+  virtual function void gen_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1);
+    setup_allowed_instr(no_branch, no_load_store);
     foreach(instr_list[i]) begin
-      `DV_CHECK_RANDOMIZE_WITH_FATAL(instr_list[i],
-        // The last instruction cannot be branch instruction as there's no forward branch target.
-        if((i == instr_list.size() - 1) || no_branch) {
-          category != BRANCH;
-        }
-        if(no_load_store) {
-          !(category inside {LOAD, STORE});
-        })
+      randomize_instr(instr_list[i]);
+    end
+    // Do not allow branch instruction as the last instruction because there's no
+    // forward branch target
+    while (instr_list[$].category == BRANCH) begin
+      void'(instr_list.pop_back());
+      if (instr_list.size() == 0) break;
+    end
+  endfunction
+
+  function void randomize_instr(riscv_instr_base instr,
+                                bit skip_rs1 = 1'b0,
+                                bit skip_rs2 = 1'b0,
+                                bit skip_rd  = 1'b0,
+                                bit skip_imm = 1'b0,
+                                bit skip_csr = 1'b0);
+    riscv_instr_name_t instr_name;
+    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(instr_name,
+                                       instr_name inside {allowed_instr};)
+    instr.copy_base_instr(cfg.instr_template[instr_name]);
+    `uvm_info(`gfn, $sformatf("%s: rs1:%0d, rs2:%0d, rd:%0d, imm:%0d",
+                              instr.instr_name.name(),
+                              instr.has_rs1,
+                              instr.has_rs2,
+                              instr.has_rd,
+                              instr.has_imm), UVM_HIGH)
+    if (instr.has_imm && !skip_imm) begin
+      instr.gen_rand_imm();
+    end
+    if (instr.has_rs1 && !skip_rs1) begin
+      if (instr.is_compressed) begin
+        // Compressed instruction could use the same register for rs1 and rd
+        instr.rs1 = instr.gen_rand_gpr(
+                         .included_reg(avail_regs),
+                         .excluded_reg({reserved_rd, cfg.reserved_regs}));
+      end else begin
+        instr.rs1 = instr.gen_rand_gpr(.included_reg(avail_regs));
+      end
+    end
+    if (instr.has_rs2 && !skip_rs2) begin
+      instr.rs2 = instr.gen_rand_gpr(.included_reg(avail_regs));
+    end
+    if (instr.has_rd && !skip_rd) begin
+      instr.rd = instr.gen_rand_gpr(
+                      .included_reg(avail_regs),
+                      .excluded_reg({reserved_rd, cfg.reserved_regs}));
+    end
+    if ((instr.category == CSR) && !skip_csr) begin
+      instr.gen_rand_csr(.privileged_mode(cfg.init_privileged_mode),
+                         .illegal_csr_instr(cfg.enable_illegal_csr_instruction));
     end
   endfunction
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
index 5ed069f..f019616 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
@@ -15,7 +15,6 @@
  */
 
 // Base class for all load/store instruction stream
-// TODO: Support load/store from instruction section.
 
 class riscv_load_store_base_instr_stream extends riscv_directed_instr_stream;
 
@@ -26,9 +25,6 @@
   rand int           addr[];
   rand int unsigned  data_page_id;
   rand riscv_reg_t   rs1_reg;
-  riscv_reg_t        reserved_rd[$];
-  // User can specify a small group of available registers to generate various hazard condition
-  rand riscv_reg_t   avail_regs[];
 
   `uvm_object_utils(riscv_load_store_base_instr_stream)
 
@@ -58,11 +54,11 @@
   endfunction
 
   function void post_randomize();
-    gen_load_store_instr();
     // rs1 cannot be modified by other instructions
     if(!(rs1_reg inside {reserved_rd})) begin
-      reserved_rd.push_back(rs1_reg);
+      reserved_rd = {reserved_rd, rs1_reg};
     end
+    gen_load_store_instr();
     add_mixed_instr();
     add_rs1_init_la_instr();
     super.post_randomize();
@@ -86,68 +82,77 @@
 
   // Generate each load/store instruction
   virtual function void gen_load_store_instr();
-    riscv_rand_instr rand_instr;
-    riscv_instr_name_t allowed_instr[];
+    bit enable_compressed_load_store;
+    riscv_instr_base instr;
     if(avail_regs.size() > 0) begin
       `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(avail_regs,
                                          unique{avail_regs};
+                                         avail_regs[0] inside {[S0 : A5]};
                                          foreach(avail_regs[i]) {
-                                           !(avail_regs[i] inside {cfg.reserved_regs});
+                                           !(avail_regs[i] inside {cfg.reserved_regs, reserved_rd});
                                          },
                                          "Cannot randomize avail_regs")
     end
+    if (rs1_reg inside {[S0 : A5]}) begin
+      enable_compressed_load_store = 1;
+    end
     foreach(addr[i]) begin
-      rand_instr = riscv_rand_instr::type_id::create("rand_instr");
-      rand_instr.cfg = cfg;
-      rand_instr.reserved_rd = reserved_rd;
+      instr = riscv_instr_base::type_id::create("instr");
       // Assign the allowed load/store instructions based on address alignment
       // This is done separately rather than a constraint to improve the randomization performance
       allowed_instr = {LB, LBU, SB};
       if (addr[i][0] == 1'b0) begin
         allowed_instr = {LH, LHU, SH, allowed_instr};
       end
-      if (addr[i][1:0] == 2'b00) begin
-        allowed_instr = {LW, SW, LWU, allowed_instr};
-        if((offset[i] inside {[0:127]}) && (offset[i] % 4 == 0)) begin
+      if (!cfg.enable_unaligned_load_store) begin
+        if (addr[i][1:0] == 2'b00) begin
+          allowed_instr = {LW, SW, allowed_instr};
+          if((offset[i] inside {[0:127]}) && (offset[i] % 4 == 0) &&
+             (RV32C inside {riscv_instr_pkg::supported_isa}) &&
+             enable_compressed_load_store) begin
+            allowed_instr = {C_LW, C_SW, allowed_instr};
+          end
+        end
+        if ((XLEN >= 64) && (addr[i][2:0] == 3'b000)) begin
+          allowed_instr = {LWU, LD, SD, allowed_instr};
+          if((offset[i] inside {[0:255]}) && (offset[i] % 8 == 0) &&
+             (RV64C inside {riscv_instr_pkg::supported_isa} &&
+             enable_compressed_load_store)) begin
+            allowed_instr = {C_LD, C_SD, allowed_instr};
+          end
+        end
+      end else begin
+        allowed_instr = {LW, SW, allowed_instr};
+        if ((offset[i] inside {[0:127]}) && (offset[i] % 4 == 0) &&
+            (RV32C inside {riscv_instr_pkg::supported_isa}) &&
+            enable_compressed_load_store) begin
           allowed_instr = {C_LW, C_SW, allowed_instr};
         end
-      end
-      if(addr[i][2:0] == 3'b000) begin
-        allowed_instr = {LD, SD, allowed_instr};
-        if((offset[i] inside {[0:255]}) && (offset[i] % 8 == 0)) begin
-          allowed_instr = {C_LD, C_SD, allowed_instr};
+        if (XLEN >= 64) begin
+          allowed_instr = {LWU, LD, SD, allowed_instr};
+          if ((offset[i] inside {[0:255]}) && (offset[i] % 8 == 0) &&
+              (RV64C inside {riscv_instr_pkg::supported_isa}) &&
+              enable_compressed_load_store) begin
+              allowed_instr = {C_LD, C_SD, allowed_instr};
+           end
         end
       end
-      `DV_CHECK_RANDOMIZE_WITH_FATAL(rand_instr,
-        solve rs1 before rd;
-        rs1 == rs1_reg;
-        instr_name inside {allowed_instr};
-        if(avail_regs.size() > 0) {
-          rd inside {avail_regs};
-        }
-        rd != rs1;
-      )
-      rand_instr.process_load_store = 0;
-      rand_instr.imm_str = $sformatf("%0d", offset[i]);
-      instr_list.push_back(rand_instr);
+      randomize_instr(instr, .skip_rs1(1'b1), .skip_imm(1'b1));
+      instr.rs1 = rs1_reg;
+      instr.set_imm(offset[i]);
+      instr.process_load_store = 0;
+      instr_list.push_back(instr);
     end
   endfunction
 
   // Insert some other instructions to mix with load/store instruction
   virtual function void add_mixed_instr();
-    riscv_rand_instr rand_instr;
+    riscv_instr_base instr;
+    setup_allowed_instr(1, 1);
     for(int i = 0; i < num_mixed_instr; i ++) begin
-      rand_instr = riscv_rand_instr::type_id::create("rand_instr");
-      rand_instr.cfg = cfg;
-      rand_instr.reserved_rd = reserved_rd;
-      `DV_CHECK_RANDOMIZE_WITH_FATAL(rand_instr,
-        if(avail_regs.size() > 0) {
-          rs1 inside {avail_regs};
-          rd inside {avail_regs};
-        }
-        !(category inside {LOAD, STORE, BRANCH, JUMP});,
-        "Cannot randomize instruction")
-      insert_instr(rand_instr);
+      instr = riscv_instr_base::type_id::create("instr");
+      randomize_instr(instr);
+      insert_instr(instr);
     end
   endfunction
 
@@ -310,7 +315,8 @@
       // Make sure each load/store sequence doesn't override the rs1 of other sequences.
       foreach(rs1_reg[j]) begin
         if(i != j) begin
-          load_store_instr_stream[i].reserved_rd.push_back(rs1_reg[j]);
+          load_store_instr_stream[i].reserved_rd =
+            {load_store_instr_stream[i].reserved_rd, rs1_reg[j]};
         end
       end
       `DV_CHECK_RANDOMIZE_WITH_FATAL(load_store_instr_stream[i],
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_page_table_list.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_page_table_list.sv
index 1b88b35..4a7b35d 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_page_table_list.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_page_table_list.sv
@@ -244,7 +244,7 @@
   // 2. For normal test, a page table fault typically means the program is accessing a large
   //    virtual address which currently not mapped a valid physical address. Need to do a
   //    memcpy to move data from lower physical address to the place the virtual address map to.
-  virtual function void gen_page_fault_handling_routine(output string instr[$]);
+  virtual function void gen_page_fault_handling_routine(ref string instr[$]);
     int unsigned  level;
     string        load_store_unit;
     bit[XLEN-1:0] bit_mask = '1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_rand_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_rand_instr.sv
index 27c2b9c..b43f5fe 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_rand_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_rand_instr.sv
@@ -23,12 +23,23 @@
 
   `uvm_object_utils(riscv_rand_instr)
 
+  constraint category_c {
+    soft category inside {LOAD, STORE, SHIFT, ARITHMETIC, LOGICAL,
+                          BRANCH, COMPARE, CSR, SYSTEM, SYNCH};
+  }
+
+  // Atomic extension instructions are default disabled
+  // AMO instruction generation is handled by riscv_amo_instr_lib.sv
+  constraint disable_a_extension_c {
+    group != RV32A;
+    group != RV64A;
+  }
+
   constraint instr_c {
     solve instr_name before imm;
     solve instr_name before rs1;
     solve instr_name before rs2;
     !(instr_name inside {riscv_instr_pkg::unsupported_instr});
-    category inside {LOAD, STORE, SHIFT, ARITHMETIC, LOGICAL, BRANCH, COMPARE, CSR, SYSTEM, SYNCH};
     group inside {riscv_instr_pkg::supported_isa};
     // Avoid using any special purpose register as rd, those registers are reserved for
     // special instructions
@@ -57,20 +68,6 @@
     instr_name != C_ADDI4SPN;
   }
 
-  constraint rvc_csr_c {
-    //  Registers specified by the three-bit rs1’, rs2’, and rd’ fields of the CIW, CL, CS,
-    //  and CB formats
-    if(format inside {CIW_FORMAT, CL_FORMAT, CS_FORMAT, CB_FORMAT}) {
-      rs1 inside {[S0:A5]};
-      rs2 inside {[S0:A5]};
-      rd  inside {[S0:A5]};
-    }
-    // C_ADDI16SP is only valid when rd == SP
-    if(instr_name == C_ADDI16SP) {
-      rd == SP;
-    }
-  }
-
   constraint constraint_cfg_knob_c {
     if(cfg.no_ebreak) {
       instr_name != EBREAK;
@@ -110,6 +107,14 @@
     }
   }
 
+  // No label is needed if there's no branch/jump instruction
+  function void post_randomize();
+    super.post_randomize();
+    if (cfg.no_branch_jump) begin
+      has_label = 1'b0;
+    end
+  endfunction
+
   `uvm_object_new
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_signature_pkg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_signature_pkg.sv
new file mode 100644
index 0000000..45194d2
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_signature_pkg.sv
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * 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.
+ */
+
+package riscv_signature_pkg;
+
+  // Will be the lowest 8 bits of the data word
+  typedef enum bit[7:0] {
+    // Information sent to the core relating its current status.
+    // Bits [12:8] of the data word will be the core_status_t value
+    // corresponding to the current core status.
+    CORE_STATUS,
+    // Information sent to the core conveying the uvm simulation result.
+    // Bit [8] of the data word will be the test_result_t value.
+    TEST_RESULT,
+    // Sent to the core to indicate a dump of GPRs to testbench.
+    // Will be followed by 32 writes of registers x0-x32.
+    WRITE_GPR,
+    // Sent to the core to indicate a write of a CSR's data.
+    // Bits [19:8] of the data word will be the CSR address.
+    // Will be followed by a second write of the actual data from the CSR.
+    WRITE_CSR
+  } signature_type_t;
+
+  typedef enum bit[4:0] {
+    INITIALIZED,
+    IN_DEBUG_MODE,
+    IN_MACHINE_MODE,
+    IN_HYPERVISOR_MODE,
+    IN_SUPERVISOR_MODE,
+    IN_USER_MODE,
+    HANDLING_IRQ,
+    HANDLING_EXCEPTION
+  } core_status_t;
+
+  typedef enum bit {
+    TEST_PASS,
+    TEST_FAIL
+  } test_result_t;
+
+
+endpackage
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_base_test.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_base_test.sv
index d878c49..f1d8186 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_base_test.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_base_test.sv
@@ -64,20 +64,21 @@
   endfunction
 
   function void get_directed_instr_stream_opts();
-    string instr_name;
-    int ratio;
     string cmd_opts_prefix;
+    string opts;
+    string opt[$];
     int i = 0;
     while(1) begin
       cmd_opts_prefix = $sformatf("directed_instr_%0d", i);
-      if($value$plusargs({cmd_opts_prefix, "=%0s"}, instr_name) &&
-         $value$plusargs({cmd_opts_prefix, "_ratio=%0d"}, ratio)) begin
-        asm_gen.add_directed_instr_stream(instr_name, ratio);
+      if($value$plusargs({cmd_opts_prefix, "=%0s"}, opts)) begin
+        uvm_split_string(opts, ",", opt);
+        `DV_CHECK_FATAL(opt.size() == 2)
+        asm_gen.add_directed_instr_stream(opt[0], opt[1].atoi());
       end else begin
         break;
       end
-      `uvm_info(`gfn, $sformatf("Got directed instr[%0d] %0s, ratio = %0d/1000",
-                                 i, instr_name, ratio), UVM_LOW)
+      `uvm_info(`gfn, $sformatf("Got directed instr[%0d] %0s, ratio = %0s/1000",
+                                 i, opt[0], opt[1]), UVM_LOW)
       i++;
     end
 
@@ -98,6 +99,7 @@
       test_name = $sformatf("%0s.%0d.S", asm_file_name, i);
       apply_directed_instr();
       `uvm_info(`gfn, "All directed instruction is applied", UVM_LOW)
+      cfg.build_instruction_template();
       asm_gen.gen_program();
       asm_gen.gen_test_file(test_name);
     end
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv
index 8761448..e4be2f4 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv
@@ -14,120 +14,6 @@
  * limitations under the License.
  */
 
-//================================================================================================
-// RISC-V Test Library
-//------------------------------------------------------------------------------------------------
-// riscv_arithmetic_basic_test :
-//  - Simple arithmetic instruction test, [machine mode]
-//
-// riscv_machine_mode_rand_test :
-//  - Random instruction test, include sub-programs, branch, load/store [machine mode]
-//
-// riscv_privileged_mode_rand_test :
-//  - Similar to riscv_machine_mode_rand_test, run in supervisor mode or user mode if supported
-//
-// riscv_rand_instr_test :
-//  - A full random test, with a mix of directed instruction stream
-//
-// riscv_rand_jump_test :
-//  - Random jump among a large number of sub programs
-//
-// riscv_mmu_stress_test:
-//  - A mixed of intense load/store instructions
-//
-// riscv_page_table_exception_test:
-//  - Running test in privileged mode with page table exceptions
-//
-// riscv_no_fence_test
-//  - Random instruction with fence disabled, allow more intense instruction execution
-//
-// riscv_sfence_exception_test
-//  - Random instruction with sfence exception. sfence.vma could be excuted in non-supervisor mode
-//    or mstatus.tvm is set.
-//
-// riscv_illegal_instr_test:
-//  - Random instruction mixed with illegal instructions
-//
-// riscv_hint_instr_test:
-//  - Random instruction mixed with HINT instructions
-//
-// riscv_ebreak_test:
-//  - Randomly inject ebreak instruction, verify core can be halted and resumed properly
-//
-// riscv_wfi_test:
-//  - Randomly inject wfi instruction, verify core can be halted and resumed properly(by interrupt)
-//
-// riscv_csr_test:
-//  - Random instructions with CSR intruction enabled
-//
-// riscv_illegal_csr_test:
-//  - Accessing non-existence CSR or CSR with the wrong privileged mode
-//
-//================================================================================================
-
-class riscv_arithmetic_basic_test extends riscv_instr_base_test;
-
-  `uvm_component_utils(riscv_arithmetic_basic_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.instr_cnt = 10000;
-    cfg.num_of_sub_program = 0;
-    cfg.no_fence = 1;
-    cfg.no_data_page = 1'b1;
-    cfg.no_branch_jump = 1'b1;
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg,
-                                   init_privileged_mode == MACHINE_MODE;
-                                   max_nested_loop == 0;)
-    `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
-                    cfg.sprint()), UVM_LOW)
-  endfunction
-
-endclass
-
-class riscv_machine_mode_rand_test extends riscv_instr_base_test;
-
-  `uvm_component_utils(riscv_machine_mode_rand_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.instr_cnt = 10000;
-    cfg.num_of_sub_program = 5;
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg,
-                                   init_privileged_mode == MACHINE_MODE;
-                                   max_nested_loop == 0;)
-    `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
-                    cfg.sprint()), UVM_LOW)
-  endfunction
-
-  virtual function void apply_directed_instr();
-    // Add load/store instruction stream
-    asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10);
-  endfunction
-
-endclass
-
-class riscv_privileged_mode_rand_test extends riscv_instr_base_test;
-
-  `uvm_component_utils(riscv_privileged_mode_rand_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.instr_cnt = 10000;
-    cfg.num_of_sub_program = 5;
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg,
-                                   init_privileged_mode != MACHINE_MODE;
-                                   max_nested_loop == 0;)
-    `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
-                    cfg.sprint()), UVM_LOW)
-  endfunction
-
-  virtual function void apply_directed_instr();
-    // Add load/store instruction stream
-    asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10);
-  endfunction
-
-endclass
 
 class riscv_rand_instr_test extends riscv_instr_base_test;
 
@@ -154,142 +40,3 @@
   endfunction
 
 endclass
-
-class riscv_rand_jump_test extends riscv_instr_base_test;
-
-  `uvm_component_utils(riscv_rand_jump_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.instr_cnt = 20000;
-    cfg.num_of_sub_program = 20;
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg,
-                                   max_nested_loop == 1;)
-    `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
-                    cfg.sprint()), UVM_LOW)
-  endfunction
-
-  virtual function void apply_directed_instr();
-    asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10);
-  endfunction
-
-endclass
-
-class riscv_mmu_stress_test extends riscv_instr_base_test;
-
-  `uvm_component_utils(riscv_mmu_stress_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.instr_cnt = 500;
-    cfg.num_of_sub_program = 0;
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg,
-                                   max_nested_loop == 0;)
-    `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
-                    cfg.sprint()), UVM_LOW)
-  endfunction
-
-  virtual function void apply_directed_instr();
-    // Mix below directed instructino streams with the random instructions
-    asm_gen.add_directed_instr_stream("riscv_cache_line_stress_instr_stream", 80);
-    asm_gen.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 80);
-    asm_gen.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 80);
-  endfunction
-
-endclass
-
-class riscv_page_table_exception_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_page_table_exception_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.enable_page_table_exception = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_no_fence_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_no_fence_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.no_fence = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_sfence_exception_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_sfence_exception_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.allow_sfence_exception = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_illegal_instr_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_illegal_instr_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.enable_illegal_instruction = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_hint_instr_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_hint_instr_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.enable_hint_instruction = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_ebreak_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_ebreak_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.no_ebreak = 1'b0;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_wfi_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_wfi_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.no_wfi = 1'b0;
-    super.randomize_cfg();
-  endfunction
-
-endclass
-
-class riscv_illegal_csr_test extends riscv_rand_instr_test;
-
-  `uvm_component_utils(riscv_illegal_csr_test)
-  `uvm_component_new
-
-  virtual function void randomize_cfg();
-    cfg.enable_illegal_csr_instruction = 1'b1;
-    super.randomize_cfg();
-  endfunction
-
-endclass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/testlist b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/testlist
deleted file mode 100644
index ec6f707..0000000
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/testlist
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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.
-
-//====================================================================
-// Test name                    : iterations :       options
-//--------------------------------------------------------------------
-riscv_arithmetic_basic_test     :      2     :
-riscv_machine_mode_rand_test    :      2     :
-riscv_privileged_mode_rand_test :      2     :
-riscv_rand_instr_test           :      2     :
-riscv_rand_jump_test            :      2     :
-riscv_mmu_stress_test           :      2     :
-riscv_page_table_exception_test :      2     :
-riscv_no_fence_test             :      2     :
-riscv_sfence_exception_test     :      2     :
-riscv_illegal_instr_test        :      2     :
-riscv_hint_instr_test           :      2     :
-riscv_ebreak_test               :      2     :
-riscv_wfi_test                  :      2     :
-//--------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/csr_template.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/csr_template.yaml
index fed03e0..feeb096 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/csr_template.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/csr_template.yaml
@@ -4,7 +4,7 @@
 # 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
+#      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,
@@ -17,12 +17,13 @@
 #- csr: CSR_NAME
 #  description: >
 #    BRIEF_DESCRIPTION
+#  address: 0x###
 #  privilege_mode: MODE (D/M/S/H/U)
 #  rv32:
 #    - MSB_FIELD_NAME:
 #      - description: >
 #          BRIEF_DESCRIPTION
-#      - type: TYPE (WPRI/WLRL/WARL)
+#      - type: TYPE (WPRI/WLRL/WARL/R)
 #      - reset_val: RESET_VAL
 #      - msb: MSB_POS
 #      - lsb: LSB_POS
@@ -36,7 +37,7 @@
 #    - MSB_FIELD_NAME:
 #      - description: >
 #          BRIEF_DESCRIPTION
-#      - type: TYPE (WPRI/WLRL/WARL)
+#      - type: TYPE (WPRI/WLRL/WARL/R)
 #      - reset_val: RESET_VAL
 #      - msb: MSB_POS
 #      - lsb: LSB_POS
@@ -53,6 +54,7 @@
 - csr: misa
   description: >
     Machine ISA Register
+  address: 0x301
   privilege_mode: M
   rv32:
     - field_name: MXL
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
index a5be72f..216cc6d 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/iss.yaml
@@ -4,7 +4,7 @@
 # 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
+#      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,
@@ -26,3 +26,8 @@
     --override riscvOVPsim/cpu/simulateexceptions=T
     --trace --tracechange --traceshowicount --program <elf>
     --finishafter 500000
+
+- iss: sail
+  path_var: SAIL_RISCV
+  cmd: >
+    <path_var> <elf>
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
index 15a6bba..f73eca2 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
@@ -4,7 +4,7 @@
 # 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
+#      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,
@@ -36,15 +36,16 @@
   compile_cmd:
     - "vmap mtiUvm $QUESTA_HOME/questasim/uvm-1.2"
     - "vlog -64
-     -access=rwc
-     -f <cwd>/files.f
-     -sv
-     -mfcu -cuname design_cuname
-     +define+UVM_REGEX_NO_DPI
-     -writetoplevels <out>/top.list
-     -l <out>/compile.log <cmp_opts>"
+      -access=rwc
+      -f <cwd>/files.f
+      -sv
+      -mfcu -cuname design_cuname
+      +define+UVM_REGEX_NO_DPI
+      -writetoplevels <out>/top.list
+      -l <out>/compile.log <cmp_opts>"
     - "vopt -64 -debug
-     +designfile -f <out>/top.list
-     -o design_opt"
+      +designfile -f <out>/top.list
+      -l <out>/optimize.log <cmp_opts>
+      -o design_opt"
   sim_cmd: >
-    vsim -64 -c -do <cwd>/questa_sim.tcl design_opt <sim_opts>  -svseed <seed>
+    vsim -64 -c -do <cwd>/questa_sim.tcl design_opt <sim_opts>  -sv_seed <seed>
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/testlist.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/testlist.yaml
index 4a7315b..22ce918 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/testlist.yaml
@@ -4,7 +4,7 @@
 # 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
+#      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,
@@ -12,19 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# ======================================================================
+# ================================================================================
 #                  Regression test list format
-# ----------------------------------------------------------------------
-# test         : Assembly test name
-# description  : Description of this test
-# gen_opts     : Instruction generator options
-# iterations   : Number of iterations of this test
-# gen_test     : Test name used by the instruction generator
-# rtl_test     : RTL simulation test name
-# cmp_opts     : Compile options passed to the instruction generator
-# sim_opts     : Simulation options passed to the instruction generator
-# compare_opts : Options for the RTL & ISS trace comparison
-# ----------------------------------------------------------------------
+# --------------------------------------------------------------------------------
+# test            : Assembly test name
+# description     : Description of this test
+# gen_opts        : Instruction generator options
+# iterations      : Number of iterations of this test
+# no_iss          : Enable/disable ISS simulator (Optional)
+# gen_test        : Test name used by the instruction generator
+# rtl_test        : RTL simulation test name
+# cmp_opts        : Compile options passed to the instruction generator
+# sim_opts        : Simulation options passed to the instruction generator
+# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional)
+# compare_opts    : Options for the RTL & ISS trace comparison
+# gcc_opts        : gcc compile options
+# --------------------------------------------------------------------------------
 
 - test: riscv_arithmetic_basic_test
   description: >
@@ -77,6 +80,18 @@
     +directed_instr_5=riscv_multi_page_load_store_instr_stream,4
   rtl_test: core_base_test
 
+# TODO: Temporarily disable this as compiler seems to generate compressed instruction with rv64im
+- test: riscv_non_compressed_instr_test
+  description: >
+    Random instruction test without compressed instructions
+  iterations: 0
+  gen_test: riscv_rand_instr_test
+  gen_opts: >
+    +march=RV32I,RV32M,RV64I,RV64M
+  gcc_opts: >
+    -march=rv64im
+  rtl_test: core_base_test
+
 - test: riscv_rand_jump_test
   description: >
     Jump among large number of sub-programs, stress testing iTLB operations.
@@ -95,7 +110,7 @@
   iterations: 2
   gen_test: riscv_instr_base_test
   gen_opts: >
-    +instr_cnt=10000
+    +instr_cnt=5000
     +num_of_sub_program=5
     +directed_instr_0=riscv_load_store_rand_instr_stream,40
     +directed_instr_1=riscv_load_store_hazard_instr_stream,40
@@ -175,33 +190,57 @@
     +no_ebreak=0
   rtl_test: core_base_test
   sim_opts: >
+    +require_signature_addr=1
     +enable_debug_seq=1
   compare_opts: >
     +compare_final_value_only=1
 
-- test: riscv_fast_interrupt_test
-  description: >
-    WFI(wait for interrupt) instruction test. If WFI is supported, processor
-    should halt execution upon decoding WFI instruction and resume execution
-    by interrupt. Otherwise WFI should be executed as NOP instruction.
-    Interrupt handling routine is skipped to allow instruction strace comparison
-    with ISS which is not interrupted during execution.
-  iterations: 2
-  gen_test: riscv_rand_instr_test
-  gen_opts: >
-    +skip_trap_handling=1
-    +no_wfi=0
-  rtl_test: core_base_test
-  sim_opts: >
-    +enable_irq_seq=1
-
 - test: riscv_full_interrupt_test
   description: >
     Random instruction test with complete interrupt handling
   iterations: 2
   gen_test: riscv_rand_instr_test
+  gen_opts: >
   rtl_test: core_base_test
   sim_opts: >
     +enable_irq_seq=1
   compare_opts: >
     +compare_final_value_only=1
+
+  # Please enable this test for your RTL simulation
+- test: riscv_csr_test
+  description: >
+    Test all CSR instructions on all implemented CSR registers
+  iterations: 0
+  no_iss: 1
+  rtl_test: core_ibex_csr_test
+  no_post_compare: 1
+
+- test: riscv_unaligned_load_store_test
+  description: >
+    Unaligned load/store test, ibex should handle it correctly without raising any exception
+  iterations: 1
+  gen_test: riscv_instr_base_test
+  gcc_opts: >
+    -mno-strict-align
+  gen_opts: >
+    +instr_cnt=6000
+    +num_of_sub_program=5
+    +directed_instr_0=riscv_load_store_rand_instr_stream,20
+    +directed_instr_1=riscv_load_store_hazard_instr_stream,20
+    +directed_instr_2=riscv_cache_line_stress_instr_stream,20
+    +directed_instr_3=riscv_multi_page_load_store_instr_stream,20
+    +enable_unaligned_load_store=1
+  rtl_test: core_ibex_base_test
+
+- test: riscv_amo_test
+  description: >
+    RISC-V atomic instruction extension test
+  iterations: 2
+  gen_test: riscv_rand_instr_test
+  gen_opts: >
+    +instr_cnt=5000
+    +num_of_sub_program=5
+    +directed_instr_0=riscv_lr_sc_instr_stream,10
+    +directed_instr_1=riscv_amo_instr_stream,10
+  rtl_test: core_base_test