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