Update lowrisc_ibex to lowRISC/ibex@ae547c8

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

* [top_pkg] Fix style lint warnings (Michael Schaffner)
* [ibex/dv] Add clocking blocks to Ibex interfaces (Udi)
* Add a stress_all_with_reset ICache test (Rupert Swarbrick)
* Invalidate in an ICache sequence after a change to mem_err_shift
  (Rupert Swarbrick)
* Fix ICache caching window test with combination sequences (Rupert
  Swarbrick)
* Add ibex_icache_stress_all test (Rupert Swarbrick)
* Tidy up properly after overriding class in ICache back_line_seq
  (Rupert Swarbrick)
* Remove empty tasks from ibex_icache_base_vseq.sv (Rupert Swarbrick)
* Use dv_base_vseq's num_trans field rather than making our own
  (Rupert Swarbrick)
* Control core sequence's transaction count from top in ICache tests
  (Rupert Swarbrick)
* Remove ibex_icache_sanity_vseq (Rupert Swarbrick)
* Configure ICache mem_error tests from the vseq (not a test class)
  (Rupert Swarbrick)
* Pass mem_err_shift to the ICache memory model on each error check
  (Rupert Swarbrick)
* Configure ICache ECC tests just from the vseq (not a test class)
  (Rupert Swarbrick)
* [rtl] disable clock between reset and fetch_enable_i (Bert Pieters)
* Add some basic protocol checking to the icache's RAM interface
  (Rupert Swarbrick)
* Enable ICache ECC in the way dvsim.py requires (Rupert Swarbrick)
* Update lec_sv2v.sh (NilsGraf)
* Update lec_sv2v.sh (NilsGraf)
* Update lec_sv2v.do (NilsGraf)
* Add LEC script to formally verify sv2v translation (Nils Graf)
* [dv/ibex] Update riscv_core_setting to match latest version of
  riscv-dv (Udi)
* Correct window_width calculation in ICache UVM scoreboard (Rupert
  Swarbrick)
* Fix ordering in ICache core monitor start-up (Rupert Swarbrick)
* Correct "cancelled_valid" sequence in ICache UVM core coverage
  (Rupert Swarbrick)
* Allow ready & branch in ICache UVM tests (Rupert Swarbrick)
* Weight branches in icache tests to favour edges of address space
  (Rupert Swarbrick)
* Update google_riscv-dv to google/riscv-dv@6cf6b4f (Udi)
* Fix documentation markup for tracer (Philipp Wagner)
* [rtl] Remove use of `define in decoder (Bert Pieters)
* Increase priority of failure messages in ICache scoreboard (Rupert
  Swarbrick)
* Fix verbosity in ECC UVM driver (Rupert Swarbrick)
* [dv] Fix DUT probe IF paths (Tom Roberts)
* Add ECC agents to ICache DV plan document (Rupert Swarbrick)
* Define an "ECC agent" for icache testing and a test that uses it
  (Rupert Swarbrick)
* Add and use a 'badbit' RAM for ICache tests (Rupert Swarbrick)
* Enable ECC in ICache tests (Rupert Swarbrick)
* Drive the branch_spec line in ICache UVM tests (Rupert Swarbrick)
* [ibex/dv] add Questa support (Bert Pieters)
* Simplify timestamps in ICache tests (Rupert Swarbrick)
* Update lowrisc_ip to lowRISC/opentitan@c91b50f3 (Rupert Swarbrick)
* [rtl] Simplify I$ ECC error handling (Tom Roberts)
* [rtl] Use outer generate loop for latch RF (Greg Chadwick)
* [doc] Add top-level status table (Tom Roberts)
* [configs] Add a maxperf config (Tom Roberts)
* [rtl] Use gated clock for wb_stage and rf (Greg Chadwick)
* [rtl] Use generate loop in FF register file (Greg Chadwick)

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index c385c59..e840e7b 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -7,17 +7,39 @@
 
 <p align="center"><img src="doc/images/blockdiagram.svg" width="650"></p>
 
-Ibex offers several configuration parameters to meet the needs of various application scenarios.
-The options include two different choices for the architecture of the multiplier and divider unit,
-as well as the possibility to drop the support for the "M" extension completely. In addition, the
-"E" extension can be enabled when opting for a minimum-area configuration.
-
 This core was initially developed as part of the [PULP platform](https://www.pulp-platform.org)
 under the name "Zero-riscy" \[[1](https://doi.org/10.1109/PATMOS.2017.8106976)\], and has been
 contributed to [lowRISC](https://www.lowrisc.org) who maintains it and develops it further. It is
 under active development, with further code cleanups, feature additions, and test and verification
 planned for the future.
 
+## Configuration
+
+Ibex offers several configuration parameters to meet the needs of various application scenarios.
+The options include different choices for the architecture of the multiplier unit, as well as a range of performance and security features.
+The table below indicates performance, area and verification status for a few selected configurations.
+These are configurations on which lowRISC is focusing for performance evaluation and design verification (see [supported configs](ibex_configs.yaml)).
+
+| Config | "small" | "maxperf" | "maxperf-pmp-bm" |
+| ------ | ------- | --------- | ---------------- |
+| Features | RV32IMC, 3 cycle mult | RV32IMC, 1 cycle mult, Branch target ALU, Writeback stage | RV32IMCB, 1 cycle mult, Branch target ALU, Writeback stage, 16 PMP regions |
+| Performance (Coremark/MHz) | 2.44 | 3.09 | 3.09 |
+| Area - Yosys (kGE) | 33.15 | 39.03 | 63.32 |
+| Area - Commercial (estimated kGE) | ~27 | ~31 | ~50 |
+| Verification status | Green | Amber | Amber |
+
+Notes:
+
+* Performance numbers are based on Cormark running on the Ibex Simple System [platform](examples/simple_system/README.md).
+  Note that Coremark was compiled without support for the B extension.
+* Yosys synthesis area numbers are based on the Ibex basic synthesis [flow](syn/README.md).
+* Commercial synthesis area numbers are a rough estimate of what might be achievable with a commercial synthesis flow and technology library.
+* Verification status is a rough guide to the overall maturity of a particular configuration.
+  Green indicates that verification is close to complete.
+  Amber indicates that some verification has been performed, but the configuration is still experimental.
+  Red indicates a new configuration with minimal/no verification.
+  Users must make their own assessment of verification readiness for any tapeout.
+
 ## Documentation
 
 The Ibex user manual can be
diff --git a/hw/vendor/lowrisc_ibex/doc/tracer.rst b/hw/vendor/lowrisc_ibex/doc/tracer.rst
index 9e87950..4ba2610 100644
--- a/hw/vendor/lowrisc_ibex/doc/tracer.rst
+++ b/hw/vendor/lowrisc_ibex/doc/tracer.rst
@@ -26,11 +26,14 @@
 3. **PC**: The program counter
 4. **Instr**: The executed instruction (base 16).
    32 bit wide instructions (8 hex digits) are uncompressed instructions, 16 bit wide instructions (4 hex digits) are compressed instructions.
-5. **Decoded instruction**: The decoded (disassembled) instruction in a format equal to what objdump produces when calling it like ``objdump -Mnumeric -Mno-aliases -D``.
+5. **Decoded instruction**:
+   The decoded (disassembled) instruction in a format equal to what objdump produces when calling it like ``objdump -Mnumeric -Mno-aliases -D``.
+
    - Unsigned numbers are given in hex (prefixed with ``0x``), signed numbers are given as decimal numbers.
    - Numeric register names are used (e.g. ``x1``).
    - Symbolic CSR names are used.
    - Jump/branch targets are given as absolute address if possible (PC + immediate).
+
 6. **Register and memory contents**: For all accessed registers, the value before and after the instruction execution is given. Writes to registers are indicated as ``registername=value``, reads as ``registername:value``. For memory accesses, the address and the loaded and stored data are given.
 
 .. code-block:: text
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf.sv
index df08595..bf8659c 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf.sv
@@ -2,10 +2,13 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-interface ibex_mem_intf#(parameter int ADDR_WIDTH = 32,
-                         parameter int DATA_WIDTH = 32);
+interface ibex_mem_intf#(
+  parameter int ADDR_WIDTH = 32,
+  parameter int DATA_WIDTH = 32
+) (
+  input clk
+);
 
-  logic                    clock;
   logic                    reset;
   logic                    request;
   logic                    grant;
@@ -17,4 +20,51 @@
   logic [DATA_WIDTH-1:0]   rdata;
   logic                    error;
 
+  clocking host_driver_cb @(posedge clk);
+    input   reset;
+    output  request;
+    input   grant;
+    output  addr;
+    output  we;
+    output  be;
+    input   rvalid;
+    output  wdata;
+    input   rdata;
+    input   error;
+  endclocking
+
+  clocking device_driver_cb @(posedge clk);
+    input   reset;
+    input   request;
+    output  grant;
+    input   addr;
+    input   we;
+    input   be;
+    output  rvalid;
+    input   wdata;
+    output  rdata;
+    output  error;
+  endclocking
+
+  clocking monitor_cb @(posedge clk);
+    input reset;
+    input request;
+    input grant;
+    input addr;
+    input we;
+    input be;
+    input rvalid;
+    input wdata;
+    input rdata;
+    input error;
+  endclocking
+
+  task automatic wait_clks(input int num);
+    repeat (num) @(posedge clk);
+  endtask
+
+  task automatic wait_neg_clks(input int num);
+    repeat (num) @(negedge clk);
+  endtask
+
 endinterface : ibex_mem_intf
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_master_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_master_driver.sv
index e8117a5..34d9abb 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_master_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_master_driver.sv
@@ -31,11 +31,11 @@
   endtask : run_phase
 
   virtual protected task get_and_drive();
-    @(negedge vif.reset);
+    @(negedge vif.host_driver_cb.reset);
     forever begin
-      @(posedge vif.clock);
+      vif.wait_clks(1);
       seq_item_port.get_next_item(req);
-      repeat(req.req_delay) @(posedge vif.clock);
+      vif.wait_clks(req.req_delay);
       $cast(rsp, req.clone());
       rsp.set_id_info(req);
       drive_transfer(rsp);
@@ -45,31 +45,31 @@
 
   virtual protected task reset_signals();
     forever begin
-      @(posedge vif.reset);
-      vif.request        <= 'h0;
-      vif.addr           <= 'hz;
-      vif.wdata          <= 'hz;
-      vif.be             <= 'bz;
-      vif.we             <= 'bz;
+      @(posedge vif.host_driver_cb.reset);
+      vif.host_driver_cb.request        <= 'h0;
+      vif.host_driver_cb.addr           <= 'hz;
+      vif.host_driver_cb.wdata          <= 'hz;
+      vif.host_driver_cb.be             <= 'bz;
+      vif.host_driver_cb.we             <= 'bz;
     end
   endtask : reset_signals
 
   virtual protected task drive_transfer (ibex_mem_intf_seq_item trans);
     if (trans.req_delay > 0) begin
-      repeat(trans.req_delay) @(posedge vif.clock);
+      vif.wait_clks(trans.req_delay);
     end
-    vif.request <= 1'b1;
-    vif.addr    <= trans.addr;
-    vif.be      <= trans.be;
-    vif.we      <= trans.read_write;
-    vif.wdata   <= trans.data;
-    wait(vif.grant === 1'b1);
-    @(posedge vif.clock);
-    vif.request <= 'h0;
-    vif.addr    <= 'hz;
-    vif.wdata   <= 'hz;
-    vif.be      <= 'bz;
-    vif.we      <= 'bz;
+    vif.host_driver_cb.request <= 1'b1;
+    vif.host_driver_cb.addr    <= trans.addr;
+    vif.host_driver_cb.be      <= trans.be;
+    vif.host_driver_cb.we      <= trans.read_write;
+    vif.host_driver_cb.wdata   <= trans.data;
+    wait (vif.host_driver_cb.grant === 1'b1);
+    vif.wait_clks(1);
+    vif.host_driver_cb.request <= 'h0;
+    vif.host_driver_cb.addr    <= 'hz;
+    vif.host_driver_cb.wdata   <= 'hz;
+    vif.host_driver_cb.be      <= 'bz;
+    vif.host_driver_cb.we      <= 'bz;
     rdata_queue.put(trans);
   endtask : drive_transfer
 
@@ -77,10 +77,10 @@
     ibex_mem_intf_seq_item tr;
     forever begin
       rdata_queue.get(tr);
-      @(posedge vif.clock);
-      while(vif.rvalid !== 1'b1) @(posedge vif.clock);
+      vif.wait_clks(1);
+      while(vif.rvalid !== 1'b1) vif.wait_clks(1);
       if(tr.read_write == READ)
-        tr.data = vif.rdata;
+        tr.data = vif.host_driver_cb.rdata;
       seq_item_port.put_response(tr);
     end
   endtask : collect_response
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_monitor.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_monitor.sv
index 8383e07..03d70dd 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_monitor.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_monitor.sv
@@ -28,12 +28,12 @@
   endfunction: build_phase
 
   virtual task run_phase(uvm_phase phase);
-    wait(vif.reset === 1'b0);
+    wait (vif.monitor_cb.reset === 1'b0);
     forever begin
       fork : check_mem_intf
         collect_address_phase();
         collect_data_phase();
-        wait(vif.reset === 1'b1);
+        wait (vif.monitor_cb.reset === 1'b1);
       join_any
       // Will only reach this point when mid-test reset is asserted
       disable check_mem_intf;
@@ -45,21 +45,21 @@
     ibex_mem_intf_seq_item mailbox_result;
     // Clear the mailbox of any content
     while (collect_data_queue.try_get(mailbox_result));
-    wait(vif.reset === 1'b0);
+    wait (vif.monitor_cb.reset === 1'b0);
   endtask
 
   virtual protected task collect_address_phase();
     ibex_mem_intf_seq_item trans_collected;
     forever begin
       trans_collected = ibex_mem_intf_seq_item::type_id::create("trans_collected");
-      while(!(vif.request && vif.grant)) @(posedge vif.clock);
-      trans_collected.addr = vif.addr;
-      trans_collected.be   = vif.be;
+      while(!(vif.monitor_cb.request && vif.monitor_cb.grant)) vif.wait_clks(1);
+      trans_collected.addr = vif.monitor_cb.addr;
+      trans_collected.be   = vif.monitor_cb.be;
       `uvm_info(get_full_name(), $sformatf("Detect request with address: %0x",
                 trans_collected.addr), UVM_HIGH)
-      if(vif.we) begin
+      if(vif.monitor_cb.we) begin
         trans_collected.read_write = WRITE;
-        trans_collected.data = vif.wdata;
+        trans_collected.data = vif.monitor_cb.wdata;
       end else begin
         trans_collected.read_write = READ;
       end
@@ -69,7 +69,7 @@
         item_collected_port.write(trans_collected);
       else
         collect_data_queue.put(trans_collected);
-      @(posedge vif.clock);
+      vif.wait_clks(1);
     end
   endtask : collect_address_phase
 
@@ -78,9 +78,9 @@
     forever begin
       collect_data_queue.get(trans_collected);
       do
-        @(posedge vif.clock);
-      while(vif.rvalid === 0);
-      trans_collected.data = vif.rdata;
+        vif.wait_clks(1);
+      while(vif.monitor_cb.rvalid === 0);
+      trans_collected.data = vif.monitor_cb.rdata;
       item_collected_port.write(trans_collected);
     end
   endtask : collect_data_phase
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv
index 58520fe..3eb2f69 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv
@@ -27,12 +27,12 @@
 
   virtual task run_phase(uvm_phase phase);
     reset_signals();
-    wait(vif.reset === 1'b0);
+    wait (vif.device_driver_cb.reset === 1'b0);
     forever begin
       fork : drive_stimulus
         send_grant();
         get_and_drive();
-        wait(vif.reset === 1'b1);
+        wait (vif.device_driver_cb.reset === 1'b1);
       join_any
       // Will only be reached after mid-test reset
       disable drive_stimulus;
@@ -52,26 +52,26 @@
       end
     end while (req != null);
     reset_signals();
-    wait(vif.reset === 1'b0);
+    wait (vif.device_driver_cb.reset === 1'b0);
   endtask
 
   virtual protected task reset_signals();
-    vif.rvalid  <= 1'b0;
-    vif.grant   <= 1'b0;
-    vif.rdata   <= 'b0;
-    vif.error   <= 1'b0;
+    vif.device_driver_cb.rvalid  <= 1'b0;
+    vif.device_driver_cb.grant   <= 1'b0;
+    vif.device_driver_cb.rdata   <= 'b0;
+    vif.device_driver_cb.error   <= 1'b0;
   endtask : reset_signals
 
   virtual protected task get_and_drive();
-    wait(vif.reset === 1'b0);
+    wait (vif.device_driver_cb.reset === 1'b0);
     fork
       begin
         forever begin
           ibex_mem_intf_seq_item req, req_c;
-          @(posedge vif.clock);
+          vif.wait_clks(1);
           seq_item_port.get_next_item(req);
           $cast(req_c, req.clone());
-          if(~vif.reset) begin
+          if(~vif.device_driver_cb.reset) begin
             rdata_queue.put(req_c);
           end
           seq_item_port.item_done();
@@ -86,8 +86,8 @@
   virtual protected task send_grant();
     int gnt_delay;
     forever begin
-      while(vif.request !== 1'b1) begin
-        @(negedge vif.clock);
+      while(vif.device_driver_cb.request !== 1'b1) begin
+        vif.wait_neg_clks(1);
       end
       if (!std::randomize(gnt_delay) with {
         gnt_delay dist {
@@ -98,11 +98,11 @@
       }) begin
         `uvm_fatal(`gfn, $sformatf("Cannot randomize grant"))
       end
-      repeat(gnt_delay) @(negedge vif.clock);
-      if(~vif.reset) begin
-        vif.grant = 1'b1;
-        @(negedge vif.clock);
-        vif.grant = 1'b0;
+      vif.wait_neg_clks(gnt_delay);
+      if(~vif.device_driver_cb.reset) begin
+        vif.device_driver_cb.grant <= 1'b1;
+        vif.wait_neg_clks(1);
+        vif.device_driver_cb.grant <= 1'b0;
       end
     end
   endtask : send_grant
@@ -110,17 +110,17 @@
   virtual protected task send_read_data();
     ibex_mem_intf_seq_item tr;
     forever begin
-      @(posedge vif.clock);
-      vif.rvalid <=  1'b0;
-      vif.rdata  <= 'x;
-      vif.error  <= 1'b0;
+      vif.wait_clks(1);
+      vif.device_driver_cb.rvalid <=  1'b0;
+      vif.device_driver_cb.rdata  <= 'x;
+      vif.device_driver_cb.error  <= 1'b0;
       rdata_queue.get(tr);
-      if(vif.reset) continue;
-      repeat(tr.rvalid_delay) @(posedge vif.clock);
-      if(~vif.reset) begin
-        vif.rvalid <=  1'b1;
-        vif.error  <=  tr.error;
-        vif.rdata  <=  tr.data;
+      if(vif.device_driver_cb.reset) continue;
+      vif.wait_clks(tr.rvalid_delay);
+      if(~vif.device_driver_cb.reset) begin
+        vif.device_driver_cb.rvalid <=  1'b1;
+        vif.device_driver_cb.error  <=  tr.error;
+        vif.device_driver_cb.rdata  <=  tr.data;
       end
     end
   endtask : send_read_data
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_if.sv
index 138f50f..c57e615 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_if.sv
@@ -2,12 +2,34 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-interface irq_if;
-  logic        clock;
+interface irq_if(input clk);
   logic        reset;
   logic        irq_software;
   logic        irq_timer;
   logic        irq_external;
   logic [14:0] irq_fast;
   logic        irq_nm;       // non-maskeable interrupt
+
+  clocking driver_cb @(posedge clk);
+    input   reset;
+    output  irq_software;
+    output  irq_timer;
+    output  irq_external;
+    output  irq_fast;
+    output  irq_nm;
+  endclocking
+
+  clocking monitor_cb @(posedge clk);
+    input reset;
+    input irq_software;
+    input irq_timer;
+    input irq_external;
+    input irq_fast;
+    input irq_nm;
+  endclocking
+
+  task automatic wait_clks(input int num);
+    repeat (num) @(posedge clk);
+  endtask
+
 endinterface
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_master_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_master_driver.sv
index defcde9..d695d95 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_master_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_master_driver.sv
@@ -22,7 +22,7 @@
     forever begin
       fork : drive_irq
         get_and_drive();
-        wait(vif.reset === 1'b1);
+        wait (vif.driver_cb.reset === 1'b1);
       join_any
       // Will only reach here on mid-test reset
       disable drive_irq;
@@ -43,7 +43,7 @@
   endtask
 
   virtual protected task get_and_drive();
-    wait(vif.reset === 1'b0);
+    wait (vif.driver_cb.reset === 1'b0);
     forever begin
       seq_item_port.try_next_item(req);
       if (req != null) begin
@@ -52,30 +52,30 @@
         drive_seq_item(rsp);
         seq_item_port.item_done(rsp);
       end else begin
-        @(posedge vif.clock);
+        vif.wait_clks(1);
       end
     end
   endtask : get_and_drive
 
   virtual protected task reset_signals();
-    @(negedge vif.reset);
+    @(negedge vif.driver_cb.reset);
     drive_reset_value();
   endtask : reset_signals
 
   virtual protected task drive_seq_item (irq_seq_item trans);
-    vif.irq_software <= trans.irq_software;
-    vif.irq_timer    <= trans.irq_timer;
-    vif.irq_external <= trans.irq_external;
-    vif.irq_fast     <= trans.irq_fast;
-    vif.irq_nm       <= trans.irq_nm;
+    vif.driver_cb.irq_software <= trans.irq_software;
+    vif.driver_cb.irq_timer    <= trans.irq_timer;
+    vif.driver_cb.irq_external <= trans.irq_external;
+    vif.driver_cb.irq_fast     <= trans.irq_fast;
+    vif.driver_cb.irq_nm       <= trans.irq_nm;
   endtask : drive_seq_item
 
   task drive_reset_value();
-    vif.irq_software <= '0;
-    vif.irq_timer    <= '0;
-    vif.irq_external <= '0;
-    vif.irq_fast     <= '0;
-    vif.irq_nm       <= '0;
+    vif.driver_cb.irq_software <= '0;
+    vif.driver_cb.irq_timer    <= '0;
+    vif.driver_cb.irq_external <= '0;
+    vif.driver_cb.irq_fast     <= '0;
+    vif.driver_cb.irq_nm       <= '0;
   endtask : drive_reset_value
 
 endclass : irq_master_driver
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_monitor.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_monitor.sv
index 639140d..050f552 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_monitor.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/common/irq_agent/irq_monitor.sv
@@ -23,10 +23,10 @@
 
   virtual task run_phase(uvm_phase phase);
     forever begin
-      wait(vif.reset === 1'b0);
+      wait (vif.monitor_cb.reset === 1'b0);
       fork : monitor_irq
         collect_irq();
-        wait(vif.reset === 1'b1);
+        wait (vif.monitor_cb.reset === 1'b1);
       join_any
       // Will only reach here on mid-test reset
       disable monitor_irq;
@@ -46,19 +46,26 @@
     bit[DATA_WIDTH-1:0] stored_irq_val = '0;
     bit[DATA_WIDTH-1:0] current_irq = '0;
     forever begin
-      current_irq = {vif.irq_nm, vif.irq_fast, 4'b0, vif.irq_external, 3'b0,
-                     vif.irq_timer, 3'b0, vif.irq_software, 3'b0};
+      current_irq = {vif.monitor_cb.irq_nm,
+                     vif.monitor_cb.irq_fast,
+                     4'b0,
+                     vif.monitor_cb.irq_external,
+                     3'b0,
+                     vif.monitor_cb.irq_timer,
+                     3'b0,
+                     vif.monitor_cb.irq_software,
+                     3'b0};
       if (current_irq !== stored_irq_val) begin
         stored_irq_val = current_irq;
         irq = irq_seq_item::type_id::create("irq");
-        irq.irq_software = vif.irq_software;
-        irq.irq_timer = vif.irq_timer;
-        irq.irq_external = vif.irq_external;
-        irq.irq_fast = vif.irq_fast;
-        irq.irq_nm = vif.irq_nm;
+        irq.irq_software = vif.monitor_cb.irq_software;
+        irq.irq_timer = vif.monitor_cb.irq_timer;
+        irq.irq_external = vif.monitor_cb.irq_external;
+        irq.irq_fast = vif.monitor_cb.irq_fast;
+        irq.irq_nm = vif.monitor_cb.irq_nm;
         irq_port.write(irq);
       end
-      @(posedge vif.clock);
+      vif.wait_clks(1);
     end
   endtask : collect_irq
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_csr_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_csr_if.sv
index 16f3fbc..399318f 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_csr_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_csr_if.sv
@@ -9,4 +9,13 @@
   logic [31:0]              csr_wdata;
   logic [31:0]              csr_rdata;
   ibex_pkg::csr_op_e        csr_op;
+
+  clocking csr_cb @(posedge clk);
+    input csr_access;
+    input csr_addr;
+    input csr_wdata;
+    input csr_rdata;
+    input csr_op;
+  endclocking
+
 endinterface
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
index f350377..5f8b8cb 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
@@ -16,6 +16,20 @@
   logic                 debug_req;
   ibex_pkg::priv_lvl_e  priv_mode;
 
+  clocking dut_cb @(posedge clk);
+    output fetch_enable;
+    output debug_req;
+    input reset;
+    input illegal_instr;
+    input ecall;
+    input wfi;
+    input ebreak;
+    input dret;
+    input mret;
+    input core_sleep;
+    input priv_mode;
+  endclocking
+
   initial begin
     debug_req = 1'b0;
   end
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv
index f6938f0..937faf9 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv
@@ -20,11 +20,19 @@
 // XLEN
 parameter int XLEN = 32;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 0;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 0;
+
 // Vector extension parameters - not used in Ibex
 parameter int VECTOR_EXTENSION_ENABLE = 0;
 parameter int VLEN = 512;
 parameter int ELEN = 64;
 parameter int SLEN = 64;
+parameter int VELEN = 4;
+parameter int SELEN = 8;
+parameter int MAX_LMUL = 8;
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/sim_makefrag_gen.py b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/sim_makefrag_gen.py
index ea9003d..8187580 100755
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/sim_makefrag_gen.py
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/sim_makefrag_gen.py
@@ -65,6 +65,21 @@
             'SIM_OPTS += {1}').format(riviera_compile_opts, riviera_sim_opts)
 
 
+def gen_questa_makefrag():
+    questa_compile_opts = run_ibex_config('questa_compile_opts', [
+        '--ins_hier_path', 'core_ibex_tb_top',
+        '--string_define_prefix', 'IBEX_CFG_'
+    ])
+
+    questa_sim_opts = run_ibex_config('questa_sim_opts', [
+        '--ins_hier_path', 'core_ibex_tb_top',
+        '--string_define_prefix', 'IBEX_CFG_'
+    ])
+
+    return ('COMPILE_OPTS += {0}'
+            'SIM_OPTS += {1}').format(questa_compile_opts, questa_sim_opts)
+
+
 def gen_xlm_makefrag():
     xlm_compile_opts = run_ibex_config('xlm_opts', [
         '--ins_hier_path', 'core_ibex_tb_top',
@@ -79,7 +94,12 @@
         'Generates a makefile fragment for use with the Ibex DV makefile that '
         'sets up sim specific variables'))
 
-    sim_fns = {'vcs': gen_vcs_makefrag, 'riviera': gen_riviera_makefrag, 'xlm': gen_xlm_makefrag}
+    sim_fns = {
+        'vcs': gen_vcs_makefrag,
+        'riviera': gen_riviera_makefrag,
+        'xlm': gen_xlm_makefrag,
+        'questa': gen_questa_makefrag
+        }
 
     argparser.add_argument('sim',
                            help='Name of the simulator',
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv
index 578fbe1..87c7a88 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv
@@ -12,9 +12,9 @@
   logic fetch_enable;
 
   clk_if         ibex_clk_if(.clk(clk), .rst_n(rst_n));
-  irq_if         irq_vif();
-  ibex_mem_intf  data_mem_vif();
-  ibex_mem_intf  instr_mem_vif();
+  irq_if         irq_vif(.clk(clk));
+  ibex_mem_intf  data_mem_vif(.clk(clk));
+  ibex_mem_intf  instr_mem_vif(.clk(clk));
 
 
   // DUT probe interface
@@ -89,10 +89,8 @@
   );
 
   // Data load/store vif connection
-  assign data_mem_vif.clock     = clk;
   assign data_mem_vif.reset     = ~rst_n;
   // Instruction fetch vif connnection
-  assign instr_mem_vif.clock    = clk;
   assign instr_mem_vif.reset    = ~rst_n;
   assign instr_mem_vif.we       = 0;
   assign instr_mem_vif.be       = 0;
@@ -118,15 +116,14 @@
   assign rvfi_if.mem_rdata      = dut.rvfi_mem_rdata;
   assign rvfi_if.mem_wdata      = dut.rvfi_mem_wdata;
   // Irq interface connections
-  assign irq_vif.clock          = clk;
   assign irq_vif.reset          = ~rst_n;
   // Dut_if interface connections
-  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.illegal_instr   = dut.u_ibex_core.id_stage_i.illegal_insn_dec;
-  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;
+  assign dut_if.ecall           = dut.u_ibex_core.id_stage_i.controller_i.ecall_insn;
+  assign dut_if.wfi             = dut.u_ibex_core.id_stage_i.controller_i.wfi_insn;
+  assign dut_if.ebreak          = dut.u_ibex_core.id_stage_i.controller_i.ebrk_insn;
+  assign dut_if.illegal_instr   = dut.u_ibex_core.id_stage_i.controller_i.illegal_insn_d;
+  assign dut_if.dret            = dut.u_ibex_core.id_stage_i.controller_i.dret_insn;
+  assign dut_if.mret            = dut.u_ibex_core.id_stage_i.controller_i.mret_insn;
   assign dut_if.reset           = ~rst_n;
   assign dut_if.priv_mode       = dut.u_ibex_core.priv_mode_id;
   // CSR interface connections
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_base_test.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_base_test.sv
index 9de3815..94fa672 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_base_test.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_base_test.sv
@@ -68,10 +68,10 @@
     enable_irq_seq = cfg.enable_irq_single_seq || cfg.enable_irq_multiple_seq;
     phase.raise_objection(this);
     run = phase;
-    dut_vif.fetch_enable = 1'b0;
+    dut_vif.dut_cb.fetch_enable <= 1'b0;
     clk_vif.wait_clks(100);
     load_binary_to_mem();
-    dut_vif.fetch_enable = 1'b1;
+    dut_vif.dut_cb.fetch_enable <= 1'b1;
     send_stimulus();
     wait_for_test_done();
     phase.drop_objection(this);
@@ -116,11 +116,11 @@
   virtual task wait_for_test_done();
     fork
       begin
-        wait (dut_vif.ecall === 1'b1);
+        wait (dut_vif.dut_cb.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;
+        dut_vif.dut_cb.fetch_enable <= 1'b0;
         fork
           check_perf_stats();
           // Wait some time for the remaining instruction to finish
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_seq_lib.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_seq_lib.sv
index c016129..1ec9da3 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_seq_lib.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_seq_lib.sv
@@ -131,15 +131,15 @@
     if (!uvm_config_db#(virtual core_ibex_dut_probe_if)::get(null, "", "dut_if", dut_vif)) begin
       `uvm_fatal(get_full_name(), "Cannot get dut_if")
     end
-    dut_vif.debug_req <= 1'b0;
+    dut_vif.dut_cb.debug_req <= 1'b0;
     super.body();
   endtask
 
   virtual task send_req();
     `uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
-    dut_vif.debug_req <= 1'b1;
+    dut_vif.dut_cb.debug_req <= 1'b1;
     clk_vif.wait_clks(50);
-    dut_vif.debug_req <= 1'b0;
+    dut_vif.dut_cb.debug_req <= 1'b0;
   endtask
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
index 01b000c..7d86982 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
@@ -47,7 +47,7 @@
       clk_vif.wait_clks($urandom_range(0, 50000));
       fork
         begin
-          dut_vif.fetch_enable = 1'b0;
+          dut_vif.dut_cb.fetch_enable <= 1'b0;
           clk_vif.reset();
         end
         begin
@@ -61,7 +61,7 @@
         end
       join
       // Assert fetch_enable to have the core start executing from boot address
-      dut_vif.fetch_enable = 1'b1;
+      dut_vif.dut_cb.fetch_enable <= 1'b1;
     end
   endtask
 
@@ -223,7 +223,7 @@
     end
     check_next_core_status(HANDLING_IRQ, "Core did not jump to vectored interrupt handler", 750);
     check_priv_mode(PRIV_LVL_M);
-    operating_mode = dut_vif.priv_mode;
+    operating_mode = dut_vif.dut_cb.priv_mode;
     // check mstatus
     wait_for_csr_write(CSR_MSTATUS, 500);
     mstatus = signature_data;
@@ -329,16 +329,16 @@
       begin
         case (ret)
           "dret": begin
-            wait (dut_vif.dret === 1'b1);
+            wait (dut_vif.dut_cb.dret === 1'b1);
           end
           "mret": begin
-            wait (dut_vif.mret === 1'b1);
+            wait (dut_vif.dut_cb.mret === 1'b1);
           end
           default: begin
             `uvm_fatal(`gfn, $sformatf("Invalid xRET instruction %0s", ret))
           end
         endcase
-        wait (dut_vif.priv_mode === select_mode());
+        wait (dut_vif.dut_cb.priv_mode === select_mode());
       end
       begin : ret_timeout
         clk_vif.wait_clks(timeout);
@@ -352,7 +352,7 @@
   endtask
 
   virtual function void check_priv_mode(priv_lvl_e mode);
-    `DV_CHECK_EQ_FATAL(dut_vif.priv_mode, mode,
+    `DV_CHECK_EQ_FATAL(dut_vif.dut_cb.priv_mode, mode,
                        "Incorrect privilege mode")
   endfunction
 
@@ -397,7 +397,7 @@
               check_stimulus();
             end : stimulus
             begin
-              wait(dut_vif.ecall === 1'b1);
+              wait (dut_vif.dut_cb.ecall === 1'b1);
               disable stimulus;
               if (run.get_objection_count(this) > 1) begin
                 run.drop_objection(this);
@@ -475,8 +475,8 @@
 
   virtual task check_stimulus();
     forever begin
-      wait (dut_vif.wfi === 1'b1);
-      wait(dut_vif.core_sleep === 1'b1);
+      wait (dut_vif.dut_cb.wfi === 1'b1);
+      wait (dut_vif.dut_cb.core_sleep === 1'b1);
       send_irq_stimulus();
     end
   endtask
@@ -492,13 +492,15 @@
   virtual task check_stimulus();
     vseq.irq_raise_single_seq_h.max_delay = 0;
     // wait for a write to mstatus - should be in init code
-    wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
-         csr_vif.csr_op != CSR_OP_READ);
+    wait (csr_vif.csr_cb.csr_access === 1'b1 &&
+          csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
+          csr_vif.csr_cb.csr_op != CSR_OP_READ);
     // send interrupt immediately after detection
     send_irq_stimulus();
     // wait for a write to mie - should be in init code
-    wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MIE &&
-         csr_vif.csr_op != CSR_OP_READ);
+    wait (csr_vif.csr_cb.csr_access === 1'b1 &&
+          csr_vif.csr_cb.csr_addr === CSR_MIE &&
+          csr_vif.csr_cb.csr_op != CSR_OP_READ);
     // send interrupt immediately after detection
     send_irq_stimulus();
   endtask
@@ -562,7 +564,7 @@
             send_debug_stimulus(operating_mode, "Core did not enter debug mode from interrupt handler");
           end
           begin
-            wait(dut_vif.dret == 1'b1);
+            wait (dut_vif.dut_cb.dret == 1'b1);
             send_irq_stimulus_end();
           end
         join
@@ -591,8 +593,9 @@
         // Send nested interrupt after the checks of the first interrupt have finished
         in_nested_trap = 1'b1;
         // wait until we are setting mstatus.mie to 1'b1 to send the next set of interrupts
-        wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
-             csr_vif.csr_op != CSR_OP_READ);
+        wait (csr_vif.csr_cb.csr_access === 1'b1 &&
+             csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
+             csr_vif.csr_cb.csr_op != CSR_OP_READ);
         send_irq_stimulus(1'b0);
         vseq.irq_raise_seq_h.max_delay = initial_irq_delay;
         in_nested_trap = 1'b0;
@@ -611,8 +614,8 @@
 
   virtual task check_stimulus();
     forever begin
-      wait (dut_vif.wfi === 1'b1);
-      wait (dut_vif.core_sleep === 1'b1);
+      wait (dut_vif.dut_cb.wfi === 1'b1);
+      wait (dut_vif.dut_cb.core_sleep === 1'b1);
       clk_vif.wait_clks($urandom_range(100));
       send_debug_stimulus(init_operating_mode, "Core did not jump into debug mode from WFI state");
     end
@@ -629,12 +632,14 @@
   virtual task check_stimulus();
     vseq.debug_seq_single_h.max_delay = 0;
     // wait for a dummy write to mstatus in init code
-    wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
-         csr_vif.csr_op != CSR_OP_READ);
+    wait (csr_vif.csr_cb.csr_access === 1'b1 &&
+          csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
+          csr_vif.csr_cb.csr_op != CSR_OP_READ);
     send_debug_stimulus(init_operating_mode, "Core did not trap to debug mode upon debug stimulus");
     // wait for a dummy write to mie in the init code
-    wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MIE &&
-         csr_vif.csr_op != CSR_OP_READ);
+    wait (csr_vif.csr_cb.csr_access === 1'b1 &&
+          csr_vif.csr_cb.csr_addr === CSR_MIE &&
+          csr_vif.csr_cb.csr_op != CSR_OP_READ);
     send_debug_stimulus(init_operating_mode, "Core did not trap to debug mode upon debug stimulus");
   endtask
 
@@ -648,7 +653,7 @@
 
   virtual task check_stimulus();
     forever begin
-      wait (dut_vif.dret === 1'b1);
+      wait (dut_vif.dut_cb.dret === 1'b1);
       check_illegal_insn("Core did not treat dret like illegal instruction");
     end
   endtask
@@ -678,7 +683,7 @@
       // capture the first write of dpc
       wait_for_csr_write(CSR_DPC, 500);
       dpc = signature_data;
-      wait (dut_vif.ebreak === 1'b1);
+      wait (dut_vif.dut_cb.ebreak === 1'b1);
       // compare the second writes of dcsr and dpc against the captured values
       wait_for_csr_write(CSR_DCSR, 1000);
       `DV_CHECK_EQ_FATAL(dcsr, signature_data,
@@ -713,7 +718,7 @@
     check_dcsr_cause(DBG_CAUSE_HALTREQ);
     wait_ret("dret", 5000);
     forever begin
-      wait (dut_vif.ebreak === 1'b1);
+      wait (dut_vif.dut_cb.ebreak === 1'b1);
       check_next_core_status(IN_DEBUG_MODE,
                              "Core did not enter debug mode after execution of ebreak", 2000);
       check_priv_mode(PRIV_LVL_M);
@@ -840,7 +845,7 @@
       exc_type = EXC_CAUSE_STORE_ACCESS_FAULT;
     end
     check_mcause(1'b0, exc_type);
-    wait (dut_vif.mret === 1'b1);
+    wait (dut_vif.dut_cb.mret === 1'b1);
     `uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
   endtask
 
@@ -876,7 +881,7 @@
                            "Core did not register correct memory fault type", 500);
     exc_type = EXC_CAUSE_INSTR_ACCESS_FAULT;
     check_mcause(1'b0, exc_type);
-    wait (dut_vif.mret === 1'b1);
+    wait (dut_vif.dut_cb.mret === 1'b1);
     `uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
   endtask
 
@@ -891,7 +896,7 @@
   virtual task check_stimulus();
     bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mcause;
     forever begin
-      wait (dut_vif.wfi === 1'b1);
+      wait (dut_vif.dut_cb.wfi === 1'b1);
       check_illegal_insn("Core did not treat U-mode WFI as illegal");
     end
   endtask
@@ -907,9 +912,9 @@
   virtual task check_stimulus();
     forever begin
       // Wait for a CSR access
-      wait (csr_vif.csr_access == 1'b1);
+      wait (csr_vif.csr_cb.csr_access == 1'b1);
       check_illegal_insn($sformatf("Core did not treat access to CSR 0x%0x from %0s as illegal",
-                                   csr_vif.csr_addr, init_operating_mode));
+                                   csr_vif.csr_cb.csr_addr, init_operating_mode));
     end
   endtask
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/yaml/rtl_simulation.yaml b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/yaml/rtl_simulation.yaml
index 81d2adf..cfceb73 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/yaml/rtl_simulation.yaml
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/core_ibex/yaml/rtl_simulation.yaml
@@ -52,6 +52,25 @@
     wave_opts: >
       -ucli -do <cwd>/vcs.tcl
 
+- tool: questa
+  compile:
+    cmd:
+      - "vmap mtiUvm $QUESTA_HOME/questasim/uvm-1.2"
+      - "vlog -64
+              -access=rwc
+              -f ibex_dv.f
+              -sv
+              -mfcu -cuname design_cuname
+              +define+UVM_REGEX_NO_DPI
+              +define+UVM
+              -writetoplevels <out>/top.list
+              -l <out>/compile.log <cmp_opts>"
+  sim:
+    cmd: >
+      vsim -64 -c <cov_opts> -do "run -a; quit -f" +designfile -f <out>/top.list <sim_opts>  -sv_seed <seed> +access +r+w +UVM_TESTNAME=<rtl_test> +bin=<binary> +ibex_tracer_file_base="<sim_dir>/trace_core" -l <sim_dir>/sim.log
+    cov_opts: >
+      -do "coverage save -onexit <out>/cov.ucdb;"
+
 - tool: dsim
   env_var: DSIM,DSIM_LIB_PATH
   compile:
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/data/ibex_icache_testplan.hjson b/hw/vendor/lowrisc_ibex/dv/uvm/icache/data/ibex_icache_testplan.hjson
index 68b9258..6ccd1d8 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/data/ibex_icache_testplan.hjson
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/data/ibex_icache_testplan.hjson
@@ -118,17 +118,17 @@
             bit error. Check that the invalid cached data is correctly
             ignored.'''
       milestone: V2
-      tests: []
+      tests: ["ibex_icache_ecc"]
     }
 
     {
       name: stress_all
-      desc: '''Run a pair of sequences back-to-back
+      desc: '''Run sequences back-to-back
 
             Tests are selected from the sequences above. With 50% probability,
             reset between the sequences.'''
       milestone: V2
-      tests: []
+      tests: ["ibex_icache_stress_all"]
     }
 
     {
@@ -138,7 +138,7 @@
             Tests are selected from the sequences above. Add occasional
             resets (in the middle of sequences)'''
       milestone: V2
-      tests: []
+      tests: ["ibex_icache_stress_all_with_reset"]
     }
   ]
 }
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/ibex_icache_dv_plan.md b/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/ibex_icache_dv_plan.md
index e6c4877..c699b27 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/ibex_icache_dv_plan.md
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/ibex_icache_dv_plan.md
@@ -26,18 +26,22 @@
 This means that the testbench cannot compare the DUT with a reference model, nor can it model the exact requests that the DUT will make of instruction memory: the whole point of a cache is that it might avoid an instruction fetch.
 
 The cache has two main interfaces, which face the core and instruction bus respectively.
-We model this with two agents: the *core agent* and the *memory agent*.
+We model this with two main agents: the *core agent* and the *memory agent*.
 The core agent will emulate a core making instruction fetch requests from the cache and the memory agent will emulate the instruction bus.
 
-In fact, there's one more logical interface: the `busy_o` signal from the cache.
+In fact, there's one more logical interface at the top-level: the `busy_o` signal from the cache.
 This signal is passed up to top-level in the design and warns the chip not to clock-gate or reset the core (because there are bus transactions in flight, or a memory invalidation in progress).
 Rather than have an extra agent just for this single-bit passive signal, we pass the signal to the monitor in the core agent, which reports changes to the scoreboard.
 
+Finally, we bind an interface in for each RAM in the cache.
+These interfaces are controlled by instances of the *ECC agent*, which is in charge of injecting occasional one- and two-bit errors which should be spotted by the cache's ECC checks.
+
 ![Testbench block diagram](tb.svg)
 
-Both agents report events to the scoreboard.
+Both main agents report events to the scoreboard.
 The core agent reports whether the cache is busy, every branch sent to the cache, invalidation requests, enabling/disabling the cache and every instruction fetched (address and contents).
 The memory agent reports every change of seed (see the [Memory Agent](#memory-agent) section below).
+The ECC agents don't currently report to the scoreboard, since they aren't supposed to have any architectural effect.
 
 ### Agents
 
@@ -73,6 +77,11 @@
 
 The memory agent is an active slave, responding to instruction fetches from the cache with either a PMP error (on the same cycle as the request) or instruction data (with an in-order request pipeline).
 
+#### ECC Agent
+
+Each ECC agent emulates possible data corruption in the cache's underlying memories.
+The sole sequence causes occasional 1- or 2-bit errors, injected by XORing valid data from the underlying memory with a mask.
+
 ### Top level testbench
 
 The top level testbench is located at [`dv/uvm/icache/dv/tb/tb.sv`](https://github.com/lowRISC/ibex/blob/master/dv/uvm/icache/dv/tb/tb.sv). It instantiates the `ibex_icache` DUT module whose source is at [`rtl/ibex_icache.sv`](https://github.com/lowRISC/ibex/blob/master/rtl/ibex_icache.sv).
@@ -80,6 +89,7 @@
 * Clock and reset interface ([`vendor/lowrisc_ip/common_ifs`](https://github.com/lowRISC/ibex/tree/master/vendor/lowrisc_ip/common_ifs))
 * Core interface ([`dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv`](https://github.com/lowRISC/ibex/blob/master/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv))
 * Memory interface ([`dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv`](https://github.com/lowRISC/ibex/blob/master/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv))
+* ECC interfaces ([`dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_if.sv`](https://github.com/lowRISC/ibex/blob/master/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_if.sv))
 
 ### Common DV utility components
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/tb.svg b/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/tb.svg
index ceb6282..37a962e 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/tb.svg
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/doc/tb.svg
@@ -7,15 +7,15 @@
    xmlns="http://www.w3.org/2000/svg"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   viewBox="0 0 1051 671"
-   stroke-miterlimit="10"
-   id="svg1659"
-   sodipodi:docname="tb.svg"
-   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+   style="fill:none;stroke:none;stroke-linecap:square;stroke-miterlimit:10"
+   height="721"
    width="1051"
-   height="671"
-   style="fill:none;stroke:none;stroke-linecap:square;stroke-miterlimit:10">
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="tb.svg"
+   id="svg1659"
+   stroke-miterlimit="10"
+   viewBox="0 0 1051 721"
+   version="1.1">
   <metadata
      id="metadata1665">
     <rdf:RDF>
@@ -31,497 +31,338 @@
   <defs
      id="defs1663">
     <marker
-       inkscape:stockid="Arrow1Lend"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow1Lend"
+       inkscape:isstock="true"
        style="overflow:visible"
-       inkscape:isstock="true">
+       id="Arrow1Lend"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Lend">
       <path
-         id="path7702"
-         d="M 0,0 5,-5 -12.5,0 5,5 Z"
-         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         inkscape:connector-curvature="0"
          transform="matrix(-0.8,0,0,-0.8,-10,0)"
-         inkscape:connector-curvature="0" />
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         id="path7702" />
     </marker>
   </defs>
   <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1043"
-     id="namedview1661"
-     showgrid="true"
-     inkscape:zoom="1.0440636"
-     inkscape:cx="531.97562"
-     inkscape:cy="326.55768"
-     inkscape:window-x="1920"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="g2507"
-     fit-margin-top="0"
-     fit-margin-left="0"
+     inkscape:guide-bbox="true"
+     showguides="true"
+     inkscape:document-rotation="0"
+     fit-margin-bottom="0"
      fit-margin-right="0"
-     fit-margin-bottom="0">
+     fit-margin-left="0"
+     fit-margin-top="0"
+     inkscape:current-layer="svg1659"
+     inkscape:window-maximized="1"
+     inkscape:window-y="0"
+     inkscape:window-x="0"
+     inkscape:cy="334.71118"
+     inkscape:cx="375.46262"
+     inkscape:zoom="0.73826445"
+     showgrid="true"
+     id="namedview1661"
+     inkscape:window-height="1043"
+     inkscape:window-width="1920"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff">
     <inkscape:grid
-       type="xygrid"
+       originy="-109.5"
+       originx="-49.500001"
        id="grid1791"
-       originx="-49.499996"
-       originy="-109.5" />
+       type="xygrid" />
   </sodipodi:namedview>
   <clipPath
      id="p.0">
     <path
-       d="M 0,0 H 1086 V 817 H 0 Z"
-       id="path1438"
+       style="clip-rule:nonzero"
        inkscape:connector-curvature="0"
-       style="clip-rule:nonzero" />
+       id="path1438"
+       d="M 0,0 H 1086 V 817 H 0 Z" />
   </clipPath>
   <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
-     inkscape:connector-curvature="0"
+     d="M -49.500001,-36.500001 H 1036.5 V 780.5 H -49.500001 Z"
      id="path1441"
-     d="M -49.499996,-36.5 H 1036.5 v 817 H -49.499996 Z" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="m 399.76248,507.2441 c 0,12.49915 -57.79852,51.22955 -103.7601,24.99829 -45.96161,-26.23126 -80.0863,-117.42416 -103.7601,-208.61664 -23.6738,-91.1925 -36.89667,-182.3845 -61.95644,-208.6167 -25.05978,-26.232181 -61.956441,12.49548 -61.956441,24.99097"
      id="path1497"
-     d="m 399.76248,507.2441 c 0,12.49915 -57.79852,51.22955 -103.7601,24.99829 -45.96161,-26.23126 -80.0863,-117.42416 -103.7601,-208.61664 -23.6738,-91.1925 -36.89667,-182.3845 -61.95644,-208.6167 -25.05978,-26.23218 -61.956436,12.49548 -61.956436,24.99097" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="m 241.68896,288.44882 c 12.51828,0 12.82883,64.17889 25.03653,121.89743 12.20767,57.71851 36.31247,108.97662 66.52112,121.8974 30.20862,12.92078 66.52112,-12.49585 66.52112,-24.9917"
      id="path1539"
-     d="m 241.68896,288.44882 c 12.51828,0 12.82883,64.17889 25.03653,121.89743 12.20767,57.71851 36.31247,108.97662 66.52112,121.8974 30.20862,12.92078 66.52112,-12.49585 66.52112,-24.9917" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="m 241.68896,220.05774 c 12.51828,0 12.82883,82.41611 25.03653,156.09299 12.20767,73.67688 36.31247,138.61453 66.52112,156.09299 30.20862,17.47839 66.52112,-12.50244 66.52112,-25.00488"
      id="path1543"
-     d="m 241.68896,220.05774 c 12.51828,0 12.82883,82.41611 25.03653,156.09299 12.20767,73.67688 36.31247,138.61453 66.52112,156.09299 30.20862,17.47839 66.52112,-12.50244 66.52112,-25.00488" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="M 27.429129,672.96063 C 14.929114,672.96063 0.66137928,576.83465 2.4290953,480.70868 4.1968113,384.58267 21.999984,288.4567 41.570868,288.4567"
      id="path1579"
-     d="M 27.429134,672.96063 C 14.929119,672.96063 0.66138378,576.83465 2.4290998,480.70868 4.1968158,384.58267 21.999989,288.4567 41.570873,288.4567" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="m 567.7257,12.017604 h 454.0787 V 256.0491 H 567.7257 Z"
      id="path1593"
-     d="m 567.7257,12.017605 h 454.0787 V 256.0491 H 567.7257 Z" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="M 565.26904,260.10367 H 1024.2611 V 497.39502 H 565.26904 Z"
      id="path1615"
-     d="M 565.26904,260.10367 H 1024.2611 V 497.39502 H 565.26904 Z" />
-  <path
-     style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
      inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
+  <path
+     d="m 399.76248,507.2441 c 0,12.50079 -36.3114,47.04083 -66.51877,25.00159 C 303.03634,510.20644 278.93298,431.58785 266.72497,341.94964 254.51696,252.31142 254.20434,151.65357 241.68371,151.65357"
      id="path1653"
-     d="m 399.76248,507.2441 c 0,12.50079 -36.3114,47.04083 -66.51877,25.00159 C 303.03634,510.20644 278.93298,431.58785 266.72497,341.94964 254.51696,252.31142 254.20434,151.65357 241.68371,151.65357" />
+     inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
   <rect
-     ry="90.000008"
-     rx="90"
-     y="10.5"
-     x="10.500019"
-     height="640"
-     width="530"
+     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff8e3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
      id="rect2206"
-     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff8e3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
-  <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666794px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="274.93945"
-     y="42.595207"
-     id="text1777"><tspan
-       sodipodi:role="line"
-       id="tspan1775"
-       x="274.93945"
-       y="42.595207"
-       style="fill:#000000;fill-opacity:1">ibex_icache_base_test</tspan></text>
-  <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="575.61847"
-     y="295.76044"
-     id="text8237"><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="295.76044"
-       id="tspan8151"><tspan
-         x="575.61847"
-         y="295.76044"
-         id="tspan8147">Square boxes: SV modules / interfaces (static)</tspan><tspan
-         dx="0"
-         x="904.83722"
-         y="295.76044"
-         id="tspan8149" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="315.76044"
-       id="tspan8157"><tspan
-         x="575.61847"
-         y="315.76044"
-         id="tspan8153">Rounded boxes: SV classes (UVM; dynamically created)</tspan><tspan
-         dx="0"
-         x="976.93097"
-         y="315.76044"
-         id="tspan8155" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="335.76044"
-       id="tspan8163"><tspan
-         x="575.61847"
-         y="335.76044"
-         id="tspan8159">Square box with cut corner: Code block (a UVM phase)</tspan><tspan
-         dx="0"
-         x="967.14966"
-         y="335.76044"
-         id="tspan8161" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="355.76044"
-       id="tspan8167"><tspan
-         x="575.61847"
-         y="355.76044"
-         id="tspan8165" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="375.76044"
-       id="tspan8171"><tspan
-         x="575.61847"
-         y="375.76044"
-         id="tspan8169">Nesting shows fields in classes, so there is an object of type </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="395.76041"
-       id="tspan8175"><tspan
-         x="575.61847"
-         y="395.76041"
-         id="tspan8173">ibex_icache_env inside the object of type </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="415.76041"
-       id="tspan8181"><tspan
-         x="575.61847"
-         y="415.76041"
-         id="tspan8177">ibex_icache_base_test.</tspan><tspan
-         dx="0"
-         x="742.93097"
-         y="415.76041"
-         id="tspan8179" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="435.76041"
-       id="tspan8185"><tspan
-         x="575.61847"
-         y="435.76041"
-         id="tspan8183" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="455.76041"
-       id="tspan8189"><tspan
-         x="575.61847"
-         y="455.76041"
-         id="tspan8187">The color of the box for a class shows the base class. For </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="475.76041"
-       id="tspan8195"><tspan
-         x="575.61847"
-         y="475.76041"
-         id="tspan8191">example, interfaces are pink; agents are green.</tspan><tspan
-         dx="0"
-         x="910.21222"
-         y="475.76041"
-         id="tspan8193" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="495.76041"
-       id="tspan8199"><tspan
-         x="575.61847"
-         y="495.76041"
-         id="tspan8197" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="515.76038"
-       id="tspan8203"><tspan
-         x="575.61847"
-         y="515.76038"
-         id="tspan8201">Many classes have handles (always called cfg) to the test's </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="535.76038"
-       id="tspan8207"><tspan
-         x="575.61847"
-         y="535.76038"
-         id="tspan8205">ibex_icache_env_cfg object. To denote this, those classes are </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="555.76038"
-       id="tspan8213"><tspan
-         x="575.61847"
-         y="555.76038"
-         id="tspan8209">connected by a dotted line to the ibex_icache_env_cfg class.</tspan><tspan
-         dx="0"
-         x="1006.2747"
-         y="555.76038"
-         id="tspan8211" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="575.76038"
-       id="tspan8217"><tspan
-         x="575.61847"
-         y="575.76038"
-         id="tspan8215" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="595.76038"
-       id="tspan8221"><tspan
-         x="575.61847"
-         y="595.76038"
-         id="tspan8219">The virtual sequence object created in the run phase has a </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="615.76038"
-       id="tspan8225"><tspan
-         x="575.61847"
-         y="615.76038"
-         id="tspan8223">p_sequencer handle to the ibex_icache_virtual_sequencer </tspan></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="635.76038"
-       id="tspan8231"><tspan
-         x="575.61847"
-         y="635.76038"
-         id="tspan8227">inside the environment (not shown).</tspan><tspan
-         dx="0"
-         x="829.24347"
-         y="635.76038"
-         id="tspan8229" /></tspan><tspan
-       sodipodi:role="line"
-       x="575.61847"
-       y="635.76038"
-       id="tspan8235"><tspan
-         x="575.61847"
-         y="655.76038"
-         id="tspan8233" /></tspan></text>
-  <g
-     id="g2617"
-     transform="translate(-49.499996,-36.5)">
-    <rect
-       ry="40"
-       rx="40"
-       y="107"
-       x="70"
-       height="310"
-       width="239.99998"
-       id="rect1908"
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff2cc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
-    <text
-       transform="scale(1.0069205,0.99312707)"
-       xml:space="preserve"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:19.8625412px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       x="189.25031"
-       y="140.77362"
-       id="text1785"><tspan
-         sodipodi:role="line"
-         id="tspan1783"
-         x="189.25031"
-         y="140.77362"
-         style="fill:#000000;fill-opacity:1;stroke-width:0.99999994px">ibex_icache_env</tspan></text>
-    <g
-       transform="translate(-5,-39.999999)"
-       id="g1896">
-      <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-         id="rect1831"
-         width="229.99998"
-         height="36.322979"
-         x="80"
-         y="205.67702"
-         ry="10"
-         rx="9.999999" />
-      <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         x="194.49219"
-         y="228.39612"
-         id="text1789"><tspan
-           sodipodi:role="line"
-           id="tspan1787"
-           x="194.49219"
-           y="228.39612">ibex_icache_env_cov</tspan></text>
-    </g>
-    <g
-       transform="translate(-4.9999695,-36.322967)"
-       id="g1901">
-      <rect
-         rx="9.999999"
-         ry="10"
-         y="247"
-         x="79.999992"
-         height="36.322979"
-         width="229.99998"
-         id="rect1852"
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
-      <text
-         id="text1856"
-         y="269.71912"
-         x="194.98438"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         xml:space="preserve"><tspan
-           y="269.71912"
-           x="194.98438"
-           id="tspan1854"
-           sodipodi:role="line">ibex_icache_scoreboard</tspan></text>
-    </g>
-    <g
-       transform="translate(-5,-31.322968)"
-       id="g1906">
-      <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-         id="rect1876"
-         width="229.99998"
-         height="36.322979"
-         x="80"
-         y="287"
-         ry="10"
-         rx="9.999999" />
-      <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         x="194.98438"
-         y="309.71912"
-         id="text1880"><tspan
-           sodipodi:role="line"
-           id="tspan1878"
-           x="194.98438"
-           y="309.71912">ibex_icache_virtual_sequencer</tspan></text>
-    </g>
-    <g
-       transform="translate(0,-45)"
-       id="g2036">
-      <rect
-         rx="9.999999"
-         ry="10"
-         y="355.67703"
-         x="75"
-         height="36.322979"
-         width="229.99998"
-         id="rect2008"
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
-      <text
-         id="text2012"
-         y="378.39615"
-         x="189.98438"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         xml:space="preserve"><tspan
-           y="378.39615"
-           x="189.98438"
-           id="tspan2010"
-           sodipodi:role="line">ibex_icache_core_agent</tspan></text>
-    </g>
-    <g
-       id="g2044">
-      <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-         id="rect2038"
-         width="229.99998"
-         height="36.322979"
-         x="75"
-         y="355.67703"
-         ry="10"
-         rx="9.999999" />
-      <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         x="189.98438"
-         y="378.39615"
-         id="text2042"><tspan
-           sodipodi:role="line"
-           id="tspan2040"
-           x="189.98438"
-           y="378.39615">ibex_icache_mem_agent</tspan></text>
-    </g>
-  </g>
-  <rect
-     ry="40"
+     width="530"
+     height="700"
+     x="10.500014"
+     y="10.499999"
      rx="40"
-     y="70.5"
-     x="290.5"
-     height="310"
-     width="239.99998"
-     id="rect2074"
-     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+     ry="40.000004" />
   <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666794px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="410.48175"
+     id="text1777"
+     y="42.595207"
+     x="274.93945"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       style="fill:#000000;fill-opacity:1"
+       y="42.595207"
+       x="274.93945"
+       id="tspan1775"
+       sodipodi:role="line">ibex_icache_base_test</tspan></text>
+  <text
+     id="text8237"
+     y="295.76044"
+     x="575.61847"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       id="tspan8151"
+       y="295.76044"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8147"
+         y="295.76044"
+         x="575.61847">Square boxes: SV modules / interfaces (static)</tspan><tspan
+         id="tspan8149"
+         y="295.76044"
+         x="904.83722"
+         dx="0" /></tspan><tspan
+       id="tspan8157"
+       y="315.76044"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8153"
+         y="315.76044"
+         x="575.61847">Rounded boxes: SV classes (UVM; dynamically created)</tspan><tspan
+         id="tspan8155"
+         y="315.76044"
+         x="976.93097"
+         dx="0" /></tspan><tspan
+       id="tspan8163"
+       y="335.76044"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8159"
+         y="335.76044"
+         x="575.61847">Square box with cut corner: Code block (a UVM phase)</tspan><tspan
+         id="tspan8161"
+         y="335.76044"
+         x="967.14966"
+         dx="0" /></tspan><tspan
+       id="tspan8167"
+       y="355.76044"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8165"
+         y="355.76044"
+         x="575.61847" /></tspan><tspan
+       id="tspan8171"
+       y="375.76044"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8169"
+         y="375.76044"
+         x="575.61847">Nesting shows fields in classes, so there is an object of type </tspan></tspan><tspan
+       id="tspan8175"
+       y="395.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8173"
+         y="395.76041"
+         x="575.61847">ibex_icache_env inside the object of type </tspan></tspan><tspan
+       id="tspan8181"
+       y="415.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8177"
+         y="415.76041"
+         x="575.61847">ibex_icache_base_test.</tspan><tspan
+         id="tspan8179"
+         y="415.76041"
+         x="742.93097"
+         dx="0" /></tspan><tspan
+       id="tspan8185"
+       y="435.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8183"
+         y="435.76041"
+         x="575.61847" /></tspan><tspan
+       id="tspan8189"
+       y="455.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8187"
+         y="455.76041"
+         x="575.61847">The color of the box for a class shows the base class. For </tspan></tspan><tspan
+       id="tspan8195"
+       y="475.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8191"
+         y="475.76041"
+         x="575.61847">example, interfaces are pink; agents are green.</tspan><tspan
+         id="tspan8193"
+         y="475.76041"
+         x="910.21222"
+         dx="0" /></tspan><tspan
+       id="tspan8199"
+       y="495.76041"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8197"
+         y="495.76041"
+         x="575.61847" /></tspan><tspan
+       id="tspan8203"
+       y="515.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8201"
+         y="515.76038"
+         x="575.61847">Many classes have handles (always called cfg) to the test's </tspan></tspan><tspan
+       id="tspan8207"
+       y="535.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8205"
+         y="535.76038"
+         x="575.61847">ibex_icache_env_cfg object. To denote this, those classes are </tspan></tspan><tspan
+       id="tspan8213"
+       y="555.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8209"
+         y="555.76038"
+         x="575.61847">connected by a dotted line to the ibex_icache_env_cfg class.</tspan><tspan
+         id="tspan8211"
+         y="555.76038"
+         x="1006.2747"
+         dx="0" /></tspan><tspan
+       id="tspan8217"
+       y="575.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8215"
+         y="575.76038"
+         x="575.61847" /></tspan><tspan
+       id="tspan8221"
+       y="595.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8219"
+         y="595.76038"
+         x="575.61847">The virtual sequence object created in the run phase has a </tspan></tspan><tspan
+       id="tspan8225"
+       y="615.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8223"
+         y="615.76038"
+         x="575.61847">p_sequencer handle to the ibex_icache_virtual_sequencer </tspan></tspan><tspan
+       id="tspan8231"
+       y="635.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8227"
+         y="635.76038"
+         x="575.61847">inside the environment (not shown).</tspan><tspan
+         id="tspan8229"
+         y="635.76038"
+         x="829.24347"
+         dx="0" /></tspan><tspan
+       id="tspan8235"
+       y="635.76038"
+       x="575.61847"
+       sodipodi:role="line"><tspan
+         id="tspan8233"
+         y="655.76038"
+         x="575.61847" /></tspan></text>
+  <rect
+     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+     id="rect2074"
+     width="239.99998"
+     height="430"
+     x="290.5"
+     y="70.5"
+     rx="25"
+     ry="25" />
+  <text
+     id="text2078"
      y="103.84506"
-     id="text2078"><tspan
-       sodipodi:role="line"
-       id="tspan2076"
-       x="410.48175"
+     x="410.48175"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       style="fill:#000000;fill-opacity:1"
        y="103.84506"
-       style="fill:#000000;fill-opacity:1">ibex_icache_env_cfg</tspan></text>
+       x="410.48175"
+       id="tspan2076"
+       sodipodi:role="line">ibex_icache_env_cfg</tspan></text>
   <g
-     transform="translate(215.5,-76.5)"
-     id="g2086">
-    <rect
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-       id="rect2080"
-       width="229.99998"
-       height="36.322979"
-       x="80"
-       y="205.67702"
-       ry="10"
-       rx="9.999999" />
-    <text
-       xml:space="preserve"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       x="194.49219"
-       y="228.39612"
-       id="text2084"><tspan
-         sodipodi:role="line"
-         id="tspan2082"
-         x="194.49219"
-         y="228.39612">ibex_icache_core_if</tspan></text>
-  </g>
-  <g
-     id="g2116"
-     transform="translate(220.5,-81.5)">
+     id="g2086"
+     transform="translate(215.5,-76.500001)">
     <rect
        rx="9.999999"
        ry="10"
-       y="355.67703"
-       x="75"
+       y="205.67702"
+       x="80"
        height="36.322979"
        width="229.99998"
-       id="rect2110"
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+       id="rect2080"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
     <text
-       id="text2114"
-       y="378.39615"
-       x="189.98438"
+       id="text2084"
+       y="228.39612"
+       x="194.49219"
        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        xml:space="preserve"><tspan
-         y="378.39615"
-         x="189.98438"
-         id="tspan2112"
-         sodipodi:role="line">ibex_icache_core_agent_cfg</tspan></text>
+         y="228.39612"
+         x="194.49219"
+         id="tspan2082"
+         sodipodi:role="line">ibex_icache_core_if</tspan></text>
   </g>
   <g
-     transform="translate(220.5,-36.5)"
-     id="g2124">
+     transform="translate(220.5,-15.177032)"
+     id="g2116">
     <rect
        style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-       id="rect2118"
+       id="rect2110"
        width="229.99998"
        height="36.322979"
        x="75"
@@ -533,300 +374,656 @@
        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        x="189.98438"
        y="378.39615"
-       id="text2122"><tspan
+       id="text2114"><tspan
          sodipodi:role="line"
-         id="tspan2120"
+         id="tspan2112"
          x="189.98438"
-         y="378.39615">ibex_icache_mem_agent_cfg</tspan></text>
+         y="378.39615">ibex_icache_core_agent_cfg</tspan></text>
   </g>
   <g
-     id="g2196"
-     transform="translate(215.5,-31.5)">
+     id="g1140">
     <rect
        rx="9.999999"
        ry="10"
-       y="205.67702"
-       x="80"
+       y="385.5"
+       x="295.5"
        height="36.322979"
        width="229.99998"
+       id="rect2118"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+    <text
+       id="text2122"
+       y="408.21912"
+       x="410.48438"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="408.21912"
+         x="410.48438"
+         id="tspan2120"
+         sodipodi:role="line">ibex_icache_mem_agent_cfg</tspan></text>
+  </g>
+  <g
+     transform="translate(215.5,-31.500001)"
+     id="g2196">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
        id="rect2190"
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+       width="229.99998"
+       height="36.322979"
+       x="80"
+       y="205.67702"
+       ry="10"
+       rx="9.999999" />
     <text
-       id="text2194"
-       y="228.39612"
-       x="194.49219"
+       xml:space="preserve"
        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       xml:space="preserve"><tspan
-         y="228.39612"
-         x="194.49219"
+       x="194.49219"
+       y="228.39612"
+       id="text2194"><tspan
+         sodipodi:role="line"
          id="tspan2192"
-         sodipodi:role="line">ibex_icache_mem_if</tspan></text>
+         x="194.49219"
+         y="228.39612">ibex_icache_mem_if</tspan></text>
   </g>
   <g
-     id="g2204"
-     transform="translate(215.5,13.5)">
+     transform="translate(215.5,13.499999)"
+     id="g2204">
     <rect
-       rx="9.999999"
-       ry="10"
-       y="205.67702"
-       x="80"
-       height="36.322979"
-       width="229.99998"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
        id="rect2198"
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+       width="229.99998"
+       height="36.322979"
+       x="80"
+       y="205.67702"
+       ry="10"
+       rx="9.999999" />
     <text
-       id="text2202"
-       y="228.39612"
-       x="194.49219"
+       xml:space="preserve"
        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       xml:space="preserve"><tspan
-         y="228.39612"
-         x="194.49219"
+       x="194.49219"
+       y="228.39612"
+       id="text2202"><tspan
+         sodipodi:role="line"
          id="tspan2200"
-         sodipodi:role="line">clk_reset_if</tspan></text>
+         x="194.49219"
+         y="228.39612">clk_reset_if</tspan></text>
   </g>
   <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="30.500004"
+     id="text2330"
      y="510.5"
-     id="text2330"><tspan
-       sodipodi:role="line"
+     x="30.5"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       y="510.5"
+       x="30.5"
        id="tspan2328"
-       x="30.500004"
-       y="525.27972" /></text>
+       sodipodi:role="line" /></text>
   <flowRoot
-     xml:space="preserve"
+     transform="translate(-49.500001,-36.500001)"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
      id="flowRoot2332"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.66666698px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     transform="translate(-49.499996,-36.5)"><flowRegion
-       id="flowRegion2334"
-       style="text-align:start;text-anchor:start"><rect
-         id="rect2336"
-         width="440"
-         height="120"
-         x="80"
+     xml:space="preserve"><flowRegion
+       style="text-align:start;text-anchor:start"
+       id="flowRegion2334"><rect
+         style="text-align:start;text-anchor:start"
          y="537"
-         style="text-align:start;text-anchor:start" /></flowRegion><flowPara
-       id="flowPara2338" /></flowRoot>  <g
-     id="g2521"
-     transform="translate(-49.499996,-36.5)">
+         x="80"
+         height="120"
+         width="440"
+         id="rect2336" /></flowRegion><flowPara
+       id="flowPara2338" /></flowRoot>
+  <g
+     transform="translate(-49.500001,63.499999)"
+     id="g2521">
     <path
-       sodipodi:nodetypes="cccccc"
-       d="m 70,447 h 470 l 40,50 V 617 H 70 Z"
-       id="path1559"
+       style="fill:#cfe2f3;fill-rule:evenodd;stroke:#000000;stroke-opacity:1"
        inkscape:connector-curvature="0"
-       style="fill:#cfe2f3;fill-rule:evenodd;stroke:#000000;stroke-opacity:1" />
+       id="path1559"
+       d="m 70,447 h 470 l 40,50 V 617 H 70 Z"
+       sodipodi:nodetypes="cccccc" />
     <g
        id="g2507">
       <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         x="90"
+         id="text2326"
          y="471.74084"
-         id="text2326"><tspan
-           sodipodi:role="line"
-           id="tspan2324"
-           x="90"
-           y="471.74084">run_phase:</tspan></text>
-      <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.66666698px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
          x="90"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="471.74084"
+           x="90"
+           id="tspan2324"
+           sodipodi:role="line">run_phase:</tspan></text>
+      <text
+         id="text8251"
          y="497.8609"
-         id="text8251"><tspan
-           sodipodi:role="line"
-           x="90"
+         x="90"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           id="tspan8241"
            y="497.8609"
-           id="tspan8241"><tspan
-             x="90"
+           x="90"
+           sodipodi:role="line"><tspan
+             id="tspan8239"
              y="497.8609"
-             id="tspan8239">In the UVM run phase, the dv_base_test class (from which the </tspan></tspan><tspan
-           sodipodi:role="line"
-           x="90"
+             x="90">In the UVM run phase, the dv_base_test class (from which the </tspan></tspan><tspan
+           id="tspan8245"
            y="517.8609"
-           id="tspan8245"><tspan
-             x="90"
-             y="517.8609"
-             id="tspan8243">ibex_icache_base_test class derives) creates and runs the sequence </tspan></tspan><tspan
-           sodipodi:role="line"
            x="90"
+           sodipodi:role="line"><tspan
+             id="tspan8243"
+             y="517.8609"
+             x="90">ibex_icache_base_test class derives) creates and runs the sequence </tspan></tspan><tspan
+           id="tspan8249"
            y="537.8609"
-           id="tspan8249"><tspan
-             x="90"
+           x="90"
+           sodipodi:role="line"><tspan
+             id="tspan8247"
              y="537.8609"
-             id="tspan8247">named by the +UVM_TEST_SEQ plusarg.</tspan></tspan></text>
+             x="90">named by the +UVM_TEST_SEQ plusarg.</tspan></tspan></text>
     </g>
     <g
        id="g2499">
       <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff3cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-         id="rect2348"
-         width="470"
-         height="39.940208"
-         x="90"
-         y="557"
+         ry="15.181121"
          rx="20"
-         ry="15.181121" />
+         y="557"
+         x="90"
+         height="39.940208"
+         width="470"
+         id="rect2348"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff3cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
       <text
-         xml:space="preserve"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         x="324.9772"
+         id="text2352"
          y="581.76636"
-         id="text2352"><tspan
-           sodipodi:role="line"
-           id="tspan2350"
+         x="324.9772"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="581.76636"
            x="324.9772"
-           y="581.76636">ibex_icache_base_vseq</tspan></text>
+           id="tspan2350"
+           sodipodi:role="line">ibex_icache_base_vseq</tspan></text>
     </g>
   </g>
   <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="575.61847"
+     id="text2356"
      y="265.32785"
-     id="text2356"><tspan
-       sodipodi:role="line"
-       id="tspan2354"
-       x="575.61847"
+     x="575.61847"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.6667px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       style="text-align:start;text-anchor:start"
        y="265.32785"
-       style="text-align:start;text-anchor:start">Legend:</tspan></text>
+       x="575.61847"
+       id="tspan2354"
+       sodipodi:role="line">Legend:</tspan></text>
   <path
-     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1"
-     d="m 290.5,105.5 c -15,0 -35,30 -35,30"
+     sodipodi:nodetypes="cc"
+     inkscape:connector-curvature="0"
      id="path1998"
-     inkscape:connector-curvature="0"
-     sodipodi:nodetypes="cc" />
-  <path
-     sodipodi:nodetypes="cc"
-     inkscape:connector-curvature="0"
-     id="path2402"
-     d="m 290.5,105.5 c -15,0 -35,75 -35,75"
+     d="m 290.5,105.5 c -15,0 -35,30 -35,30"
      style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1" />
   <path
      style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1"
-     d="m 290.5,105.5 c -15,0 -35,120 -35,120"
-     id="path2404"
+     d="m 290.5,105.5 c -15,0 -35,75 -35,75"
+     id="path2402"
      inkscape:connector-curvature="0"
      sodipodi:nodetypes="cc" />
   <path
      sodipodi:nodetypes="cc"
      inkscape:connector-curvature="0"
-     id="path2406"
-     d="m 290.5,105.5 c -15,0 -30,10 -30,10"
+     id="path2404"
+     d="m 290.5,105.5 c -15,0 -35,120 -35,120"
      style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1"
+     d="m 290.5,105.5 c -15,0 -30,10 -30,10"
+     id="path2406"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
   <rect
-     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#dad2ea;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-     id="rect2619"
-     width="470"
-     height="219.99998"
-     x="570.5"
-     y="10.499996"
+     ry="0"
      rx="0"
-     ry="0" />
-  <rect
-     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-     id="rect7655"
-     width="180"
-     height="150"
-     x="840.5"
-     y="60.500008" />
-  <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="930.08954"
-     y="141.69531"
-     id="text7659"><tspan
-       sodipodi:role="line"
-       x="930.08954"
-       y="141.69531"
-       id="tspan7970">ICache</tspan></text>
+     y="10.499995"
+     x="570.5"
+     height="219.99998"
+     width="470"
+     id="rect2619"
+     style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#dad2ea;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
   <g
-     id="g7675"
-     transform="translate(-49.499996,-149)">
-    <rect
-       y="222"
-       x="640"
-       height="35"
-       width="170"
-       id="rect7666"
-       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
-    <text
-       id="text7670"
-       y="244.05762"
-       x="724.40332"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       xml:space="preserve"><tspan
-         y="244.05762"
-         x="724.40332"
-         id="tspan7668"
-         sodipodi:role="line">core_if</tspan></text>
-  </g>
-  <g
-     id="g7683"
-     transform="translate(-49.499996,-104)">
+     transform="translate(-49.500001,-149)"
+     id="g7675">
     <rect
        style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-       id="rect7677"
+       id="rect7666"
        width="170"
        height="35"
        x="640"
        y="222" />
     <text
        xml:space="preserve"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        x="724.40332"
        y="244.05762"
-       id="text7681"><tspan
+       id="text7670"><tspan
          sodipodi:role="line"
-         id="tspan7679"
+         id="tspan7668"
          x="724.40332"
-         y="244.05762">mem_if</tspan></text>
+         y="244.05762">core_if</tspan></text>
   </g>
   <g
-     transform="translate(-49.499996,-59)"
-     id="g7691">
+     transform="translate(-49.500001,-104)"
+     id="g7683">
     <rect
        y="222"
        x="640"
        height="35"
        width="170"
-       id="rect7685"
+       id="rect7677"
        style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
     <text
-       id="text7689"
+       id="text7681"
        y="244.05762"
        x="724.40332"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        xml:space="preserve"><tspan
          y="244.05762"
          x="724.40332"
+         id="tspan7679"
+         sodipodi:role="line">mem_if</tspan></text>
+  </g>
+  <g
+     id="g7691"
+     transform="translate(-49.500001,-59.000001)">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect7685"
+       width="170"
+       height="35"
+       x="640"
+       y="222" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="724.40332"
+       y="244.05762"
+       id="text7689"><tspan
+         sodipodi:role="line"
          id="tspan7687"
-         sodipodi:role="line">clk_rst_if</tspan></text>
+         x="724.40332"
+         y="244.05762">clk_rst_if</tspan></text>
   </g>
   <path
-     style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     d="m 765.5,90.5 10,-15 v 10 h 50 v -10 l 10,15 -10,15 v -10 h -50 v 10 z"
+     inkscape:connector-curvature="0"
      id="path7693"
+     d="m 765.5,90.499999 10,-15 v 10 h 50 v -10 l 10,15 L 825.5,105.5 V 95.499999 h -50 V 105.5 Z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+  <path
+     style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 765.5,135.5 10,-15 v 10 h 50 v -10 l 10,15 -10,15 v -10 h -50 v 10 z"
+     id="path7695"
      inkscape:connector-curvature="0" />
   <path
      inkscape:connector-curvature="0"
-     id="path7695"
-     d="m 765.5,135.5 10,-15 v 10 h 50 v -10 l 10,15 -10,15 v -10 h -50 v 10 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-  <path
-     style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
-     d="m 765.5,183 h 70"
      id="path7697"
-     inkscape:connector-curvature="0" />
+     d="m 765.5,183 h 70"
+     style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)" />
   <text
-     xml:space="preserve"
-     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.33333397px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-     x="612.0202"
+     id="text7968"
      y="45.608871"
-     id="text7968"><tspan
-       sodipodi:role="line"
-       id="tspan7966"
+     x="612.0202"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     xml:space="preserve"><tspan
+       y="45.608871"
        x="612.0202"
-       y="45.608871">tb.sv</tspan></text>
+       id="tspan7966"
+       sodipodi:role="line">tb.sv</tspan></text>
+  <g
+     id="g1295">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect7655"
+       width="180"
+       height="150"
+       x="840.5"
+       y="60.500008" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="930.08527"
+       y="109.6452"
+       id="text7659"><tspan
+         sodipodi:role="line"
+         x="930.08527"
+         y="109.6452"
+         id="tspan7970">ICache</tspan></text>
+    <g
+       id="g1040"
+       transform="translate(-7.5000083,5.2941127)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect1032"
+         width="120.00001"
+         height="24.705883"
+         x="885.5"
+         y="155.79411" />
+      <rect
+         y="150.5"
+         x="880.5"
+         height="24.705883"
+         width="120.00001"
+         id="rect1030"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect1028"
+         width="120.00001"
+         height="24.705883"
+         x="875.5"
+         y="145.5" />
+      <rect
+         y="140.5"
+         x="870.5"
+         height="24.705883"
+         width="120.00001"
+         id="rect993"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fce6ce;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <text
+         id="text997"
+         y="157.41055"
+         x="930.11914"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.3333px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="157.41055"
+           x="930.11914"
+           id="tspan995"
+           sodipodi:role="line">ecc_if</tspan></text>
+    </g>
+  </g>
+  <g
+     transform="translate(3.9999955)"
+     id="g1065">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect1057"
+       width="209.99998"
+       height="33.164459"
+       x="307.5"
+       y="276.177"
+       ry="10"
+       rx="9.999999" />
+    <rect
+       rx="9.999999"
+       ry="10"
+       y="272.177"
+       x="303.5"
+       height="33.164459"
+       width="209.99998"
+       id="rect1055"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect1053"
+       width="209.99998"
+       height="33.164459"
+       x="299.5"
+       y="268.177"
+       ry="10"
+       rx="9.999999" />
+    <rect
+       rx="9.999999"
+       ry="10"
+       y="264.177"
+       x="295.5"
+       height="33.164459"
+       width="209.99998"
+       id="rect1042"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f4cccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+    <text
+       id="text1046"
+       y="284.96625"
+       x="399.95312"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="284.96625"
+         x="399.95312"
+         id="tspan1044"
+         sodipodi:role="line">ibex_icache_ecc_if</tspan></text>
+  </g>
+  <g
+     id="g1135">
+    <rect
+       rx="9.999999"
+       ry="10"
+       y="444.5"
+       x="311.5"
+       height="33.164459"
+       width="209.99998"
+       id="rect1067"
+       style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
+    <rect
+       style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+       id="rect1069"
+       width="209.99998"
+       height="33.164459"
+       x="307.5"
+       y="440.5"
+       ry="10"
+       rx="9.999999" />
+    <rect
+       rx="9.999999"
+       ry="10"
+       y="436.5"
+       x="303.5"
+       height="33.164459"
+       width="209.99998"
+       id="rect1071"
+       style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
+    <rect
+       style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+       id="rect1073"
+       width="209.99998"
+       height="33.164459"
+       x="299.5"
+       y="432.5"
+       ry="10"
+       rx="9.999999" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="403.95312"
+       y="453.28925"
+       id="text1077"><tspan
+         sodipodi:role="line"
+         id="tspan1075"
+         x="403.95312"
+         y="453.28925">ibex_icache_ecc_agent_cfg</tspan></text>
+  </g>
+  <g
+     id="g1188">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#fff2cc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect1908"
+       width="239.99998"
+       height="430"
+       x="20.5"
+       y="70.5"
+       rx="25"
+       ry="25.000002" />
+    <text
+       id="text1785"
+       y="104.02103"
+       x="140.09052"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.6667px;line-height:19.8625px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#f18080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"
+       transform="scale(1.0069205,0.99312707)"><tspan
+         style="fill:#000000;fill-opacity:1;stroke-width:1px"
+         y="104.02103"
+         x="140.09052"
+         id="tspan1783"
+         sodipodi:role="line">ibex_icache_env</tspan></text>
+    <g
+       id="g1896"
+       transform="translate(-54.500001,-76.5)">
+      <rect
+         rx="9.999999"
+         ry="10"
+         y="205.67702"
+         x="80"
+         height="36.322979"
+         width="229.99998"
+         id="rect1831"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <text
+         id="text1789"
+         y="228.39612"
+         x="194.49219"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="228.39612"
+           x="194.49219"
+           id="tspan1787"
+           sodipodi:role="line">ibex_icache_env_cov</tspan></text>
+    </g>
+    <g
+       id="g1901"
+       transform="translate(-54.499971,-72.822968)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect1852"
+         width="229.99998"
+         height="36.322979"
+         x="79.999992"
+         y="247"
+         ry="10"
+         rx="9.999999" />
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         x="194.98438"
+         y="269.71912"
+         id="text1856"><tspan
+           sodipodi:role="line"
+           id="tspan1854"
+           x="194.98438"
+           y="269.71912">ibex_icache_scoreboard</tspan></text>
+    </g>
+    <g
+       id="g1906"
+       transform="translate(-54.500001,-67.822969)">
+      <rect
+         rx="9.999999"
+         ry="10"
+         y="287"
+         x="80"
+         height="36.322979"
+         width="229.99998"
+         id="rect1876"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffe599;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <text
+         id="text1880"
+         y="309.71912"
+         x="194.98438"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="309.71912"
+           x="194.98438"
+           id="tspan1878"
+           sodipodi:role="line">ibex_icache_virtual_sequencer</tspan></text>
+    </g>
+    <g
+       id="g2036"
+       transform="translate(-49.500001,-16.500001)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect2008"
+         width="229.99998"
+         height="36.322979"
+         x="75"
+         y="355.67703"
+         ry="10"
+         rx="9.999999" />
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         x="189.98438"
+         y="378.39615"
+         id="text2012"><tspan
+           sodipodi:role="line"
+           id="tspan2010"
+           x="189.98438"
+           y="378.39615">ibex_icache_core_agent</tspan></text>
+    </g>
+    <g
+       id="g2044"
+       transform="translate(-49.500001,28.499999)">
+      <rect
+         rx="9.999999"
+         ry="10"
+         y="355.67703"
+         x="75"
+         height="36.322979"
+         width="229.99998"
+         id="rect2038"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <text
+         id="text2042"
+         y="378.39615"
+         x="189.98438"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         xml:space="preserve"><tspan
+           y="378.39615"
+           x="189.98438"
+           id="tspan2040"
+           sodipodi:role="line">ibex_icache_mem_agent</tspan></text>
+    </g>
+    <g
+       id="g1154"
+       transform="translate(-270)">
+      <rect
+         rx="9.999999"
+         ry="10"
+         y="444.5"
+         x="311.5"
+         height="33.164459"
+         width="209.99998"
+         id="rect1142"
+         style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
+      <rect
+         style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+         id="rect1144"
+         width="209.99998"
+         height="33.164459"
+         x="307.5"
+         y="440.5"
+         ry="10"
+         rx="9.999999" />
+      <rect
+         rx="9.999999"
+         ry="10"
+         y="436.5"
+         x="303.5"
+         height="33.164459"
+         width="209.99998"
+         id="rect1146"
+         style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
+      <rect
+         style="color:#000000;font-variation-settings:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#d9ead3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+         id="rect1148"
+         width="209.99998"
+         height="33.164459"
+         x="299.5"
+         y="432.5"
+         ry="10"
+         rx="9.999999" />
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:20px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         x="403.95312"
+         y="453.28925"
+         id="text1152"><tspan
+           sodipodi:role="line"
+           id="tspan1150"
+           x="403.95312"
+           y="453.28925">ibex_icache_ecc_agent</tspan></text>
+    </g>
+  </g>
 </svg>
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.core b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.core
index 610367c..e61837e 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.core
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.core
@@ -10,6 +10,7 @@
       - lowrisc:dv:dv_lib
       - lowrisc:dv:ibex_icache_core_agent
       - lowrisc:dv:ibex_icache_mem_agent
+      - lowrisc:dv:ibex_icache_ecc_agent
     files:
       - ibex_icache_env_pkg.sv
       - ibex_icache_env_cfg.sv: {is_include_file: true}
@@ -19,13 +20,15 @@
       - ibex_icache_env.sv: {is_include_file: true}
       - seq_lib/ibex_icache_vseq_list.sv: {is_include_file: true}
       - seq_lib/ibex_icache_base_vseq.sv: {is_include_file: true}
-      - seq_lib/ibex_icache_sanity_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_passthru_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_caching_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_invalidation_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_oldval_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_back_line_vseq.sv: {is_include_file: true}
       - seq_lib/ibex_icache_many_errors_vseq.sv: {is_include_file: true}
+      - seq_lib/ibex_icache_ecc_vseq.sv: {is_include_file: true}
+      - seq_lib/ibex_icache_combo_vseq.sv: {is_include_file: true}
+      - seq_lib/ibex_icache_reset_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.sv
index c2469bc..97f4515 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env.sv
@@ -13,6 +13,9 @@
   ibex_icache_core_agent core_agent;
   ibex_icache_mem_agent  mem_agent;
 
+  ibex_icache_ecc_agent  ecc_tag_agents[];
+  ibex_icache_ecc_agent  ecc_data_agents[];
+
   // Heartbeat tracking
   uvm_callbacks_objection           hb_objection;
   uvm_heartbeat                     heartbeat;
@@ -29,9 +32,28 @@
     mem_agent = ibex_icache_mem_agent::type_id::create("mem_agent", this);
     uvm_config_db#(ibex_icache_mem_agent_cfg)::set(this, "mem_agent*", "cfg", cfg.mem_agent_cfg);
 
+    // If ECC is enabled, create ECC agents for the RAMs. We have already created config objects for
+    // them (the test called create_ecc_agent_cfgs in its build_phase method), so we just have to
+    // make an agent for each config. In practice, there will be the same number of tag and data
+    // agents, but this code doesn't really care.
+    ecc_tag_agents  = new[cfg.ecc_tag_agent_cfgs.size()];
+    for (int unsigned i = 0; i < cfg.ecc_tag_agent_cfgs.size(); i++) begin
+      string tname = $sformatf("ecc_tag_agents[%0d]", i);
+      ecc_tag_agents[i] = ibex_icache_ecc_agent::type_id::create(tname, this);
+      uvm_config_db#(ibex_icache_ecc_agent_cfg)::set(this, {tname, "*"}, "cfg", cfg.ecc_tag_agent_cfgs[i]);
+    end
+    ecc_data_agents  = new[cfg.ecc_data_agent_cfgs.size()];
+    for (int unsigned i = 0; i < cfg.ecc_data_agent_cfgs.size(); i++) begin
+      string dname = $sformatf("ecc_data_agents[%0d]", i);
+      ecc_data_agents[i] = ibex_icache_ecc_agent::type_id::create(dname, this);
+      uvm_config_db#(ibex_icache_ecc_agent_cfg)::set(this, {dname, "*"}, "cfg", cfg.ecc_data_agent_cfgs[i]);
+    end
+
     hb_objection = new("hb_objection");
     heartbeat    = new("heartbeat", this, hb_objection);
     hb_event     = new("hb_event");
+
+    cfg.clk_rst_vif.set_sole_clock();
   endfunction
 
   function void connect_phase(uvm_phase phase);
@@ -41,15 +63,37 @@
       mem_agent.monitor.analysis_port.connect(scoreboard.mem_fifo.analysis_export);
       core_agent.driver.analysis_port.connect(scoreboard.seed_fifo.analysis_export);
     end
-    if (cfg.is_active && cfg.mem_agent_cfg.is_active && cfg.core_agent_cfg.is_active) begin
-      core_agent.driver.analysis_port.connect(mem_agent.sequencer.seed_fifo.analysis_export);
-    end
 
-    if (cfg.is_active && cfg.core_agent_cfg.is_active) begin
-      virtual_sequencer.core_sequencer_h = core_agent.sequencer;
-    end
-    if (cfg.is_active && cfg.mem_agent_cfg.is_active) begin
-      virtual_sequencer.mem_sequencer_h = mem_agent.sequencer;
+    // If we are active, wire up each active agent to a sequencer in the virtual sequencer.
+    if (cfg.is_active) begin
+      if (cfg.mem_agent_cfg.is_active && cfg.core_agent_cfg.is_active) begin
+        core_agent.driver.analysis_port.connect(mem_agent.sequencer.seed_fifo.analysis_export);
+      end
+
+      if (cfg.core_agent_cfg.is_active) begin
+        virtual_sequencer.core_sequencer_h = core_agent.sequencer;
+      end
+      if (cfg.mem_agent_cfg.is_active) begin
+        virtual_sequencer.mem_sequencer_h = mem_agent.sequencer;
+      end
+
+      // We assume that either all ECC tag/data agents are active or none of them are.
+      `DV_CHECK_EQ_FATAL(cfg.ecc_tag_agent_cfgs.size(), ecc_tag_agents.size())
+      if ((cfg.ecc_tag_agent_cfgs.size() > 0) && (cfg.ecc_tag_agent_cfgs[0].is_active)) begin
+        virtual_sequencer.ecc_tag_sequencers = new[cfg.ecc_tag_agent_cfgs.size()];
+        foreach (ecc_tag_agents[i]) begin
+          `DV_CHECK_FATAL(cfg.ecc_tag_agent_cfgs[i].is_active);
+          virtual_sequencer.ecc_tag_sequencers[i] = ecc_tag_agents[i].sequencer;
+        end
+      end
+      `DV_CHECK_EQ_FATAL(cfg.ecc_data_agent_cfgs.size(), ecc_data_agents.size())
+      if ((cfg.ecc_data_agent_cfgs.size() > 0) && (cfg.ecc_data_agent_cfgs[0].is_active)) begin
+        virtual_sequencer.ecc_data_sequencers = new[cfg.ecc_data_agent_cfgs.size()];
+        foreach (ecc_data_agents[i]) begin
+          `DV_CHECK_FATAL(cfg.ecc_data_agent_cfgs[i].is_active);
+          virtual_sequencer.ecc_data_sequencers[i] = ecc_data_agents[i].sequencer;
+        end
+      end
     end
 
     // Register the heartbeat objection with both sequencers (so they know how to reset it)
@@ -69,8 +113,8 @@
     // is triggered.
     heartbeat.start(hb_event);
     forever begin
-      // Every 2000 clocks, check the heartbeat monitor
-      cfg.core_agent_cfg.vif.wait_clks(2000);
+      // Every 2000 clocks, check the heartbeat monitor (not stopping early on reset)
+      cfg.core_agent_cfg.vif.wait_clks(2000, 1'b0);
       hb_event.trigger();
     end
   endtask
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_cfg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_cfg.sv
index c531553..19b67f5 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_cfg.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_cfg.sv
@@ -4,13 +4,30 @@
 
 class ibex_icache_env_cfg extends dv_base_env_cfg;
 
+  // If set, the scoreboard won't check caching ratios
+  bit disable_caching_ratio_test = 0;
+
   // ext component cfgs
   rand ibex_icache_core_agent_cfg   core_agent_cfg;
   rand ibex_icache_mem_agent_cfg    mem_agent_cfg;
 
+  // Force the clock frequency to 50MHz. The clock frequency doesn't really matter for ICache
+  // testing and 50MHz dumped waves are nice to read because clock edges are multiples of 10ns.
+  constraint clk_freq_50_c {
+    clk_freq_mhz == ClkFreq50Mhz;
+  }
+
+  // Config objects for ECC components (see create_ecc_agent_cfgs). Since these are created after
+  // initialization, they won't get randomized automatically, so we do that manually at the bottom
+  // of create_ecc_agent_cfgs.
+  ibex_icache_ecc_agent_cfg         ecc_tag_agent_cfgs[];
+  ibex_icache_ecc_agent_cfg         ecc_data_agent_cfgs[];
+
   `uvm_object_utils_begin(ibex_icache_env_cfg)
-    `uvm_field_object(core_agent_cfg, UVM_DEFAULT)
-    `uvm_field_object(mem_agent_cfg,  UVM_DEFAULT)
+    `uvm_field_object      (core_agent_cfg,      UVM_DEFAULT)
+    `uvm_field_object      (mem_agent_cfg,       UVM_DEFAULT)
+    `uvm_field_array_object(ecc_tag_agent_cfgs,  UVM_DEFAULT)
+    `uvm_field_array_object(ecc_data_agent_cfgs, UVM_DEFAULT)
   `uvm_object_utils_end
 
   `uvm_object_new
@@ -20,4 +37,20 @@
     mem_agent_cfg  = ibex_icache_mem_agent_cfg::type_id::create ("mem_agent_cfg");
   endfunction
 
+  // Create tag and data ECC agents for each way. If ECC is disabled, this should still be called,
+  // but with num_ecc_ways = 0.
+  function automatic void create_ecc_agent_cfgs(int unsigned num_ecc_ways);
+    ecc_tag_agent_cfgs = new[num_ecc_ways];
+    ecc_data_agent_cfgs = new[num_ecc_ways];
+    for (int unsigned i = 0; i < num_ecc_ways; i++) begin
+      string tname = $sformatf("ecc_tag_agent_cfgs[%0d]", i);
+      string dname = $sformatf("ecc_data_agent_cfgs[%0d]", i);
+      ecc_tag_agent_cfgs[i] = ibex_icache_ecc_agent_cfg::type_id::create(tname);
+      ecc_data_agent_cfgs[i] = ibex_icache_ecc_agent_cfg::type_id::create(dname);
+
+      `DV_CHECK_RANDOMIZE_FATAL(ecc_tag_agent_cfgs[i])
+      `DV_CHECK_RANDOMIZE_FATAL(ecc_data_agent_cfgs[i])
+    end
+  endfunction
+
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_pkg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_pkg.sv
index 1bc056a..b897261 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_env_pkg.sv
@@ -9,6 +9,7 @@
   import dv_utils_pkg::*;
   import ibex_icache_core_agent_pkg::*;
   import ibex_icache_mem_agent_pkg::*;
+  import ibex_icache_ecc_agent_pkg::*;
   import dv_lib_pkg::*;
 
   // macro includes
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_scoreboard.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_scoreboard.sv
index b7c147f..2ce093c 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_scoreboard.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_scoreboard.sv
@@ -26,7 +26,7 @@
   ibex_icache_mem_model #(BusWidth) mem_model;
 
   // A queue of memory seeds.
-  bit [31:0]   mem_seeds[$];
+  bit [31:0]   mem_seeds[$] = {32'd0};
 
   // Tracks the next address we expect to see on a fetch. This gets reset to 'X, then is set to an
   // address after each branch transaction.
@@ -119,17 +119,17 @@
     seed_fifo = new("seed_fifo", this);
     mem_model = new("mem_model",
                     cfg.mem_agent_cfg.disable_pmp_errs,
-                    cfg.mem_agent_cfg.disable_mem_errs,
-                    cfg.mem_agent_cfg.mem_err_shift);
+                    cfg.mem_agent_cfg.disable_mem_errs);
   endfunction
 
   task run_phase(uvm_phase phase);
     super.run_phase(phase);
-    window_reset();
+    tracking_reset();
     fork
       process_core_fifo();
       process_mem_fifo();
       process_seed_fifo();
+      monitor_negedge_reset();
     join_none
   endtask
 
@@ -205,6 +205,9 @@
       mem_fifo.get(item);
       `uvm_info(`gfn, $sformatf("received mem transaction:\n%0s", item.sprint()), UVM_HIGH)
 
+      // Looks like we are in reset. Discard the item.
+      if (!cfg.clk_rst_vif.rst_n) continue;
+
       if (item.is_grant) begin
         mem_trans_count += 1;
         window_take_mem_read();
@@ -225,10 +228,31 @@
     end
   endtask
 
-  virtual function void reset(string kind = "HARD");
-    super.reset(kind);
+  // Trigger start_reset on every negedge of the reset line. Never returns.
+  task monitor_negedge_reset();
+    forever begin
+      @(negedge cfg.clk_rst_vif.rst_n) start_reset();
+    end
+  endtask
+
+  // A function called on negedge of rst_n
+  function void start_reset();
     next_addr = 'X;
-    mem_seeds = {32'd0};
+
+    // Throw away any old seeds
+    invalidate_seed = mem_seeds.size - 1;
+    mem_seeds = mem_seeds[invalidate_seed:$];
+    invalidate_seed = 0;
+    last_branch_seed = 0;
+
+    // Forget about any pending bus transactions (they've been thrown away anyway)
+    mem_trans_count = 0;
+  endfunction
+
+  // Called on the posedge of rst_n which ends the reset period.
+  function void reset(string kind = "HARD");
+    super.reset(kind);
+    tracking_reset();
   endfunction
 
   function void check_phase(uvm_phase phase);
@@ -260,7 +284,7 @@
         if (chatty) begin
           `uvm_info(`gfn,
                     $sformatf("Not seed 0x%08h: expected seen_err but saw 0.", seed),
-                    UVM_MEDIUM)
+                    UVM_LOW)
         end
         return 0;
       end
@@ -276,7 +300,7 @@
       if (chatty) begin
         `uvm_info(`gfn,
                   $sformatf("Not seed 0x%08h: got unexpected error flag.", seed),
-                  UVM_MEDIUM)
+                  UVM_LOW)
       end
       return 0;
     end
@@ -289,7 +313,7 @@
                     $sformatf("Not seed 0x%08h (expected cmp 0x(%04h)%04h; saw 0x(%04h)%04h).",
                               seed, exp_insn_data[31:16], exp_insn_data[15:0],
                               seen_insn_data[31:16], seen_insn_data[15:0]),
-                    UVM_MEDIUM)
+                    UVM_LOW)
         end
         return 0;
       end
@@ -299,7 +323,7 @@
           `uvm_info(`gfn,
                     $sformatf("Not seed 0x%08h (expected uncomp 0x%08h; saw 0x%08h).",
                               seed, exp_insn_data, seen_insn_data),
-                    UVM_MEDIUM)
+                    UVM_LOW)
         end
         return 0;
       end
@@ -334,7 +358,7 @@
         `uvm_info(`gfn,
                   $sformatf("Not seeds 0x%08h/0x%08h (expected error in low word).",
                             seed_lo, seed_hi),
-                  UVM_MEDIUM)
+                  UVM_LOW)
       end
       return 0;
     end
@@ -344,7 +368,7 @@
         `uvm_info(`gfn,
                   $sformatf("Not seeds 0x%08h/0x%08h (exp/seen top errors %0d/%0d).",
                             seed_lo, seed_hi, exp_err_hi, seen_err_plus2),
-                  UVM_MEDIUM)
+                  UVM_LOW)
       end
       return 0;
     end
@@ -354,7 +378,7 @@
         `uvm_info(`gfn,
                   $sformatf("Match for seeds 0x%08h/0x%08h (seen upper error).",
                             seed_lo, seed_hi),
-                  UVM_MEDIUM)
+                  UVM_LOW)
       end
       return 1'b1;
     end
@@ -365,7 +389,7 @@
         `uvm_info(`gfn,
                   $sformatf("Not seeds 0x%08h/0x%08h (exp/seen data 0x%08h/0x%08h).",
                             seed_lo, seed_hi, exp_insn_data, seen_insn_data),
-                  UVM_MEDIUM)
+                  UVM_LOW)
       end
       return 0;
     end
@@ -406,7 +430,8 @@
 
     return is_fetch_compatible_1(seen_insn_data,
                                  seen_err,
-                                 mem_model.is_either_error(seed, addr_lo),
+                                 mem_model.is_either_error(seed, addr_lo,
+                                                           cfg.mem_agent_cfg.mem_err_shift),
                                  rdata[31:0],
                                  seed,
                                  chatty);
@@ -445,13 +470,13 @@
     lo_bits_to_drop = BusWidth - lo_bits_to_take;
 
     // Do the first read (from the low address) and shift right to drop the bits that we don't need.
-    exp_err_lo = mem_model.is_either_error(seed_lo, addr_lo);
+    exp_err_lo = mem_model.is_either_error(seed_lo, addr_lo, cfg.mem_agent_cfg.mem_err_shift);
     rdata      = mem_model.read_data(seed_lo, addr_lo) >> lo_bits_to_drop;
     exp_data   = rdata[31:0];
 
     // Now do the second read (from the upper address). Shift the result up by lo_bits_to_take,
     // which will discard some top bits. Then extract 32 bits and OR with what we have so far.
-    exp_err_hi = mem_model.is_either_error(seed_hi, addr_hi);
+    exp_err_hi = mem_model.is_either_error(seed_hi, addr_hi, cfg.mem_agent_cfg.mem_err_shift);
     rdata      = mem_model.read_data(seed_hi, addr_hi) << lo_bits_to_take;
     exp_data   = exp_data | rdata[31:0];
 
@@ -587,11 +612,17 @@
     end
   endtask
 
+  // Completely reset cache tracking, waiting for busy to drop to be certain that invalidation is
+  // done
+  function automatic void tracking_reset();
+    not_invalidating = 1'b0;
+    window_reset();
+  endfunction
+
   // Reset the caching tracking window
   function automatic void window_reset();
     insns_in_window = 0;
     reads_in_window = 0;
-    not_invalidating = 1'b0;
     window_range_lo = ~(31'b0);
     window_range_hi = 0;
   endfunction
@@ -604,10 +635,16 @@
 
   // Register an instruction fetch with the caching tracking window
   function automatic void window_take_insn(bit [31:0] addr, bit err);
-    bit [31:0]   window_width;
+    bit [32:0]   window_width;
     int unsigned fetch_ratio_pc;
 
-    if (err) begin
+    // Ignore instructions and reset the window if this check is disabled in the configuration.
+    // Resetting the window each time avoids cases where we run an ECC sequence for a while (where
+    // the check should be disabled), then switch to a normal sequence (where the check should be
+    // enabled) just before the window finishes.
+    //
+    // Similarly, bail on an error since that would significantly lower the cache hit ratio.
+    if (err || cfg.disable_caching_ratio_test) begin
       window_reset();
       return;
     end
@@ -625,14 +662,14 @@
     // We have a full window. Has the address range been sufficiently small? The fatal check is for
     // the scoreboard logic: this should hold true as soon as we've seen an instruction.
     `DV_CHECK_LE_FATAL(window_range_lo, window_range_hi);
-    window_width = (window_range_hi - window_range_lo + 3) / 4;
+    window_width = ({1'b0, window_range_hi} - {1'b0, window_range_lo} + 33'd3) / 4;
 
     `uvm_info(`gfn,
               $sformatf("Completed window with %0d insns and %0d reads, range [0x%08h, 0x%08h].",
                         insns_in_window, reads_in_window, window_range_lo, window_range_hi),
               UVM_HIGH)
 
-    if (window_width <= max_window_width) begin
+    if (window_width[31:0] <= max_window_width) begin
       // The range has been small enough, so we can actually check whether the caching is working.
       // Calculate the R we've seen (as a percentage).
       fetch_ratio_pc = (reads_in_window * 100 * 7 / 4) / insns_in_window;
@@ -643,7 +680,7 @@
                            "%0d instructions and address range [0x%08h, 0x%08h] ",
                            "(window width %0d)"},
                           fetch_ratio_pc, insns_in_window,
-                          window_range_lo, window_range_hi, window_width))
+                          window_range_lo, window_range_hi, window_width[31:0]))
     end
 
     // Start the next window
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_virtual_sequencer.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_virtual_sequencer.sv
index 32a1e8e..c5c5e05 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_virtual_sequencer.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/ibex_icache_virtual_sequencer.sv
@@ -9,6 +9,9 @@
   ibex_icache_core_sequencer core_sequencer_h;
   ibex_icache_mem_sequencer  mem_sequencer_h;
 
+  ibex_icache_ecc_sequencer  ecc_tag_sequencers[];
+  ibex_icache_ecc_sequencer  ecc_data_sequencers[];
+
   `uvm_component_new
 
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_back_line_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_back_line_vseq.sv
index dac4210..b016b9c 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_back_line_vseq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_back_line_vseq.sv
@@ -8,12 +8,27 @@
   `uvm_object_new
 
   virtual task pre_start();
+    uvm_factory        f;
+    uvm_object_wrapper wrapper;
+    string             base_name, back_name, old_name, inst_path;
+
     // The base class creates a sequence for the core and memory agents in its pre_start method. We
-    // want to override its decision and use a different sequence for the core
-    ibex_icache_core_base_seq::type_id::
-      set_inst_override(ibex_icache_core_back_line_seq::get_type(), "*");
+    // want to override its decision and use a different sequence for the core. To do so, we use the
+    // factory's set_inst_override_by_name. Once we've called the base class's pre_start method, we
+    // tidy up the override again (to allow sequence chaining).
+    f = uvm_factory::get();
+    base_name = ibex_icache_core_base_seq::type_name;
+    back_name = ibex_icache_core_back_line_seq::type_name;
+    inst_path = {`gfn, ".*"};
+
+    wrapper = f.find_override_by_name(base_name, inst_path);
+    old_name = (wrapper == null) ? base_name : wrapper.get_type_name();
+    f.set_inst_override_by_name(base_name, back_name, inst_path);
 
     super.pre_start();
+
+    f.set_inst_override_by_name(base_name, old_name, inst_path);
+
   endtask : pre_start
 
 endclass : ibex_icache_back_line_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_base_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_base_vseq.sv
index e6c5288..6398e9e 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_base_vseq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_base_vseq.sv
@@ -11,41 +11,111 @@
   `uvm_object_utils(ibex_icache_base_vseq)
   `uvm_object_new
 
-  // The two actual sequences. We don't subclass them in subclasses of this virtual sequence, but we
-  // might want to set control knobs. To allow this, we construct the sequences in pre_start.
+  // Should we generate ECC errors in the underlying SRAM objects?
+  bit enable_ecc_errors = 0;
+
+  // The mem_err_shift parameter to use for the memory model with this sequence. Gets written to the
+  // sequencer's config when the sequence runs.
+  int unsigned mem_err_shift = 3;
+
+  // Non-null if this is an item after the first in a "combo" run, which runs several of these
+  // sequences back-to-back. Must be set before pre_start to have any effect.
+  ibex_icache_base_vseq prev_sequence = null;
+
+  // The core and memory sequences. We don't subclass them in subclasses of this virtual sequence,
+  // but we might want to set control knobs. To allow this, we construct the sequences in pre_start.
   // Subclasses should override pre_start, call this super to construct the sequence, and then set
   // any control knobs they need.
   ibex_icache_core_base_seq core_seq;
   ibex_icache_mem_resp_seq  mem_seq;
 
-  virtual task dut_init(string reset_kind = "HARD");
-    super.dut_init();
-  endtask
+  // ECC sequences. The arrays are created in pre_start and are nonempty if ECC errors are enabled.
+  ibex_icache_ecc_base_seq  ecc_tag_seqs[];
+  ibex_icache_ecc_base_seq  ecc_data_seqs[];
+
+  // The number of transactions to run (passed to the core sequence). This gets randomised to
+  // something sensible by default, but can be overridden by setting it before starting the
+  // sequence.
+  constraint num_trans_c { num_trans inside {[800:1000]}; }
 
   virtual task pre_start();
     super.pre_start();
+
     `uvm_create_on(core_seq, p_sequencer.core_sequencer_h)
     `uvm_create_on(mem_seq, p_sequencer.mem_sequencer_h)
+
+    // Unlike the other sequences, the core sequence has a finite number of items. Set that to our
+    // number of transactions here.
+    core_seq.num_trans = num_trans;
+
+    if (prev_sequence != null) begin
+      // If there was a previous sequence, pass it down to core_seq and mem_seq
+      core_seq.prev_sequence = prev_sequence.core_seq;
+      mem_seq.prev_sequence = prev_sequence.mem_seq;
+
+      // If the new memory sequence will change mem_err_shift, we need to tell the core to
+      // invalidate at the start of its sequence.
+      if (cfg.mem_agent_cfg.mem_err_shift != mem_err_shift) begin
+        core_seq.must_invalidate = 1'b1;
+      end
+    end
+
+    // Write mem_err_shift into the config object (which the scoreboard and memory sequence will
+    // both see)
+    cfg.mem_agent_cfg.mem_err_shift = mem_err_shift;
+
+    // If enable_ecc_errors then create any ECC sequences we need (one for each sequencer in
+    // p_sequencer.ecc_tag_sequencers and p_sequencer.ecc_data_sequencers).
+    ecc_tag_seqs = new[enable_ecc_errors ? p_sequencer.ecc_tag_sequencers.size() : 0];
+    foreach (ecc_tag_seqs[i]) begin
+      `uvm_create_on(ecc_tag_seqs[i], p_sequencer.ecc_tag_sequencers[i])
+    end
+    ecc_data_seqs = new[enable_ecc_errors ? p_sequencer.ecc_data_sequencers.size() : 0];
+    foreach (ecc_data_seqs[i]) begin
+      `uvm_create_on(ecc_data_seqs[i], p_sequencer.ecc_data_sequencers[i])
+    end
   endtask : pre_start
 
   virtual task body();
-    // Start the core and memory sequences. We use fork/join_any so that we don't wait for the
-    // memory sequence (which is reactive so will never finish).
     fork
+      // The core sequence blocks until it has run all its items.
       begin
         `DV_CHECK_RANDOMIZE_FATAL(core_seq)
         core_seq.start(p_sequencer.core_sequencer_h);
       end
-      begin
-        `DV_CHECK_RANDOMIZE_FATAL(mem_seq)
-        mem_seq.start(p_sequencer.mem_sequencer_h);
-      end
+
+      // These sequences will never end. We wrap them all up together in a fork/join so that we can
+      // fork/join_none any ECC sequences (which yield immediately so that we can start them in a
+      // loop), but still have a process that never yields, to use as a child for the surrounding
+      // fork/join_any.
+      fork
+        begin
+          `DV_CHECK_RANDOMIZE_FATAL(mem_seq)
+          mem_seq.start(p_sequencer.mem_sequencer_h);
+        end
+        foreach (ecc_tag_seqs[i]) begin
+          start_ecc_body(ecc_tag_seqs[i], p_sequencer.ecc_tag_sequencers[i]);
+        end
+        foreach (ecc_data_seqs[i]) begin
+          start_ecc_body(ecc_data_seqs[i], p_sequencer.ecc_data_sequencers[i]);
+        end
+      join
     join_any
+
+    // The core sequence has finished. Kill all the other sequences
+    mem_seq.kill();
+    foreach (ecc_tag_seqs[i]) ecc_tag_seqs[i].kill();
+    foreach (ecc_data_seqs[i]) ecc_data_seqs[i].kill();
+
   endtask : body
 
-  virtual task dut_shutdown();
-    // check for pending ibex_icache operations and wait for them to complete
-    // TODO
+  // Randomize and then run a given (never ending) ECC sequence on the given sequencer. Returns
+  // immediately (so you can start sequences in a loop).
+  protected task start_ecc_body(ibex_icache_ecc_base_seq seq, ibex_icache_ecc_sequencer sqr);
+    `DV_CHECK_RANDOMIZE_FATAL(seq);
+    fork begin
+      seq.start(sqr);
+    end join_none
   endtask
 
 endclass : ibex_icache_base_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_combo_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_combo_vseq.sv
new file mode 100644
index 0000000..3eb0c9e
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_combo_vseq.sv
@@ -0,0 +1,128 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// A "combination vseq", which runs proper virtual sequences in a random order.
+
+class ibex_icache_combo_vseq
+  extends dv_base_vseq #(
+    .CFG_T               (ibex_icache_env_cfg),
+    .COV_T               (ibex_icache_env_cov),
+    .VIRTUAL_SEQUENCER_T (ibex_icache_virtual_sequencer)
+  );
+  `uvm_object_utils(ibex_icache_combo_vseq)
+  `uvm_object_new
+
+  // The number of transactions across the combined sequences
+  constraint num_trans_c { num_trans inside {[800:1000]}; }
+
+  // The virtual sequences from which we'll build the test. Note that this doesn't contain
+  // "ibex_icache_oldval_vseq": that sequence is for a specific test, which has a slightly different
+  // checker.
+  string seq_names[] = {"ibex_icache_back_line_vseq",
+                        "ibex_icache_base_vseq", // for sanity test
+                        "ibex_icache_caching_vseq",
+                        "ibex_icache_ecc_vseq",
+                        "ibex_icache_invalidation_vseq",
+                        "ibex_icache_many_errors_vseq",
+                        "ibex_icache_passthru_vseq"};
+
+  // If this is set, occasionally reset the DUT and start a new sequence at a time that the core
+  // sequence wouldn't normally expect.
+  bit random_reset = 1'b0;
+
+  // How many sequences have we executed so far?
+  int unsigned seqs_so_far = 0;
+
+  // The child (virtual) sequence
+  ibex_icache_base_vseq child_seq;
+
+  // The previous sequence that we ran.
+  ibex_icache_base_vseq prev_seq = null;
+
+  task body();
+    int unsigned trans_so_far = 0;
+
+    while (trans_so_far < num_trans) begin
+      int unsigned seq_idx;
+      uvm_sequence seq;
+      int unsigned trans_now;
+      bit          should_reset;
+
+      seq_idx = $urandom_range(0, seq_names.size - 1);
+
+      // Pick the number of transactions to run. We don't want too many, because the whole point is
+      // that we're interested in the edges between sequences. Note that we don't bother to ensure
+      // that trans_so_far + trans_now <= num_trans: it won't really matter if we overshoot by a
+      // little.
+      trans_now = $urandom_range(50, 100);
+
+      // We don't need to reset if seq_idx == 0 (because we did a reset before starting this task).
+      // Otherwise, we always reset between sequences if random_reset is true. We'd always need to
+      // if we killed the previous sequence, and it's easier not to bother tracking properly. If
+      // random_reset is false (the usual back-to-back sequence test), we reset 1 time in 2.
+      if (seq_idx == 0) should_reset = 1'b0;
+      else if (random_reset) should_reset = 1'b1;
+      else should_reset = $urandom_range(0, 1);
+
+      `uvm_info(`gfn,
+                $sformatf("Running sequence '%s' (%0d transactions; reset=%0d).",
+                          seq_names[seq_idx], trans_now, should_reset),
+                UVM_HIGH)
+
+      seq = create_seq_by_name(seq_names[seq_idx]);
+      `downcast(child_seq, seq)
+
+      child_seq.set_sequencer(p_sequencer);
+      `DV_CHECK_RANDOMIZE_FATAL(child_seq)
+
+      child_seq.num_trans = trans_now;
+      child_seq.do_dut_init = should_reset;
+      child_seq.prev_sequence = prev_seq;
+
+      // The memory agent is careful to avoid consuming requests from its sequencer's request_fifo
+      // until it has handled them. This is important if we're not resetting (it essentially allows
+      // the sequence to change under the feet of the rest of the environment without it noticing),
+      // but we need to make sure we discard any pending requests on an actual reset. Do that here.
+      if (should_reset && seqs_so_far > 0) begin
+        p_sequencer.mem_sequencer_h.request_fifo.flush();
+      end
+
+      run_sequence();
+
+      prev_seq = child_seq;
+      trans_so_far += trans_now;
+      seqs_so_far  += 1;
+    end
+  endtask : body
+
+  // Run a sequence. If random_reset = 0, this will run to completion. Otherwise, the sequence may
+  // be stopped early.
+  protected task run_sequence();
+    int unsigned cycles_till_reset;
+    bit          reached_timeout = 1'b0;
+
+    if (!random_reset) begin
+      child_seq.start(p_sequencer, this);
+    end else begin
+      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(cycles_till_reset,
+                                         cycles_till_reset dist {
+                                           [100:500]  :/ 1,
+                                           [501:1000] :/ 4
+                                         };)
+      fork
+        child_seq.start(p_sequencer, this);
+        begin
+          repeat (cycles_till_reset) @(cfg.clk_rst_vif.cb);
+          reached_timeout = 1'b1;
+        end
+      join_any
+    end
+
+    if (reached_timeout) child_seq.kill();
+
+    // Kill the timer process if it's still going.
+    disable fork;
+  endtask : run_sequence
+
+endclass : ibex_icache_combo_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_ecc_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_ecc_vseq.sv
new file mode 100644
index 0000000..ed5340c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_ecc_vseq.sv
@@ -0,0 +1,33 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// A sequence that injects ECC errors and checks we deal with them correctly.
+//
+// This is based on the caching vseq, which means we should see lots of cache hits (some of which
+// will be corrupt).
+
+class ibex_icache_ecc_vseq extends ibex_icache_caching_vseq;
+
+  `uvm_object_utils(ibex_icache_ecc_vseq)
+  `uvm_object_new
+
+  virtual task pre_start();
+    enable_ecc_errors = 1'b1;
+    super.pre_start();
+  endtask : pre_start
+
+  // Wrap the underlying body, setting the disable_caching_ratio_test flag to tell the scoreboard
+  // not to track cache hit ratios. This test corrupts data in the ICache's memory. The corruptions
+  // are spotted, and behave as if the cache missed. This (obviously) lowers the cache hit rate, so
+  // we don't want the test to make sure it's high enough.
+  virtual task body();
+    bit old_dcrt = p_sequencer.cfg.disable_caching_ratio_test;
+    p_sequencer.cfg.disable_caching_ratio_test = 1'b1;
+
+    super.body();
+
+    p_sequencer.cfg.disable_caching_ratio_test = old_dcrt;
+  endtask : body
+
+endclass : ibex_icache_ecc_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_many_errors_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_many_errors_vseq.sv
index 051d054..65ad763 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_many_errors_vseq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_many_errors_vseq.sv
@@ -5,7 +5,14 @@
 class ibex_icache_many_errors_vseq extends ibex_icache_base_vseq;
 
   `uvm_object_utils(ibex_icache_many_errors_vseq)
-  `uvm_object_new
+
+  function new (string name="");
+    super.new(name);
+
+    // Increase the error rate (to roughly 50%) for this sequence.
+    mem_err_shift = 1;
+
+  endfunction : new
 
   virtual task pre_start();
     super.pre_start();
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_reset_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_reset_vseq.sv
new file mode 100644
index 0000000..14526ad
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_reset_vseq.sv
@@ -0,0 +1,20 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// A version of the combination vseq that injects resets at unexpected times.
+
+class ibex_icache_reset_vseq extends ibex_icache_combo_vseq;
+
+  `uvm_object_utils(ibex_icache_reset_vseq)
+  `uvm_object_new
+
+  task pre_do (bit is_item);
+    super.pre_do(is_item);
+
+    // Enable "random reset" functionality, which resets the DUT (and starts a new sequence) at
+    // random times.
+    random_reset = 1'b1;
+  endtask : pre_do
+
+endclass : ibex_icache_reset_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_sanity_vseq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_sanity_vseq.sv
deleted file mode 100644
index 8e8a07e..0000000
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_sanity_vseq.sv
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-// Basic sanity test
-
-class ibex_icache_sanity_vseq extends ibex_icache_base_vseq;
-
-  `uvm_object_utils(ibex_icache_sanity_vseq)
-  `uvm_object_new
-
-  // No customisation of base class needed
-
-endclass : ibex_icache_sanity_vseq
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv
index 846e351..ed24e24 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv
@@ -3,10 +3,12 @@
 // SPDX-License-Identifier: Apache-2.0
 
 `include "ibex_icache_base_vseq.sv"
-`include "ibex_icache_sanity_vseq.sv"
 `include "ibex_icache_passthru_vseq.sv"
 `include "ibex_icache_caching_vseq.sv"
 `include "ibex_icache_invalidation_vseq.sv"
 `include "ibex_icache_oldval_vseq.sv"
 `include "ibex_icache_back_line_vseq.sv"
 `include "ibex_icache_many_errors_vseq.sv"
+`include "ibex_icache_ecc_vseq.sv"
+`include "ibex_icache_combo_vseq.sv"
+`include "ibex_icache_reset_vseq.sv"
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_driver.sv
index 689145f..8f70897 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_driver.sv
@@ -59,12 +59,30 @@
     // Drive the enable state
     cfg.vif.driver_cb.enable <= req.enable;
 
+    // Maybe drive the ready line high while the branch happens. This should have no effect, but is
+    // allowed by the interface so we should make sure it happens occasionally. The signal will be
+    // controlled properly by read_insns afterwards.
+    cfg.vif.driver_cb.ready <= $urandom_range(16) == 0;
+
+    // Branch, invalidate and set new seed immediately. When the branch has finished, read num_insns
+    // instructions and wiggle the branch_spec line until everything is done.
     fork
+      begin
         cfg.vif.branch_to(req.branch_addr);
-        if (req.invalidate) invalidate();
-        if (req.new_seed != 0) drive_new_seed(req.new_seed);
-        read_insns(rsp, req.num_insns);
+        cfg.vif.driver_cb.ready <= 1'b0;
+        fork
+          read_insns(rsp, req.num_insns);
+          drive_branch_spec();
+        join_any
+      end
+      if (req.invalidate) invalidate();
+      if (req.new_seed != 0) drive_new_seed(req.new_seed);
     join
+
+    // Kill the drive_branch_spec process and reset branch_spec if necessary.
+    disable fork;
+    cfg.vif.driver_cb.branch_spec <= 0;
+
   endtask
 
   // Drive the cache for a "req transaction".
@@ -89,12 +107,24 @@
     // Drive the enable state
     cfg.vif.driver_cb.enable <= req.enable;
 
+    // Lower req, invalidate and set new seed immediately. After req_low_cycles cycles, start
+    // reading instructions (providing there hasn't been a reset). Wiggle the branch_spec line the
+    // whole time.
     fork
-        if (req_low_cycles > 0) lower_req(req_low_cycles);
-        if (req.invalidate) invalidate();
-        if (req.new_seed != 0) drive_new_seed(req.new_seed);
-    join
-    read_insns(rsp, req.num_insns);
+      begin
+        fork
+          if (req_low_cycles > 0) lower_req(req_low_cycles);
+          if (req.invalidate) invalidate();
+          if (req.new_seed != 0) drive_new_seed(req.new_seed);
+        join
+        if (cfg.vif.rst_n) read_insns(rsp, req.num_insns);
+      end
+      drive_branch_spec();
+    join_any
+
+    // Kill the drive_branch_spec process and reset branch_spec if necessary.
+    disable fork;
+    cfg.vif.driver_cb.branch_spec <= 0;
   endtask
 
   // Read up to num_insns instructions from the cache, stopping early on an error. If there was an
@@ -107,6 +137,16 @@
         rsp.saw_error = 1'b1;
         break;
       end
+      // Return early on reset
+      if (!cfg.vif.rst_n) break;
+    end
+  endtask
+
+  // Randomly drive the branch_spec line one cycle in 64. Never returns.
+  task automatic drive_branch_spec();
+    forever begin
+      cfg.vif.driver_cb.branch_spec <= $urandom_range(64) == 0;
+      @(cfg.vif.driver_cb);
     end
   endtask
 
@@ -114,30 +154,34 @@
   virtual task automatic read_insn();
     int unsigned delay;
 
-    // Maybe (1 time in 10) wait for a valid signal before even considering asserting ready.
-    if ($urandom_range(9) == 0)
-      wait (cfg.vif.driver_cb.valid);
+    // Maybe (1 time in 10) wait for a valid signal before even considering asserting ready. Stops
+    // early on reset.
+    if ($urandom_range(9) == 0) begin
+      cfg.vif.wait_valid();
+      if (!cfg.vif.rst_n)
+        return;
+    end
 
     // Then pick how long we wait before asserting that we are ready.
     //
     // TODO: Make this configurable and weight 0 more heavily.
     cfg.vif.wait_clks($urandom_range(3));
 
-    // Assert ready and then wait until valid
+    // Assert ready and then wait until valid. If we see a reset, we stop early
     cfg.vif.driver_cb.ready <= 1'b1;
     while (1'b1) begin
-      @(cfg.vif.driver_cb);
-      if (cfg.vif.driver_cb.valid)
+      @(cfg.vif.driver_cb or negedge cfg.vif.rst_n);
+      if (cfg.vif.driver_cb.valid || !cfg.vif.rst_n)
         break;
     end
 
     cfg.vif.driver_cb.ready <= 1'b0;
   endtask
 
-  // Lower the req line for the given number of cycles
+  // Lower the req line for the given number of cycles. Returns early on reset
   virtual task automatic lower_req(int unsigned num_cycles);
     cfg.vif.driver_cb.req <= 1'b0;
-    repeat (num_cycles) @(cfg.vif.driver_cb);
+    cfg.vif.wait_clks(num_cycles);
     cfg.vif.driver_cb.req <= 1'b1;
   endtask
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv
index a809689..3bf8a62 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_if.sv
@@ -95,9 +95,28 @@
     driver_cb.invalidate <= 1'b0;
   endtask
 
-  // A task that waits for num_clks posedges on the clk signal
-  task automatic wait_clks(int num_clks);
-    repeat (num_clks) @(driver_cb);
+  // A task that waits for num_clks posedges on the clk signal. Returns early on reset if
+  // stop_on_reset is true.
+  task automatic wait_clks(int num_clks, bit stop_on_reset = 1'b1);
+    if (stop_on_reset && !rst_n) return;
+    if (stop_on_reset) begin
+      fork
+        repeat (num_clks) @(driver_cb);
+        @(negedge rst_n);
+      join_any
+      disable fork;
+    end else begin
+      repeat (num_clks) @(driver_cb);
+    end
+  endtask
+
+  // Wait until the valid signal goes high. Returns early on reset
+  task automatic wait_valid();
+    fork
+      @(negedge rst_n);
+      wait (driver_cb.valid);
+    join_any
+    disable fork;
   endtask
 
   // Reset all the signals from the core to the cache (the other direction is controlled by the
@@ -122,11 +141,9 @@
   // back to a covergroup.
   sequence cancelled_valid;
     @(posedge clk)
-      $rose(valid)
+      (valid & ~ready)
       ##1
-      (valid & ~ready) [*0:$]
-      ##1
-      (branch, cover_cancelled_valid());
+      (~valid, cover_cancelled_valid());
   endsequence : cancelled_valid
   cover property (cancelled_valid);
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_monitor.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_monitor.sv
index 3ba90c4..8aab9ac 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_monitor.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_monitor.sv
@@ -21,13 +21,15 @@
   endfunction
 
   task run_phase(uvm_phase phase);
-    super.run_phase(phase);
-
     if (cfg.en_cov) begin
       fork
         process_cancelled_valid();
       join_none
     end
+
+    super.run_phase(phase);
+
+    disable fork;
   endtask
 
   // collect transactions forever - already forked in dv_base_moditor::run_phase
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_back_line_seq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_back_line_seq.sv
index 8449daa..ab26919 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_back_line_seq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_back_line_seq.sv
@@ -20,9 +20,9 @@
     // "back a bit" from the previous address.
     if (!req_phase) begin
       min_addr = base_addr;
-      max_addr = base_addr + 64;
+      max_addr = top_restricted_addr;
     end else begin
-      min_addr = last_branch - 16;
+      min_addr = last_branch < 16 ? 0 : last_branch - 16;
       max_addr = last_branch;
     end
 
@@ -39,9 +39,9 @@
        // of jumping back when the cache isn't ready yet).
        num_insns <= 5;
 
-       // The cache should always be enabled and never invalidated
+       // The cache should always be enabled and never invalidated (unless must_invalidate is true)
        enable == 1'b1;
-       invalidate == 1'b0;
+       invalidate == must_invalidate;
     )
 
     finish_item(req);
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv
index ad9c061..97420b8 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv
@@ -12,6 +12,10 @@
 
   `uvm_object_new
 
+  // Non-null if this is an item after the first in a "combo" run, which runs several of these
+  // sequences back-to-back. Must be set before pre_start to have any effect.
+  ibex_icache_core_base_seq prev_sequence = null;
+
   // If this is set, any branch target address should be within 64 bytes of base_addr and runs of
   // instructions should have a maximum length of 100.
   bit constrain_branches = 1'b0;
@@ -24,7 +28,11 @@
   // setting.
   bit const_enable = 1'b0;
 
-  // If this bit is set, we will never invalidate the cache (useful for hit ratio tracking)
+  // If this bit is set, the next request will invalidate the cache.
+  bit must_invalidate = 1'b0;
+
+  // If this bit is set, we will never invalidate the cache (useful for hit ratio tracking), except
+  // if must_invalidate is set.
   bit no_invalidate = 1'b0;
 
   // The expected number of items between each new memory seed when the cache is disabled. A new
@@ -40,14 +48,34 @@
   // The expected number of items between enable/disable toggles.
   int unsigned gap_between_toggle_enable = 49;
 
-
   // Number of test items (note that a single test item may contain many instruction fetches)
-  protected rand int count;
-  constraint c_count { count inside {[800:1000]}; }
+  //
+  // The default value is for convenience. This should be constrained by whatever virtual sequence
+  // is using the core sequence.
+  int unsigned num_trans = 1000;
 
   // The base address used when constrain_branches is true.
   protected rand bit[31:0] base_addr;
 
+  // The top of the possible range of addresses used when constrain_branches is true. Set at the
+  // start of body().
+  protected bit [31:0] top_restricted_addr;
+
+  // Distribution for base_addr which adds extra weight to each end of the address space
+  constraint c_base_addr { base_addr dist { [0:15]                      :/ 1,
+                                            [16:32'hfffffff0]           :/ 2,
+                                            [32'hfffffff0:32'hffffffff] :/ 1 }; }
+
+  // Make sure that base_addr is even (otherwise you can fail to generate items if you pick a base
+  // addr of 32'hffffffff with constrained addresses enabled: the only address large enough is
+  // 32'hffffffff, but it doesn't have a zero bottom bit).
+  constraint c_base_addr_alignment {
+    // The branch address is always required to be half-word aligned. We don't bother conditioning
+    // this on the type of transaction because branch_addr is forced to be zero in anything but a
+    // branch transaction.
+    !base_addr[0];
+  }
+
   // If this is set, the next request should be constrained to have trans_type
   // ICacheCoreTransTypeBranch. It's initially 1 because the core must start with a branch to tell
   // the cache where to fetch from in the first place.
@@ -70,6 +98,10 @@
     // can set initial_enable after constructing the sequence, but before running it.
     cache_enabled = initial_enable;
 
+    // If constrain_branches is true, any branch must land in [base_addr:(base_addr + 64)]. We need
+    // to make sure that this doesn't wrap, though.
+    top_restricted_addr = (base_addr <= (32'hffffffff - 64)) ? base_addr + 64 : 32'hffffffff;
+
     run_reqs();
   endtask
 
@@ -88,7 +120,15 @@
 
        // If this is a branch and constrain_branches is true then constrain any branch target.
        (constrain_branches && (req.trans_type == ICacheCoreTransTypeBranch)) ->
-         req.branch_addr inside {[base_addr:(base_addr + 64)]};
+         req.branch_addr inside {[base_addr:top_restricted_addr]};
+
+       // If this is a branch and constrain_branches is false, we don't constrain the branch target,
+       // but we do weight the bottom and top of the address space a bit higher. This is a weaker
+       // version of the weighting that we place on base_addr.
+       (!constrain_branches && (req.trans_type == ICacheCoreTransTypeBranch)) ->
+         req.branch_addr dist { [0:63]                      :/ 1,
+                                [64:32'hffffffbf]           :/ 20,
+                                [32'hffffffc0:32'hffffffff] :/ 1 };
 
        // If this is a branch and constrain_branches is true, we can ask for up to 100 instructions
        // (independent of insns_since_branch)
@@ -107,8 +147,12 @@
        // fetches)
        enable dist { cache_enabled :/ gap_between_toggle_enable, ~cache_enabled :/ 1 };
 
-       // If no_invalidate is set, we shouldn't ever touch the invalidate line.
-       no_invalidate -> invalidate == 1'b0;
+       // If must_invalidate is set, we have to invalidate with this item.
+       must_invalidate -> invalidate == 1'b1;
+
+       // If no_invalidate is set, we shouldn't ever touch the invalidate line, unless
+       // must_invalidate is set (which will only apply once).
+       (no_invalidate && !must_invalidate) -> invalidate == 1'b0;
 
        // Start an invalidation every 1+gap_between_invalidations items.
        invalidate dist { 1'b0 :/ gap_between_invalidations, 1'b1 :/ 1 };
@@ -138,14 +182,17 @@
                           req.num_insns);
   endtask
 
-  // Generate and run count items. Subclasses probably want to configure the parameters above before
+  // Generate and run num_trans items. Subclasses probably want to configure the parameters above before
   // running this.
   protected task run_reqs();
     req = ibex_icache_core_req_item::type_id::create("req");
     rsp = ibex_icache_core_rsp_item::type_id::create("rsp");
 
-    repeat (count - 1) begin
+    repeat (num_trans - 1) begin
       run_req(req, rsp);
+
+      // Always clear the must_invalidate flag after an item (it's a 1-shot thing)
+      must_invalidate = 1'b0;
     end
   endtask
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/README.md b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/README.md
new file mode 100644
index 0000000..7b41268
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/README.md
@@ -0,0 +1,3 @@
+# ICache ECC Agent
+
+This very simple agent can be used to inject single-bit and double-bit errors on the interface of a `prim_ram_1p`, used for checking ECC error detection.
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.core b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.core
new file mode 100644
index 0000000..ea28be9
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.core
@@ -0,0 +1,30 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:ibex_icache_ecc_agent:0.1"
+description: "IBEX_ICACHE DV UVM agent"
+filesets:
+  files_dv:
+    depend:
+      - lowrisc:dv:dv_utils
+      - lowrisc:dv:dv_lib
+      - lowrisc:prim:assert
+    files:
+      - ibex_icache_ecc_if.sv
+      - ibex_icache_ecc_protocol_checker.sv
+      - ibex_icache_ecc_agent_pkg.sv
+      - ibex_icache_ecc_item.sv: {is_include_file: true}
+      - ibex_icache_ecc_bus_item.sv: {is_include_file: true}
+      - ibex_icache_ecc_agent_cfg.sv: {is_include_file: true}
+      - ibex_icache_ecc_driver.sv: {is_include_file: true}
+      - ibex_icache_ecc_monitor.sv: {is_include_file: true}
+      - ibex_icache_ecc_agent.sv: {is_include_file: true}
+      - seq_lib/ibex_icache_ecc_base_seq.sv: {is_include_file: true}
+      - seq_lib/ibex_icache_ecc_seq_list.sv: {is_include_file: true}
+    file_type: systemVerilogSource
+
+targets:
+  default:
+    filesets:
+      - files_dv
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.sv
new file mode 100644
index 0000000..7f490c6
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent.sv
@@ -0,0 +1,23 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class ibex_icache_ecc_agent extends dv_base_agent #(
+  .CFG_T          (ibex_icache_ecc_agent_cfg),
+  .DRIVER_T       (ibex_icache_ecc_driver),
+  .SEQUENCER_T    (ibex_icache_ecc_sequencer),
+  .MONITOR_T      (ibex_icache_ecc_monitor)
+);
+
+  `uvm_component_utils(ibex_icache_ecc_agent)
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+    // get ibex_icache_ecc_if handle
+    if (!uvm_config_db#(virtual ibex_icache_ecc_if)::get(this, "", "vif", cfg.vif)) begin
+      `uvm_fatal(`gfn, "failed to get ibex_icache_ecc_if handle from uvm_config_db")
+    end
+  endfunction
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_cfg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_cfg.sv
new file mode 100644
index 0000000..4db78a1
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_cfg.sv
@@ -0,0 +1,18 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class ibex_icache_ecc_agent_cfg extends dv_base_agent_cfg;
+
+  // Knobs
+  bit          error_prob_pc = 10;
+
+  // interface handle used by driver, monitor & the sequencer, via cfg handle
+  virtual ibex_icache_ecc_if vif;
+
+  `uvm_object_utils_begin(ibex_icache_ecc_agent_cfg)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_pkg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_pkg.sv
new file mode 100644
index 0000000..9591f50
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_agent_pkg.sv
@@ -0,0 +1,30 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+package ibex_icache_ecc_agent_pkg;
+  // dep packages
+  import uvm_pkg::*;
+  import dv_utils_pkg::*;
+  import dv_lib_pkg::*;
+
+  // macro includes
+  `include "uvm_macros.svh"
+  `include "dv_macros.svh"
+
+  typedef class ibex_icache_ecc_item;
+  typedef class ibex_icache_ecc_agent_cfg;
+
+  typedef dv_base_sequencer #(.ITEM_T(ibex_icache_ecc_item),
+                              .CFG_T (ibex_icache_ecc_agent_cfg)) ibex_icache_ecc_sequencer;
+
+  // package sources
+  `include "ibex_icache_ecc_item.sv"
+  `include "ibex_icache_ecc_bus_item.sv"
+  `include "ibex_icache_ecc_agent_cfg.sv"
+  `include "ibex_icache_ecc_driver.sv"
+  `include "ibex_icache_ecc_monitor.sv"
+  `include "ibex_icache_ecc_agent.sv"
+  `include "ibex_icache_ecc_seq_list.sv"
+
+endpackage: ibex_icache_ecc_agent_pkg
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_bus_item.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_bus_item.sv
new file mode 100644
index 0000000..33e11af
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_bus_item.sv
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// An item that represents a transaction seen on the interface.
+//
+// Since the interface is a bit weird here (bound in with forced data), we just report the address
+// and data of each read transaction together with its XOR mask.
+
+class ibex_icache_ecc_bus_item extends uvm_sequence_item;
+
+  logic [31:0]  addr;
+  logic [127:0] bad_bit_mask;
+  logic [127:0] sram_rdata;
+
+  `uvm_object_utils_begin(ibex_icache_ecc_bus_item)
+    `uvm_field_int (bad_bit_mask, UVM_DEFAULT | UVM_HEX)
+    `uvm_field_int (sram_rdata,   UVM_DEFAULT | UVM_HEX)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_driver.sv
new file mode 100644
index 0000000..8e813ca
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_driver.sv
@@ -0,0 +1,32 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class ibex_icache_ecc_driver
+  extends dv_base_driver #(.ITEM_T (ibex_icache_ecc_item),
+                           .CFG_T  (ibex_icache_ecc_agent_cfg));
+
+  `uvm_component_utils(ibex_icache_ecc_driver)
+  `uvm_component_new
+
+  virtual task reset_signals();
+    cfg.vif.reset();
+  endtask
+
+  virtual task get_and_drive();
+    forever begin
+      seq_item_port.get_next_item(req);
+      `uvm_info(`gfn, $sformatf("rcvd item:\n%0s", req.sprint()), UVM_HIGH)
+
+      cfg.vif.wait_reads(req.delay);
+      if (req.two_bits) begin
+        cfg.vif.corrupt_read_1(req.bit_pos0);
+      end else begin
+        cfg.vif.corrupt_read_2(req.bit_pos0, req.bit_pos1);
+      end
+
+      seq_item_port.item_done();
+    end
+  endtask
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_if.sv
new file mode 100644
index 0000000..60e671c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_if.sv
@@ -0,0 +1,96 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// An interface that gets bound into a badbit_ram_1p with .*
+
+interface ibex_icache_ecc_if
+  (input logic          clk_i,
+   input logic          req_i,
+   input logic          write_i,
+   input logic [31:0]   width,
+   input logic [31:0]   addr,
+   input logic [127:0]  wdata,
+   input logic [127:0]  wmask,
+   input logic [127:0]  rdata,
+
+   output logic [127:0] bad_bit_mask);
+
+  // SVA module
+  ibex_icache_ecc_protocol_checker checker_i (.*);
+
+  // The address for the last monitored req transaction
+  logic [31:0]  last_addr = 'x;
+
+  bit rst_n = 1'b1;
+
+  // Start a process that will drive the rst_n line low until the next clock, but return
+  // immediately. If rst_n is already low, does nothing.
+  task automatic reset();
+    if (!rst_n) return;
+    rst_n = 1'b0;
+    fork
+      begin
+        @(posedge clk_i);
+        rst_n = 1'b1;
+      end
+    join_none
+  endtask
+
+  // Wait until a cycle with req_i & ~write_i (signalling the start of a read).
+  //
+  // Returns early on reset.
+  task automatic wait_for_read_start();
+    while (rst_n && !(req_i & ~write_i)) @(posedge clk_i);
+  endtask
+
+  // Wait for num_reads complete reads. Ends on the clock posedge where the last read's data is
+  // returned.
+  //
+  // Returns early on reset.
+  task automatic wait_reads(int unsigned num_reads);
+    repeat (num_reads) begin
+      wait_for_read_start();
+      if (!rst_n) break;
+      @(posedge clk_i);
+    end
+  endtask
+
+  // Set a bit to be toggled on the next read
+  task static corrupt_read_1(int unsigned pos);
+    wait_for_read_start();
+    if (!rst_n) return;
+
+    bad_bit_mask = 128'b1 << (pos % width);
+    @(posedge clk_i);
+    bad_bit_mask = 0;
+  endtask
+
+  // Set two bits to be toggled on the next read
+  task static corrupt_read_2(int unsigned pos0, int unsigned pos1);
+    wait_for_read_start();
+    if (!rst_n) return;
+
+    bad_bit_mask = (128'b1 << (pos0 % width)) | (128'b1 << (pos1 % width));
+    @(posedge clk_i);
+    bad_bit_mask = 0;
+  endtask
+
+  // Wait for a read, setting last_addr accordingly.
+  //
+  // This can be called re-entrantly, despite writing last_addr (it will just write the same value
+  // more than once).
+  //
+  // Returns early on reset.
+  task automatic wait_read();
+    wait_for_read_start();
+    if (!rst_n) return;
+    last_addr = addr;
+    @(posedge clk_i);
+  endtask
+
+  initial begin
+    bad_bit_mask = 0;
+  end
+
+endinterface
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_item.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_item.sv
new file mode 100644
index 0000000..34944c1
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_item.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// A sequence item that represents a bit twiddle.
+//
+// The item will wait <delay> other reads before taking effect. When it does take effect, it toggles
+// 1 or 2 bits in the read value. If <two_bits> is true, the bits at positions <bit_pos0> and
+// <bit_pos1> will be toggled. Otherwise, just the bit at <bit_pos0> will be.
+//
+// <bit_pos0> and <bit_pos1> are interpreted modulo the interface width in the driver, so don't need
+// constraining.
+
+class ibex_icache_ecc_item extends uvm_sequence_item;
+
+  rand bit          two_bits;
+  rand int unsigned bit_pos0;
+  rand int unsigned bit_pos1;
+  rand int unsigned delay;
+
+  `uvm_object_utils_begin(ibex_icache_ecc_item)
+    `uvm_field_int (two_bits, UVM_DEFAULT)
+    `uvm_field_int (bit_pos0, UVM_DEFAULT)
+    `uvm_field_int (bit_pos1, UVM_DEFAULT)
+    `uvm_field_int (delay,    UVM_DEFAULT)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_monitor.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_monitor.sv
new file mode 100644
index 0000000..f2b1054
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_monitor.sv
@@ -0,0 +1,35 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class ibex_icache_ecc_monitor extends dv_base_monitor #(
+    .ITEM_T (ibex_icache_ecc_bus_item),
+    .CFG_T  (ibex_icache_ecc_agent_cfg)
+  );
+  `uvm_component_utils(ibex_icache_ecc_monitor)
+
+  // the base class provides the following handles for use:
+  // ibex_icache_ecc_agent_cfg: cfg
+  // ibex_icache_ecc_agent_cov: cov
+  // uvm_analysis_port #(ibex_icache_ecc_bus_item): analysis_port
+
+  `uvm_component_new
+
+  // collect transactions forever - already forked in dv_base_moditor::run_phase
+  virtual protected task collect_trans(uvm_phase phase);
+    ibex_icache_ecc_bus_item trans;
+    forever begin
+      cfg.vif.wait_read();
+      // If this isn't a reset pulse, we have a read transaction. Report it.
+      if (!cfg.vif.rst_n) begin
+        trans = ibex_icache_ecc_bus_item::type_id::create("trans");
+        trans.addr         = cfg.vif.last_addr;
+        trans.bad_bit_mask = cfg.vif.bad_bit_mask;
+        trans.sram_rdata   = cfg.vif.rdata;
+        analysis_port.write(trans);
+      end
+      @(posedge cfg.vif.clk_i);
+    end
+  endtask
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_protocol_checker.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_protocol_checker.sv
new file mode 100644
index 0000000..9dff146
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/ibex_icache_ecc_protocol_checker.sv
@@ -0,0 +1,37 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// An interface that contains SV assertions to check that the icache <-> SRAM interface is being
+// driven correctly.
+//
+// This should be instantiated inside ibex_icache_ecc_if. The input names are the same as the
+// signals in the interface (no _i suffix), so that this can be instantiated with .*
+
+`include "prim_assert.sv"
+
+interface ibex_icache_ecc_protocol_checker
+  (input logic         clk_i,
+   input logic         req_i,
+   input logic         write_i,
+   input logic [31:0]  width,
+   input logic [31:0]  addr,
+   input logic [127:0] wdata,
+   input logic [127:0] wmask,
+   input logic [127:0] rdata);
+
+  // The req line should never be unknown. Note that we have no reset signal here, so we assert this
+  // is true at all times (fortunately, it seems that the DUT holds req low when in reset).
+  `ASSERT_KNOWN(ReqKnown, req_i, clk_i, 0)
+
+  // If there is a request, the write signal should be known
+  `ASSERT_KNOWN_IF(WriteKnown, write_i, req_i, clk_i, 0)
+
+  // If there is a request with write_i high, the address and write mask should be known, and so
+  // should any data to be written. We don't require the address to be known for reads: reading
+  // rubbish is fine, so long as we ignore it later.
+  `ASSERT_KNOWN_IF(AddrKnown,  addr,          req_i & write_i, clk_i, 0)
+  `ASSERT_KNOWN_IF(WMaskKnown, wmask,         req_i & write_i, clk_i, 0)
+  `ASSERT_KNOWN_IF(WDataKnown, wdata & wmask, req_i & write_i, clk_i, 0)
+
+endinterface
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_base_seq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_base_seq.sv
new file mode 100644
index 0000000..e37c94b
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_base_seq.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 ibex_icache_ecc_base_seq
+  extends dv_base_seq #(.REQ         (ibex_icache_ecc_item),
+                        .CFG_T       (ibex_icache_ecc_agent_cfg),
+                        .SEQUENCER_T (ibex_icache_ecc_sequencer));
+  `uvm_object_utils(ibex_icache_ecc_base_seq)
+
+  `uvm_object_new
+
+  virtual task body();
+    forever begin
+      req = ibex_icache_ecc_item::type_id::create("req");
+      start_item(req);
+      `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
+                                     req.delay dist {0       :/ 1,
+                                                     [1:20]  :/ 1,
+                                                     [21:50] :/ 1};)
+      finish_item(req);
+    end
+  endtask
+
+endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_seq_list.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_seq_list.sv
new file mode 100644
index 0000000..ccc8b96
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_ecc_agent/seq_lib/ibex_icache_ecc_seq_list.sv
@@ -0,0 +1,5 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "ibex_icache_ecc_base_seq.sv"
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_driver.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_driver.sv
index ca5546b..10bca4a 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_driver.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_driver.sv
@@ -30,7 +30,15 @@
   endfunction
 
   virtual task reset_signals();
+    ibex_icache_mem_resp_item resp;
+    bit [32:0]                req;
+
     cfg.vif.reset();
+
+    // Flush mailboxes of pending requests and responses
+    while (req_queue.try_get(req)) ;
+    while (rdata_queue.try_get(resp)) ;
+
   endtask
 
   virtual task get_and_drive();
@@ -40,6 +48,7 @@
       take_requests();
       drive_pmp();
       drive_responses();
+      drive_resets();
     join
   endtask
 
@@ -93,7 +102,11 @@
 
     forever begin
       rdata_queue.get(item);
+      if (!cfg.vif.rst_n) continue;
+
       cfg.vif.wait_clks(item.delay);
+      if (!cfg.vif.rst_n) continue;
+
       cfg.vif.send_response(item.err, item.rdata);
     end
   endtask
@@ -117,6 +130,8 @@
       req_queue.get(data);
       {err, address} = data;
 
+      if (!cfg.vif.rst_n) continue;
+
       // If err is false, this is a request which shouldn't trigger a PMP error.
       if (!err) continue;
 
@@ -131,8 +146,8 @@
         req_queue.peek(data);
         begin
           cfg.vif.pmp_err <= 1'b1;
-          // Wait for an address change or req to de-assert
-          @(negedge cfg.vif.req or cfg.vif.addr);
+          // Wait for a reset, an address change or req to de-assert
+          @(negedge cfg.vif.rst_n or negedge cfg.vif.req or cfg.vif.addr);
         end
       join_any
       disable fork;
@@ -140,4 +155,9 @@
     end
   endtask
 
+  // Watch for resets and call reset_signals as needed
+  task automatic drive_resets();
+    forever @(negedge cfg.vif.rst_n) reset_signals();
+  endtask
+
 endclass
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv
index f3ff1ef..ff2e1d1 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_if.sv
@@ -55,9 +55,14 @@
     driver_cb.gnt     <= 1'b0;
   endtask
 
-  // Wait for num_clks posedges on the clk signal
+  // Wait for num_clks posedges on the clk signal. Returns early on a reset.
   task automatic wait_clks(int num_clks);
-    repeat (num_clks) @(driver_cb);
+    if (!rst_n) return;
+    fork
+      repeat (num_clks) @(driver_cb);
+      @(negedge rst_n);
+    join_any
+    disable fork;
   endtask
 
   // Drive a response with the given rdata and possible error signals for a single cycle
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_model.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_model.sv
index 6d163e7..8196d5d 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_model.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_model.sv
@@ -29,29 +29,24 @@
   // If set, disable memory errors
   protected bit no_mem_errs;
 
-  // The power of two by which to divide the address space to get the error range: see is_error for
-  // details.
-  protected int unsigned error_shift;
-
   function new(string       name="",
                bit          disable_pmp_errs=0,
-               bit          disable_mem_errs=0,
-               int unsigned err_shift=3);
+               bit          disable_mem_errs=0);
     no_pmp_errs = disable_pmp_errs;
     no_mem_errs = disable_mem_errs;
-    error_shift = err_shift;
   endfunction
 
   `uvm_object_utils_begin(ibex_icache_mem_model)
     `uvm_field_int (no_pmp_errs, UVM_DEFAULT)
     `uvm_field_int (no_mem_errs, UVM_DEFAULT)
-    `uvm_field_int (error_shift, UVM_DEFAULT)
   `uvm_object_utils_end
 
   // Return true if reading BusWidth bits from address intersects with the error range given by the
   // current seed. The error range has a length of (1/2^error_shift) times the size of the address
   // space.
-  protected function automatic logic is_error(bit [31:0] seed, logic [31:0] address);
+  protected function automatic logic
+  is_error(bit [31:0] seed, logic [31:0] address, int unsigned error_shift);
+
     logic [31:0] rng_lo, rng_hi, rng_w0, rng_w1;
     rng_lo = seed ^ 32'hdeadbeef;
     rng_w0 = 32'd1 << (32 - error_shift);
@@ -65,18 +60,18 @@
   endfunction
 
   // Return true if reading BusWidth bits from address should give a PMP error
-  function automatic logic is_pmp_error(bit [31:0] seed, logic [31:0] address);
-    return (! no_pmp_errs) && is_error(seed, address ^ 32'h12344321);
+  function automatic logic is_pmp_error(bit [31:0] seed, logic [31:0] addr, int unsigned err_shift);
+    return (! no_pmp_errs) && is_error(seed, addr ^ 32'h12344321, err_shift);
   endfunction
 
   // Return true if reading BusWidth bits from address should give a memory error
-  function automatic logic is_mem_error(bit [31:0] seed, logic [31:0] address);
-    return (! no_mem_errs) && is_error(seed, address ^ 32'hf00dbeef);
+  function automatic logic is_mem_error(bit [31:0] seed, logic [31:0] addr, int unsigned err_shift);
+    return (! no_mem_errs) && is_error(seed, addr ^ 32'hf00dbeef, err_shift);
   endfunction
 
   // Return true if reading BusWidth bits from address should give some sort of error
-  function automatic logic is_either_error(bit [31:0] seed, logic [31:0] address);
-    return is_pmp_error(seed, address) || is_mem_error(seed, address);
+  function automatic logic is_either_error(bit [31:0] seed, logic [31:0] addr, int unsigned err_shift);
+    return is_pmp_error(seed, addr, err_shift) || is_mem_error(seed, addr, err_shift);
   endfunction
 
   // Return BusWidth bits of data from reading at address.
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv
index ad4a3a6..5e60cbf 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv
@@ -6,7 +6,9 @@
 
 class ibex_icache_mem_resp_seq extends ibex_icache_mem_base_seq;
 
-  // Knobs
+  // Non-null if this is an item after the first in a "combo" run, which runs several of these
+  // sequences back-to-back. Must be set before pre_start to have any effect.
+  ibex_icache_mem_resp_seq prev_sequence = null;
 
   protected ibex_icache_mem_model #(.BusWidth (32)) mem_model;
 
@@ -24,30 +26,44 @@
   // To avoid this problem, we keep a queue of pending addresses along with their corresponding
   // seeds. When a grant message comes in, we know that we can look up the correct seed there,
   // discarding results until we find it.
-  protected bit [63:0] pending_grants[$];
-  protected bit [31:0] cur_seed = 0;
+  bit [63:0] pending_grants[$];
+  bit [31:0] cur_seed = 0;
 
   `uvm_object_utils(ibex_icache_mem_resp_seq)
   `uvm_object_new
 
   task pre_start();
     super.pre_start();
-    mem_model = new("mem_model", cfg.disable_pmp_errs, cfg.disable_mem_errs, cfg.mem_err_shift);
+    mem_model = new("mem_model", cfg.disable_pmp_errs, cfg.disable_mem_errs);
+
+    // Take any pending grants and seed from a previous sequence
+    if (prev_sequence) begin
+      pending_grants = prev_sequence.pending_grants;
+      cur_seed = prev_sequence.cur_seed;
+    end
   endtask
 
   task body();
     ibex_icache_mem_req_item  req_item  = new("req_item");
+    ibex_icache_mem_req_item  req_item2 = new("req_item2");
     ibex_icache_mem_resp_item resp_item = new("resp_item");
 
     forever begin
-      // Wait for a transaction request.
-      p_sequencer.request_fifo.get(req_item);
+      // Wait for a transaction request. We use peek, handle the request, and then get (and drop)
+      // the item. This means that if our sequence is killed in the middle of handling it, the item
+      // will still be passed from the monitor to any later sequence.
+      p_sequencer.request_fifo.get_peek_export.peek(req_item);
 
       if (!req_item.is_grant) begin
         take_req(resp_item, req_item);
       end else begin
         take_gnt(resp_item, req_item);
       end
+
+      // Get and drop the request item now that we've dealt with it. As a sanity check, make sure
+      // that the two items match.
+      p_sequencer.request_fifo.get_peek_export.get(req_item2);
+      `DV_CHECK_EQ_FATAL(req_item, req_item2)
     end
   endtask
 
@@ -75,7 +91,7 @@
     resp_item.is_grant = 1'b0;
     resp_item.address  = req_item.address;
     resp_item.rdata    = 'X;
-    resp_item.err = mem_model.is_pmp_error(cur_seed, req_item.address);
+    resp_item.err = mem_model.is_pmp_error(cur_seed, req_item.address, cfg.mem_err_shift);
 
     start_item(resp_item);
     `DV_CHECK_RANDOMIZE_FATAL(resp_item)
@@ -116,7 +132,7 @@
     // Using the seed that we saw for the request, check the memory model for a (non-PMP) error
     // at this address. On success, look up the memory data too.
     resp_item.is_grant = 1'b1;
-    resp_item.err      = mem_model.is_mem_error(gnt_seed, req_item.address);
+    resp_item.err      = mem_model.is_mem_error(gnt_seed, req_item.address, cfg.mem_err_shift);
     resp_item.address  = req_item.address;
     resp_item.rdata    = resp_item.err ? 'X : mem_model.read_data(gnt_seed, req_item.address);
 
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim.core b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim.core
index 1992b80..403f8d1 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim.core
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim.core
@@ -18,8 +18,17 @@
 
 targets:
   sim:
+    parameters:
+      - PRIM_DEFAULT_IMPL=prim_pkg::ImplBadbit
     filesets:
       - files_rtl
       - files_dv
     toplevel: tb
     default_tool: vcs
+
+parameters:
+  PRIM_DEFAULT_IMPL:
+    datatype: str
+    paramtype: vlogdefine
+    description: Primitives implementation to use, e.g. "prim_pkg::ImplGeneric".
+    default: prim_pkg::ImplBadbit
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson
index 19c5995..17742df 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson
@@ -20,10 +20,26 @@
   // Testplan hjson file.
   testplan: "{proj_root}/dv/uvm/icache/data/ibex_icache_testplan.hjson"
 
-
   // Import additional common sim cfg files.
-  import_cfgs: [// Project wide common sim cfg file
-                "{proj_root}/dv/uvm/data/common_sim_cfg.hjson"]
+  import_cfgs: [
+      // Project wide common sim cfg file
+      "{proj_root}/dv/uvm/data/common_sim_cfg.hjson"
+  ]
+
+  build_modes: [
+    {
+      name: default
+      en_build_modes: ["{tool}_icache_ecc"]
+    }
+    {
+      name: vcs_icache_ecc
+      build_opts: ["-gv tb.ICacheECC=1"]
+    }
+    {
+      name: riviera_icache_ecc
+      run_opts: ["-gICacheECC=1"]
+    }
+  ]
 
   // Default iterations for all tests - each test entry can override this.
   reseed: 50
@@ -42,7 +58,7 @@
   tests: [
     {
       name: ibex_icache_sanity
-      uvm_test_seq: ibex_icache_sanity_vseq
+      uvm_test_seq: ibex_icache_base_vseq
     }
 
     {
@@ -74,7 +90,21 @@
     {
       name: ibex_icache_many_errors
       uvm_test_seq: ibex_icache_many_errors_vseq
-      uvm_test: ibex_icache_many_errors_test
+    }
+
+    {
+      name: ibex_icache_ecc
+      uvm_test_seq: ibex_icache_ecc_vseq
+    }
+
+    {
+      name: ibex_icache_stress_all
+      uvm_test_seq: ibex_icache_combo_vseq
+    }
+
+    {
+      name: ibex_icache_stress_all_with_reset
+      uvm_test_seq: ibex_icache_reset_vseq
     }
   ]
 
@@ -87,8 +117,10 @@
               "ibex_icache_caching",
               "ibex_icache_invalidation",
               "ibex_icache_back_line",
-              "ibex_icache_many_errors"]
+              "ibex_icache_many_errors",
+              "ibex_icache_ecc",
+              "ibex_icache_stress_all",
+              "ibex_icache_stress_all_with_reset"]
     }
   ]
 }
-
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/README.md b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/README.md
new file mode 100644
index 0000000..22aebb5
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/README.md
@@ -0,0 +1,11 @@
+Badbit RAM
+==========
+
+This is an SRAM wrapper that allows a testbench to force bit errors onthe read interface.
+
+This works as a dummy technology library.
+Instantiate it by adding setting `PRIM_DEFAULT_IMPL` to prim_pkg::ImplBadbit (see the README.md in the prim directory for details).
+To use it, bind a module or interface into an instance of `prim_badbit_ram_1p` and force the value of `bad_bit_mask`, which is XOR'd with rdata.
+
+To make this easier to use, we don't vary the width of `bad_bit_mask` with the `Width` parameter: it's a constant 128.
+This means that the bound interface doesn't need to be parameterised.
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.core b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.core
new file mode 100644
index 0000000..df81ec5
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.core
@@ -0,0 +1,20 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+name: "lowrisc:prim_badbit:ram_1p"
+description: "Single-port RAM which allows a bound interface to inject errors"
+filesets:
+  files_rtl:
+    depend:
+      - lowrisc:prim_generic:ram_1p
+      - lowrisc:prim:assert
+    files:
+      - prim_badbit_ram_1p.sv
+    file_type: systemVerilogSource
+
+targets:
+  default:
+    filesets:
+      - files_rtl
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.sv
new file mode 100644
index 0000000..f7201f0
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/prim_badbit/prim_badbit_ram_1p.sv
@@ -0,0 +1,83 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Single-port SRAM model which allows a test to corrupt read responses from the underlying memory.
+//
+// To use this, instantiate it then bind in a module or interface that has bad_bit_mask as an
+// output. A nonzero bit in bad_bit_mask will cause the corresponding bit to be flipped in the
+// response.
+
+`include "prim_assert.sv"
+
+module prim_badbit_ram_1p #(
+  parameter  int Width           = 32,   // bit
+  parameter  int Depth           = 128,
+  parameter  int DataBitsPerMask = 1,    // Number of data bits per bit of write mask
+  parameter      MemInitFile     = "",   // VMEM file to initialize the memory with
+
+  localparam int Aw              = $clog2(Depth)  // derived parameter
+) (
+  input  logic             clk_i,
+
+  input  logic             req_i,
+  input  logic             write_i,
+  input  logic [Aw-1:0]    addr_i,
+  input  logic [Width-1:0] wdata_i,
+  input  logic [Width-1:0] wmask_i,
+  output logic [Width-1:0] rdata_o // Read data. Data is returned one cycle after req_i is high.
+);
+
+  logic [Width-1:0] sram_rdata;
+
+  prim_generic_ram_1p #(
+    .Width           (Width),
+    .Depth           (Depth),
+    .DataBitsPerMask (DataBitsPerMask),
+    .MemInitFile     (MemInitFile)
+  ) u_mem (
+    .clk_i   (clk_i),
+
+    .req_i   (req_i),
+    .write_i (write_i),
+    .addr_i  (addr_i),
+    .wdata_i (wdata_i),
+    .wmask_i (wmask_i),
+    .rdata_o (sram_rdata)
+  );
+
+  // This module doesn't work with Verilator (because of the wired-or). Because we define the
+  // "badbit" ram as a technology library, it gets picked up and parsed by any tool using the Ibex
+  // repo. Rather than telling Verilator to ignore the whole lot (which causes NOTFOUNDMODULE
+  // warnings), we just hide the actual guts.
+`ifdef VERILATOR
+  assign rdata_o = sram_rdata;
+`else
+  // Making bad_bit_mask a constant size makes this easier to use (because you don't need to faff
+  // around with parameterised interfaces in your UVM database). Check that rdata_o is actually
+  // controllable. Similarly, we make the address a constant width: make sure that's large enough.
+  `ASSERT_INIT(WidthSmallEnough, Width <= 128)
+  `ASSERT_INIT(AddrSmallEnough, Aw <= 32)
+
+  // Make the Width parameter easily accessible to bound-in modules.
+  logic [31:0] width;
+  assign width = Width;
+
+  // Similarly, extend addr, wdata, wmask and sram_rdata (the un-fiddled value)
+  logic [31:0]  addr;
+  logic [127:0] wdata, wmask, rdata;
+  assign addr  = {{32-Aw{1'b0}}, addr_i};
+  assign wdata = {{128-Width{1'b0}}, wdata_i};
+  assign wmask = {{128-Width{1'b0}}, wmask_i};
+  assign rdata = {{128-Width{1'b0}}, sram_rdata};
+
+  // To inject errors, bind in an interface with bad_bit_mask as an output and assign one of the
+  // bits in bad_bit_mask[Width-1:0] to one. The wired-OR together with an assignment to zero means
+  // this acts like a weak pull-down.
+  wor [127:0] bad_bit_mask;
+  assign bad_bit_mask = 128'b0;
+
+  assign rdata_o = sram_rdata ^ bad_bit_mask;
+`endif // VERILATOR
+
+endmodule
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tb/tb.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tb/tb.sv
index 60a8d30..c4925c4 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tb/tb.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tb/tb.sv
@@ -2,7 +2,7 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 //
-module tb;
+module tb #(parameter bit ICacheECC = 1'b0);
   // dep packages
   import uvm_pkg::*;
   import dv_utils_pkg::*;
@@ -22,7 +22,9 @@
   ibex_icache_mem_if  mem_if  (.clk(clk), .rst_n(rst_n));
 
   // dut
-  ibex_icache dut (
+  ibex_icache #(
+    .ICacheECC (ICacheECC)
+  ) dut (
     .clk_i           (clk),
     .rst_ni          (rst_n),
 
@@ -51,12 +53,45 @@
     .instr_rvalid_i  (mem_if.rvalid)
   );
 
+  // If the ICacheECC parameter is set in the DUT, generate another interface for each tag ram and
+  // each data ram, binding them into the RAMs themselves. ECC tests can use these to insert errors
+  // into memory lookups.
+  generate if (dut.ICacheECC) begin : gen_ecc
+    for (genvar w = 0; w < dut.NumWays; w++) begin : gen_ecc_ifs
+      bind dut.gen_rams[w].tag_bank.gen_badbit.u_impl_badbit  ibex_icache_ecc_if tag_bank_if (.*);
+      bind dut.gen_rams[w].data_bank.gen_badbit.u_impl_badbit ibex_icache_ecc_if data_bank_if (.*);
+
+      initial begin
+        uvm_config_db#(virtual ibex_icache_ecc_if)::
+          set(null,
+              $sformatf("*.env.ecc_tag_agents[%0d]*", w),
+              "vif",
+              dut.gen_rams[w].tag_bank.gen_badbit.u_impl_badbit.tag_bank_if);
+
+        uvm_config_db#(virtual ibex_icache_ecc_if)::
+          set(null,
+              $sformatf("*.env.ecc_data_agents[%0d]*", w),
+              "vif",
+              dut.gen_rams[w].data_bank.gen_badbit.u_impl_badbit.data_bank_if);
+      end
+    end
+  end
+  endgenerate
+
   initial begin
     // drive clk and rst_n from clk_if
     clk_rst_if.set_active();
+
+    // Store virtual interfaces into the UVM config database. ECC interfaces are done separately
+    // above because otherwise you have to repeat the (verbose) generate loop.
     uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if);
     uvm_config_db#(virtual ibex_icache_core_if)::set(null, "*.env.core_agent*", "vif", core_if);
     uvm_config_db#(virtual ibex_icache_mem_if)::set(null, "*.env.mem_agent*", "vif", mem_if);
+
+    // Record the number of (ECC) ways in the config database. The top-level environment's config
+    // will use this to decide how many agents to create.
+    uvm_config_db#(int unsigned)::set(null, "*", "num_ecc_ways", dut.ICacheECC ? dut.NumWays : 0);
+
     $timeformat(-12, 0, " ps", 12);
     run_test();
   end
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_base_test.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_base_test.sv
index 7939614..ecce213 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_base_test.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_base_test.sv
@@ -15,8 +15,19 @@
   // ibex_icache_env:     env
 
   virtual function void build_phase(uvm_phase phase);
+    int unsigned num_ecc_ways;
+    if (!uvm_config_db#(int unsigned)::get(this, "", "num_ecc_ways", num_ecc_ways)) begin
+      `uvm_fatal(`gfn, "failed to get num_ecc_ways from uvm_config_db")
+    end
+
     super.build_phase(phase);
+
     cfg.has_ral = 1'b0;
+
+    // Create config objects for each of the ECC agents. We can't do that in the config object
+    // itself (because that's not a component, so doesn't have access to the uvm_config_db).
+    cfg.create_ecc_agent_cfgs(num_ecc_ways);
+
   endfunction
 
   // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_many_errors_test.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_many_errors_test.sv
deleted file mode 100644
index 1c3bdc6..0000000
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_many_errors_test.sv
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-class ibex_icache_many_errors_test extends ibex_icache_base_test;
-
-  `uvm_component_utils(ibex_icache_many_errors_test)
-  `uvm_component_new
-
-  virtual function void build_phase(uvm_phase phase);
-    super.build_phase(phase);
-
-    // Increase the error rate (to roughly 50%)
-    cfg.mem_agent_cfg.mem_err_shift = 1;
-  endfunction
-
-endclass : ibex_icache_many_errors_test
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test.core b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test.core
index ec7a617..b580205 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test.core
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test.core
@@ -12,7 +12,6 @@
       - ibex_icache_test_pkg.sv
       - ibex_icache_base_test.sv: {is_include_file: true}
       - ibex_icache_oldval_test.sv: {is_include_file: true}
-      - ibex_icache_many_errors_test.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test_pkg.sv b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test_pkg.sv
index f76d0b7..4d62127 100644
--- a/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/dv/uvm/icache/dv/tests/ibex_icache_test_pkg.sv
@@ -19,6 +19,5 @@
   // package sources
   `include "ibex_icache_base_test.sv"
   `include "ibex_icache_oldval_test.sv"
-  `include "ibex_icache_many_errors_test.sv"
 
 endpackage
diff --git a/hw/vendor/lowrisc_ibex/ibex_configs.yaml b/hw/vendor/lowrisc_ibex/ibex_configs.yaml
index 9d7f64d..6929140 100644
--- a/hw/vendor/lowrisc_ibex/ibex_configs.yaml
+++ b/hw/vendor/lowrisc_ibex/ibex_configs.yaml
@@ -24,7 +24,19 @@
 
 # Three-stage pipeline with additional branch traget ALU and 1 cycle multiplier
 # (2 cycles for mulh) so mul does not stall (mulh stall 1 cycles). This is the
-# maximum performance configuration. PMP is enabled with 16 regions.
+# maximum performance configuration.
+experimental-maxperf:
+  RV32E                    : 0
+  RV32M                    : 1
+  RV32B                    : 0
+  BranchTargetALU          : 1
+  WritebackStage           : 1
+  MultiplierImplementation : "single-cycle"
+  PMPEnable                : 0
+  PMPGranularity           : 0
+  PMPNumRegions            : 4
+
+# experimental-maxperf config above plus PMP enabled with 16 regions.
 experimental-maxperf-pmp:
   RV32E                    : 0
   RV32M                    : 1
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
index de0e59f..0f59328 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
@@ -591,9 +591,9 @@
     `define _N(stg) (16 >> stg)
 
     // bext / bdep control bit generation
-    for (genvar stg=0; stg<5; stg++) begin
+    for (genvar stg=0; stg<5; stg++) begin : gen_stage
       // number of segs: 2** stg
-      for (genvar seg=0; seg<2**stg; seg++) begin
+      for (genvar seg=0; seg<2**stg; seg++) begin : gen_segment
 
         assign lrotc_stage[stg][2*`_N(stg)*(seg+1)-1 : 2*`_N(stg)*seg] =
             {{`_N(stg){1'b0}},{`_N(stg){1'b1}}} <<
@@ -611,7 +611,7 @@
     end
     `undef _N
 
-    for (genvar stg=0; stg<5; stg++) begin
+    for (genvar stg=0; stg<5; stg++) begin : gen_zbe_mask
       assign butterfly_zbe_mask_not[stg] =
           ~(butterfly_zbe_mask_l[stg] | butterfly_zbe_mask_r[stg]);
     end
@@ -708,17 +708,17 @@
     // Shuffle / Unshuffle //
     /////////////////////////
 
-    localparam logic [31:0] SHUFFLE_MASK_L [0:3] =
-        '{32'h00ff_0000, 32'h0f00_0f00, 32'h3030_3030, 32'h4444_4444};
-    localparam logic [31:0] SHUFFLE_MASK_R [0:3] =
-        '{32'h0000_ff00, 32'h00f0_00f0, 32'h0c0c_0c0c, 32'h2222_2222};
+    localparam logic [31:0] SHUFFLE_MASK_L [4] =
+        '{32'h4444_4444, 32'h3030_3030, 32'h0f00_0f00, 32'h00ff_0000};
+    localparam logic [31:0] SHUFFLE_MASK_R [4] =
+        '{32'h2222_2222, 32'h0c0c_0c0c, 32'h00f0_00f0, 32'h0000_ff00};
 
-    localparam logic [31:0] FLIP_MASK_L [0:3] =
-        '{32'h2200_1100, 32'h0044_0000, 32'h4411_0000, 32'h1100_0000};
-    localparam logic [31:0] FLIP_MASK_R [0:3] =
-        '{32'h0088_0044, 32'h0000_2200, 32'h0000_8822, 32'h0000_0088};
+    localparam logic [31:0] FLIP_MASK_L [4] =
+        '{32'h1100_0000, 32'h4411_0000, 32'h0044_0000, 32'h2200_1100};
+    localparam logic [31:0] FLIP_MASK_R [4] =
+        '{32'h0000_0088, 32'h0000_8822, 32'h0000_2200, 32'h0088_0044};
 
-    logic [31:0] SHUFFLE_MASK_NOT [0:3];
+    logic [31:0] SHUFFLE_MASK_NOT [4];
     for(genvar i = 0; i < 4; i++) begin : gen_shuffle_mask_not
       assign SHUFFLE_MASK_NOT[i] = ~(SHUFFLE_MASK_L[i] | SHUFFLE_MASK_R[i]);
     end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index ccb6bdc..2bbc373 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -15,7 +15,6 @@
     input  logic                  clk_i,
     input  logic                  rst_ni,
 
-    input  logic                  fetch_enable_i,        // start decoding
     output logic                  ctrl_busy_o,           // core is busy processing instrs
 
     // decoder related signals
@@ -396,14 +395,11 @@
 
     unique case (ctrl_fsm_cs)
       RESET: begin
-        // just wait for fetch_enable
         instr_req_o   = 1'b0;
         pc_mux_o      = PC_BOOT;
         pc_set_o      = 1'b1;
         pc_set_spec_o = 1'b1;
-        if (fetch_enable_i) begin
-          ctrl_fsm_ns = BOOT_SET;
-        end
+        ctrl_fsm_ns   = BOOT_SET;
       end
 
       BOOT_SET: begin
@@ -719,6 +715,7 @@
               exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
               csr_mtval_o = lsu_addr_last_i;
             end
+            default: ;
           endcase
         end else begin
           // special instructions and pipeline flushes
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 2303813..6fd1b40 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -353,8 +353,17 @@
       core_busy_q <= core_busy_d;
     end
   end
+  // capture fetch_enable_i in fetch_enable_q, once for ever
+  logic fetch_enable_q;
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      fetch_enable_q <= 1'b0;
+    end else if (fetch_enable_i) begin
+      fetch_enable_q <= 1'b1;
+    end
+  end
 
-  assign clock_en     = core_busy_q | debug_req_i | irq_pending | irq_nm_i;
+  assign clock_en     = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i);
   assign core_sleep_o = ~clock_en;
 
   // main clock gate of the core
@@ -460,7 +469,6 @@
       .rst_ni                       ( rst_ni                   ),
 
       // Processor Enable
-      .fetch_enable_i               ( fetch_enable_i           ),
       .ctrl_busy_o                  ( ctrl_busy                ),
       .illegal_insn_o               ( illegal_insn_id          ),
 
@@ -705,7 +713,7 @@
   ibex_wb_stage #(
     .WritebackStage ( WritebackStage )
   ) wb_stage_i (
-    .clk_i                      ( clk_i                    ),
+    .clk_i                      ( clk                      ),
     .rst_ni                     ( rst_ni                   ),
     .en_wb_i                    ( en_wb                    ),
     .instr_type_wb_i            ( instr_type_wb            ),
@@ -740,7 +748,7 @@
       .DataWidth         (32),
       .DummyInstructions (DummyInstructions)
   ) register_file_i (
-      .clk_i            ( clk_i          ),
+      .clk_i            ( clk            ),
       .rst_ni           ( rst_ni         ),
 
       .test_en_i        ( test_en_i      ),
@@ -770,7 +778,7 @@
   assign outstanding_load_id  = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & ~id_stage_i.lsu_we;
   assign outstanding_store_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec &  id_stage_i.lsu_we;
 
-  if (WritebackStage) begin
+  if (WritebackStage) begin : gen_wb_stage
     // When the writeback stage is present a load/store could be in ID or WB. A Load/store in ID can
     // see a response before it moves to WB when it is unaligned otherwise we should only see
     // a response when load/store is in WB.
@@ -782,7 +790,7 @@
 
     // When writing back the result of a load, the load must have made it to writeback
     `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_wb, clk_i, !rst_ni)
-  end else begin
+  end else begin : gen_no_wb_stage
     // Without writeback stage only look into whether load or store is in ID to determine if
     // a response is expected.
     assign outstanding_load_resp  = outstanding_load_id;
@@ -967,33 +975,33 @@
   // second stage. RVFI outputs are all straight from flops. So 2 stage pipeline requires a single
   // set of flops (instr_info => RVFI_out), 3 stage pipeline requires two sets (instr_info => wb
   // => RVFI_out)
-  localparam RVFI_STAGES = WritebackStage ? 2 : 1;
+  localparam int RVFI_STAGES = WritebackStage ? 2 : 1;
 
-  logic        rvfi_stage_valid     [RVFI_STAGES-1:0];
-  logic [63:0] rvfi_stage_order     [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_insn      [RVFI_STAGES-1:0];
-  logic        rvfi_stage_trap      [RVFI_STAGES-1:0];
-  logic        rvfi_stage_halt      [RVFI_STAGES-1:0];
-  logic        rvfi_stage_intr      [RVFI_STAGES-1:0];
-  logic [ 1:0] rvfi_stage_mode      [RVFI_STAGES-1:0];
-  logic [ 1:0] rvfi_stage_ixl       [RVFI_STAGES-1:0];
-  logic [ 4:0] rvfi_stage_rs1_addr  [RVFI_STAGES-1:0];
-  logic [ 4:0] rvfi_stage_rs2_addr  [RVFI_STAGES-1:0];
-  logic [ 4:0] rvfi_stage_rs3_addr  [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_rs1_rdata [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_rs2_rdata [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_rs3_rdata [RVFI_STAGES-1:0];
-  logic [ 4:0] rvfi_stage_rd_addr   [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_rd_wdata  [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_pc_rdata  [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_pc_wdata  [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_mem_addr  [RVFI_STAGES-1:0];
-  logic [ 3:0] rvfi_stage_mem_rmask [RVFI_STAGES-1:0];
-  logic [ 3:0] rvfi_stage_mem_wmask [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES-1:0];
-  logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES-1:0];
+  logic        rvfi_stage_valid     [RVFI_STAGES];
+  logic [63:0] rvfi_stage_order     [RVFI_STAGES];
+  logic [31:0] rvfi_stage_insn      [RVFI_STAGES];
+  logic        rvfi_stage_trap      [RVFI_STAGES];
+  logic        rvfi_stage_halt      [RVFI_STAGES];
+  logic        rvfi_stage_intr      [RVFI_STAGES];
+  logic [ 1:0] rvfi_stage_mode      [RVFI_STAGES];
+  logic [ 1:0] rvfi_stage_ixl       [RVFI_STAGES];
+  logic [ 4:0] rvfi_stage_rs1_addr  [RVFI_STAGES];
+  logic [ 4:0] rvfi_stage_rs2_addr  [RVFI_STAGES];
+  logic [ 4:0] rvfi_stage_rs3_addr  [RVFI_STAGES];
+  logic [31:0] rvfi_stage_rs1_rdata [RVFI_STAGES];
+  logic [31:0] rvfi_stage_rs2_rdata [RVFI_STAGES];
+  logic [31:0] rvfi_stage_rs3_rdata [RVFI_STAGES];
+  logic [ 4:0] rvfi_stage_rd_addr   [RVFI_STAGES];
+  logic [31:0] rvfi_stage_rd_wdata  [RVFI_STAGES];
+  logic [31:0] rvfi_stage_pc_rdata  [RVFI_STAGES];
+  logic [31:0] rvfi_stage_pc_wdata  [RVFI_STAGES];
+  logic [31:0] rvfi_stage_mem_addr  [RVFI_STAGES];
+  logic [ 3:0] rvfi_stage_mem_rmask [RVFI_STAGES];
+  logic [ 3:0] rvfi_stage_mem_wmask [RVFI_STAGES];
+  logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES];
+  logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES];
 
-  logic        rvfi_stage_valid_d   [RVFI_STAGES-1:0];
+  logic        rvfi_stage_valid_d   [RVFI_STAGES];
 
   assign rvfi_valid     = rvfi_stage_valid    [RVFI_STAGES-1];
   assign rvfi_order     = rvfi_stage_order    [RVFI_STAGES-1];
@@ -1019,7 +1027,7 @@
   assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1];
   assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1];
 
-  if (WritebackStage) begin
+  if (WritebackStage) begin : gen_rvfi_wb_stage
     logic unused_instr_new_id;
 
     assign unused_instr_new_id = instr_new_id;
@@ -1046,7 +1054,7 @@
         rvfi_instr_new_wb_q <= instr_id_done;
       end
     end
-  end else begin
+  end else begin : gen_rvfi_no_wb_stage
     // Without writeback stage first RVFI stage is output stage so simply valid the cycle after
     // instruction leaves ID/EX (and so has retired)
     assign rvfi_stage_valid_d[0] = instr_id_done & ~dummy_instr_id;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
index 2c0722f..465b931 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
@@ -44,8 +44,8 @@
 
 `ifdef FPGA_XILINX
   // Set DSP pragma for supported xilinx FPGAs
-  localparam dsp_pragma = CounterWidth < 49  ? "yes" : "no";
-  (* use_dsp = dsp_pragma *) logic [CounterWidth-1:0] counter_q;
+  localparam int DspPragma = CounterWidth < 49  ? "yes" : "no";
+  (* use_dsp = DspPragma *) logic [CounterWidth-1:0] counter_q;
 
   // DSP output register requires synchronous reset.
   `define COUNTER_FLOP_RST posedge clk_i
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index b4df9bd..0b6f934 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -137,12 +137,12 @@
     priv_lvl_e mpp;
     logic      mprv;
     logic      tw;
-  } Status_t;
+  } status_t;
 
   typedef struct packed {
     logic      mpie;
     priv_lvl_e mpp;
-  } StatusStk_t;
+  } status_stk_t;
 
   typedef struct packed {
       x_debug_ver_e xdebugver;
@@ -160,7 +160,7 @@
       logic         nmip;
       logic         step;
       priv_lvl_e    prv;
-  } Dcsr_t;
+  } dcsr_t;
 
   // CPU control register fields
   typedef struct packed {
@@ -169,14 +169,14 @@
     logic        dummy_instr_en;
     logic        data_ind_timing;
     logic        icache_enable;
-  } CpuCtrl_t;
+  } cpu_ctrl_t;
 
   // Interrupt and exception control signals
   logic [31:0] exception_pc;
 
   // CSRs
   priv_lvl_e   priv_lvl_q, priv_lvl_d;
-  Status_t     mstatus_q, mstatus_d;
+  status_t     mstatus_q, mstatus_d;
   irqs_t       mie_q, mie_d;
   logic [31:0] mscratch_q, mscratch_d;
   logic [31:0] mepc_q, mepc_d;
@@ -184,14 +184,14 @@
   logic [31:0] mtval_q, mtval_d;
   logic [31:0] mtvec_q, mtvec_d;
   irqs_t       mip;
-  Dcsr_t       dcsr_q, dcsr_d;
+  dcsr_t       dcsr_q, dcsr_d;
   logic [31:0] depc_q, depc_d;
   logic [31:0] dscratch0_q, dscratch0_d;
   logic [31:0] dscratch1_q, dscratch1_d;
 
   // CSRs for recoverable NMIs
   // NOTE: these CSRS are nonstandard, see https://github.com/riscv/riscv-isa-manual/issues/261
-  StatusStk_t  mstack_q, mstack_d;
+  status_stk_t mstack_q, mstack_d;
   logic [31:0] mstack_epc_q, mstack_epc_d;
   logic  [5:0] mstack_cause_q, mstack_cause_d;
 
@@ -221,7 +221,7 @@
   logic [31:0] tmatch_value_rdata;
 
   // CPU control bits
-  CpuCtrl_t    cpuctrl_rdata, cpuctrl_wdata;
+  cpu_ctrl_t   cpuctrl_rdata, cpuctrl_wdata;
 
   // CSR update logic
   logic [31:0] csr_wdata_int;
@@ -685,7 +685,7 @@
       mepc_q         <= '0;
       mcause_q       <= '0;
       mtval_q        <= '0;
-      mtvec_q        <= 32'b01;
+      mtvec_q        <= 32'h0000_0001;
       dcsr_q         <= '{
           xdebugver: XDEBUGVER_STD,
           cause:     DBG_CAUSE_NONE, // 3'h0
@@ -1054,7 +1054,7 @@
   // CPU control fields
   assign cpuctrl_rdata.unused_ctrl = '0;
   // Cast register write data
-  assign cpuctrl_wdata = CpuCtrl_t'(csr_wdata_int);
+  assign cpuctrl_wdata = cpu_ctrl_t'(csr_wdata_int);
 
   // Generate fixed time execution bit
   if (DataIndTiming) begin : gen_dit
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
index 96acd3d..b895275 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
@@ -3,11 +3,6 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-// Source/Destination register instruction index
-`define REG_S1 19:15
-`define REG_S2 24:20
-`define REG_S3 31:27
-`define REG_D  11:07
 
 /**
  * Instruction decoder
@@ -111,6 +106,11 @@
 
   logic [31:0] instr;
   logic [31:0] instr_alu;
+  // Source/Destination register instruction index
+  logic [4:0] instr_rs1;
+  logic [4:0] instr_rs2;
+  logic [4:0] instr_rs3;
+  logic [4:0] instr_rd;
 
   logic        use_rs3;
 
@@ -137,14 +137,18 @@
   assign imm_j_type_o = { {12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
 
   // immediate for CSR manipulation (zero extended)
-  assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
+  assign zimm_rs1_type_o = { 27'b0, instr_rs1 }; // rs1
 
   // source registers
-  assign rf_raddr_a_o = use_rs3 ? instr[`REG_S3] : instr[`REG_S1]; // rs3 / rs1
-  assign rf_raddr_b_o = instr[`REG_S2]; // rs2
+  assign instr_rs1 = instr[19:15];
+  assign instr_rs2 = instr[24:20];
+  assign instr_rs3 = instr[31:27];
+  assign rf_raddr_a_o = use_rs3 ? instr_rs3 : instr_rs1; // rs3 / rs1
+  assign rf_raddr_b_o = instr_rs2; // rs2
 
   // destination register
-  assign rf_waddr_o   = instr[`REG_D]; // rd
+  assign instr_rd = instr[11:7];
+  assign rf_waddr_o   = instr_rd; // rd
 
   ////////////////////
   // Register check //
@@ -166,7 +170,7 @@
     // CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
     // CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
     if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
-        instr[`REG_S1] == '0) begin
+        instr_rs1 == '0) begin
       csr_op_o = CSR_OP_READ;
     end
   end
@@ -555,7 +559,7 @@
           endcase
 
           // rs1 and rd must be 0
-          if (instr[`REG_S1] != 5'b0 || instr[`REG_D] != 5'b0) begin
+          if (instr_rs1 != 5'b0 || instr_rd != 5'b0) begin
             illegal_insn = 1'b1;
           end
         end else begin
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
index f65725b..e606a41 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
@@ -562,9 +562,8 @@
                                  (fill_cache_q[fb] & fill_busy_q[fb] &
                                   icache_enable_i & ~icache_inval_i);
     // Record whether the request hit in the cache
-    assign fill_hit_ic1[fb]    = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1;
-    assign fill_hit_d[fb]      = (fill_hit_ic1[fb] & ~ecc_err_ic1) |
-                                 (fill_hit_q[fb] & fill_busy_q[fb]);
+    assign fill_hit_ic1[fb]    = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1 & ~ecc_err_ic1;
+    assign fill_hit_d[fb]      = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]);
 
     ///////////////////////////////////////////
     // Fill buffer external request tracking //
@@ -585,7 +584,7 @@
     // External requests are completed when the counter is filled or when the request is cancelled
     assign fill_ext_done[fb]   = (fill_ext_cnt_q[fb][LINE_BEATS_W] |
                                   // external requests are considered complete if the request hit
-                                  (fill_hit_ic1[fb] & ~ecc_err_ic1) | fill_hit_q[fb] |
+                                  fill_hit_ic1[fb] | fill_hit_q[fb] |
                                   // external requests will stop once any PMP error is received
                                   fill_err_q[fb][fill_ext_off[fb]] |
                                   // cancel if the line is stale and won't be cached
@@ -618,7 +617,7 @@
                                   (fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]);
 
     // Calculate when a beat of data is output. Any ECC error squashes the output that cycle.
-    assign fill_out_grant[fb]  = fill_out_arb[fb] & output_ready & ~ecc_err_ic1;
+    assign fill_out_grant[fb]  = fill_out_arb[fb] & output_ready;
 
     // Count the beats of data output to the IF stage
     assign fill_out_cnt_d[fb]  = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[LINE_W-1:BUS_W]} :
@@ -742,8 +741,8 @@
 
     // Data either comes from the cache or the bus. If there was an ECC error, we must take
     // the incoming bus data since the cache hit data is corrupted.
-    assign fill_data_d[fb] = (fill_hit_ic1[fb] & ~ecc_err_ic1) ? hit_data_ic1[LineSize-1:0] :
-                                                                 {LINE_BEATS{instr_rdata_i}};
+    assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1[LineSize-1:0] :
+                                                {LINE_BEATS{instr_rdata_i}};
 
     for (genvar b = 0; b < LINE_BEATS; b++) begin : gen_data_buf
       // Error tracking (per beat)
@@ -865,8 +864,7 @@
   // Output data is valid (from any of the three possible sources). Note that fill_out_arb
   // must be used here rather than fill_out_req because data can become valid out of order
   // (e.g. cache hit data can become available ahead of an older outstanding miss).
-  // Any ECC error suppresses the output that cycle.
-  assign data_valid = |fill_out_arb & ~ecc_err_ic1;
+  assign data_valid = |fill_out_arb;
 
   // Skid buffer data
   assign skid_data_d = output_data[31:16];
@@ -1017,4 +1015,8 @@
   `ASSERT_INIT(ecc_tag_param_legal, (TAG_SIZE <= 27))
   `ASSERT_INIT(ecc_data_param_legal, (LineSize <= 121))
 
+  // Lookups in the tag ram should always give a known result
+  `ASSERT_KNOWN(TagHitKnown,     lookup_valid_ic1 & tag_hit_ic1)
+  `ASSERT_KNOWN(TagInvalidKnown, lookup_valid_ic1 & tag_invalid_ic1)
+
 endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index f976b77..ee63142 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -28,7 +28,6 @@
     input  logic                      clk_i,
     input  logic                      rst_ni,
 
-    input  logic                      fetch_enable_i,
     output logic                      ctrl_busy_o,
     output logic                      illegal_insn_o,
 
@@ -526,7 +525,6 @@
       .clk_i                          ( clk_i                   ),
       .rst_ni                         ( rst_ni                  ),
 
-      .fetch_enable_i                 ( fetch_enable_i          ),
       .ctrl_busy_o                    ( ctrl_busy_o             ),
 
       // decoder related signals
@@ -816,12 +814,6 @@
 
   assign instr_done = ~stall_id & ~flush_id & instr_executing;
 
-  if (WritebackStage) begin
-    assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i;
-  end else begin
-    assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i;
-  end
-
   // Signal instruction in ID is in it's first cycle. It can remain in its
   // first cycle if it is stalled.
   assign instr_first_cycle      = instr_valid_i & (id_fsm_q == FIRST_CYCLE);
@@ -841,6 +833,8 @@
 
     logic instr_kill;
 
+    assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i;
+
     // Is a memory access ongoing that isn't finishing this cycle
     assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) &
                                        ~lsu_resp_valid_i;
@@ -920,7 +914,9 @@
     assign stall_wb = en_wb_o & ~ready_wb_i;
 
     assign perf_dside_wait_o = instr_valid_i & ~instr_kill & (outstanding_memory_access | stall_ld_hz);
-  end else begin
+  end else begin : gen_no_stall_mem
+
+    assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i;
 
     assign data_req_allowed = instr_first_cycle;
 
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 715a97c..4dd429d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -42,7 +42,7 @@
   localparam int unsigned NUM_WORDS  = 2**ADDR_WIDTH;
 
   logic [NUM_WORDS-1:0][DataWidth-1:0] rf_reg;
-  logic [NUM_WORDS-1:1][DataWidth-1:0] rf_reg_tmp;
+  logic [NUM_WORDS-1:1][DataWidth-1:0] rf_reg_q;
   logic [NUM_WORDS-1:1]                we_a_dec;
 
   always_comb begin : we_a_decoder
@@ -51,13 +51,13 @@
     end
   end
 
-  // loop from 1 to NUM_WORDS-1 as R0 is nil
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      rf_reg_tmp <= '{default:'0};
-    end else begin
-      for (int r = 1; r < NUM_WORDS; r++) begin
-        if (we_a_dec[r]) rf_reg_tmp[r] <= wdata_a_i;
+  // No flops for R0 as it's hard-wired to 0
+  for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
+    always_ff @(posedge clk_i or negedge rst_ni) begin
+      if (!rst_ni) begin
+        rf_reg_q[i] <= '0;
+      end else if(we_a_dec[i]) begin
+        rf_reg_q[i] <= wdata_a_i;
       end
     end
   end
@@ -66,21 +66,21 @@
   // real instructions.
   if (DummyInstructions) begin : g_dummy_r0
     logic        we_r0_dummy;
-    logic [31:0] rf_r0;
+    logic [31:0] rf_r0_q;
 
     // Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions)
     assign we_r0_dummy = we_a_i & dummy_instr_id_i;
 
     always_ff @(posedge clk_i or negedge rst_ni) begin
       if (!rst_ni) begin
-        rf_r0 <= '0;
+        rf_r0_q <= '0;
       end else if (we_r0_dummy) begin
-        rf_r0 <= wdata_a_i;
+        rf_r0_q <= wdata_a_i;
       end
     end
 
     // Output the dummy data for dummy instructions, otherwise R0 reads as zero
-    assign rf_reg[0] = dummy_instr_id_i ? rf_r0 : '0;
+    assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0;
 
   end else begin : g_normal_r0
     logic unused_dummy_instr_id;
@@ -90,7 +90,7 @@
     assign rf_reg[0] = '0;
   end
 
-  assign rf_reg[NUM_WORDS-1:1] = rf_reg_tmp[NUM_WORDS-1:1];
+  assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1];
 
   assign rdata_a_o = rf_reg[raddr_a_i];
   assign rdata_b_o = rf_reg[raddr_b_i];
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 5b99761..7cc4446 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -109,11 +109,11 @@
 
   // 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
-    for (int k = 1; k < NUM_WORDS; k++) begin : latch_wdata_word_iter
-      if (mem_clocks[k]) begin
-        mem[k] = wdata_a_q;
+  // The process is synchronized with the clocks mem_clocks[i], i = 1, ..., NUM_WORDS-1.
+  for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_latches
+    always_latch begin
+      if (mem_clocks[i]) begin
+        mem[i] = wdata_a_q;
       end
     end
   end
diff --git a/hw/vendor/lowrisc_ibex/syn/lec_sv2v.do b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.do
new file mode 100644
index 0000000..7dba52c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.do
@@ -0,0 +1,55 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// LEC dofile for script lec_sv2v.sh.  A similar script is used in 
+// OpenTitan, any updates or fixes here may need to be reflected in the 
+// OpenTitan script as well:
+// https://github.com/lowRISC/opentitan/blob/master/hw/formal/lec_sv2v.do
+
+//-------------------------------------------------------------------------
+// read in golden (SystemVerilog) and revised (Verilog)
+//-------------------------------------------------------------------------
+
+// map all multi-dimensional ports (including structs) onto 1-dim. ports
+set naming rule -mdportflatten
+
+read design -golden -sv09 -f flist_gold -rootonly -root $LEC_TOP
+read design -revised -sys -f flist_rev  -rootonly -root $LEC_TOP
+// TODO: instead of using switch -sys (for old SystemVerilog,
+// older than sv2009) we should use -ve (for Verilog). But
+// this currently doesn't work because sv2v doesn't translate
+// .* port connections. Is that an sv2v bug?
+
+//-------------------------------------------------------------------------
+// pre-LEC reports
+//-------------------------------------------------------------------------
+report rule check -verbose
+report design data
+report black box
+report module
+
+//-------------------------------------------------------------------------
+// compare
+//-------------------------------------------------------------------------
+set system mode lec
+set parallel option -threads 8
+
+// map unreachable points
+set mapping method -nets -mem -unreach
+map key points
+report unmapped points
+
+add compare point -all
+compare -threads 8 -noneq_stop 1
+analyze abort -compare
+
+//-------------------------------------------------------------------------
+// reports
+//-------------------------------------------------------------------------
+report compare data -class nonequivalent -class abort -class notcompared
+report verification -verbose
+report statistics
+usage
+
+exit -force
diff --git a/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh
new file mode 100755
index 0000000..089f428
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/syn/lec_sv2v.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+# This script converts all SystemVerilog RTL files to Verilog
+# using sv2v and then runs LEC (Cadence Conformal) to check if
+# the generated Verilog is logically equivalent to the original
+# SystemVerilog.  A similar script is used in OpenTitan, any updates 
+# or fixes here may need to be reflected in the OpenTitan script as well
+# https://github.com/lowRISC/opentitan/blob/master/util/syn_yosys.sh
+#
+# The following tools are required:
+#  - sv2v: SystemVerilog-to-Verilog converter from github.com/zachjs/sv2v
+#  - Cadence Conformal
+#
+# Usage:
+#   ./lec_sv2v.sh |& tee lec.log
+
+#-------------------------------------------------------------------------
+# use fusesoc to generate files and file list
+#-------------------------------------------------------------------------
+rm -Rf build lec_out
+fusesoc --cores-root .. run --tool=icarus --target=lint \
+  --setup "lowrisc:ibex:ibex_core" > /dev/null 2>&1
+
+# copy all files to lec_out
+mkdir lec_out
+cp build/*/src/*/*.sv build/*/src/*/*/*.sv lec_out
+cd lec_out
+
+# copy file list and remove incdir, RVFI define, and sim-file
+egrep -v 'incdir|RVFI|simulator_ctrl' ../build/*/*/*.scr > flist_gold
+
+# remove all hierarchical paths
+sed -i 's!.*/!!' flist_gold
+
+# generate revised flist by replacing '.sv' by '.v' and removing packages
+sed 's/.sv/.v/' flist_gold | grep -v "_pkg.v" > flist_rev
+
+#-------------------------------------------------------------------------
+# convert all RTL files to Verilog using sv2v
+#-------------------------------------------------------------------------
+printf "\nSV2V ERRORS:\n"
+
+for file in *.sv; do
+  module=`basename -s .sv $file`
+  sv2v --define=SYNTHESIS *_pkg.sv prim_assert.sv $file > ${module}.v
+done
+
+# remove *pkg.v files (they are empty files and not needed)
+rm -f *_pkg.v prim_assert.v prim_util_memload.v
+
+# overwrite the prim_clock_gating modules with the module from ../rtl
+cp ../rtl/prim_clock_gating.v .
+cp ../rtl/prim_clock_gating.v prim_clock_gating.sv
+
+#-------------------------------------------------------------------------
+# run LEC (generated Verilog vs. original SystemVerilog)
+#-------------------------------------------------------------------------
+printf "\n\nLEC RESULTS:\n"
+
+for file in *.v; do
+  export LEC_TOP=`basename -s .v $file`
+
+  # special case is file ibex_register_file_ff.sv, whose module has a
+  # different name than its file name
+  if [[ $LEC_TOP == "ibex_register_file_ff" ]]; then
+    export LEC_TOP="ibex_register_file"
+  fi
+
+  # run Conformal LEC
+  lec -xl -nogui -nobanner \
+    -dofile  ../lec_sv2v.do \
+    -logfile lec_${LEC_TOP}.log \
+    <<< "exit -force" > /dev/null 2>&1
+
+  # summarize results
+  check=`grep "Compare Results" lec_${LEC_TOP}.log`
+  if [ $? -ne 0 ]; then
+    result="CRASH"
+  else
+    result=`echo $check | awk '{ print $4 }'`
+  fi
+  printf "%-25s %s\n" $LEC_TOP $result
+done
diff --git a/hw/vendor/lowrisc_ibex/util/ibex_config.py b/hw/vendor/lowrisc_ibex/util/ibex_config.py
index 1aa6fcf..1329e71 100755
--- a/hw/vendor/lowrisc_ibex/util/ibex_config.py
+++ b/hw/vendor/lowrisc_ibex/util/ibex_config.py
@@ -226,6 +226,12 @@
         SimOpts('riviera_compile_opts', 'Riviera compile',
                 lambda p, v: None,
                 lambda d, v: '+define+' + d + '=' + v, '/'),
+        SimOpts('questa_sim_opts', 'Questa simulate',
+                lambda p, v: '-g/' + p + '=' + v,
+                lambda d, v: None, '/'),
+        SimOpts('questa_compile_opts', 'Questa compile',
+                lambda p, v: None,
+                lambda d, v: '+define+' + d + '=' + v, '/'),
         SimOpts('xlm_opts', 'Xcelium compile',
                 lambda p, v: '-defparam ' + p + '=' + v,
                 lambda d, v: '-define ' + d + '=' + v, '.'),
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 fdfbb51..57ed1a9 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: 1ad73cc43f8f84d93d49040f8b2928e74efdd854
+    rev: 6cf6b4f389272d8ff5e2b397af43ac6c0dfba2e2
   }
 }
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.flake8 b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.flake8
new file mode 100644
index 0000000..5b0913f
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.flake8
@@ -0,0 +1,10 @@
+[flake8]
+
+# Maximum line length
+max-line-length = 100
+
+ignore =
+  # Ignore unexpected spaces around keyword / parameter equals
+  E251,
+  # Do not complain about line breaks after operators
+  W504
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.travis.yml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.travis.yml
index dada2b9..2c25db4 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.travis.yml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.travis.yml
@@ -2,8 +2,6 @@
 dist: xenial
 matrix:
     include:
-        - python: 3.5
-          env: TOX_ENV=py35
         - python: 3.6
           env: TOX_ENV=py36
         - python: 3.7
@@ -15,3 +13,4 @@
 script:
     - sphinx-build -E -W -b linkcheck docs/source build
     - pip uninstall -y riscv-dv
+    - flake8 --show-source pygen/pygen_src/ --config=.flake8
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
new file mode 100644
index 0000000..8392a3c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
@@ -0,0 +1,408 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+Regression script for RISC-V random instruction generator
+
+"""
+
+
+from collections import defaultdict
+from pygen_src.riscv_instr_gen_config import riscv_instr_gen_config
+from pygen_src.riscv_instr_pkg import riscv_instr_group_t
+from pygen_src.isa import rv32i_instr  # NOQA
+import random
+from bitstring import BitArray
+import logging
+from copy import copy
+import sys
+
+
+class riscv_instr:
+
+    logging.basicConfig(level=logging.INFO)
+    instr_registry = {}
+
+    def __init__(self):
+        self.instr_names = []
+        self.instr_group = defaultdict(list)
+        self.instr_category = defaultdict(list)
+        self.basic_instr = []
+        self.instr_template = {}
+
+        self.exclude_reg = []
+        self.include_reg = []
+
+        self.group = None
+        self.format = None
+        self.category = None
+        self.instr_name = None
+        self.imm_type = None
+        self.imm_len = 0
+
+        self.csr = None
+        self.rs2 = None
+        self.rs1 = None
+        self.rd = None
+        self.imm = BitArray(hex="0x00000000")
+
+        self.imm_mask = BitArray(hex="0xffffffff")
+        self.is_branch_target = None
+        self.has_label = 1
+        self.atomic = 0
+        self.branch_assigned = None
+        self.process_load_store = 1
+        self.is_compressed = None
+        self.is_illegal_instr = None
+        self.is_hint_instr = None
+        self.is_floating_point = None
+        self.imm_str = None
+        self.comment = None
+        self.label = None
+        self.is_local_numeric_label = None
+        self.idx = -1
+        self.has_rs1 = 1
+        self.has_rs2 = 1
+        self.has_rd = 1
+        self.has_imm = 1
+
+        # Fields Added for debugging These fields are actually from a different files.
+        self.unsupported_instr = []
+        self.XLEN = 32
+        self.supported_isa = [riscv_instr_group_t.RV32I]
+        self.implemented_csr = []
+
+    @classmethod
+    def register(cls, instr_name):
+        logging.info("Registering %s", instr_name.name)
+        cls.instr_registry[instr_name.name] = 1
+        if(instr_name is None):
+            print("\n")
+        return 1
+
+    def create_instr_list(self, cfg):
+        self.instr_names.clear()
+        self.instr_group.clear()
+        self.instr_category.clear()
+        for instr_name, values in self.instr_registry.items():
+            if(instr_name in self.unsupported_instr):
+                continue
+            instr_inst = self.create_instr(instr_name)
+            self.instr_template[instr_name] = instr_inst
+
+            if (not instr_inst.is_supported(cfg)):
+                continue
+            if ((self.XLEN != 32) and (instr_name == "C_JAL")):
+                continue
+            if (("SP" in cfg.reserved_regs) and (instr_name == "C_ADDI16SP")):
+                continue
+            if (cfg.enable_sfence and instr_name == "SFENCE_VMA"):
+                continue
+            if (instr_name in ["FENCE", "FENCE_I", "SFENCE_VMA"]):
+                continue
+            if (instr_inst.group in self.supported_isa and
+                    not(cfg.disable_compressed_instr and
+                        instr_inst.group in ["RV32C", "RV64C", "RV32DC", "RV32FC", "RV128C"]) and
+                    not(not(cfg.enable_floating_point) and instr_inst.group in
+                        ["RV32F", "RV64F", "RV32D", "RV64D"])):
+                self.instr_category[instr_inst.category.name].append(instr_name)
+                self.instr_group[instr_inst.group.name].append(instr_name)
+                self.instr_names.append(instr_name)
+
+        self.build_basic_instruction_list(cfg)
+        self.create_csr_filter(cfg)
+
+    def create_instr(self, instr_name):
+        """TODO This method is specific to RV32I instruction only.
+        It must be scaled to all instruction extensions."""
+        try:
+            instr_inst = eval("rv32i_instr.riscv_" + instr_name + "_instr()")
+        except Exception:
+            logging.critical("Failed to create instr: %0s", instr_name)
+            sys.exit(1)
+        return instr_inst
+
+    def is_supported(self, cfg):
+        return 1
+
+    def build_basic_instruction_list(self, cfg):
+        self.basic_instr = (self.instr_category["SHIFT"] + self.instr_category["ARITHMETIC"] +
+                            self.instr_category["LOGICAL"] + self.instr_category["COMPARE"])
+        if(cfg.no_ebreak == 0):
+            self.basic_instr.append("EBREAK")
+            for items in self.supported_isa:
+                if("RV32C" in self.supported_isa and not(cfg.disable_compressed_instr)):
+                    self.basic_instr.append("C_EBREAK")
+                    break
+        if(cfg.no_dret == 0):
+            self.basic_instr.append("DRET")
+        if(cfg.no_fence == 0):
+            self.basic_instr.append(self.instr_category["SYNCH"])
+        if(cfg.no_csr_instr == 0 and cfg.init_privileged_mode == "MACHINE_MODE"):
+            self.basic_instr.append(self.instr_category["CSR"])
+        if(cfg.no_wfi == 0):
+            self.basic_instr.append("WFI")
+
+    def create_csr_filter(self, cfg):
+        self.include_reg.clear()
+        self.exclude_reg.clear()
+
+        if(cfg.enable_illegal_csr_instruction):
+            self.exclude_reg = self.implemented_csr
+        elif(cfg.enable_access_invalid_csr_level):
+            self.include_reg = cfg.invalid_priv_mode_csrs
+        else:
+            if(cfg.init_privileged_mode == "MACHINE_MODE"):    # Machine Mode
+                self.include_reg.append("MSCRATCH")
+            elif(cfg.init_privileged_mode == "SUPERVISOR_MODE"):  # Supervisor Mode
+                self.include_reg.append("SSCRATCH")
+            else:                                              # User Mode
+                self.include_reg.append("USCRATCH")
+
+    def get_rand_instr(self, include_instr=[], exclude_instr=[],
+                       include_category=[], exclude_category=[],
+                       include_group=[], exclude_group=[]):
+        idx = BitArray(uint = 0, length = 32)
+        name = ""
+        allowed_instr = []
+        disallowed_instr = []
+        # allowed_categories = []
+
+        for items in include_category:
+            allowed_instr.append(self.instr_category[items])
+
+        for items in exclude_category:
+            if(items in self.instr_category):
+                disallowed_instr.append(self.instr_category[items])
+        for items in include_group:
+            allowed_instr.append(self.instr_group[items])
+        for items in exclude_group:
+            if(items in self.instr_group):
+                disallowed_instr.append(self.instr_group[items])
+
+        disallowed_instr.extend(exclude_instr)
+
+        if(len(disallowed_instr) == 0):
+            if(len(include_instr) > 0):
+                idx = random.randrange(0, len(include_instr) - 1)
+                name = include_instr[idx]
+            elif(len(allowed_instr > 0)):
+                idx = random.randrange(0, len(allowed_instr) - 1)
+                name = allowed_instr[idx]
+            else:
+                idx = random.randrange(0, len(self.instr_names) - 1)
+                name = self.instr_names[idx]
+        else:
+            # TODO
+            instr_names_set = set(self.instr_names)
+            disallowed_instr_set = set(disallowed_instr)
+            allowed_instr_set = set(allowed_instr)
+            include_instr_set = set(include_instr)
+            excluded_instr_names_list = list(instr_names_set - disallowed_instr_set)
+            excluded_allowed_instr_list = list(allowed_instr_set - disallowed_instr_set)
+            include_instr_list = list(include_instr_set - disallowed_instr_set)
+
+            name = random.choice(excluded_instr_names_list)
+            if(len(include_instr) > 0):
+                name = random.choice(include_instr_list)
+            if(len(allowed_instr) > 0):
+                name = random.choice(excluded_allowed_instr_list)
+            if(name is None):
+                logging.critical("%s Cannot generate random instruction", riscv_instr.__name__)
+                sys.exit(1)
+
+        instr_h = copy(self.instr_template[name])
+        return instr_h
+
+    def get_load_store_instr(self, load_store_instr):
+        instr_h = riscv_instr()
+        if(len(load_store_instr) == 0):
+            load_store_instr = self.instr_category["LOAD"] + \
+                self.instr_category["STORE"]
+        self.idx = random.randrange(0, len(load_store_instr) - 1)
+        name = load_store_instr[self.idx]
+        instr_h = copy(self.instr_template[name])
+        return instr_h
+
+    def get_instr(self, name):
+        if (not self.instr_template.get(name)):
+            logging.critical("Cannot get instr %s", name)
+        instr_h = copy(self.instr_template[name])
+        return instr_h
+
+    def set_rand_mode(self):
+        # rand_mode setting for Instruction Format
+        if(self.format.name == "R_FORMAT"):
+            self.has_imm = 0
+        if(self.format.name == "I_FORMAT"):
+            self.has_rs2 = 0
+        if(self.format.name in ["S_FORMAT", "B_FORMAT"]):
+            self.has_rd = 0
+        if(self.format.name in ["U_FORMAT", "J_FORMAT"]):
+            self.has_rs1 = 0
+            self.has_rs2 = 0
+
+        # rand_mode setting for Instruction Category
+        if(self.category.name == "CSR"):
+            self.has_rs2 = 0
+            if(self.format.name == "I_FORMAT"):
+                self.has_rs1 = 0
+
+    def pre_randomize(self):
+        pass  # TODO
+
+    def set_imm_len(self):
+        if(self.format.name in ["U_FORMAT", "J_FORMAT"]):
+            self.imm_len = 20
+        elif(self.format.name in ["I_FORMAT", "S_FORMAT", "B_FORMAT"]):
+            if(self.imm_type.name == "UIMM"):
+                self.imm_len = 5
+            else:
+                self.imm_len = 11
+        self.imm_mask = self.imm_mask << self.imm_len
+
+    def extend_imm(self):
+        sign = 0
+        self.imm = self.imm << (32 - self.imm_len)
+        # sign = imm[31]
+        sign = self.imm.bin[0:1:1]
+        self.imm = self.imm >> (32 - self.imm_len)
+        # Signed extension
+        if((sign and not(self.format == "U_FORMAT")) or (self.imm_type in ["UIMM", "NZUIMM"])):
+            self.imm = self.imm_mask | self.imm
+
+    def post_randomize(self):
+        self.extend_imm()
+        self.update_imm_str()
+
+    def convert2asm(self):
+        pass
+
+    def get_opcode(self):
+        if(self.instr_name.name == "LUI"):
+            return (BitArray(uint = 55, length = 7).bin)
+        elif(self.instr_name.name == "AUIPC"):
+            return (BitArray(uint = 23, length = 7).bin)
+        elif(self.instr_name.name == "JAL"):
+            return (BitArray(uint = 23, length = 7).bin)
+        elif(self.instr_name.name == "JALR"):
+            return (BitArray(uint = 111, length = 7).bin)
+        elif(self.instr_name.name in ["BEQ", "BNE", "BLT", "BGE", "BLTU", "BGEU"]):
+            return (BitArray(uint = 103, length = 7).bin)
+        elif(self.instr_name.name in ["LB", "LH", "LW", "LBU", "LHU", "LWU", "LD"]):
+            return (BitArray(uint = 99, length = 7).bin)
+        elif(self.instr_name.name in ["SB", "SH", "SW", "SD"]):
+            return (BitArray(uint = 35, length = 7).bin)
+        elif(self.instr_name.name in ["ADDI", "SLTI", "SLTIU", "XORI", "ORI", "ANDI",
+                                      "SLLI", "SRLI", "SRAI", "NOP"]):
+            return (BitArray(uint = 19, length = 7).bin)
+        elif(self.instr_name.name in ["ADD", "SUB", "SLL", "SLT", "SLTU", "XOR", "SRL",
+                                      "SRA", "OR", "AND", "MUL", "MULH", "MULHSU", "MULHU",
+                                      "DIV", "DIVU", "REM", "REMU"]):
+            return (BitArray(uint = 51, length = 7).bin)
+        elif(self.instr_name.name in ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]):
+            return (BitArray(uint = 27, length = 7).bin)
+        elif(self.instr_name.name in ["MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM", "REMU"]):
+            return (BitArray(uint = 51, length = 7).bin)
+        elif(self.instr_name.name in ["FENCE", "FENCE_I"]):
+            return (BitArray(uint = 15, length = 7).bin)
+        elif(self.instr_name.name in ["ECALL", "EBREAK", "CSRRW", "CSRRS", "CSRRC", "CSRRWI",
+                                      "CSRRSI", "CSRRCI"]):
+            return (BitArray(uint = 115, length = 7).bin)
+        elif(self.instr_name.name in ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "MULW", "DIVW",
+                                      "DIVUW", "REMW", "REMUW"]):
+            return (BitArray(uint = 59, length = 7).bin)
+        elif(self.instr_name.name in ["ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET", "WFI",
+                                      "SFENCE_VMA"]):
+            return (BitArray(uint = 115, length = 7).bin)
+        else:
+            logging.critical("Unsupported instruction %0s", self.instr_name.name)
+            sys.exit(1)
+
+    def get_func3(self):
+        if(self.instr_name.name in ["JALR", "BEQ", "LB", "SB", "ADDI", "NOP", "ADD", "SUB",
+                                    "FENCE", "ECALL", "EBREAK", "ADDIW", "ADDW", "SUBW", "MUL",
+                                    "MULW", "ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET",
+                                    "WFI", "SFENCE_VMA"]):
+            return (BitArray(uint = 0, length = 3).bin)
+        elif(self.instr_name.name in ["BNE", "LH", "SH", "SLLI", "SLL", "FENCE_I", "CSRRW", "SLLIW",
+                                      "SLLW", "MULH"]):
+            return (BitArray(uint = 1, length = 3).bin)
+        elif(self.instr_name.name in ["LW", "SW", "SLTI", "SLT", "CSRRS", "MULHS"]):
+            return (BitArray(uint = 2, length = 3).bin)
+        elif(self.instr_name.name in ["SLTIU", "SLTU", "CSRRC", "LD", "SD", "MULHU"]):
+            return (BitArray(uint = 3, length = 3).bin)
+        elif(self.instr_name.name in ["BLT", "LBU", "XORI", "XOR", "DIV", "DIVW"]):
+            return (BitArray(uint = 4, length = 3).bin)
+        elif(self.instr_name.name in ["BGE", "LHU", "SRLI", "SRAI", "SRL", "SRA", "CSRRWI", "SRLIW",
+                                      "SRAIW", "SRLW",
+                                      "SRAW", "DIVU", "DIVUW"]):
+            return (BitArray(uint = 5, length = 3).bin)
+        elif(self.instr_name.name in ["BLTU", "ORI", "OR", "CSRRSI", "LWU", "REM", "REMW"]):
+            return (BitArray(uint = 6, length = 3).bin)
+        elif(self.instr_name.name in ["BGEU", "ANDI", "AND", "CSRRCI", "REMU", "REMUW"]):
+            return (BitArray(uint = 7, length = 3).bin)
+        else:
+            logging.critical("Unsupported instruction %0s", self.instr_name.name)
+            sys.exit(1)
+
+    def get_func7(self):
+        if(self.instr_name.name in ["SLLI", "SRLI", "ADD", "SLL", "SLT", "SLTU", "XOR",
+                                    "SRL", "OR", "AND", "FENCE", "FENCE_I", "SLLIW",
+                                    "SRLIW", "ADDW", "SLLW", "SRLW", "ECALL", "EBREAK", "URET"]):
+            return (BitArray(uint = 0, length = 7).bin)
+        elif(self.instr_name.name in ["SUB", "SRA", "SRAIW", "SUBW", "SRAW"]):
+            return (BitArray(uint = 32, length = 7).bin)
+        elif(self.instr_name.name in ["MUL", "MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM",
+                                      "REMU", "MULW", "DIVW", "DIVUW", "REMW", "REMUW"]):
+            return (BitArray(uint = 1, length = 7).bin)
+        elif(self.instr_name.name in ["SRET", "WFI"]):
+            return (BitArray(uint = 8, length = 7).bin)
+        elif(self.instr_name.name == "MRET"):
+            return (BitArray(uint = 24, length = 7).bin)
+        elif(self.instr_name.name == "DRET"):
+            return (BitArray(uint = 61, length = 7).bin)
+        elif(self.instr_name.name == "SFENCE_VMA"):
+            return (BitArray(uint = 9, length = 7).bin)
+        else:
+            logging.critical("Unsupported instruction %0s", self.instr_name.name)
+            sys.exit(1)
+
+    def convert2bin(self):
+        pass  # TODO
+
+    def get_instr_name(self):
+        get_instr_name = self.instr_name.name
+        for i in get_instr_name:
+            if(i == "_"):
+                get_instr_name = get_instr_name.replace(i, ".")
+        return get_instr_name
+
+    def get_c_gpr(self, gpr):
+        return self.gpr
+
+    def get_imm(self):
+        return self.imm_str
+
+    def clear_unused_label(self):
+        if(self.has_label and not(self.is_branch_target) and self.is_local_numeric_label):
+            self.has_label = 0
+
+    def do_copy(self):
+        pass  # TODO
+
+    def update_imm_str(self):
+        self.imm_str = str(self.imm)
+
+
+riscv_instr_ins = riscv_instr()
+cfg = riscv_instr_gen_config()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py
new file mode 100644
index 0000000..a7ed7ac
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py
@@ -0,0 +1,141 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+Regression script for RISC-V random instruction generator
+
+"""
+
+from pygen_src.riscv_defines import DEFINE_INSTR
+from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
+                                       riscv_instr_category_t, riscv_instr_group_t, imm_t)
+
+
+# LOAD instructions
+DEFINE_INSTR(riscv_instr_name_t.LB, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.LH, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.LW, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.LBU, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.LHU, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
+# STORE instructions
+DEFINE_INSTR(riscv_instr_name_t.SB, riscv_instr_format_t.S_FORMAT,
+             riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SH, riscv_instr_format_t.S_FORMAT,
+             riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SW, riscv_instr_format_t.S_FORMAT,
+             riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
+# SHIFT intructions
+DEFINE_INSTR(riscv_instr_name_t.SLL, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SLLI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SRL, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SRLI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SRA, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SRAI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
+# ARITHMETIC intructions
+DEFINE_INSTR(riscv_instr_name_t.ADD, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.ADDI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.NOP, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SUB, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.LUI, riscv_instr_format_t.U_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.AUIPC, riscv_instr_format_t.U_FORMAT,
+             riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+# LOGICAL instructions
+DEFINE_INSTR(riscv_instr_name_t.XOR, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.XORI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.OR, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.ORI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.AND, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.ANDI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
+# COMPARE instructions
+DEFINE_INSTR(riscv_instr_name_t.SLT, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SLTI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SLTU, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SLTIU, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
+# BRANCH instructions
+DEFINE_INSTR(riscv_instr_name_t.BEQ, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.BNE, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.BLT, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.BGE, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.BLTU, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.BGEU, riscv_instr_format_t.B_FORMAT,
+             riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
+# JUMP instructions
+DEFINE_INSTR(riscv_instr_name_t.JAL, riscv_instr_format_t.J_FORMAT,
+             riscv_instr_category_t.JUMP, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.JALR, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.JUMP, riscv_instr_group_t.RV32I, g=globals())
+# SYNCH instructions
+DEFINE_INSTR(riscv_instr_name_t.FENCE, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.FENCE_I, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SFENCE_VMA, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
+# SYSTEM instructions
+DEFINE_INSTR(riscv_instr_name_t.ECALL, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.EBREAK, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.URET, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.SRET, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.MRET, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.DRET, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.WFI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.INTERRUPT, riscv_instr_group_t.RV32I, g=globals())
+# CSR instructions
+DEFINE_INSTR(riscv_instr_name_t.CSRRW, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.CSRRS, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.CSRRC, riscv_instr_format_t.R_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.CSRRWI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.CSRRSI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
+DEFINE_INSTR(riscv_instr_name_t.CSRRCI, riscv_instr_format_t.I_FORMAT,
+             riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
new file mode 100644
index 0000000..d4f2b23
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
@@ -0,0 +1,39 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+Regression script for RISC-V random instruction generator
+
+"""
+
+from pygen_src.riscv_instr_pkg import imm_t
+from pygen_src.isa.riscv_instr import riscv_instr
+
+
+def DEFINE_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=imm_t.IMM, g=globals()):
+    class_name = f"riscv_{instr_n.name}_instr"
+
+    def __init__(self):
+        riscv_instr.__init__(self)
+        self.instr_name = instr_n
+        self.format = instr_format
+        self.category = instr_category
+        self.group = instr_group
+        self.imm_type = imm_tp
+
+        self.set_imm_len()
+        self.set_rand_mode()
+    NewClass = type(class_name, (riscv_instr,), {
+        "__init__": __init__,
+        "valid": riscv_instr.register(instr_n)
+    })
+    g[class_name] = NewClass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
new file mode 100644
index 0000000..6d59010
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
@@ -0,0 +1,34 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+Regression script for RISC-V random instruction generator
+
+"""
+
+
+class riscv_instr_gen_config:
+    def __init__(self):
+        self.enable_floating_point = 1
+        self.disable_compressed_instr = 1
+        self.num_of_test = 3
+        self.no_fence = 1
+        self.enable_sfence = 0
+        self.reserved_regs = []
+        self.enable_illegal_csr_instruction = 0
+        self.enable_access_invalid_csr_level = 0
+        self.invalid_priv_mode_csrs = []
+        self.init_privileged_mode = "MACHINE_MODE"
+        self.no_ebreak = 1
+        self.no_dret = 1
+        self.no_csr_instr = 1
+        self.no_wfi = 1
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
new file mode 100644
index 0000000..5edc6a4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
@@ -0,0 +1,602 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+Regression script for RISC-V random instruction generator
+
+"""
+
+from enum import Enum, auto
+
+
+class riscv_instr_name_t(Enum):
+    # RV32I instructions
+    LUI = 0
+    AUIPC = auto()
+    JAL = auto()
+    JALR = auto()
+    BEQ = auto()
+    BNE = auto()
+    BLT = auto()
+    BGE = auto()
+    BLTU = auto()
+    BGEU = auto()
+    LB = auto()
+    LH = auto()
+    LW = auto()
+    LBU = auto()
+    LHU = auto()
+    SB = auto()
+    SH = auto()
+    SW = auto()
+    ADDI = auto()
+    SLTI = auto()
+    SLTIU = auto()
+    XORI = auto()
+    ORI = auto()
+    ANDI = auto()
+    SLLI = auto()
+    SRLI = auto()
+    SRAI = auto()
+    ADD = auto()
+    SUB = auto()
+    SLL = auto()
+    SLT = auto()
+    SLTU = auto()
+    XOR = auto()
+    SRL = auto()
+    SRA = auto()
+    OR = auto()
+    AND = auto()
+    NOP = auto()
+    FENCE = auto()
+    FENCE_I = auto()
+    ECALL = auto()
+    EBREAK = auto()
+    CSRRW = auto()
+    CSRRS = auto()
+    CSRRC = auto()
+    CSRRWI = auto()
+    CSRRSI = auto()
+    CSRRCI = auto()
+    # RV32B instructions
+    ANDN = auto()
+    ORN = auto()
+    XNOR = auto()
+    GORC = auto()
+    SLO = auto()
+    SRO = auto()
+    ROL = auto()
+    ROR = auto()
+    SBCLR = auto()
+    SBSET = auto()
+    SBINV = auto()
+    SBEXT = auto()
+    GREV = auto()
+    SLOI = auto()
+    SROI = auto()
+    RORI = auto()
+    SBCLRI = auto()
+    SBSETI = auto()
+    SBINVI = auto()
+    SBEXTI = auto()
+    GORCI = auto()
+    GREVI = auto()
+    CMIX = auto()
+    CMOV = auto()
+    FSL = auto()
+    FSR = auto()
+    FSRI = auto()
+    CLZ = auto()
+    CTZ = auto()
+    PCNT = auto()
+    SEXT_B = auto()
+    SEXT_H = auto()
+    CRC32_B = auto()
+    CRC32_H = auto()
+    CRC32_W = auto()
+    CRC32C_B = auto()
+    CRC32C_H = auto()
+    CRC32C_W = auto()
+    CLMUL = auto()
+    CLMULR = auto()
+    CLMULH = auto()
+    MIN = auto()
+    MAX = auto()
+    MINU = auto()
+    MAXU = auto()
+    SHFL = auto()
+    UNSHFL = auto()
+    BDEP = auto()
+    BEXT = auto()
+    PACK = auto()
+    PACKU = auto()
+    BMATOR = auto()
+    BMATXOR = auto()
+    PACKH = auto()
+    BFP = auto()
+    SHFLI = auto()
+    UNSHFLI = auto()
+    # RV64B instructions
+    ADDIWU = auto()
+    SLLIU_W = auto()
+    ADDWU = auto()
+    SUBWU = auto()
+    BMATFLIP = auto()
+    CRC32_D = auto()
+    CRC32C_D = auto()
+    ADDU_W = auto()
+    SUBU_W = auto()
+    SLOW = auto()
+    SROW = auto()
+    ROLW = auto()
+    RORW = auto()
+    SBCLRW = auto()
+    SBSETW = auto()
+    SBINVW = auto()
+    SBEXTW = auto()
+    GORCW = auto()
+    GREVW = auto()
+    SLOIW = auto()
+    SROIW = auto()
+    RORIW = auto()
+    SBCLRIW = auto()
+    SBSETIW = auto()
+    SBINVIW = auto()
+    GORCIW = auto()
+    GREVIW = auto()
+    FSLW = auto()
+    FSRW = auto()
+    FSRIW = auto()
+    CLZW = auto()
+    CTZW = auto()
+    PCNTW = auto()
+    CLMULW = auto()
+    CLMULRW = auto()
+    CLMULHW = auto()
+    SHFLW = auto()
+    UNSHFLW = auto()
+    BDEPW = auto()
+    BEXTW = auto()
+    PACKW = auto()
+    PACKUW = auto()
+    BFPW = auto()
+    # RV32M instructions
+    MUL = auto()
+    MULH = auto()
+    MULHSU = auto()
+    MULHU = auto()
+    DIV = auto()
+    DIVU = auto()
+    REM = auto()
+    REMU = auto()
+    # RV64M instructions
+    MULW = auto()
+    DIVW = auto()
+    DIVUW = auto()
+    REMW = auto()
+    REMUW = auto()
+    # RV32F instructions
+    FLW = auto()
+    FSW = auto()
+    FMADD_S = auto()
+    FMSUB_S = auto()
+    FNMSUB_S = auto()
+    FNMADD_S = auto()
+    FADD_S = auto()
+    FSUB_S = auto()
+    FMUL_S = auto()
+    FDIV_S = auto()
+    FSQRT_S = auto()
+    FSGNJ_S = auto()
+    FSGNJN_S = auto()
+    FSGNJX_S = auto()
+    FMIN_S = auto()
+    FMAX_S = auto()
+    FCVT_W_S = auto()
+    FCVT_WU_S = auto()
+    FMV_X_W = auto()
+    FEQ_S = auto()
+    FLT_S = auto()
+    FLE_S = auto()
+    FCLASS_S = auto()
+    FCVT_S_W = auto()
+    FCVT_S_WU = auto()
+    FMV_W_X = auto()
+    # RV64F instruction
+    FCVT_L_S = auto()
+    FCVT_LU_S = auto()
+    FCVT_S_L = auto()
+    FCVT_S_LU = auto()
+    # RV32D instructions
+    FLD = auto()
+    FSD = auto()
+    FMADD_D = auto()
+    FMSUB_D = auto()
+    FNMSUB_D = auto()
+    FNMADD_D = auto()
+    FADD_D = auto()
+    FSUB_D = auto()
+    FMUL_D = auto()
+    FDIV_D = auto()
+    FSQRT_D = auto()
+    FSGNJ_D = auto()
+    FSGNJN_D = auto()
+    FSGNJX_D = auto()
+    FMIN_D = auto()
+    FMAX_D = auto()
+    FCVT_S_D = auto()
+    FCVT_D_S = auto()
+    FEQ_D = auto()
+    FLT_D = auto()
+    FLE_D = auto()
+    FCLASS_D = auto()
+    FCVT_W_D = auto()
+    FCVT_WU_D = auto()
+    FCVT_D_W = auto()
+    FCVT_D_WU = auto()
+    # RV64D
+    FCVT_L_D = auto()
+    FCVT_LU_D = auto()
+    FMV_X_D = auto()
+    FCVT_D_L = auto()
+    FCVT_D_LU = auto()
+    FMV_D_X = auto()
+    # RV64I
+    LWU = auto()
+    LD = auto()
+    SD = auto()
+    ADDIW = auto()
+    SLLIW = auto()
+    SRLIW = auto()
+    SRAIW = auto()
+    ADDW = auto()
+    SUBW = auto()
+    SLLW = auto()
+    SRLW = auto()
+    SRAW = auto()
+    # RV32C
+    C_LW = auto()
+    C_SW = auto()
+    C_LWSP = auto()
+    C_SWSP = auto()
+    C_ADDI4SPN = auto()
+    C_ADDI = auto()
+    C_LI = auto()
+    C_ADDI16SP = auto()
+    C_LUI = auto()
+    C_SRLI = auto()
+    C_SRAI = auto()
+    C_ANDI = auto()
+    C_SUB = auto()
+    C_XOR = auto()
+    C_OR = auto()
+    C_AND = auto()
+    C_BEQZ = auto()
+    C_BNEZ = auto()
+    C_SLLI = auto()
+    C_MV = auto()
+    C_EBREAK = auto()
+    C_ADD = auto()
+    C_NOP = auto()
+    C_J = auto()
+    C_JAL = auto()
+    C_JR = auto()
+    C_JALR = auto()
+    # RV64C
+    C_ADDIW = auto()
+    C_SUBW = auto()
+    C_ADDW = auto()
+    C_LD = auto()
+    C_SD = auto()
+    C_LDSP = auto()
+    C_SDSP = auto()
+    # RV128C
+    C_SRLI64 = auto()
+    C_SRAI64 = auto()
+    C_SLLI64 = auto()
+    C_LQ = auto()
+    C_SQ = auto()
+    C_LQSP = auto()
+    C_SQSP = auto()
+    # RV32FC
+    C_FLW = auto()
+    C_FSW = auto()
+    C_FLWSP = auto()
+    C_FSWSP = auto()
+    # RV32DC
+    C_FLD = auto()
+    C_FSD = auto()
+    C_FLDSP = auto()
+    C_FSDSP = auto()
+    # RV32A
+    LR_W = auto()
+    SC_W = auto()
+    AMOSWAP_W = auto()
+    AMOADD_W = auto()
+    AMOAND_W = auto()
+    AMOOR_W = auto()
+    AMOXOR_W = auto()
+    AMOMIN_W = auto()
+    AMOMAX_W = auto()
+    AMOMINU_W = auto()
+    AMOMAXU_W = auto()
+    # RV64A
+    LR_D = auto()
+    SC_D = auto()
+    AMOSWAP_D = auto()
+    AMOADD_D = auto()
+    AMOAND_D = auto()
+    AMOOR_D = auto()
+    AMOXOR_D = auto()
+    AMOMIN_D = auto()
+    AMOMAX_D = auto()
+    AMOMINU_D = auto()
+    AMOMAXU_D = auto()
+    # Vector instructions
+    VSETVL = auto()
+    VSETVLI = auto()
+    VADD = auto()
+    VSUB = auto()
+    VRSUB = auto()
+    VWADDU = auto()
+    VWSUBU = auto()
+    VWADD = auto()
+    VWSUB = auto()
+    VADC = auto()
+    VMADC = auto()
+    VSBC = auto()
+    VMSBC = auto()
+    VAND = auto()
+    VOR = auto()
+    VXOR = auto()
+    VSLL = auto()
+    VSRL = auto()
+    VSRA = auto()
+    VNSRL = auto()
+    VNSRA = auto()
+    VMSEQ = auto()
+    VMSNE = auto()
+    VMSLTU = auto()
+    VMSLT = auto()
+    VMSLEU = auto()
+    VMSLE = auto()
+    VMSGTU = auto()
+    VMSGT = auto()
+    VMINU = auto()
+    VMIN = auto()
+    VMAXU = auto()
+    VMAX = auto()
+    VMUL = auto()
+    VMULH = auto()
+    VMULHU = auto()
+    VMULHSU = auto()
+    VDIVU = auto()
+    VDIV = auto()
+    VREMU = auto()
+    VREM = auto()
+    VWMUL = auto()
+    VWMULU = auto()
+    VWMULSU = auto()
+    VMACC = auto()
+    VNMSAC = auto()
+    VMADD = auto()
+    VNMSUB = auto()
+    VWMACCU = auto()
+    VWMACC = auto()
+    VWMACCSU = auto()
+    VWMACCUS = auto()
+    '''
+    VQMACCU = auto()
+    VQMACC = auto()
+    VQMACCSU = auto()
+    VQMACCUS = auto()
+    '''
+    VMERGE = auto()
+    VMV = auto()
+    VSADDU = auto()
+    VSADD = auto()
+    VSSUBU = auto()
+    VSSUB = auto()
+    VAADDU = auto()
+    VAADD = auto()
+    VASUBU = auto()
+    VASUB = auto()
+    VSSRL = auto()
+    VSSRA = auto()
+    VNCLIPU = auto()
+    VNCLIP = auto()
+    VFADD = auto()
+    VFSUB = auto()
+    VFRSUB = auto()
+    VFMUL = auto()
+    VFDIV = auto()
+    VFRDIV = auto()
+    VFWMUL = auto()
+    VFMACC = auto()
+    VFNMACC = auto()
+    VFMSAC = auto()
+    VFNMSAC = auto()
+    VFMADD = auto()
+    VFNMADD = auto()
+    VFMSUB = auto()
+    VFNMSUB = auto()
+    VFWMACC = auto()
+    VFWNMACC = auto()
+    VFWMSAC = auto()
+    VFWNMSAC = auto()
+    VFSQRT_V = auto()
+    VFMIN = auto()
+    VFMAX = auto()
+    VFSGNJ = auto()
+    VFSGNJN = auto()
+    VFSGNJX = auto()
+    VMFEQ = auto()
+    VMFNE = auto()
+    VMFLT = auto()
+    VMFLE = auto()
+    VMFGT = auto()
+    VMFGE = auto()
+    VFCLASS_V = auto()
+    VFMERGE = auto()
+    VFMV = auto()
+    VFCVT_XU_F_V = auto()
+    VFCVT_X_F_V = auto()
+    VFCVT_F_XU_V = auto()
+    VFCVT_F_X_V = auto()
+    VFWCVT_XU_F_V = auto()
+    VFWCVT_X_F_V = auto()
+    VFWCVT_F_XU_V = auto()
+    VFWCVT_F_X_V = auto()
+    VFWCVT_F_F_V = auto()
+    VFNCVT_XU_F_W = auto()
+    VFNCVT_X_F_W = auto()
+    VFNCVT_F_XU_W = auto()
+    VFNCVT_F_X_W = auto()
+    VFNCVT_F_F_W = auto()
+    VFNCVT_ROD_F_F_W = auto()
+    # Vector reduction instruction
+    VREDSUM_VS = auto()
+    VREDMAXU_VS = auto()
+    VREDMAX_VS = auto()
+    VREDMINU_VS = auto()
+    VREDMIN_VS = auto()
+    VREDAND_VS = auto()
+    VREDOR_VS = auto()
+    VREDXOR_VS = auto()
+    VWREDSUMU_VS = auto()
+    VWREDSUM_VS = auto()
+    VFREDOSUM_VS = auto()
+    VFREDSUM_VS = auto()
+    VFREDMAX_VS = auto()
+    VFWREDOSUM_VS = auto()
+    VFWREDSUM_VS = auto()
+    # Vector mask instruction
+    VMAND_MM = auto()
+    VMNAND_MM = auto()
+    VMANDNOT_MM = auto()
+    VMXOR_MM = auto()
+    VMOR_MM = auto()
+    VMNOR_MM = auto()
+    VMORNOT_MM = auto()
+    VMXNOR_MM = auto()
+    VPOPC_M = auto()
+    VFIRST_M = auto()
+    VMSBF_M = auto()
+    VMSIF_M = auto()
+    VMSOF_M = auto()
+    VIOTA_M = auto()
+    VID_V = auto()
+    # Vector permutation instruction
+    VMV_X_S = auto()
+    VMV_S_X = auto()
+    VFMV_F_S = auto()
+    VFMV_S_F = auto()
+    VSLIDEUP = auto()
+    VSLIDEDOWN = auto()
+    VSLIDE1UP = auto()
+    VSLIDE1DOWN = auto()
+    VRGATHER = auto()
+    VCOMPRESS = auto()
+    VMV1R_V = auto()
+    VMV2R_V = auto()
+    VMV4R_V = auto()
+    VMV8R_V = auto()
+    # Supervisor instruction
+    DRET = auto()
+    MRET = auto()
+    URET = auto()
+    SRET = auto()
+    WFI = auto()
+    SFENCE_VMA = auto()
+    # Custom instructions
+    # import riscv_custom_instr_enum #TODO: Right now it's not working as expected fix it
+    # You can add other instructions here
+    INVALID_INSTR = auto()
+
+
+class riscv_instr_format_t(Enum):
+    J_FORMAT = 0
+    U_FORMAT = auto()
+    I_FORMAT = auto()
+    B_FORMAT = auto()
+    R_FORMAT = auto()
+    S_FORMAT = auto()
+    R4_FORMAT = auto()
+    # Compressed instruction format
+    CI_FORMAT = auto()
+    CB_FORMAT = auto()
+    CJ_FORMAT = auto()
+    CR_FORMAT = auto()
+    CA_FORMAT = auto()
+    CL_FORMAT = auto()
+    CS_FORMAT = auto()
+    CSS_FORMAT = auto()
+    CIW_FORMAT = auto()
+    # Vector instruction format
+    VSET_FORMAT = auto()
+    VA_FORMAT = auto()
+    VS2_FORMAT = auto()  # op vd,vs2
+    VL_FORMAT = auto()
+    VS_FORMAT = auto()
+
+
+class riscv_instr_category_t(Enum):
+    LOAD = 0
+    STORE = auto()
+    SHIFT = auto()
+    ARITHMETIC = auto()
+    LOGICAL = auto()
+    COMPARE = auto()
+    BRANCH = auto()
+    JUMP = auto()
+    SYNCH = auto()
+    SYSTEM = auto()
+    COUNTER = auto()
+    CSR = auto()
+    CHANGELEVEL = auto()
+    TRAP = auto()
+    INTERRUPT = auto()
+    # `VECTOR_INCLUDE("riscv_instr_pkg_inc_riscv_instr_category_t.sv") TODO: Fix this
+    AMO = auto()  # (last one)
+
+
+class riscv_instr_group_t(Enum):
+    RV32I = 0
+    RV64I = auto()
+    RV32M = auto()
+    RV64M = auto()
+    RV32A = auto()
+    RV64A = auto()
+    RV32F = auto()
+    RV32FC = auto()
+    RV64F = auto()
+    RV32D = auto()
+    RV32DC = auto()
+    RV64D = auto()
+    RV32C = auto()
+    RV64C = auto()
+    RV128I = auto()
+    RV128C = auto()
+    RV32V = auto()
+    RV32B = auto()
+    RV64V = auto()
+    RV64B = auto()
+    RV32X = auto()
+    RV64X = auto()
+
+
+class imm_t(Enum):
+    IMM = 0      # Signed immediate
+    UIMM = auto()  # Unsigned immediate
+    NZUIMM = auto()  # Non-zero unsigned immediate
+    NZIMM = auto()  # Non-zero signed immediate
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
new file mode 100644
index 0000000..67bcb6a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
@@ -0,0 +1,29 @@
+"""

+Copyright 2020 Google LLC

+Copyright 2020 PerfectVIPs Inc.

+

+Licensed under the Apache License, Version 2.0 (the "License");

+you may not use this file except in compliance with the License.

+You may obtain a copy of the License at

+http://www.apache.org/licenses/LICENSE-2.0

+Unless required by applicable law or agreed to in writing, software

+distributed under the License is distributed on an "AS IS" BASIS,

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

+See the License for the specific language governing permissions and

+limitations under the License.

+Regression script for RISC-V random instruction generator

+

+"""

+

+import sys

+sys.path.append("../../")

+from pygen_src.isa.rv32i_instr import * # NOQA

+from pygen_src.isa.riscv_instr import cfg, riscv_instr_ins # NOQA

+

+

+class riscv_instr_base_test:

+    def __init__(self):

+        pass

+

+    for _ in range(cfg.num_of_test):

+        riscv_instr_ins.create_instr_list(cfg)

diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
index e616e98..a6b0913 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
@@ -6,3 +6,4 @@
 sphinx-issues
 sphinx_rtd_theme
 rst2pdf
+flake8
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
index 35853f0..bcfcf98 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
@@ -37,7 +37,7 @@
         if (category == LOAD) begin
           asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fd.name(), get_imm(), rs1.name());
         end else if (instr_name inside {FMV_X_W, FMV_X_D, FCVT_W_S, FCVT_WU_S,
-                                        FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D, FCVT_LU_S,
+                                        FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D,
                                         FCVT_W_D, FCVT_WU_D}) begin
           asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), fs1.name());
         end else if (instr_name inside {FMV_W_X, FMV_D_X, FCVT_S_W, FCVT_S_WU,
@@ -158,7 +158,9 @@
     end
     case(format)
       I_FORMAT: begin
-        `DV_CHECK_FATAL(operands.size() == 2)
+        // TODO ovpsim has an extra operand rte as below
+        // fcvt.d.s fs1,fs4,rte
+        //`DV_CHECK_FATAL(operands.size() == 2)
         if (has_fs1) begin
           fs1 = get_fpr(operands[1]);
           fs1_value = get_gpr_state(operands[1]);
@@ -177,6 +179,13 @@
         get_val(operands[1], imm);
       end
       R_FORMAT: begin
+        // convert Pseudoinstructions for ovpsim
+        // fmv.s rd, rs -> fsgnj.s rd, rs, rs
+        if (operands.size() == 2 && instr_name inside {FSGNJ_S, FSGNJX_S, FSGNJN_S, FSGNJ_D,
+                                                       FSGNJX_D, FSGNJN_D}) begin
+          operands.push_back(operands[$]);
+        end
+
         if (has_fs2 || category == CSR) begin
           `DV_CHECK_FATAL(operands.size() == 3)
         end else begin
@@ -205,7 +214,6 @@
   endfunction : update_src_regs
 
   virtual function void update_dst_regs(string reg_name, string val_str);
-    $display("update_dst_regs %0s", reg_name);
     get_val(val_str, gpr_state[reg_name], .hex(1));
     if (has_fd) begin
       fd = get_fpr(reg_name);
@@ -218,9 +226,59 @@
 
   virtual function riscv_fpr_t get_fpr(input string str);
     str = str.toupper();
-    if (!fpr_enum::from_name(str, get_fpr)) begin
+    if (!uvm_enum_wrapper#(riscv_fpr_t)::from_name(str, get_fpr)) begin
       `uvm_fatal(`gfn, $sformatf("Cannot convert %0s to FPR", str))
     end
   endfunction : get_fpr
 
+  virtual function void pre_sample();
+    super.pre_sample();
+
+    // for single precision sign bit is bit 31, upper 32 bits are all 1s
+    // for double precision, it's 63
+    if (group inside {RV32F, RV64F}) begin
+      fs1_sign = get_fp_operand_sign(fs1_value, 31);
+      fs2_sign = get_fp_operand_sign(fs2_value, 31);
+      fs3_sign = get_fp_operand_sign(fs2_value, 31);
+      fd_sign = get_fp_operand_sign(fd_value, 31);
+    end else if (instr_name == FCVT_S_D) begin
+      fs1_sign = get_fp_operand_sign(fs1_value, 63);
+      fd_sign = get_fp_operand_sign(fd_value, 31);
+    end else if (instr_name == FCVT_D_S) begin
+      fs1_sign = get_fp_operand_sign(fs1_value, 31);
+      fd_sign = get_fp_operand_sign(fd_value, 63);
+    end else begin
+      fs1_sign = get_fp_operand_sign(fs1_value, 63);
+      fs2_sign = get_fp_operand_sign(fs2_value, 63);
+      fs3_sign = get_fp_operand_sign(fs2_value, 63);
+      fd_sign = get_fp_operand_sign(fd_value, 63);
+    end
+  endfunction : pre_sample
+
+  virtual function operand_sign_e get_fp_operand_sign(bit [XLEN-1:0] value, int idx);
+    if (value[idx]) begin
+      return NEGATIVE;
+    end else begin
+      return POSITIVE;
+    end
+  endfunction
+
+  virtual function void check_hazard_condition(riscv_instr pre_instr);
+    riscv_floating_point_instr pre_fp_instr;
+    super.check_hazard_condition(pre_instr);
+    if ($cast(pre_fp_instr, pre_instr) && pre_fp_instr.has_fd) begin
+      if ((has_fs1 && (fs1 == pre_fp_instr.fd)) || (has_fs2 && (fs2 == pre_fp_instr.fd))
+          || (has_fs3 && (fs3 == pre_fp_instr.fd))) begin
+        gpr_hazard = RAW_HAZARD;
+      end else if (has_fd && (fd == pre_fp_instr.fd)) begin
+        gpr_hazard = WAW_HAZARD;
+      end else if (has_fd && ((pre_fp_instr.has_fs1 && (pre_fp_instr.fs1 == fd)) ||
+                              (pre_fp_instr.has_fs2 && (pre_fp_instr.fs2 == fd)) ||
+                              (pre_fp_instr.has_fs3 && (pre_fp_instr.fs3 == fd)))) begin
+        gpr_hazard = WAR_HAZARD;
+      end else begin
+        gpr_hazard = NO_HAZARD;
+      end
+    end
+  endfunction
 endclass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
index 087884e..88e1325 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
@@ -32,6 +32,8 @@
   static privileged_reg_t    exclude_reg[];
   static privileged_reg_t    include_reg[];
 
+  riscv_instr_gen_config     m_cfg;
+
   // Instruction attributes
   riscv_instr_group_t        group;
   riscv_instr_format_t       format;
@@ -124,7 +126,9 @@
           !(cfg.disable_compressed_instr &&
             (instr_inst.group inside {RV32C, RV64C, RV32DC, RV32FC, RV128C})) &&
           !(!cfg.enable_floating_point &&
-            (instr_inst.group inside {RV32F, RV64F, RV32D, RV64D}))
+            (instr_inst.group inside {RV32F, RV64F, RV32D, RV64D})) &&
+          !(!cfg.enable_vector_extension &&
+            (instr_inst.group inside {RVV}))
           ) begin
         instr_category[instr_inst.category].push_back(instr_name);
         instr_group[instr_inst.group].push_back(instr_name);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh
index e828f81..18b7925 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh
@@ -260,10 +260,6 @@
                               gpr_hazard.name(), lsu_hazard.name()), UVM_FULL)
   endfunction
 
-  virtual function void sample_cov();
-    pre_sample();
-  endfunction
-
   virtual function void update_src_regs(string operands[$]);
     privileged_reg_t preg;
     case(format)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
index 5fc70b4..f76f53c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
@@ -1,5 +1,6 @@
 /*
  * Copyright 2020 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +15,8 @@
  * limitations under the License.
  */
 
+
+// Base class for RISC-V vector exenstion ISA, implmented based on spec v0.8
 class riscv_vector_instr extends riscv_floating_point_instr;
 
   rand riscv_vreg_t vs1;
@@ -21,14 +24,17 @@
   rand riscv_vreg_t vs3;
   rand riscv_vreg_t vd;
   rand va_variant_t va_variant;
+  rand bit          vm;
+  rand bit          wd;
   bit               has_vd = 1'b1;
   bit               has_vs1 = 1'b1;
   bit               has_vs2 = 1'b1;
   bit               has_vs3 = 1'b1;
   bit               has_vm = 1'b0;
   bit               has_va_variant;
-  bit               is_widen_instr;
+  bit               is_widening_instr;
   bit               is_narrowing_instr;
+  bit               is_quad_widening_instr;
   bit               is_convert_instr;
   va_variant_t      allowed_va_variants[$];
 
@@ -38,34 +44,132 @@
     }
   }
 
-  // TODO: Handle different LMUL setting
-  // The destination vector register group cannot overlap a source vector
-  // register group of a different element width
-  constraint widen_instr_c {
-    int'(vd) % 2 == 0;
-    if (has_vs1) {
-      vs1 != vd;
-      vs1 != vd + 1;
-    }
-    if (has_vs2) {
-      vs2 != vd;
-      vs2 != vd + 1;
+  // Section 3.3.2: Vector Register Grouping (vlmul)
+  // Instructions specifying a vector operand with an odd-numbered vector register will raisean
+  // illegal instruction exception.
+  // TODO: Exclude the instruction that ignore VLMUL
+  constraint operand_group_c {
+    if (m_cfg.vector_cfg.vtype.vlmul > 0) {
+      vd  % m_cfg.vector_cfg.vtype.vlmul == 0;
+      vs1 % m_cfg.vector_cfg.vtype.vlmul == 0;
+      vs2 % m_cfg.vector_cfg.vtype.vlmul == 0;
+      vs3 % m_cfg.vector_cfg.vtype.vlmul == 0;
     }
   }
 
-  // rs2 is double-width source register
-  // The destination vector register group cannot overlap the rst source
-  // vector register group (specied by vs2)
+  // Section 11.2: Widening Vector Arithmetic Instructions
+  constraint widening_instr_c {
+    if (is_widening_instr) {
+     // The destination vector register group results are arranged as if both
+     // SEW and LMUL were at twice their current settings.
+     vd % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
+     // The destination vector register group cannot overlap a source vector
+     // register group of a different element width (including the mask register if masked)
+     !(vs1 inside {[vd : vd + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
+     !(vs2 inside {[vd : vd + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
+     (vm == 0) -> (vd != 0);
+     // Double-width result, first source double-width, second source single-width
+     if (va_variant inside {WV, WX}) {
+       vs2 % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
+     }
+    }
+  }
+
+  // Section 11.3: Narrowing Vector Arithmetic Instructions
   constraint narrowing_instr_c {
-    if (has_vs2) {
-      int'(vs2) % 2 == 0;
-      vd != vs2;
-      vd != vs2 + 1;
+    if (is_narrowing_instr) {
+      // The source and destination vector register numbers must be aligned
+      // appropriately for the vector registergroup size
+      vs2 % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
+      // The destination vector register group cannot overlap the rst source
+      // vector register group (specied by vs2)
+      !(vd inside {[vs2 : vs2 + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
+      // The destination vector register group cannot overlap the mask register
+      // if used, unless LMUL=1 (implemented in vmask_overlap_c)
     }
   }
 
-  // The source and destination vector register numbers must be aligned
-  // appropriately for the vector registergroup size
+  // 12.3. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
+  constraint add_sub_with_carry_c {
+    if (m_cfg.vector_cfg.vtype.vlmul > 1) {
+      // For vadc and vsbc, an illegal instruction exception is raised if the
+      // destination vector register is v0 and LMUL> 1
+      if (instr_name inside {VADC, VSBC}) {
+        vd != 0;
+      }
+      // For vmadc and vmsbc, an illegal instruction exception is raised if the
+      // destination vector register overlaps asource vector register group and LMUL > 1
+      if (instr_name inside {VMADC, VMSBC}) {
+        vd != vs2;
+        vd != vs1;
+      }
+    }
+  }
+
+  // 12.7. Vector Integer Comparison Instructions
+  // For all comparison instructions, an illegal instruction exception is raised if the
+  // destination vector register overlaps a source vector register group and LMUL > 1
+  constraint compare_instr_c {
+    if (category == COMPARE) {
+      vd != vs2;
+      vd != vs1;
+    }
+  }
+
+  // 16.8. Vector Iota Instruction
+  // An illegal instruction exception is raised if the destination vector register group
+  // overlaps the source vector mask register. If the instruction is masked, an illegal
+  // instruction exception is issued if the destination vector register group overlaps v0.
+  constraint vector_itoa_c {
+    if (instr_name == VIOTA_M) {
+      vd != vs2;
+      (vm == 0) -> (vd != 0);
+    }
+  }
+
+  // 16.9. Vector Element Index Instruction
+  // The vs2 eld of the instruction must be set to v0, otherwise the encoding is reserved
+  constraint vector_element_index_c {
+    if (instr_name == VID_V) {
+      vs2 == 0;
+      // TODO; Check if this constraint is needed
+      vd != vs2;
+    }
+  }
+
+  // Section 17.3  Vector Slide Instructions
+  // The destination vector register group for vslideup cannot overlap the vector register
+  // group of the source vector register group or the mask register
+  constraint vector_slide_c {
+    if (instr_name inside {VSLIDEUP, VSLIDE1UP, VSLIDEDOWN, VSLIDE1DOWN}) {
+      vd != vs2;
+      vd != vs1;
+      (vm == 0) -> (vd != 0);
+    }
+  }
+
+  // Section 17.4: Vector Register Gather Instruction
+  // For any vrgather instruction, the destination vector register group cannot overlap
+  // with the source vector register group
+  constraint vector_gather_c {
+    if (instr_name == VRGATHER) {
+      vd != vs2;
+      vd != vs1;
+      (vm == 0) -> (vd != 0);
+    }
+  }
+
+  // Section 17.5: Vector compress instruction
+  // The destination vector register group cannot overlap the source vector register
+  // group or the source vector mask register
+  constraint vector_compress_c {
+    if (instr_name == VCOMPRESS) {
+      vd != vs2;
+      vd != vs1;
+      (vm == 0) -> (vd != 0);
+    }
+  }
+
   constraint vmv_alignment_c {
     if (instr_name == VMV2R_V) {
       int'(vs2) % 2 == 0;
@@ -81,9 +185,86 @@
     }
   }
 
+  /////////////////// Vector mask constraint ///////////////////
+
+  // Section 5.3
+  // The destination vector register group for a masked vector instruction can only overlap
+  // the source mask register (v0) when LMUL=1
+  constraint vmask_overlap_c {
+    (vm == 0) && (m_cfg.vector_cfg.vtype.vlmul > 1) -> (vd != 0);
+  }
+
+  constraint vector_mask_enable_c {
+    // Below instruction is always masked
+    if (instr_name inside {VMERGE, VFMERGE, VADC, VSBC}) {
+      vm == 1'b0;
+    }
+  }
+
+  constraint vector_mask_disable_c {
+    // (vm=0) is reserved for below ops
+    if (instr_name inside {VMV, VFMV, VCOMPRESS, VFMV_F_S, VFMV_S_F, VMV_X_S, VMV_S_X,
+                           VMV1R_V, VMV2R_V, VMV4R_V, VMV8R_V}) {
+      vm == 1'b1;
+    }
+  }
+
+  // 16.1. Vector Mask-Register Logical Instructions
+  // No vector mask for these instructions
+  constraint vector_mask_instr_c {
+    if (instr_name inside {[VMAND_MM : VMXNOR_MM]}) {
+      vm == 1'b1;
+    }
+  }
+
+  constraint disable_floating_point_varaint_c {
+    if (!m_cfg.vector_cfg.vec_fp) {
+      va_variant != VF;
+    }
+  }
+
+  // TODO: Check why this is needed?
+  constraint vector_load_store_mask_overlap_c {
+    if (category == STORE) {
+      (vm == 0) -> (vs3 != 0);
+    }
+  }
+
   `uvm_object_utils(riscv_vector_instr)
   `uvm_object_new
 
+  // Filter unsupported instructions based on configuration
+  virtual function bit is_supported(riscv_instr_gen_config cfg);
+    string name = instr_name.name();
+    // 19.2.2. Vector Add with Carry/Subtract with Borrow Reserved under EDIV>1
+    if ((cfg.vector_cfg.vtype.vediv > 1) &&
+        (instr_name inside {VADC, VSBC, VMADC, VMSBC})) begin
+      return 1'b0;
+    end
+    // Disable widening/narrowing instruction when LMUL == 8
+    if ((!cfg.vector_cfg.vec_narrowing_widening) &&
+        (is_widening_instr || is_narrowing_instr)) begin
+      return 1'b0;
+    end
+    if (!cfg.vector_cfg.vec_quad_widening && is_quad_widening_instr) begin
+      return 1'b0;
+    end
+    // TODO: Clean up this list, it's causing gcc compile error now
+    if (instr_name inside {VWMACCSU, VMERGE, VFMERGE, VMADC, VMSBC}) begin
+      return 1'b0;
+    end
+    // The standard vector floating-point instructions treat 16-bit, 32-bit, 64-bit,
+    // and 128-bit elements as IEEE-754/2008-compatible values. If the current SEW does
+    // not correspond to a supported IEEE floating-pointtype, an illegal instruction
+    // exception is raised
+    if (!cfg.vector_cfg.vec_fp) begin
+      if ((name.substr(0, 1) == "VF") || (name.substr(0, 2) == "VMF")) begin
+        return 1'b0;
+      end
+    end
+    return 1'b1;
+  endfunction
+
   // Convert the instruction to assembly code
   virtual function string convert2asm(string prefix = "");
     string asm_str;
@@ -148,17 +329,32 @@
               end
             endcase
           end
-          if (instr_name inside {VMADC, VADC, VSBC, VMSBC, VMERGE, VFMERGE}) begin
-            if (va_variant inside {VVM, VIM, VXM, VFM}) begin
-              asm_str = {asm_str, ",v0"};
-            end
-          end else begin
-            //asm_str = {asm_str, ",v0.t"};
-          end
         end
       end
-      default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
+      VL_FORMAT: begin
+        asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vd.name(), rs1.name());
+      end
+      VS_FORMAT: begin
+        asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vs3.name(), rs1.name());
+      end
+      VLS_FORMAT: begin
+        asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), rs2.name());
+      end
+      VSS_FORMAT: begin
+        asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), rs2.name());
+      end
+      VLV_FORMAT: begin
+        asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), vs2.name());
+      end
+      VSV_FORMAT: begin
+        asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), vs2.name());
+      end
+      default: begin
+        `uvm_fatal(`gfn, $sformatf("Unsupported format %0s", format.name()))
+      end
     endcase
+    // Add vector mask
+    asm_str = {asm_str, vec_vm_str()};
     if(comment != "") begin
       asm_str = {asm_str, " #",comment};
     end
@@ -183,10 +379,14 @@
     has_fs3 = 0;
     has_fd  = 0;
     has_imm = 0;
-    if (name.substr(0, 1) == "VW") begin
-      is_widen_instr = 1'b1;
+    if ((name.substr(0, 1) == "VW") || (name.substr(0, 2) == "VFW")) begin
+      is_widening_instr = 1'b1;
     end
-    if (name.substr(0, 1) == "VN") begin
+    if (name.substr(0, 2) == "VQW") begin
+      is_quad_widening_instr = 1'b1;
+      is_widening_instr = 1'b1;
+    end
+    if ((name.substr(0, 1) == "VN") || (name.substr(0, 2) == "VFN")) begin
       is_narrowing_instr = 1'b1;
     end
     if (uvm_is_match("*CVT*", name)) begin
@@ -204,4 +404,16 @@
     end
   endfunction : set_rand_mode
 
+  virtual function string vec_vm_str();
+    if (vm) begin
+      return "";
+    end else begin
+      if (instr_name inside {VMERGE, VFMERGE, VADC, VSBC, VMADC, VMSBC}) begin
+        return ",v0";
+      end else begin
+        return ",v0.t";
+      end
+    end
+  endfunction
+
 endclass : riscv_vector_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
index 9198417..2a3eb7e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
@@ -1,5 +1,6 @@
 /*
  * Copyright 2020 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,185 +16,237 @@
  */
 
 // Vector CSR access instruction
-`DEFINE_INSTR(VSETVLI,    VSET_FORMAT, CSR, RV32V)
-`DEFINE_INSTR(VSETVL,     VSET_FORMAT, CSR, RV32V)
+`DEFINE_INSTR(VSETVLI,    VSET_FORMAT, CSR, RVV)
+`DEFINE_INSTR(VSETVL,     VSET_FORMAT, CSR, RVV)
 
 // Vector integer arithmetic instruction
-`DEFINE_VA_INSTR(VADD,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSUB,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VRSUB,    VA_FORMAT, ARITHMETIC, RV32V, {VX, VI})
-`DEFINE_VA_INSTR(VWADDU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
-`DEFINE_VA_INSTR(VWSUBU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
-`DEFINE_VA_INSTR(VWADD,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
-`DEFINE_VA_INSTR(VWSUB,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
-`DEFINE_VA_INSTR(VADC,     VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM})
-`DEFINE_VA_INSTR(VMADC,    VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM, VV, VX, VI})
-`DEFINE_VA_INSTR(VSBC,     VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM})
-`DEFINE_VA_INSTR(VMSBC,    VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VV, VX})
-`DEFINE_VA_INSTR(VAND,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VOR,      VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VXOR,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSLL,     VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSRL,     VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSRA,     VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VNSRL,    VA_FORMAT, SHIFT, RV32V, {WV, WX, WI})
-`DEFINE_VA_INSTR(VNSRA,    VA_FORMAT, SHIFT, RV32V, {WV, WX, WI})
-`DEFINE_VA_INSTR(VMSEQ,    VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VMSNE,    VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VMSLTU,   VA_FORMAT, COMPARE, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMSLT,    VA_FORMAT, COMPARE, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMSLEU,   VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VMSLE,    VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VMSGTU,   VA_FORMAT, COMPARE, RV32V, {VX, VI})
-`DEFINE_VA_INSTR(VMSGT,    VA_FORMAT, COMPARE, RV32V, {VX, VI})
-`DEFINE_VA_INSTR(VMINU,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMIN,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMAXU,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMAX,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMUL,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMULH,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMULHU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMULHSU,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VDIVU,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VDIV,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VREMU,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VREM,     VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMUL,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMULU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMULSU,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMACC,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VNMSAC,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VMADD,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VNMSUB,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMACCU,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMACC,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMACCSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VWMACCUS, VA_FORMAT, ARITHMETIC, RV32V, {VX})
-/*
-`DEFINE_VA_INSTR(VQMACCU,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VQMACC,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VQMACCSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VQMACCUS, VA_FORMAT, ARITHMETIC, RV32V, {VX})
+`DEFINE_VA_INSTR(VADD,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSUB,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VRSUB,    VA_FORMAT, ARITHMETIC, RVV, {VX, VI})
+`DEFINE_VA_INSTR(VWADDU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
+`DEFINE_VA_INSTR(VWSUBU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
+`DEFINE_VA_INSTR(VWADD,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
+`DEFINE_VA_INSTR(VWSUB,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
+`DEFINE_VA_INSTR(VADC,     VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM})
+`DEFINE_VA_INSTR(VMADC,    VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM, VV, VX, VI})
+`DEFINE_VA_INSTR(VSBC,     VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM})
+`DEFINE_VA_INSTR(VMSBC,    VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VV, VX})
+`DEFINE_VA_INSTR(VAND,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VOR,      VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VXOR,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSLL,     VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSRL,     VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSRA,     VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VNSRL,    VA_FORMAT, SHIFT, RVV, {WV, WX, WI})
+`DEFINE_VA_INSTR(VNSRA,    VA_FORMAT, SHIFT, RVV, {WV, WX, WI})
+`DEFINE_VA_INSTR(VMSEQ,    VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VMSNE,    VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VMSLTU,   VA_FORMAT, COMPARE, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMSLT,    VA_FORMAT, COMPARE, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMSLEU,   VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VMSLE,    VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VMSGTU,   VA_FORMAT, COMPARE, RVV, {VX, VI})
+`DEFINE_VA_INSTR(VMSGT,    VA_FORMAT, COMPARE, RVV, {VX, VI})
+`DEFINE_VA_INSTR(VMINU,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMIN,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMAXU,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMAX,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMUL,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMULH,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMULHU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMULHSU,  VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VDIVU,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VDIV,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VREMU,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VREM,     VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMUL,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMULU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMULSU,  VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMACC,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VNMSAC,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VMADD,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VNMSUB,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMACCU,  VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMACC,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMACCSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VWMACCUS, VA_FORMAT, ARITHMETIC, RVV, {VX})
+/* Quad widening is not yet supported
+`DEFINE_VA_INSTR(VQMACCU,  VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VQMACC,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VQMACCSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VQMACCUS, VA_FORMAT, ARITHMETIC, RVV, {VX})
 */
-`DEFINE_VA_INSTR(VMERGE,   VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM})
-`DEFINE_VA_INSTR(VMV,      VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
+`DEFINE_VA_INSTR(VMERGE,   VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM})
+`DEFINE_VA_INSTR(VMV,      VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
 
 // Vector Fixed-Point Arithmetic Instructions
-`DEFINE_VA_INSTR(VSADDU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSADD,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSSUBU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VSSUB,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VAADDU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VAADD,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VASUBU,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VASUB,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
-`DEFINE_VA_INSTR(VSSRL,    VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VSSRA,    VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
-`DEFINE_VA_INSTR(VNCLIPU,  VA_FORMAT, ARITHMETIC, RV32V, {WV, WX, WI})
-`DEFINE_VA_INSTR(VNCLIP,   VA_FORMAT, ARITHMETIC, RV32V, {WV, WX, WI})
+`DEFINE_VA_INSTR(VSADDU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSADD,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSSUBU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VSSUB,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VAADDU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VAADD,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VASUBU,   VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VASUB,    VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
+`DEFINE_VA_INSTR(VSSRL,    VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VSSRA,    VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
+`DEFINE_VA_INSTR(VNCLIPU,  VA_FORMAT, ARITHMETIC, RVV, {WV, WX, WI})
+`DEFINE_VA_INSTR(VNCLIP,   VA_FORMAT, ARITHMETIC, RVV, {WV, WX, WI})
 
 // Vector Floating-Point Instructions
-`DEFINE_VA_INSTR(VFADD,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFSUB,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFRSUB,   VA_FORMAT, ARITHMETIC, RV32V, {VF})
-`DEFINE_VA_INSTR(VFMUL,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFDIV,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFRDIV,   VA_FORMAT, ARITHMETIC, RV32V, {VF})
-`DEFINE_VA_INSTR(VFWMUL,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFMACC,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFNMACC,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFMSAC,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFNMSAC,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFMADD,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFNMADD,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFMSUB,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFNMSUB,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFWMACC,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFWNMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFWMSAC,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFWNMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFSQRT_V, VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFMIN,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFMAX,    VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFSGNJ,   VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFSGNJN,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VFSGNJX,  VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VMFEQ,    VA_FORMAT, COMPARE, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VMFNE,    VA_FORMAT, COMPARE, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VMFLT,    VA_FORMAT, COMPARE, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VMFLE,    VA_FORMAT, COMPARE, RV32V, {VV, VF})
-`DEFINE_VA_INSTR(VMFGT,    VA_FORMAT, COMPARE, RV32V, {VF})
-`DEFINE_VA_INSTR(VMFGE,    VA_FORMAT, COMPARE, RV32V, {VF})
-`DEFINE_VA_INSTR(VFCLASS_V,VS2_FORMAT, COMPARE, RV32V)
-`DEFINE_VA_INSTR(VFMERGE,  VA_FORMAT, ARITHMETIC, RV32V, {VFM})
-`DEFINE_VA_INSTR(VFMV,     VA_FORMAT, ARITHMETIC, RV32V, {VF})
+`DEFINE_VA_INSTR(VFADD,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFSUB,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFRSUB,   VA_FORMAT, ARITHMETIC, RVV, {VF})
+`DEFINE_VA_INSTR(VFMUL,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFDIV,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFRDIV,   VA_FORMAT, ARITHMETIC, RVV, {VF})
+`DEFINE_VA_INSTR(VFWMUL,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFMACC,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFNMACC,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFMSAC,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFNMSAC,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFMADD,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFNMADD,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFMSUB,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFNMSUB,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFWMACC,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFWNMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFWMSAC,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFWNMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFSQRT_V, VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFMIN,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFMAX,    VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFSGNJ,   VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFSGNJN,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VFSGNJX,  VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VMFEQ,    VA_FORMAT, COMPARE, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VMFNE,    VA_FORMAT, COMPARE, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VMFLT,    VA_FORMAT, COMPARE, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VMFLE,    VA_FORMAT, COMPARE, RVV, {VV, VF})
+`DEFINE_VA_INSTR(VMFGT,    VA_FORMAT, COMPARE, RVV, {VF})
+`DEFINE_VA_INSTR(VMFGE,    VA_FORMAT, COMPARE, RVV, {VF})
+`DEFINE_VA_INSTR(VFCLASS_V,VS2_FORMAT, COMPARE, RVV)
+`DEFINE_VA_INSTR(VFMERGE,  VA_FORMAT, ARITHMETIC, RVV, {VFM})
+`DEFINE_VA_INSTR(VFMV,     VA_FORMAT, ARITHMETIC, RVV, {VF})
 
 // Vector conversion instructions
-`DEFINE_VA_INSTR(VFCVT_XU_F_V,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFCVT_X_F_V,      VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFCVT_F_XU_V,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFCVT_F_X_V,      VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWCVT_XU_F_V,    VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWCVT_X_F_V,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWCVT_F_XU_V,    VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWCVT_F_X_V,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWCVT_F_F_V,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_XU_F_W,    VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_X_F_W,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_F_XU_W,    VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_F_X_W,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_F_F_W,     VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFNCVT_ROD_F_F_W, VS2_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VFCVT_XU_F_V,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFCVT_X_F_V,      VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFCVT_F_XU_V,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFCVT_F_X_V,      VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWCVT_XU_F_V,    VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWCVT_X_F_V,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWCVT_F_XU_V,    VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWCVT_F_X_V,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWCVT_F_F_V,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_XU_F_W,    VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_X_F_W,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_F_XU_W,    VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_F_X_W,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_F_F_W,     VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFNCVT_ROD_F_F_W, VS2_FORMAT, ARITHMETIC, RVV)
 
 // Vector reduction instruction
-`DEFINE_VA_INSTR(VREDSUM_VS,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDMAXU_VS,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDMAX_VS,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDMINU_VS,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDMIN_VS,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDAND_VS,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDOR_VS,     VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VREDXOR_VS,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VWREDSUMU_VS,  VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VWREDSUM_VS,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFREDOSUM_VS,  VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFREDSUM_VS,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFREDMAX_VS,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWREDOSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFWREDSUM_VS,  VA_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VREDSUM_VS,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDMAXU_VS,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDMAX_VS,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDMINU_VS,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDMIN_VS,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDAND_VS,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDOR_VS,     VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VREDXOR_VS,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VWREDSUMU_VS,  VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VWREDSUM_VS,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFREDOSUM_VS,  VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFREDSUM_VS,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFREDMAX_VS,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWREDOSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFWREDSUM_VS,  VA_FORMAT, ARITHMETIC, RVV)
 
 // Vector mask instruction
-`DEFINE_VA_INSTR(VMAND_MM,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMNAND_MM,   VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMANDNOT_MM, VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMXOR_MM,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMOR_MM,     VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMNOR_MM,    VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMORNOT_MM,  VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMXNOR_MM,   VA_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VMAND_MM,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMNAND_MM,   VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMANDNOT_MM, VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMXOR_MM,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMOR_MM,     VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMNOR_MM,    VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMORNOT_MM,  VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMXNOR_MM,   VA_FORMAT, ARITHMETIC, RVV)
 
-`DEFINE_VA_INSTR(VPOPC_M,   VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFIRST_M,  VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMSBF_M,   VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMSIF_M,   VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMSOF_M,   VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VIOTA_M,   VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VID_V,     VS2_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VPOPC_M,   VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFIRST_M,  VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMSBF_M,   VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMSIF_M,   VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMSOF_M,   VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VIOTA_M,   VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VID_V,     VS2_FORMAT, ARITHMETIC, RVV)
 
 // Vector permutation instruction
-`DEFINE_VA_INSTR(VMV_X_S,  VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMV_S_X,  VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFMV_F_S, VA_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VFMV_S_F, VA_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VMV_X_S,  VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMV_S_X,  VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFMV_F_S, VA_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VFMV_S_F, VA_FORMAT, ARITHMETIC, RVV)
 
-`DEFINE_VA_INSTR(VSLIDEUP,    VA_FORMAT, ARITHMETIC, RV32V, {VI,VX})
-`DEFINE_VA_INSTR(VSLIDEDOWN,  VA_FORMAT, ARITHMETIC, RV32V, {VI,VX})
-`DEFINE_VA_INSTR(VSLIDE1UP,   VA_FORMAT, ARITHMETIC, RV32V, {VX})
-`DEFINE_VA_INSTR(VSLIDE1DOWN, VA_FORMAT, ARITHMETIC, RV32V, {VX})
-`DEFINE_VA_INSTR(VRGATHER,    VA_FORMAT, ARITHMETIC, RV32V, {VV,VX,VI})
-`DEFINE_VA_INSTR(VCOMPRESS,   VA_FORMAT, ARITHMETIC, RV32V, {VM})
+`DEFINE_VA_INSTR(VSLIDEUP,    VA_FORMAT, ARITHMETIC, RVV, {VI,VX})
+`DEFINE_VA_INSTR(VSLIDEDOWN,  VA_FORMAT, ARITHMETIC, RVV, {VI,VX})
+`DEFINE_VA_INSTR(VSLIDE1UP,   VA_FORMAT, ARITHMETIC, RVV, {VX})
+`DEFINE_VA_INSTR(VSLIDE1DOWN, VA_FORMAT, ARITHMETIC, RVV, {VX})
+`DEFINE_VA_INSTR(VRGATHER,    VA_FORMAT, ARITHMETIC, RVV, {VV,VX,VI})
+`DEFINE_VA_INSTR(VCOMPRESS,   VA_FORMAT, ARITHMETIC, RVV, {VM})
 
-`DEFINE_VA_INSTR(VMV1R_V, VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMV2R_V, VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMV4R_V, VS2_FORMAT, ARITHMETIC, RV32V)
-`DEFINE_VA_INSTR(VMV8R_V, VS2_FORMAT, ARITHMETIC, RV32V)
+`DEFINE_VA_INSTR(VMV1R_V, VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMV2R_V, VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMV4R_V, VS2_FORMAT, ARITHMETIC, RVV)
+`DEFINE_VA_INSTR(VMV8R_V, VS2_FORMAT, ARITHMETIC, RVV)
+
+// -------------------------------------------------------------------------
+//  Section 7. Vector Loads and Stores
+// -------------------------------------------------------------------------
+// Section 7.4 - Vector Unit-Stride Instructions
+`DEFINE_VA_INSTR(VLE_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSE_V, VS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VLB_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSB_V, VS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VLH_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSH_V, VS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VLW_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSW_V, VS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VLBU_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLHU_V, VS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLWU_V, VL_FORMAT, LOAD, RVV)
+// Section 7.5 - Vector Strided Instructions
+`DEFINE_VA_INSTR(VLSB_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSH_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSW_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSBU_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSHU_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSWU_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLSE_V, VLS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSSB_V, VSS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSSH_V, VSS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSSW_V, VSS_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSSE_V, VSS_FORMAT, STORE, RVV)
+// Section 7.6 - Vector Indexed Instructions
+`DEFINE_VA_INSTR(VLXB_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXH_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXW_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXBU_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXHU_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXWU_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXE_V, VLV_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSXB_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXH_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXW_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXE_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXB_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXH_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXW_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXE_V, VSV_FORMAT, STORE, RVV)
+// Section 7.7 - Vector Unit-Stride Fault-Only-First Loads
+`DEFINE_VA_INSTR(VLBFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLHFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLWFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLBUFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLHUFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLWUFF_V, VL_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLEFF_V, VL_FORMAT, LOAD, RVV)
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 96d3cad..d9a4876 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
@@ -1,5 +1,6 @@
 /*
  * Copyright 2018 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -78,7 +79,7 @@
       gen_init_section(hart);
       // If PMP is supported, we want to generate the associated trap handlers and the test_done
       // section at the start of the program so we can allow access through the pmpcfg0 CSR
-      if (support_pmp && !cfg.bare_program_mode) begin
+      if (riscv_instr_pkg::support_pmp && !cfg.bare_program_mode) begin
         gen_trap_handlers(hart);
         // Ecall handler
         gen_ecall_handler(hart);
@@ -119,7 +120,7 @@
       instr_stream = {instr_stream, $sformatf("%sj test_done", indent)};
       // Test done section
       // If PMP isn't supported, generate this in the normal location
-      if (hart == 0 & !support_pmp) begin
+      if (hart == 0 & !riscv_instr_pkg::support_pmp) begin
         gen_test_done();
       end
       // Shuffle the sub programs and insert to the instruction stream
@@ -320,7 +321,8 @@
     if (cfg.disable_compressed_instr) begin
       instr_stream.push_back(".option norvc;");
     end
-    str = {"csrr x5, mhartid"};
+    str.push_back(".include \"user_init.s\"");
+    str.push_back("csrr x5, mhartid");
     for (int hart = 0; hart < cfg.num_of_harts; hart++) begin
       str = {str, $sformatf("li x6, %0d", hart),
                   $sformatf("beq x5, x6, %0df", hart)};
@@ -411,19 +413,19 @@
     string str;
     str = format_string(get_label("init:", hart), LABEL_STR_LEN);
     instr_stream.push_back(str);
+    if (cfg.enable_floating_point) begin
+      init_floating_point_gpr();
+    end
     init_gpr();
     // Init stack pointer to point to the end of the user stack
     str = {indent, $sformatf("la x%0d, %0suser_stack_end", cfg.sp, hart_prefix(hart))};
     instr_stream.push_back(str);
-    if (cfg.enable_floating_point) begin
-      init_floating_point_gpr();
-    end
     if (cfg.enable_vector_extension) begin
-      init_vector_engine();
+      randomize_vec_gpr_and_csr();
     end
     core_is_initialized();
     gen_dummy_csr_write(); // TODO add a way to disable xStatus read
-    if (support_pmp) begin
+    if (riscv_instr_pkg::support_pmp) begin
       str = {indent, "j main"};
       instr_stream.push_back(str);
     end
@@ -446,7 +448,7 @@
         RV32B, RV64B         : misa[MISA_EXT_B] = 1'b1;
         RV32F, RV64F, RV32FC : misa[MISA_EXT_F] = 1'b1;
         RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1;
-        RV32V, RV64V         : misa[MISA_EXT_V] = 1'b1;
+        RVV                  : misa[MISA_EXT_V] = 1'b1;
         RV32X, RV64X         : misa[MISA_EXT_X] = 1'b1;
         default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported",
                                    supported_isa[i].name()))
@@ -515,7 +517,7 @@
     string str;
     bit [DATA_WIDTH-1:0] reg_val;
     // Init general purpose registers with random values
-    for(int i = 0; i < 32; i++) begin
+    for(int i = 0; i < NUM_GPR; i++) begin
       if (i inside {cfg.sp, cfg.tp}) continue;
       `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(reg_val,
         reg_val dist {
@@ -530,38 +532,132 @@
     end
   endfunction
 
+  // Initialize vector general purpose registers
+  virtual function void init_vec_gpr();
+    int SEW;
+    int LMUL;
+    int EDIV = 1;
+    int len = (ELEN <= XLEN) ? ELEN : XLEN;
+    int num_elements = VLEN / len;
+    if (!(RVV inside {supported_isa})) return;
+    LMUL = 1;
+    SEW = (ELEN <= XLEN) ? ELEN : XLEN;
+    instr_stream.push_back($sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl));
+    // vec registers will be loaded from a scalar GPR, one element at a time
+    instr_stream.push_back($sformatf("%svsetvli x%0d, x%0d, e%0d, m%0d, d%0d",
+                                     indent, cfg.gpr[0], cfg.gpr[1], SEW, LMUL, EDIV));
+    instr_stream.push_back("vec_reg_init:");
+    for (int v = 1; v < NUM_VEC_GPR; v++) begin
+      for (int e = 0; e < num_elements; e++) begin
+        if (e > 0) instr_stream.push_back($sformatf("%0svmv.v.v v0, v%0d", indent, v));
+        instr_stream.push_back($sformatf("%0sli x%0d, 0x%0x",
+                                         indent, cfg.gpr[0], $urandom_range(0, 2 ** SEW - 1)));
+        instr_stream.push_back($sformatf("%0svslide1up.vx v%0d, v0, t0", indent, v));
+      end
+    end
+  endfunction
+
   // Initialize floating point general purpose registers
   virtual function void init_floating_point_gpr();
     int int_gpr;
     string str;
-    // TODO: Initialize floating point GPR with more interesting numbers
-    for(int i = 0; i < 32; i++) begin
-      int_gpr = $urandom_range(0, 31);
-      // Use a random integer GPR to initialize floating point GPR
-      if (RV64F inside {supported_isa}) begin
-        str = $sformatf("%0sfcvt.d.l f%0d, x%0d", indent, i, int_gpr);
-      end else begin
-        str = $sformatf("%0sfcvt.s.w f%0d, x%0d", indent, i, int_gpr);
-      end
-      instr_stream.push_back(str);
+    for(int i = 0; i < NUM_FLOAT_GPR; i++) begin
+      randcase
+        1: init_floating_point_gpr_with_spf(i);
+        RV64D inside {supported_isa}: init_floating_point_gpr_with_dpf(i);
+      endcase
     end
     // Initialize rounding mode of FCSR
     str = $sformatf("%0sfsrmi %0d", indent, cfg.fcsr_rm);
     instr_stream.push_back(str);
   endfunction
 
-  // Initialize vector registers
-  virtual function void init_vector_engine();
-    string str[$];
-    // Initialize vtype, vl
-    str = {str, $sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl),
-                $sformatf("vsetvli x%0d, x%0d, e%0d",
-                          cfg.gpr[0], cfg.gpr[1], 8 * (2 ** cfg.vector_cfg.vtype.vsew))};
-    for(int i = 0; i < 32; i++) begin
-      // Use integer register to initialize vector register
-      str = {str, $sformatf("vmv.v.x v%0d, x%0d", i, i)};
+  // get instructions initialize floating_point_gpr with single precision floating value
+  virtual function void init_floating_point_gpr_with_spf(int int_floating_gpr);
+    string str;
+    bit [31:0] imm = get_rand_spf_value();
+    int int_gpr = $urandom_range(0, NUM_GPR - 1);
+
+    str = $sformatf("%0sli x%0d, %0d", indent, int_gpr, imm);
+    instr_stream.push_back(str);
+    str = $sformatf("%0sfmv.w.x f%0d, x%0d", indent, int_floating_gpr, int_gpr);
+    instr_stream.push_back(str);
+  endfunction
+
+  // get instructions initialize floating_point_gpr with double precision floating value
+  virtual function void init_floating_point_gpr_with_dpf(int int_floating_gpr);
+    string str;
+    bit [63:0] imm = get_rand_dpf_value();
+    int int_gpr1 = $urandom_range(1, NUM_GPR - 1);
+    int int_gpr2 = $urandom_range(1, NUM_GPR - 1);
+
+    str = $sformatf("%0sli x%0d, %0d", indent, int_gpr1, imm[63:32]);
+    instr_stream.push_back(str);
+    // shift to upper 32bits
+    repeat (2) begin
+      str = $sformatf("%0sslli x%0d, x%0d, 16", indent, int_gpr1, int_gpr1);
+      instr_stream.push_back(str);
     end
-    instr_stream = {instr_stream, str};
+    str = $sformatf("%0sli x%0d, %0d", indent, int_gpr2, imm[31:0]);
+    instr_stream.push_back(str);
+    str = $sformatf("%0sor x%0d, x%0d, x%0d", indent, int_gpr2, int_gpr2, int_gpr1);
+    instr_stream.push_back(str);
+    str = $sformatf("%0sfmv.d.x f%0d, x%0d", indent, int_floating_gpr, int_gpr2);
+    instr_stream.push_back(str);
+  endfunction
+
+  // get a random single precision floating value
+  virtual function bit [XLEN-1:0] get_rand_spf_value();
+    bit [31:0] value;
+
+    randcase
+      // infinity
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value inside {32'h7f80_0000, 32'hff80_0000};)
+      // largest
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value inside {32'h7f7f_ffff, 32'hff7f_ffff};)
+      // zero
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value inside {32'h0000_0000, 32'h8000_0000};)
+      // NaN
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value inside {32'h7f80_0001, 32'h7fc0_0000};)
+      // normal
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value[30:SINGLE_PRECISION_FRACTION_BITS] > 0;)
+      // subnormal
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+                                            value[30:SINGLE_PRECISION_FRACTION_BITS] == 0;)
+    endcase
+    return value;
+  endfunction
+
+  // get a random double precision floating value
+  virtual function bit [XLEN-1:0] get_rand_dpf_value();
+    bit [63:0] value;
+
+    randcase
+      // infinity
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value inside {64'h7ff0_0000_0000_0000, 64'hfff0_0000_0000_0000};)
+      // largest
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value inside {64'h7fef_ffff_ffff_ffff, 64'hffef_ffff_ffff_ffff};)
+      // zero
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value inside {64'h0000_0000_0000_0000, 64'h8000_0000_0000_0000};)
+      // NaN
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value inside {64'h7ff0_0000_0000_0001, 64'h7ff8_0000_0000_0000};)
+      // normal
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value[62:DOUBLE_PRECISION_FRACTION_BITS] > 0;)
+      // subnormal
+      1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
+             value[62:DOUBLE_PRECISION_FRACTION_BITS] == 0;)
+    endcase
+    return value;
   endfunction
 
   // Generate "test_done" section, test is finished by an ECALL instruction
@@ -795,7 +891,7 @@
   virtual function void gen_all_trap_handler(int hart);
     string instr[$];
     // If PMP isn't supported, generate the relevant trap handler sections as per usual
-    if (!support_pmp) begin
+    if (!riscv_instr_pkg::support_pmp) begin
       gen_trap_handlers(hart);
       // Ecall handler
       gen_ecall_handler(hart);
@@ -1450,4 +1546,25 @@
     instr_stream = {instr_stream, debug_rom.instr_stream};
   endfunction
 
+  //---------------------------------------------------------------------------------------
+  // Vector extension generation
+  //---------------------------------------------------------------------------------------
+
+  virtual function void randomize_vec_gpr_and_csr();
+    if (!(RVV inside {supported_isa})) return;
+    instr_stream.push_back({indent, $sformatf("li x%0d, %0d", cfg.gpr[0], cfg.vector_cfg.vxsat)});
+    instr_stream.push_back({indent, $sformatf("csrw vxsat, x%0d", cfg.gpr[0])});
+    instr_stream.push_back({indent, $sformatf("li x%0d, %0d", cfg.gpr[0], cfg.vector_cfg.vxrm)});
+    instr_stream.push_back({indent, $sformatf("csrw vxrm, x%0d", cfg.gpr[0])});
+    init_vec_gpr(); // GPR init uses a temporary SEW/LMUL setting before the final value set below.
+    instr_stream.push_back($sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl));
+    instr_stream.push_back($sformatf("%svsetvli x%0d, x%0d, e%0d, m%0d, d%0d",
+                                     indent,
+                                     cfg.gpr[0],
+                                     cfg.gpr[1],
+                                     cfg.vector_cfg.vtype.vsew,
+                                     cfg.vector_cfg.vtype.vlmul,
+                                     cfg.vector_cfg.vtype.vediv));
+  endfunction
+
 endclass
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 3dfba5d..f3bc708 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
@@ -192,9 +192,9 @@
       instr_list[i].atomic = 1'b1;
     end
     jump.has_label = 1'b1;
-    jump.label = "1";
+    jump.label = $sformatf("%0s_j%0d", label, idx);
     jump.comment = $sformatf("jump %0s -> %0s", label, target_program_label);
-    branch.imm_str = "1f";
+    branch.imm_str = jump.label;
     branch.comment = "branch to jump instr";
     branch.branch_assigned = 1'b1;
   endfunction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
index 9c016e6..33896ad 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
@@ -228,17 +228,62 @@
   `INSTR_CG_BEGIN(INSTR_NAME) \
     cp_imm_sign : coverpoint instr.imm_sign;
 
-// TODO, will handle special value later
-// single-precision floating point special values coverpoint
-`define FP_SPECIAL_VALUES_CP(VAR, NAME) \
-    cp_fp_special_values_on_``NAME`` : coverpoint VAR { \
+// single/double precision floating point special values coverpoint
+`define FP_SPECIAL_VALUES_CP(VAR, NAME, PRECISION = S) \
+    cp_sfp_special_values_on_``NAME`` : coverpoint VAR[31:0] { \
+      option.weight = (`"PRECISION`" == "S"); \
+      type_option.weight = (`"PRECISION`" == "S"); \
       bins infinity[] = {32'h7f80_0000, 32'hff80_0000}; \
       bins largest[]  = {32'h7f7f_ffff, 32'hff7f_ffff}; \
-      bins zeros[]    = {32'h0000_0000, 32'h1000_0000}; \
-      bins NaN[]      = {32'h7fc0_0000, 32'h7f80_0000}; \
+      bins zeros[]    = {32'h0000_0000, 32'h8000_0000}; \
+      bins NaN[]      = {32'h7f80_0001, 32'h7fc0_0000}; \
+    } \
+    cp_sfp_subnormal_on_``NAME`` : coverpoint VAR[30:SINGLE_PRECISION_FRACTION_BITS] == 0 { \
+      option.weight = (`"PRECISION`" == "S"); \
+      type_option.weight = (`"PRECISION`" == "S"); \
+    } \
+    cp_dfp_special_values_on_``NAME`` : coverpoint VAR { \
+      option.weight = (`"PRECISION`" == "D"); \
+      type_option.weight = (`"PRECISION`" == "D"); \
+      bins infinity[] = {64'h7ff0_0000_0000_0000, 64'hfff0_0000_0000_0000}; \
+      bins largest[]  = {64'h7fef_ffff_ffff_ffff, 64'hffef_ffff_ffff_ffff}; \
+      bins zeros[]    = {64'h0000_0000_0000_0000, 64'h8000_0000_0000_0000}; \
+      bins NaN[]      = {64'h7ff0_0000_0000_0001, 64'h7ff8_0000_0000_0000}; \
+    } \
+    cp_dfp_subnormal_on_``NAME`` : coverpoint VAR[62:DOUBLE_PRECISION_FRACTION_BITS-1] == 0 { \
+      option.weight = (`"PRECISION`" == "D"); \
+      type_option.weight = (`"PRECISION`" == "D"); \
     }
 
-`define FP_R_INSTR_CG_BEGIN(INSTR_NAME) \
+`define FP_LOAD_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_rs1         : coverpoint instr.rs1 { \
+      `DV(ignore_bins zero = {ZERO};) \
+    } \
+    cp_fd          : coverpoint instr.fd; \
+    cp_imm_sign    : coverpoint instr.imm_sign; \
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
+    `DV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \
+    `DV(cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
+      bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
+    })
+
+`define FP_STORE_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_rs1         : coverpoint instr.rs1 { \
+        `DV(ignore_bins zero = {ZERO};) \
+    } \
+    cp_fs2         : coverpoint instr.fs2; \
+    cp_imm_sign    : coverpoint instr.imm_sign; \
+    `FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
+    `DV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
+      bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
+    }) \
+    `DV(cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
+      bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
+    })
+
+`define FP_R_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
   `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
     cp_fs1         : coverpoint instr.fs1; \
     cp_fs2         : coverpoint instr.fs2; \
@@ -246,9 +291,12 @@
     cp_fs1_sign    : coverpoint instr.fs1_sign; \
     cp_fs2_sign    : coverpoint instr.fs2_sign; \
     cp_fd_sign     : coverpoint instr.fd_sign; \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
     `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
 
-`define FP_R4_INSTR_CG_BEGIN(INSTR_NAME) \
+`define FP_R4_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
   `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
     cp_fs1         : coverpoint instr.fs1; \
     cp_fs2         : coverpoint instr.fs2; \
@@ -259,14 +307,74 @@
     cp_fs3_sign    : coverpoint instr.fs3_sign; \
     cp_fd_sign     : coverpoint instr.fd_sign; \
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fs3_sign, cp_fd_sign; \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fs3_value, fs3_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
     `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
 
-`define FSQRT_INSTR_CG_BEGIN(INSTR_NAME) \
+`define FSQRT_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
   `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
     cp_fs1         : coverpoint instr.fs1; \
     cp_fd          : coverpoint instr.fd;  \
     cp_fs1_sign    : coverpoint instr.fs1_sign; \
     cp_fd_sign     : coverpoint instr.fd_sign; \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+// FCVT integer to floating
+`define FP_I2F_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S, SIGN_TYP = SIGN) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_rs1         : coverpoint instr.rs1; \
+    cp_fd          : coverpoint instr.fd; \
+    cp_rs1_sign    : coverpoint instr.rs1_sign { \
+      option.weight = (`"SIGN_TYP`" == "SIGN"); \
+      type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
+    } \
+    cp_fd_sign     : coverpoint instr.fd_sign { \
+      option.weight = (`"SIGN_TYP`" == "SIGN"); \
+      type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
+    } \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+// FCVT floating to integer
+`define FP_F2I_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S, SIGN_TYP = SIGN) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_fs1         : coverpoint instr.fs1; \
+    cp_rd          : coverpoint instr.rd;  \
+    cp_fs1_sign    : coverpoint instr.fs1_sign; \
+    cp_rd_sign     : coverpoint instr.rd_sign { \
+      option.weight = (`"SIGN_TYP`" == "SIGN"); \
+      type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
+    } \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+// floating compare instructions
+`define FP_CMP_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_fs1         : coverpoint instr.fs1; \
+    cp_fs2         : coverpoint instr.fs2; \
+    cp_rd          : coverpoint instr.rd;  \
+    cp_fs1_sign    : coverpoint instr.fs1_sign; \
+    cp_fs2_sign    : coverpoint instr.fs2_sign; \
+    `CP_VALUE_RANGE(compare_result, instr.rd_value, 0, 1) \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
+    `FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define FCLASS_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
+  `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
+    cp_fs1         : coverpoint instr.fs1; \
+    cp_rd          : coverpoint instr.rd;  \
+    cp_fs1_sign    : coverpoint instr.fs1_sign; \
+    cp_rd_value    : coverpoint instr.rd_value { \
+      bins values[] = {0, 'b1, 'b10, 'b100, 'b1000, 'b1_0000, 'b10_0000, \
+                       'b100_0000, 'b1000_0000, 'b1_0000_0000, 'b10_0000_0000}; \
+      illegal_bins others = default; \
+    } \
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
     `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
 
 `define B_I_INSTR_CG_BEGIN(INSTR_NAME) \
@@ -317,7 +425,6 @@
 class riscv_instr_cover_group;
 
   riscv_instr_gen_config  cfg;
-  riscv_instr             cur_instr;
   riscv_instr             pre_instr;
   riscv_instr_name_t      instr_list[$];
   int unsigned            instr_cnt;
@@ -537,72 +644,219 @@
   `CG_END
 
   // floating instructions
-  `INSTR_CG_BEGIN(flw, riscv_floating_point_instr)
-    cp_rs1         : coverpoint instr.rs1 {
-      `DV(ignore_bins zero = {ZERO};)
-    }
-    cp_fd          : coverpoint instr.fd;
-    cp_imm_sign    : coverpoint instr.imm_sign;
-    `DV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
-    `DV(cp_lsu_hazard  : coverpoint instr.lsu_hazard {
-      bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
-    })
+  `FP_LOAD_INSTR_CG_BEGIN(flw)
   `CG_END
 
-  `INSTR_CG_BEGIN(fsw, riscv_floating_point_instr)
-    cp_rs1         : coverpoint instr.rs1 {
-        `DV(ignore_bins zero = {ZERO};)
-    }
-    cp_fs2         : coverpoint instr.fs2;
-    cp_imm_sign    : coverpoint instr.imm_sign;
-    `DV(cp_gpr_hazard  : coverpoint instr.gpr_hazard {
-      bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
-    })
-    `DV(cp_lsu_hazard  : coverpoint instr.lsu_hazard {
-      bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD};
-    })
+  `FP_LOAD_INSTR_CG_BEGIN(fld, D)
+  `CG_END
+
+  `FP_STORE_INSTR_CG_BEGIN(fsw)
+  `CG_END
+
+  `FP_STORE_INSTR_CG_BEGIN(fsd, D)
   `CG_END
 
   `FP_R_INSTR_CG_BEGIN(fadd_s)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
   `CG_END
 
+  `FP_R_INSTR_CG_BEGIN(fadd_d, D)
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
+  `CG_END
+
   `FP_R_INSTR_CG_BEGIN(fsub_s)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
   `CG_END
 
+  `FP_R_INSTR_CG_BEGIN(fsub_d, D)
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
+  `CG_END
+
   `FP_R_INSTR_CG_BEGIN(fmul_s)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
   `CG_END
 
+  `FP_R_INSTR_CG_BEGIN(fmul_d, D)
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
+  `CG_END
+
   `FP_R_INSTR_CG_BEGIN(fdiv_s)
-    cp_div_result: coverpoint instr.div_result;
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fdiv_d, D)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
   `CG_END
 
   `FSQRT_INSTR_CG_BEGIN(fsqrt_s)
   `CG_END
 
+  `FSQRT_INSTR_CG_BEGIN(fsqrt_d, D)
+  `CG_END
+
   `FP_R_INSTR_CG_BEGIN(fmin_s)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
   `CG_END
 
+  `FP_R_INSTR_CG_BEGIN(fmin_d, D)
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
+  `CG_END
+
   `FP_R_INSTR_CG_BEGIN(fmax_s)
     cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
   `CG_END
 
+  `FP_R_INSTR_CG_BEGIN(fmax_d, D)
+    cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
+  `CG_END
+
   `FP_R4_INSTR_CG_BEGIN(fmadd_s)
   `CG_END
 
+  `FP_R4_INSTR_CG_BEGIN(fmadd_d, D)
+  `CG_END
+
   `FP_R4_INSTR_CG_BEGIN(fnmadd_s)
   `CG_END
 
+  `FP_R4_INSTR_CG_BEGIN(fnmadd_d, D)
+  `CG_END
+
   `FP_R4_INSTR_CG_BEGIN(fmsub_s)
   `CG_END
 
+  `FP_R4_INSTR_CG_BEGIN(fmsub_d, D)
+  `CG_END
+
   `FP_R4_INSTR_CG_BEGIN(fnmsub_s)
   `CG_END
 
+  `FP_R4_INSTR_CG_BEGIN(fnmsub_d, D)
+  `CG_END
+
+  // FCVT floating to floating
+  `INSTR_CG_BEGIN(fcvt_s_d, riscv_floating_point_instr)
+    cp_fs1         : coverpoint instr.fs1;
+    cp_fd          : coverpoint instr.fd;
+    cp_fs1_sign    : coverpoint instr.fs1_sign;
+    cp_fd_sign     : coverpoint instr.fd_sign;
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, D)
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, S)
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+  `CG_END
+
+  `INSTR_CG_BEGIN(fcvt_d_s, riscv_floating_point_instr)
+    cp_fs1         : coverpoint instr.fs1;
+    cp_fd          : coverpoint instr.fd;
+    cp_fs1_sign    : coverpoint instr.fs1_sign;
+    cp_fd_sign     : coverpoint instr.fd_sign;
+    `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, S)
+    `FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, D)
+    `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_w_s)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_wu_s, , UNSIGN)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_l_s)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_lu_s, UNSIGN)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_l_d, D)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_lu_d, D, UNSIGN)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_w_d, D)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fcvt_wu_d, D, UNSIGN)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_s_w)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_s_wu, , UNSIGN)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_s_l)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_d_l, D)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_s_lu, , UNSIGN)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_d_w, D)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_d_lu, D, UNSIGN)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fcvt_d_wu, D, UNSIGN)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnj_s)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnj_d, D)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnjn_s)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnjn_d, D)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnjx_s)
+  `CG_END
+
+  `FP_R_INSTR_CG_BEGIN(fsgnjx_d, D)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fmv_x_w)
+  `CG_END
+
+  `FP_F2I_INSTR_CG_BEGIN(fmv_x_d, D)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fmv_w_x)
+  `CG_END
+
+  `FP_I2F_INSTR_CG_BEGIN(fmv_d_x, D)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(feq_s)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(feq_d, D)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(flt_s)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(flt_d, D)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(fle_s)
+  `CG_END
+
+  `FP_CMP_INSTR_CG_BEGIN(fle_d, D)
+  `CG_END
+
+  `FCLASS_INSTR_CG_BEGIN(fclass_s)
+  `CG_END
+
+  `FCLASS_INSTR_CG_BEGIN(fclass_d, D)
+  `CG_END
+
   // B extension
   // Count Leading/Trailing Zeros (clz, ctz)
   `B_R_INSTR_NO_RS2_CG_BEGIN(clz)
@@ -1462,8 +1716,6 @@
   function new(riscv_instr_gen_config cfg);
     string opts;
     this.cfg = cfg;
-    cur_instr = riscv_instr::type_id::create("cur_instr");
-    pre_instr = riscv_instr::type_id::create("pre_instr");
     build_instr_list();
     `ifdef COMPLIANCE_MODE
       compliance_mode = 1;
@@ -1659,6 +1911,64 @@
       fnmadd_s_cg = new();
       fmsub_s_cg  = new();
       fnmsub_s_cg = new();
+      fcvt_w_s_cg  = new();
+      fcvt_wu_s_cg = new();
+      fcvt_s_w_cg  = new();
+      fcvt_s_wu_cg = new();
+      fsgnj_s_cg   = new();
+      fsgnjn_s_cg  = new();
+      fsgnjx_s_cg  = new();
+      fmv_x_w_cg   = new();
+      fmv_w_x_cg   = new();
+      feq_s_cg     = new();
+      flt_s_cg     = new();
+      fle_s_cg     = new();
+      fclass_s_cg  = new();
+    `CG_SELECTOR_END
+
+    `CG_SELECTOR_BEGIN(RV32D)
+      fld_cg      = new();
+      fsd_cg      = new();
+      fadd_d_cg   = new();
+      fsub_d_cg   = new();
+      fdiv_d_cg   = new();
+      fmul_d_cg   = new();
+      fmadd_d_cg  = new();
+      fnmadd_d_cg = new();
+      fmsub_d_cg  = new();
+      fnmsub_d_cg = new();
+      fsqrt_d_cg  = new();
+      fmin_d_cg   = new();
+      fmax_d_cg   = new();
+      fsgnj_d_cg   = new();
+      fsgnjn_d_cg  = new();
+      fsgnjx_d_cg  = new();
+      feq_d_cg     = new();
+      flt_d_cg     = new();
+      fle_d_cg     = new();
+      fcvt_w_d_cg  = new();
+      fcvt_wu_d_cg = new();
+      fcvt_d_w_cg  = new();
+      fcvt_d_wu_cg = new();
+      fclass_d_cg  = new();
+    `CG_SELECTOR_END
+
+    `CG_SELECTOR_BEGIN(RV64F)
+      fcvt_l_s_cg  = new();
+      fcvt_lu_s_cg = new();
+      fcvt_s_l_cg  = new();
+      fcvt_s_lu_cg = new();
+    `CG_SELECTOR_END
+
+    `CG_SELECTOR_BEGIN(RV64D)
+      fmv_x_d_cg   = new();
+      fmv_d_x_cg   = new();
+      fcvt_d_s_cg  = new();
+      fcvt_s_d_cg  = new();
+      fcvt_l_d_cg  = new();
+      fcvt_lu_d_cg = new();
+      fcvt_d_l_cg  = new();
+      fcvt_d_lu_cg = new();
     `CG_SELECTOR_END
 
     `CG_SELECTOR_BEGIN(RV32B)
@@ -1913,18 +2223,67 @@
       C_ADDW     : `SAMPLE(c_addw_cg, instr)
       C_ADDIW    : `SAMPLE(c_addiw_cg, instr)
       FLW        : `SAMPLE_F(flw_cg, instr)
+      FLD        : `SAMPLE_F(fld_cg, instr)
       FSW        : `SAMPLE_F(fsw_cg, instr)
+      FSD        : `SAMPLE_F(fsd_cg, instr)
       FADD_S     : `SAMPLE_F(fadd_s_cg, instr)
+      FADD_D     : `SAMPLE_F(fadd_d_cg, instr)
       FSUB_S     : `SAMPLE_F(fsub_s_cg, instr)
+      FSUB_D     : `SAMPLE_F(fsub_d_cg, instr)
       FMUL_S     : `SAMPLE_F(fmul_s_cg, instr)
+      FMUL_D     : `SAMPLE_F(fmul_d_cg, instr)
       FDIV_S     : `SAMPLE_F(fdiv_s_cg, instr)
+      FDIV_D     : `SAMPLE_F(fdiv_d_cg, instr)
       FSQRT_S    : `SAMPLE_F(fsqrt_s_cg, instr)
+      FSQRT_D    : `SAMPLE_F(fsqrt_d_cg, instr)
       FMIN_S     : `SAMPLE_F(fmin_s_cg, instr)
+      FMIN_D     : `SAMPLE_F(fmin_d_cg, instr)
       FMAX_S     : `SAMPLE_F(fmax_s_cg, instr)
+      FMAX_D     : `SAMPLE_F(fmax_d_cg, instr)
       FMADD_S    : `SAMPLE_F(fmadd_s_cg, instr)
+      FMADD_D    : `SAMPLE_F(fmadd_d_cg, instr)
       FNMADD_S   : `SAMPLE_F(fnmadd_s_cg, instr)
+      FNMADD_D   : `SAMPLE_F(fnmadd_d_cg, instr)
       FMSUB_S    : `SAMPLE_F(fmsub_s_cg, instr)
+      FMSUB_D    : `SAMPLE_F(fmsub_d_cg, instr)
       FNMSUB_S   : `SAMPLE_F(fnmsub_s_cg, instr)
+      FNMSUB_D   : `SAMPLE_F(fnmsub_d_cg, instr)
+      FCVT_W_S   : `SAMPLE_F(fcvt_w_s_cg, instr)
+      FCVT_WU_S  : `SAMPLE_F(fcvt_wu_s_cg, instr)
+      FCVT_L_S   : `SAMPLE_F(fcvt_l_s_cg, instr)
+      FCVT_LU_S  : `SAMPLE_F(fcvt_lu_s_cg, instr)
+      FCVT_L_D   : `SAMPLE_F(fcvt_l_d_cg, instr)
+      FCVT_LU_D  : `SAMPLE_F(fcvt_lu_d_cg, instr)
+      FCVT_S_D   : `SAMPLE_F(fcvt_s_d_cg, instr)
+      FCVT_D_S   : `SAMPLE_F(fcvt_d_s_cg, instr)
+      FCVT_W_D   : `SAMPLE_F(fcvt_w_d_cg, instr)
+      FCVT_WU_D  : `SAMPLE_F(fcvt_wu_d_cg, instr)
+      FCVT_S_W   : `SAMPLE_F(fcvt_s_w_cg, instr)
+      FCVT_S_WU  : `SAMPLE_F(fcvt_s_wu_cg, instr)
+      FCVT_S_L   : `SAMPLE_F(fcvt_s_l_cg, instr)
+      FCVT_D_L   : `SAMPLE_F(fcvt_d_l_cg, instr)
+      FCVT_S_LU  : `SAMPLE_F(fcvt_s_lu_cg, instr)
+      FCVT_D_W   : `SAMPLE_F(fcvt_d_w_cg, instr)
+      FCVT_D_LU  : `SAMPLE_F(fcvt_d_lu_cg, instr)
+      FCVT_D_WU  : `SAMPLE_F(fcvt_d_wu_cg, instr)
+      FSGNJ_S    : `SAMPLE_F(fsgnj_s_cg, instr)
+      FSGNJ_D    : `SAMPLE_F(fsgnj_d_cg, instr)
+      FSGNJN_S   : `SAMPLE_F(fsgnjn_s_cg, instr)
+      FSGNJN_D   : `SAMPLE_F(fsgnjn_d_cg, instr)
+      FSGNJX_S   : `SAMPLE_F(fsgnjx_s_cg, instr)
+      FSGNJX_D   : `SAMPLE_F(fsgnjx_d_cg, instr)
+      FMV_X_W    : `SAMPLE_F(fmv_x_w_cg, instr)
+      FMV_X_D    : `SAMPLE_F(fmv_x_d_cg, instr)
+      FMV_W_X    : `SAMPLE_F(fmv_w_x_cg, instr)
+      FMV_D_X    : `SAMPLE_F(fmv_d_x_cg, instr)
+      FEQ_S      : `SAMPLE_F(feq_s_cg, instr)
+      FEQ_D      : `SAMPLE_F(feq_d_cg, instr)
+      FLT_S      : `SAMPLE_F(flt_s_cg, instr)
+      FLT_D      : `SAMPLE_F(flt_d_cg, instr)
+      FLE_S      : `SAMPLE_F(fle_s_cg, instr)
+      FLE_D      : `SAMPLE_F(fle_d_cg, instr)
+      FCLASS_S   : `SAMPLE_F(fclass_s_cg, instr)
+      FCLASS_D   : `SAMPLE_F(fclass_d_cg, instr)
       // RV32B
       CLZ        : `SAMPLE_B(clz_cg, instr)
       CTZ        : `SAMPLE_B(ctz_cg, instr)
@@ -2068,8 +2427,7 @@
       end
     end
    `VECTOR_INCLUDE("riscv_instr_cover_group_inc_sample.sv")
-    pre_instr.copy(instr);
-    pre_instr.mem_addr = instr.mem_addr;
+    pre_instr = instr;
   endfunction
 
   // Check if the instruction is supported
@@ -2096,11 +2454,12 @@
     instr_name = instr_name.first;
     do begin
       riscv_instr instr;
-      if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR)) begin
+      if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR) &&
+          riscv_instr::instr_registry.exists(instr_name)) begin
         instr = riscv_instr::create_instr(instr_name);
         if ((instr.group inside {supported_isa}) &&
             (instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C,
-                                 RV32V, RV64V, RV64B, RV32B})) begin
+                                 RVV, RV64B, RV32B})) begin
           if (((instr_name inside {URET}) && !support_umode_trap) ||
               ((instr_name inside {SRET, SFENCE_VMA}) &&
               !(SUPERVISOR_MODE inside {supported_privileged_mode})) ||
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
index 5f92aa6..3200353 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
@@ -328,6 +328,8 @@
   constraint mstatus_c {
     if (set_mstatus_mprv) {
       mstatus_mprv == 1'b1;
+    } else {
+      mstatus_mprv == 1'b0;
     }
     if (SATP_MODE == BARE) {
       mstatus_mxr == 0;
@@ -591,7 +593,7 @@
     get_invalid_priv_lvl_csr();
   endfunction
 
-  function void setup_instr_distribution();
+  virtual function void setup_instr_distribution();
     string opts;
     int val;
     get_int_arg_value("+dist_control_mode=", dist_control_mode);
@@ -643,7 +645,7 @@
     end
   endfunction
 
-  function void get_non_reserved_gpr();
+  virtual function void get_non_reserved_gpr();
   endfunction
 
   function void post_randomize();
@@ -659,7 +661,7 @@
     end
   endfunction
 
-  function void check_setting();
+  virtual function void check_setting();
     bit support_64b;
     bit support_128b;
     foreach (riscv_instr_pkg::supported_isa[i]) begin
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 c60dd57..de51c44 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
@@ -1,5 +1,6 @@
 /*
  * Copyright 2018 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -89,9 +90,8 @@
     RV64C,
     RV128I,
     RV128C,
-    RV32V,
+    RVV,
     RV32B,
-    RV64V,
     RV64B,
     RV32X,
     RV64X
@@ -474,12 +474,10 @@
     VWMACC,
     VWMACCSU,
     VWMACCUS,
-    /*
-    VQMACCU,
-    VQMACC,
-    VQMACCSU,
-    VQMACCUS,
-    */
+    //VQMACCU,
+    //VQMACC,
+    //VQMACCSU,
+    //VQMACCUS,
     VMERGE,
     VMV,
     VSADDU,
@@ -494,6 +492,7 @@
     VSSRA,
     VNCLIPU,
     VNCLIP,
+    // 14. Vector Floating-Point Instructions
     VFADD,
     VFSUB,
     VFRSUB,
@@ -543,7 +542,7 @@
     VFNCVT_F_X_W,
     VFNCVT_F_F_W,
     VFNCVT_ROD_F_F_W,
-    // Vector reduction instruction
+    // 15. Vector reduction instruction
     VREDSUM_VS,
     VREDMAXU_VS,
     VREDMAX_VS,
@@ -590,6 +589,51 @@
     VMV2R_V,
     VMV4R_V,
     VMV8R_V,
+    // Vector load/store instruction
+    VLE_V,
+    VSE_V,
+    VLB_V,
+    VSB_V,
+    VLH_V,
+    VSH_V,
+    VLW_V,
+    VSW_V,
+    VLBU_V,
+    VLHU_V,
+    VLWU_V,
+    VLSB_V,
+    VLSH_V,
+    VLSW_V,
+    VLSBU_V,
+    VLSHU_V,
+    VLSWU_V,
+    VLSE_V,
+    VSSB_V,
+    VSSH_V,
+    VSSW_V,
+    VSSE_V,
+    VLXB_V,
+    VLXH_V,
+    VLXW_V,
+    VLXBU_V,
+    VLXHU_V,
+    VLXWU_V,
+    VLXE_V,
+    VSXB_V,
+    VSXH_V,
+    VSXW_V,
+    VSXE_V,
+    VSUXB_V,
+    VSUXH_V,
+    VSUXW_V,
+    VSUXE_V,
+    VLBFF_V,
+    VLHFF_V,
+    VLWFF_V,
+    VLBUFF_V,
+    VLHUFF_V,
+    VLWUFF_V,
+    VLEFF_V,
     // Supervisor instruction
     DRET,
     MRET,
@@ -606,6 +650,9 @@
   // Maximum virtual address bits used by the program
   parameter int MAX_USED_VADDR_BITS = 30;
 
+  parameter int SINGLE_PRECISION_FRACTION_BITS = 23;
+  parameter int DOUBLE_PRECISION_FRACTION_BITS = 52;
+
   typedef enum bit [4:0] {
     ZERO = 5'b00000,
     RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
@@ -645,7 +692,11 @@
     VA_FORMAT,
     VS2_FORMAT, // op vd,vs2
     VL_FORMAT,
-    VS_FORMAT
+    VS_FORMAT,
+    VLV_FORMAT,
+    VSV_FORMAT,
+    VLS_FORMAT,
+    VSS_FORMAT
   } riscv_instr_format_t;
 
 
@@ -1090,9 +1141,9 @@
   typedef struct packed {
     bit ill;
     bit [XLEN-2:7] reserved;
-    bit [1:0] vediv;
-    bit [2:0] vsew;
-    bit [1:0] vlmul;
+    int vediv;
+    int vsew;
+    int vlmul;
   } vtype_t;
 
   typedef enum bit [1:0] {
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 e2a22e9..b343608 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
@@ -275,6 +275,12 @@
       str = {prefix, instr_stream.instr_list[i].convert2asm()};
       instr_string_list.push_back(str);
     end
+    // If PMP is supported, need to align <main> to a 4-byte boundary.
+    // TODO(udi) - this might interfere with multi-hart programs,
+    //             may need to specifically match hart0.
+    if (riscv_instr_pkg::support_pmp && !uvm_re_match("*main*", label_name)) begin
+      instr_string_list.push_front(".align 2");
+    end
     insert_illegal_hint_instr();
     prefix = format_string($sformatf("%0d:", i), LABEL_STR_LEN);
     if(!is_main_program) 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 ab72deb..0f737e2 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
@@ -186,6 +186,18 @@
     setup_instruction_dist(no_branch, no_load_store);
   endfunction
 
+  virtual function void randomize_avail_regs();
+    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, reserved_rd});
+                                         },
+                                         "Cannot randomize avail_regs")
+    end
+  endfunction
+
   function void setup_instruction_dist(bit no_branch = 1'b0, bit no_load_store = 1'b1);
     if (cfg.dist_control_mode) begin
       category_dist = cfg.category_dist;
@@ -227,6 +239,7 @@
     end
     instr = riscv_instr::get_rand_instr(.include_instr(allowed_instr),
                                         .exclude_instr(exclude_instr));
+    instr.m_cfg = cfg;
     randomize_gpr(instr);
   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 94c771e..e95e3cc 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
@@ -1,5 +1,6 @@
 /*
  * Copyright 2018 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -120,19 +121,11 @@
   virtual function void gen_load_store_instr();
     bit enable_compressed_load_store;
     riscv_instr 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, reserved_rd});
-                                         },
-                                         "Cannot randomize avail_regs")
-    end
+    randomize_avail_regs();
     if ((rs1_reg inside {[S0 : A5], SP}) && !cfg.disable_compressed_instr) begin
       enable_compressed_load_store = 1;
     end
-    foreach(addr[i]) begin
+    foreach (addr[i]) begin
       // 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};
@@ -450,6 +443,7 @@
   }
 
   `uvm_object_utils(riscv_load_store_rand_addr_instr_stream)
+  `uvm_object_new
 
    virtual function void randomize_offset();
     int offset_, addr_;
@@ -465,7 +459,7 @@
       offset[i] = offset_;
       addr[i] = addr_offset + offset_;
     end
-  endfunction `uvm_object_new
+  endfunction
 
   virtual function void add_rs1_init_la_instr(riscv_reg_t gpr, int id, int base = 0);
     riscv_instr instr[$];
@@ -524,3 +518,136 @@
   endfunction
 
 endclass
+
+class riscv_vector_unit_stride_load_store_instr_stream extends riscv_mem_access_stream;
+
+  typedef enum {B_ALIGNMENT, H_ALIGNMENT, W_ALIGNMENT, E_ALIGNMENT} alignment_e;
+
+  rand alignment_e alignment;
+  rand int unsigned data_page_id;
+  rand int unsigned num_mixed_instr;
+  rand riscv_reg_t rs1_reg;
+
+  constraint vec_mixed_instr_c {
+    num_mixed_instr inside {[0:10]};
+  }
+
+  constraint vec_rs1_c {
+    !(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
+  }
+
+  constraint vec_data_page_id_c {
+    data_page_id < max_data_page_id;
+  }
+
+  constraint alignment_sew_c {
+    if (cfg.vector_cfg.vtype.vsew <= 16) {alignment != W_ALIGNMENT;}
+    if (cfg.vector_cfg.vtype.vsew <=  8) {alignment != H_ALIGNMENT;}
+  }
+
+  int base;
+  int max_load_store_addr;
+  riscv_instr load_store_instr;
+
+  `uvm_object_utils(riscv_vector_unit_stride_load_store_instr_stream)
+  `uvm_object_new
+
+  virtual function int get_addr_alignment_mask(int alignment_bytes);
+    return alignment_bytes - 1;
+  endfunction
+
+  function void post_randomize();
+    randomize_base();
+    // rs1 cannot be modified by other instructions
+    if(!(rs1_reg inside {reserved_rd})) reserved_rd = {reserved_rd, rs1_reg};
+    randomize_avail_regs();
+    gen_load_store_instr();
+    add_mixed_instr(num_mixed_instr);
+    add_rs1_init_la_instr(rs1_reg, data_page_id, base);
+    super.post_randomize();
+  endfunction
+
+  virtual function void randomize_base();
+    int ss = stride_span();
+    bit success;
+
+    repeat (10) begin
+      max_load_store_addr = data_page[data_page_id].size_in_bytes - ss;
+      if (max_load_store_addr >= 0) begin
+        success = 1'b1;
+        break;
+      end
+      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(data_page_id, data_page_id < max_data_page_id;)
+    end
+
+    assert (success) else begin
+      `uvm_fatal(`gfn, $sformatf({"Expected positive value for max_load_store_addr, got %0d.",
+        "  Perhaps more memory needs to be allocated in the data pages for vector loads and stores.",
+        "\ndata_page_id:%0d\ndata_page[data_page_id].size_in_bytes:%0d\nstride_span:%0d",
+        "\nalignment:%s\nstride_bytes:%0d\nVLEN:%0d\nLMUL:%0d\ncfg.vector_cfg.vtype.vsew:%0d\n\n"},
+        max_load_store_addr, data_page_id, data_page[data_page_id].size_in_bytes, ss,
+        alignment.name(), stride_bytes(), VLEN,
+        cfg.vector_cfg.vtype.vlmul, cfg.vector_cfg.vtype.vsew))
+    end
+
+    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(base, base >= 0; base <= max_load_store_addr;)
+
+    if (!cfg.enable_unaligned_load_store) begin
+      base &= ~get_addr_alignment_mask(stride_bytes());
+    end
+  endfunction
+
+  virtual function int stride_span();
+    int num_elements = VLEN * cfg.vector_cfg.vtype.vlmul / cfg.vector_cfg.vtype.vsew;
+    stride_span = num_elements * stride_bytes();
+  endfunction
+
+  virtual function int stride_bytes();
+    stride_bytes = 0;
+    if (alignment == B_ALIGNMENT) stride_bytes = 1;
+    else if (alignment == H_ALIGNMENT) stride_bytes = 2;
+    else if (alignment == W_ALIGNMENT) stride_bytes = 4;
+    else if (alignment == E_ALIGNMENT) stride_bytes = cfg.vector_cfg.vtype.vsew;
+  endfunction
+
+  // Generate each load/store instruction
+  virtual function void gen_load_store_instr();
+    build_allowed_instr();
+    randomize_vec_load_store_instr();
+    instr_list.push_back(load_store_instr);
+  endfunction
+
+  virtual function void build_allowed_instr();
+    if (alignment == B_ALIGNMENT) add_byte_aligned_vec_load_stores();
+    else if (alignment == H_ALIGNMENT) add_h_aligned_vec_load_stores();
+    else if (alignment == W_ALIGNMENT) add_w_aligned_vec_load_stores();
+    else if (alignment == E_ALIGNMENT) add_element_vec_load_stores();
+  endfunction
+
+  virtual function void add_element_vec_load_stores();
+    allowed_instr = {VLE_V, VSE_V, allowed_instr};
+  endfunction
+
+  virtual function void add_byte_aligned_vec_load_stores();
+    allowed_instr = {VLB_V, VSB_V, VLBU_V, allowed_instr};
+  endfunction
+
+  virtual function void add_h_aligned_vec_load_stores();
+    allowed_instr = {VLH_V, VSH_V, VLHU_V, allowed_instr};
+  endfunction
+
+  virtual function void add_w_aligned_vec_load_stores();
+    allowed_instr = {VLW_V, VSW_V, VLWU_V, allowed_instr};
+  endfunction
+
+  virtual function void randomize_vec_load_store_instr();
+    load_store_instr = riscv_instr::get_load_store_instr(allowed_instr);
+    load_store_instr.m_cfg = cfg;
+    load_store_instr.has_rs1 = 0;
+    load_store_instr.has_imm = 0;
+    randomize_gpr(load_store_instr);
+    load_store_instr.rs1 = rs1_reg;
+    load_store_instr.process_load_store = 0;
+  endfunction
+
+endclass
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 d05bffd..5cc3772 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
@@ -495,7 +495,7 @@
                // Unset U bit
                $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]),
                // Save PTE back to memory
-               $sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
+               $sformatf("s%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
                // Move to the next PTE
                $sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN/8),
                // If not the end of the kernel space, process the next PTE
@@ -513,14 +513,14 @@
                $sformatf("add x%0d, x%0d, x%0d", cfg.gpr[0], cfg.gpr[2], cfg.gpr[0]),
                $sformatf("li x%0d, 0x%0x", cfg.gpr[2], ubit_mask),
                // Assume 20 PTEs for kernel data pages
-               $sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], 20 * XLEN/8),
+               $sformatf("addi x%0d, x%0d, %0d", cfg.gpr[1], cfg.gpr[1], 20 * XLEN/8),
                "2:",
                // Load the PTE from the memory
                $sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
                // Unset U bit
                $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]),
                // Save PTE back to memory
-               $sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
+               $sformatf("s%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
                // Move to the next PTE
                $sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN/8),
                // If not the end of the kernel space, process the next PTE
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
index dd58c91..90ce5c3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
@@ -1,5 +1,6 @@
 /*
  * Copyright 2020 Google LLC
+ * Copyright 2020 Andes Technology Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,21 +23,75 @@
   rand vxrm_t            vxrm;
   rand bit               vxsat;
 
+  // Allow only vector instructions from the random sequences
+  rand bit only_vec_instr;
+  constraint only_vec_instr_c {soft only_vec_instr == 0;}
+
+  // Allow vector floating-point instructions (Allows vtype.vsew to be set <16 or >32).
+  rand bit vec_fp;
+
+  // Allow vector narrowing or widening instructions.
+  rand bit vec_narrowing_widening;
+
+  // Allow vector quad-widening instructions.
+  rand bit vec_quad_widening;
+
+  constraint vec_quad_widening_c {
+    (!vec_narrowing_widening) -> (!vec_quad_widening);
+    // FP requires at least 16 bits and quad-widening requires no more than ELEN/4 bits.
+    (ELEN < 64) -> (!(vec_fp && vec_quad_widening));
+  }
+
+  rand bit allow_illegal_vec_instr;
+  constraint allow_illegal_vec_instr_c {soft allow_illegal_vec_instr == 0;}
+
+  // Cause frequent hazards for the Vector Registers:
+  //  * Write-After-Read (WAR)
+  //  * Read-After-Write (RAW)
+  //  * Read-After-Read (RAR)
+  //  * Write-After-Write (WAW)
+  // These hazard conditions are induced by keeping a small (~5) list of registers to select from.
+  rand bit vec_reg_hazards;
+
   constraint legal_c {
     solve vtype before vl;
     solve vl before vstart;
-    vstart <= vl;
-    vtype.vsew <= $clog2(VLEN/8);
-    vl <= (1 << ($clog2(VLEN/8) - vtype.vsew));
+    vstart inside {[0:vl]};
+    vl inside {[1:VLEN/vtype.vsew]};
   }
 
   // Basic constraint for initial bringup
   constraint bringup_c {
     vstart == 0;
-    vl == (1 << ($clog2(VLEN/8) - vtype.vsew));
-    vtype.vlmul == 0;
-    vtype.vediv == 0;
-    vtype.vsew == 2;
+    vl == VLEN/vtype.vsew;
+    vtype.vediv == 1;
+  }
+
+  // For all widening instructions, the destination element width must be a supported element
+  // width and the destination LMUL value must also be a supported LMUL value
+  constraint vlmul_c {
+    vtype.vlmul inside {1, 2, 4, 8};
+    vtype.vlmul <= MAX_LMUL;
+    if (vec_narrowing_widening) {
+      vtype.vlmul < 8;
+    }
+    if (vec_quad_widening) {
+      vtype.vlmul < 4;
+    }
+  }
+
+  constraint vsew_c {
+    vtype.vsew inside {8, 16, 32, 64, 128};
+    vtype.vsew <= ELEN;
+    // TODO: Determine the legal range of floating point format
+    if (vec_fp) {vtype.vsew inside {32};}
+    if (vec_narrowing_widening) {vtype.vsew < ELEN;}
+    if (vec_quad_widening) {vtype.vsew < (ELEN >> 1);}
+  }
+
+  constraint vdeiv_c {
+    vtype.vediv inside {1, 2, 4, 8};
+    vtype.vediv <= (vtype.vsew / SELEN);
   }
 
   `uvm_object_utils_begin(riscv_vector_cfg)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
index 46d466b..707e919 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
@@ -54,14 +54,39 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
+
 // ----------------------------------------------------------------------------
 // Previleged CSR implementation
 // ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
index 78d7724..04a2f55 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
@@ -54,11 +54,35 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 2;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
index c93e3f3..49c97c8 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
@@ -54,14 +54,36 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
+
 // ----------------------------------------------------------------------------
 // Previleged CSR implementation
 // ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
index 1fc0348..1aaf1a1 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
@@ -54,11 +54,35 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
index dfc99c8..df33010 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
@@ -54,11 +54,35 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
index 386c675..4ca59cd 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
@@ -54,11 +54,35 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
index f9033d1..d418120 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
@@ -21,17 +21,17 @@
 parameter int XLEN = 64;
 
 // Parameter for SATP mode, set to BARE if address translation is not supported
-parameter satp_mode_t SATP_MODE = SV39;
+parameter satp_mode_t SATP_MODE = BARE;
 
 // Supported Privileged mode
-privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
+privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
 
 // Unsupported instructions
-riscv_instr_name_t unsupported_instr[] = {VWMACCSU};
+riscv_instr_name_t unsupported_instr[] = {};
 
 // ISA supported by the processor
 riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C, RV32A, RV64A,
-                                        RV32F, RV64F, RV32D, RV64D, RV32V, RV64V};
+                                        RV32F, RV64F, RV32D, RV64D, RVV};
 // Interrupt mode support
 mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
 
@@ -54,14 +54,38 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 1;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
+
 // ----------------------------------------------------------------------------
 // Previleged CSR implementation
 // ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
index 350e43b..50698ab 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
@@ -47,3 +47,19 @@
   iterations: 2
   gen_test: riscv_instr_base_test
   rtl_test: core_base_test
+
+- test: riscv_vector_load_store_test
+  description: >
+    Vector load/store random test
+  gen_opts: >
+    +instr_cnt=10000
+    +num_of_sub_program=0
+    +enable_floating_point=1
+    +enable_vector_extension=1
+    +directed_instr_0=riscv_vector_unit_stride_load_store_instr_stream,4
+    +no_branch_jump=1
+    +boot_mode=m
+    +no_csr_instr=1
+  iterations: 2
+  gen_test: riscv_instr_base_test
+  rtl_test: core_base_test
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
index 8511dc4..0071ffa 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
@@ -54,11 +54,34 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
index 2f67acf..3bf90a5 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
@@ -54,11 +54,35 @@
 // Support unaligned load/store
 bit support_unaligned_load_store = 1'b1;
 
+// GPR setting
+parameter int NUM_FLOAT_GPR = 32;
+parameter int NUM_GPR = 32;
+parameter int NUM_VEC_GPR = 32;
+
+// ----------------------------------------------------------------------------
+// Vector extension configuration
+// ----------------------------------------------------------------------------
+
 // Parameter for vector extension
 parameter int VECTOR_EXTENSION_ENABLE = 0;
+
 parameter int VLEN = 512;
-parameter int ELEN = 64;
-parameter int SLEN = 64;
+
+// Maximum size of a single vector element
+parameter int ELEN = 32;
+
+// Minimum size of a sub-element, which must be at most 8-bits.
+parameter int SELEN = 8;
+
+// Maximum size of a single vector element (encoded in vsew format)
+parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
+// ----------------------------------------------------------------------------
+// Multi-harts configuration
+// ----------------------------------------------------------------------------
 
 // Number of harts
 parameter int NUM_HARTS = 1;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
index fb0fa20..8bfc625 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv
@@ -132,11 +132,12 @@
         riscv_instr instr;
         instr = riscv_instr::get_instr(instr_name);
         if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
-                                RV32F, RV32B, RV64B}) begin
+                                RV32F, RV64F, RV32D, RV64D,
+                                RV32B, RV64B}) begin
           assign_trace_info_to_instr(instr);
+          instr.pre_sample();
+          instr_cg.sample(instr);
         end
-        instr.pre_sample();
-        instr_cg.sample(instr);
         return 1'b1;
       end
     end
@@ -177,6 +178,27 @@
         instr_name[i] = "_";
       end
     end
+
+    case (instr_name)
+      // rename to new name as ovpsim still uses old name
+     "FMV_S_X": instr_name = "FMV_W_X";
+     "FMV_X_S": instr_name = "FMV_X_W";
+      // convert Pseudoinstructions
+      // fmv.s rd, rs fsgnj.s rd, rs, rs Copy single-precision register
+      // fabs.s rd, rs fsgnjx.s rd, rs, rs Single-precision absolute value
+      // fneg.s rd, rs fsgnjn.s rd, rs, rs Single-precision negate
+      // fmv.d rd, rs fsgnj.d rd, rs, rs Copy double-precision register
+      // fabs.d rd, rs fsgnjx.d rd, rs, rs Double-precision absolute value
+      // fneg.d rd, rs fsgnjn.d rd, rs, rs Double-precision negate
+      "FMV_S":  instr_name = "FSGNJ_S";
+      "FABS_S": instr_name = "FSGNJX_S";
+      "FNEG_S": instr_name = "FSGNJN_S";
+      "FMV_D":  instr_name = "FSGNJ_D";
+      "FABS_D": instr_name = "FSGNJX_D";
+      "FNEG_D": instr_name = "FSGNJN_D";
+      default: ;
+    endcase
+
     return instr_name;
   endfunction : process_instr_name
 
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/user_extension/user_init.s b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/user_extension/user_init.s
new file mode 100644
index 0000000..2f8b49f
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/user_extension/user_init.s
@@ -0,0 +1,2 @@
+# Add custom initialization assembly code here
+# This file will be included at the very beginning of the program