Update lowrisc_ibex to lowRISC/ibex@a33a91b2
Update code from upstream repository
https://github.com/lowRISC/ibex.git to revision
a33a91b2326b560c76b780d12cae200a1302fb7d
* [lint] Fix some AscentLint errors (Pirmin Vogel)
* [dv] Set UVM_VERBOSITY to UVM_LOW (Greg Chadwick)
* [dv] Fix bad reference to instr_req_out (Greg Chadwick)
* [rtl] Move PMP checking to IF stage output (Tom Roberts)
* [rtl] Replace always_ff with always @(posedge .. in FPGA regfile
(Pirmin Vogel)
* [dv] Fix PMP error handling for icache (Greg Chadwick)
* [dv] Add missing copyright header (Greg Chadwick)
* [dv] Add recoverable NMI handling to cosim (Greg Chadwick)
* [dv] Fix dside memory checking (Greg Chadwick)
* [dv] Fix cosim memory size (Greg Chadwick)
* Update google_riscv-dv to google/riscv-dv@6053014 (Michael
Schaffner)
* [ibex_top] Use correct ECC codeword for '0 reset in regfile (Michael
Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@be1359d27 (Michael Schaffner)
* [rtl, bitmanip] Add xperm.[nbh] instruction (Zbp, draft v.0.93)
(Pirmin Vogel)
* [rtl, bitmanip] Clarify situation around zext.[bh] pseudo-
instructions (Pirmin Vogel)
* [rtl] Fix typo in comment (Pirmin Vogel)
* [rtl, bitmanip] Align Zbb implementation with draft v.0.93 and
v.1.0.0 (Pirmin Vogel)
* [rtl, bitmanip] Align Zbs implementation with draft v.0.93 and
v.1.0.0 (Pirmin Vogel)
* [rtl, bitmanip] Rename bext/bdep to bcompress/bdecompress (Pirmin
Vogel)
* Update google_riscv-dv to google/riscv-dv@ea8dd25 (Pirmin Vogel)
* [secded] Switch to inverted ECC codes (Michael Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@34ba5e45f (Michael Schaffner)
* Update lowrisc_ip to lowRISC/opentitan@3a672eb36 (Canberk Topal)
* [dv/icache] Add missing window reset call (Tom Roberts)
* Move NT branch addr calculation to ID stage (Sam Shahrestani)
* Update lowrisc_ip to lowRISC/opentitan@ad629e3e6 (Rupert Swarbrick)
* [ci] Add co-simulation testing of CoreMark (Greg Chadwick)
* [coremark] Add option to coremark build to suppress pcount dump
(Greg Chadwick)
* [cosim] Update documentation for cosim (Greg Chadwick)
* [cosim] Add Simple System with cosim (Greg Chadwick)
* [simple_system] Refactor Simple System (Greg Chadwick)
* [dv] Add matched instruction count to cosim (Greg Chadwick)
* [dv] Adjust cosim include paths (Greg Chadwick)
* [bitmanip][zba] Add support for Zba (address calculation) extension
(Michael Munday)
* [dv] get ibex dv co-sim to run w questa (Miguel Escobar)
* [doc] Update DIT documentation for unaligned ld/st (Tom Roberts)
* Change use of blocking assignment to non-blocking inside always_ff
(Henner Zeller)
* [dv] Add co-simulation environment support to UVM testbench (Greg
Chadwick)
* [rtl] RVFI changes and extensions for co-simulation (Greg Chadwick)
* [dv] Add co-simulation framework (Greg Chadwick)
* [rtl,dv,doc] Flip priority of fast interrupts (Greg Chadwick)
* [ibex/ml] add CSR/mem_error tests to ml_testlist (Udi)
* [syn] Use read_verilog -defer in yosys_run_synth.tcl (Zachary Snow)
* remove unused RD in branch insn from tracer (zeeshanrafique23)
* Add missing parameters to ibex_top_tracing (Rupert Swarbrick)
* set verible action version to 'main' (Wojciech Sipak)
* bump verible action version (Wojciech Sipak)
* [rtl] Fix retired instruction counters (Greg Chadwick)
* [rtl] Factor ID exceptions into instruction kill (Greg Chadwick)
* [ci] Add GHA workflows to review PRs using Verible (Wojciech Sipak)
* [dv] Fix transaction ordering in ibex_mem_intf_monitor (Greg
Chadwick)
* [rtl] Implement mvendorid/marchid/mimpid CSRs (Greg Chadwick)
* [style] Indent package bodies (Philipp Wagner)
* [style] Indent module header with two spaces (Philipp Wagner)
* [style] Use logical operators for reset (Philipp Wagner)
* [style] Fix whitespace issues around operators (Philipp Wagner)
* [style] Format module instantiations in tabular format (Philipp
Wagner)
Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index e9dd890..f14402b 100644
--- a/hw/vendor/lowrisc_ibex.lock.hjson
+++ b/hw/vendor/lowrisc_ibex.lock.hjson
@@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/ibex.git
- rev: 48f11c673348908c37d3eaa9bd1cd0a5b5c69253
+ rev: a33a91b2326b560c76b780d12cae200a1302fb7d
}
}
diff --git a/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml b/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml
new file mode 100644
index 0000000..bff5d75
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/.github/workflows/pr_lint_review.yml
@@ -0,0 +1,49 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: pr-lint-review
+
+on:
+ workflow_run:
+ workflows: ["pr-trigger"]
+ types:
+ - completed
+
+jobs:
+ review_triggered:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ # this workflow does not run in a PR context
+ # download 'event.json' file from a PR-tiggered workflow
+ # to mock the PR context and make a review
+ - name: 'Download artifact'
+ id: get-artifacts
+ uses: actions/github-script@v3.1.0
+ with:
+ script: |
+ var artifacts = await github.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: ${{github.event.workflow_run.id }},
+ });
+ var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
+ return artifact.name == "event.json"
+ })[0];
+ var download = await github.actions.downloadArtifact({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: matchArtifact.id,
+ archive_format: 'zip',
+ });
+ var fs = require('fs');
+ fs.writeFileSync('${{github.workspace}}/event.json.zip', Buffer.from(download.data));
+ - run: |
+ unzip event.json.zip
+ - name: Run Verible linter action
+ uses: chipsalliance/verible-linter-action@main
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ suggest_fixes: 'false'
+ config_file: 'vendor/lowrisc_ip/lint/tools/veriblelint/rules.vbl'
diff --git a/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml b/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml
new file mode 100644
index 0000000..b969698
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml
@@ -0,0 +1,25 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: pr-trigger
+
+on:
+ pull_request:
+
+jobs:
+ upload:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Copy event file
+ run: cp "$GITHUB_EVENT_PATH" ./event.json
+
+ # If this workflow is triggered by a PR from a fork
+ # it won't have sufficient access rights to make a review
+ # so we just save the file needed to do the review
+ # in a context with proper access rights
+ - name: Upload event file as artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: event.json
+ path: event.json
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index ace6903..ae618fa 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -28,7 +28,7 @@
| Config | "micro" | "small" | "maxperf" | "maxperf-pmp-bmfull" |
| ------ | ------- | --------| ----------| -------------------- |
| Features | RV32EC | RV32IMC, 3 cycle mult | RV32IMC, 1 cycle mult, Branch target ALU, Writeback stage | RV32IMCB, 1 cycle mult, Branch target ALU, Writeback stage, 16 PMP regions |
-| Performance (CoreMark/MHz) | 0.904 | 2.47 | 3.13 | 3.05 |
+| Performance (CoreMark/MHz) | 0.904 | 2.47 | 3.13 | 3.13 |
| Area - Yosys (kGE) | 17.44 | 26.06 | 35.64 | 58.74 |
| Area - Commercial (estimated kGE) | ~16 | ~24 | ~33 | ~54 |
| Verification status | Red | Green | Amber | Amber |
@@ -38,7 +38,6 @@
* Performance numbers are based on CoreMark running on the Ibex Simple System [platform](examples/simple_system/README.md).
Note that different ISAs (use of B and C extensions) give the best results for different configurations.
See the [Benchmarks README](examples/sw/benchmarks/README.md) for more information.
- The "maxperf-pmp-bmfull" configuration sets a `SpecBranch` parameter in `ibex_core.sv`; this helps timing but has a small negative performance impact.
* Yosys synthesis area numbers are based on the Ibex basic synthesis [flow](syn/README.md) using the latch-based register file.
* Commercial synthesis area numbers are a rough estimate of what might be achievable with a commercial synthesis flow and technology library.
* For comparison, the original "Zero-riscy" core yields an area of 23.14kGE using our Yosys synthesis flow.
diff --git a/hw/vendor/lowrisc_ibex/azure-pipelines.yml b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
index 4306e0b..78aca02 100644
--- a/hw/vendor/lowrisc_ibex/azure-pipelines.yml
+++ b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
@@ -88,6 +88,11 @@
git checkout "$RISCV_COMPLIANCE_GIT_VERSION"
displayName: Get RISC-V Compliance test suite
+ - bash: |
+ # Build CoreMark without performance counter dump for co-simulation testing
+ make -C ./examples/sw/benchmarks/coremark SUPPRESS_PCOUNT_DUMP=1
+ displayName: Build CoreMark
+
# Run Ibex RTL CI per supported configuration
- template : ci/ibex-rtl-ci-steps.yml
parameters:
diff --git a/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml b/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
index 5b1a853..907b17a 100644
--- a/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
+++ b/hw/vendor/lowrisc_ibex/ci/ibex-rtl-ci-steps.yml
@@ -65,3 +65,23 @@
done
exit $fail
displayName: Run RISC-V Compliance test for Ibex RV32IMC for ${{ config }}
+
+ - bash: |
+ # Setup environment to use cosim with Simple System
+ export IBEX_COSIM_ISS_ROOT=/opt/spike-cosim
+ export LD_LIBRARY_PATH=/opt/spike-cosim/lib:$LD_LIBRARY_PATH
+
+ # Build simple system with co-simulation
+ fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim $IBEX_CONFIG_OPTS
+
+ if [ $? != 0 ]; then
+ echo -n "##vso[task.logissue type=error]"
+ echo "Build Simple System with co-simulation failed. Run fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim $IBEX_CONFIG_OPTS to check and fix all errors."
+ fi
+
+ build/lowrisc_ibex_ibex_simple_system_cosim_0/sim-verilator/Vibex_simple_system --meminit=ram,examples/sw/benchmarks/coremark/coremark.elf
+ if [ $? != 0 ]; then
+ echo -n "##vso[task.logissue type=error]"
+ echo "Running CoreMark failed co-simulation testing"
+ fi
+ displayName: Run CoreMark for ${{ config }}
diff --git a/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh b/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
index 5fef79f..7c64102 100755
--- a/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
+++ b/hw/vendor/lowrisc_ibex/ci/install-build-deps.sh
@@ -32,6 +32,11 @@
$SUDO_CMD sh -c "echo 'deb http://download.opensuse.org/repositories/home:/phiwag:/edatools/xUbuntu_$VERSION_ID/ /' > /etc/apt/sources.list.d/edatools.list"
$SUDO_CMD apt-get update
+ # Make spike-cosim repository available
+ curl -Ls https://download.opensuse.org/repositories/home:gac_lowrisc/xUbuntu_18.04/Release.key | $SUDO_CMD apt-key add -
+ $SUDO_CMD sh -c "echo 'deb http://download.opensuse.org/repositories/home:/gac_lowrisc/xUbuntu_18.04/ /' > /etc/apt/sources.list.d/spike-cosim.list" sudo apt update
+ $SUDO_CMD apt-get update
+
# Packaged dependencies
# Install python3-yaml through apt to get a version with libyaml bindings,
# which is significantly faster than the pure Python version.
@@ -53,6 +58,7 @@
libelf-dev \
clang-format \
"verilator-$VERILATOR_VERSION" \
+ spike-cosim \
xz-utils
# Python dependencies
diff --git a/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst b/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
index c58407a..a113815 100644
--- a/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
+++ b/hw/vendor/lowrisc_ibex/doc/02_user/getting_started.rst
@@ -11,3 +11,17 @@
Ibex comes with three different register file implementations that can be selected using the enumerated parameter ``RegFile`` defined in :file:`rtl/ibex_pkg.sv`.
Depending on the target technology, either the flip-flop-based ("ibex_pkg::RegFileFF", default), the latch-based ("ibex_pkg::RegFileLatch") or an FPGA-targeted ("ibex_pkg::RegFileFPGA") implementation should be selected.
For more information about the three register file implementations and their trade-offs, check out :ref:`register-file`.
+
+Identification CSRs
+-------------------
+
+The RISC-V Privileged Architecture specifies several read-only CSRs that identify the vendor and micro-architecture of a CPU.
+These are ``mvendorid``, ``marchid`` and ``mimpid``.
+The fixed, read-only values for these CSRs are defined in :file:`rtl/ibex_pkg.sv`.
+Implementers should carefully consider appropriate values for these registers.
+Ibex, as an open source implementation, has an assigned architecture ID (``marchid``) of 22.
+(Allocations are specified in `marchid.md of the riscv-isa-manual repository <https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md>`_.)
+If significant changes are made to the micro-architecture a different architecture ID should be used.
+The vendor ID and implementation ID (``mvendorid`` and ``mimpid``) both read as 0 by default, meaning non-implemented.
+Implementers may wish to use other values here.
+Please see the RISC-V Privileged Architecture specification for more details on what these IDs represent and how they should be chosen.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst
new file mode 100644
index 0000000..f2e99ac
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/cosim.rst
@@ -0,0 +1,178 @@
+.. _cosim:
+
+Co-simulation System
+====================
+
+Overview
+--------
+
+A co-simulation system is provided that can run in either the Ibex UVM DV environment or with Simple System.
+This system runs a RISC-V ISS (currently only Spike is supported) in lockstep with an Ibex core.
+All instructions executed by Ibex and memory transactions generated are checked against the behaviour of the ISS.
+This system supports memory errors, interrupt and debug requests which are observed in the RTL simulation and forwarded to the ISS so the ISS and RTL remain in sync.
+The system uses a generic interface to allow support of multiple ISSes.
+Only VCS is supported as a simulator, though no VCS specific functionality is required so adding support for another simulator should be straight-forward.
+
+To run the co-simulation system the `ibex-cosim branch from the lowRISC fork of Spike <https://github.com/lowRISC/riscv-isa-sim/tree/ibex>`_ is required.
+
+The RISC-V Formal Interface (RVFI) is used to provide information about retired instructions and instructions that produce synchronous traps for checking.
+The RVFI has been extended to provide interrupt and debug information and the value of the ``mcycle`` CSR.
+These extended signals have the prefix ``rvfi_ext``
+
+The co-simulation system is EXPERIMENTAL.
+It is disabled by default in the UVM DV environment currently, however it is intended to become the primary checking method for the UVM testbench.
+
+Setup and Usage
+---------------
+
+Clone the `lowRISC fork of Spike <https://github.com/lowRISC/riscv-isa-sim>`_ and checkout the ``ibex_cosim`` branch.
+Follow the Spike build instructions to build and install Spike.
+The build will install multiple header files and libraries, it is recommended a custom install location (using ``--prefix=<path>`` with ``configure``) is used to avoid cluttering system directories.
+The ``--enable-commitlog`` and ``--enable-misaligned`` options must be passed to ``configure``.
+
+Once built, the ``IBEX_COSIM_ISS_ROOT`` environment variable must be set to the Spike root install directory (as given by ``--prefix=<path>`` to ``configure``) in order to build either the UVM DV environment or Simple System with co-simulation support.
+
+To build/run the UVM DV environment with the co-simulator add the ``COSIM=1`` argument to the make command.
+To build Simple System with the co-simulator build the ``lowrisc:ibex:ibex_simple_system_cosim`` core.
+
+Quick Build and Run Instructions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Build and install the co-simulator
+
+.. code-block:: bash
+
+ # Get the Ibex co-simulation spike branch
+ git clone -b ibex_cosim https://github.com/lowRISC/riscv-isa-sim.git riscv-isa-sim-cosim
+
+ # Setup build directory
+ cd riscv-isa-sim-cosim
+ mkdir build
+ cd build
+
+ # Configure and build spike
+ ../configure --enable-commitlog --enable-misaligned --prefix=/opt/spike-cosim
+ sudo make -j8 install
+
+ # Setup IBEX_COSIM_ISS_ROOT so build flow can find the co-simulator
+ export IBEX_COSIM_ISS_ROOT=/opt/spike-cosim
+
+Run the UVM DV regression with co-simulation enabled
+
+.. code-block:: bash
+
+ # Run regression with co-simulation enabled
+ cd <ibex_area>/dv/uvm/core_ibex
+ make COSIM=1
+
+Build and run Simple System with the co-simulation enabled
+
+.. code-block:: bash
+
+ # Build simulator
+ fusesoc --cores-root=. run --target=sim --setup --build lowrisc:ibex:ibex_simple_system_cosim --RV32E=0 --RV32M=ibex_pkg::RV32MFast
+
+ # Build coremark test binary, with performance counter dump disabled. The
+ # co-simulator system doesn't produce matching performance counters in spike so
+ # any read of those CSRs results in a mismatch and a failure.
+ make -C ./examples/sw/benchmarks/coremark SUPPRESS_PCOUNT_DUMP=1
+
+ # Spike's libsoftfloat.so needs to be accessible so add it to LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH=/opt/spike-cosim/lib:$LD_LIBRARY_PATH
+
+ # Run coremark binary with co-simulation checking
+ build/lowrisc_ibex_ibex_simple_system_cosim_0/sim-verilator/Vibex_simple_system --meminit=ram,examples/sw/benchmarks/coremark/coremark.elf
+
+Co-simulation details
+----------------------
+
+The co-simulation system uses DPI calls to link the DV and ISS sides together.
+A C++ interface is defined in ``dv/cosim/cosim.h`` with a DPI wrapper provided by ``dv/cosim/cosim_dpi.cc`` and ``dv/cosim/cosim_dpi.h``.
+A ``chandle``, which points to some class instance that implements the interface, must be provided by the DV environment.
+All the co-simulation DPI calls take this ``chandle`` as a first argument.
+
+The details below discuss the C++ interface.
+The DPI version of the interface is almost identical, with all functions prefaced with ``riscv_cosim`` and taking a ``chandle`` of the co-simulation instance to use.
+
+The core function of the co-simulation interface is the ``step`` function:
+
+.. code-block:: c++
+
+ virtual bool step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc, bool sync_trap);
+
+``step`` takes arguments giving the PC of the most recently retired or synchronously trapping instruction in the DUT along with details of any register write that occurred.
+
+Where ``step`` is provided with a retired (successfully executed) instruction it steps the ISS by one instruction and checks it executed the same instruction, with the same register write result, as the DUT.
+
+When ``step`` is provided with an instruction that produces a synchronous trap, it checks the ISS also traps on the same instruction but does not step to the next executed instruction.
+That instruction will be the first instruction of the trap handler and will be checked/stepped by the next call to ``step`` when it retires from the DUT.
+
+Any data memory accesses that the ISS produces during the ``step`` are checked against observed DUT memory accesses.
+
+``step`` returns false if any checks have failed.
+If any errors occur during the step they can be accessed via ``get_errors`` which returns a vector of error messages.
+For the DPI interface errors are accessed using ``riscv_cosim_get_num_errors`` and ``riscv_cosim_get_error``.
+When errors have been checked they can be cleared with ``clear_errors``.
+
+Trap Handling
+^^^^^^^^^^^^^
+
+Traps are separated into two categories, synchronous and asynchronous.
+Synchronous traps are caused by a particular instruction's execution (e.g. an illegal instruction).
+Asynchronous traps are caused by external interrupts.
+Note that in Ibex error responses to both loads and store produce a synchronous trap so the co-simulation system has the same behaviour.
+
+A synchronous trap is associated with a particular instruction and prevents that instruction from completing its execution.
+That instruction doesn't retire, but is still made visible on the RVFI.
+The ``rvfi_trap`` signal is asserted for an instruction that causes a synchronous trap.
+As described above ``step`` should be called for any instruction that causes a synchronous trap to check the trap is also seen by the ISS.
+
+An asynchronous trap can be seen as occurring between instructions and as such doesn't have an associated instruction, nothing will be seen on RVFI with ``rvfi_trap`` set.
+The co-simulation system will immediately take any pending asynchronous trap when ``step`` is called, expecting the instruction checked with ``step`` to be the first instruction of the trap handler.
+
+While a debug request is not strictly an asynchronous trap (it doesn't use the same exception handling mechanism), they work identically to asynchronous traps for the co-simulation system.
+When a debug request is pending when ``step`` is called the co-simulation will expect the instruction checked by ``step`` to be the first instruction of the debug handler.
+
+Interrupts and Debug Requests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The DV environment must observe any incoming interrupts and debug requests generated by the testbench and notify the co-simulation system of them using ``set_mip``, ``set_debug_req`` and ``set_nmi``.
+An interrupt or debug request will take immediate effect at the next ``step`` (if architecturally required to do so).
+The DV environment is responsible for determining when to call ``set_mip``, ``set_debug_req`` and ``set_nmi`` to ensure a RTL and co-simulation match.
+
+The state of the incoming interrupts and debug request is sampled when an instruction moves from IF to ID/EX.
+The sampled state is tracked with the rest of the RVFI pipeline and used to call ``set_mip``, ``set_debug_req`` and ``set_nmi`` when the instruction is output by the RVFI.
+See the comments in :file:`rtl/ibex_core.sv`, around the ``new_debug_req``, ``new_nmi`` and ``new_irq`` signals for further details.
+
+Memory Access Checking and Bus Errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The co-simulation system must be informed of all Dside accesses performed by the RTL using ``notify_dside_access``.
+See :file:`dv/cosim/cosim.h` for further details.
+As Ibex doesn't perform speculative Dside memory accesses, all notified accesses are expected to match with accesses performed by the ISS in the same order they are notified.
+
+Accesses notified via ``notify_dside_access`` can specify they saw an error response, the co-simulation system will produce the appropriate trap when the ISS attempts to access the address that saw the error.
+
+Accesses must be notified before they occur in the ISS for the access matching and trapping on errors to work.
+
+Iside accesses from Ibex can be speculative, so there is no simple link between accesses produced by the RTL and the accesses performed by the ISS for the Iside.
+This means no direct checking of Iside accesses is done, however errors on the Iside accesses that result in an instruction fault trap need to be notified to the co-simulation system.
+``set_iside_error`` does this, it is provided with the address that saw the bus error and it should be called immediately before the ``step`` that will process the trap.
+The co-simulation system will produce an instruction fault trap if it attempts to access the provided error address in the ``step`` call following the ``set_iside_error`` call.
+
+Two methods are available for dealing with bus errors on the Iside, they differ in where they probe.
+One probes on the external instr_X memory interface, the other probes internally within the IF stage.
+The probe used is selected by the ``probe_imem_for_err`` field of the ``core_ibex_cosim_cfg`` structure.
+When set external probing is used, otherwise internal probing is used.
+
+Both probe points look for addresses that have seen bus errors.
+If an instruction entering ID/EX fetches from an address that has seen a bus error (as recorded by one of the probing methods) its ``rvfi_order_id`` is recorded.
+When a faulting instruction is reported on the RVFI and its ``rvfi_order_id`` matches a recorded faulting one ``set_iside_error`` is called with the faulting address before the next ``step``.
+
+The external interface probe should be used when it is guaranteed that a bus error to address A on the external interface results in a fetch error the next time an instruction with address A is observed entering the ID/EX stage (providing no successful access to A has occurred in the mean time).
+Otherwise the internal probe should be used.
+When Ibex is used with the prefetch buffer this guarantee holds and the external probe can be used.
+When Ibex is used with the instruction cache this guarantee does not hold and the internal probe must be used.
+
+Care should be taken when using the internal probe as it will miss any bug that causes instruction faults to be ignored by the prefetch buffer or ICache (or whatever else has been used in place of these by a custom implementation).
+In the case of the Ibex ICache a separate testbench ensures instruction faults are dealt with appropriately within the ICache.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
index 24b5ece..c73894a 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/cs_registers.rst
@@ -94,6 +94,12 @@
+---------+--------------------+--------+-----------------------------------------------+
| 0xB9F | ``mhpmcounter31h`` | WARL | Upper 32 bits of ``mhmpcounter31`` |
+---------+--------------------+--------+-----------------------------------------------+
+| 0xF11 | ``mvendorid`` | R | Machine Vendor ID |
++---------+--------------------+--------+-----------------------------------------------+
+| 0xF12 | ``marchid`` | R | Machine Architecture ID |
++---------+--------------------+--------+-----------------------------------------------+
+| 0xF13 | ``mimpid`` | R | Machine Implementation ID |
++---------+--------------------+--------+-----------------------------------------------+
| 0xF14 | ``mhartid`` | R | Hardware Thread ID |
+---------+--------------------+--------+-----------------------------------------------+
@@ -576,6 +582,38 @@
Any access to these registers will trap.
It is recommended that trap handler software provides a means of accessing platform-defined ``mtime(h)`` timers where available.
+Machine Vendor ID (mvendorid)
+-----------------------------
+
+CSR Address: ``0xF11``
+
+Reset Value: ``0x0000_0000``
+
+Use the ``CSR_MVENDORID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
+Machine Architecture ID (marchid)
+---------------------------------
+
+CSR Address: ``0xF12``
+
+Reset Value: ``0x0000_0016``
+
+Use the ``CSR_MARCHID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+The value used is allocated specifically to Ibex.
+If significant changes are made a different ID should be used.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
+Machine Implementation ID (mimpid)
+----------------------------------
+
+CSR Address: ``0xF13``
+
+Reset Value: ``0x0000_0000``
+
+Use the ``CSR_MIMPID_VALUE`` parameter in :file:`rtl/ibex_pkg.sv` to change the fixed value.
+Details of what the ID represents can be found in the RISC-V Privileged Specification.
+
.. _csr-mhartid:
Hardware Thread ID (mhartid)
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
index 567c149..a80dd47 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/exception_interrupts.rst
@@ -50,7 +50,8 @@
For more information, see the :ref:`cs-registers` documentation.
If multiple interrupts are pending, they are handled in the priority order defined by the RISC-V Privileged Specification, version 1.11 (see Machine Interrupt Registers, Section 3.1.9).
-The highest priority is given to the interrupt with the highest ID, except for timer interrupts, which have the lowest priority.
+The fast interrupts have a platform defined priority.
+In Ibex they take priority over all other interrupts and between fast interrupts the highest priority is given to the interrupt with the lowest ID.
The NMI is enabled independent of the values in the ``mstatus`` and ``mie`` CSRs, and it is not visible through the ``mip`` CSR.
It has interrupt ID 31, i.e., it has the highest priority of all interrupts and the core jumps to the trap-handler base address (in ``mtvec``) plus 0x7C to handle the NMI.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
index 6c96aaf..6ab1dd5 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/index.rst
@@ -22,5 +22,6 @@
debug
tracer
verification
+ cosim
rvfi
history
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
index b79d5e4..3a57e49 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/instruction_decode_execute.rst
@@ -87,7 +87,7 @@
+---------------------------------+---------------+--------------------------+
| Zbp (Permutation) | Full | None |
+---------------------------------+---------------+--------------------------+
- | Zbe (Bit extract/deposit) | Full | All |
+ | Zbe (Bit compress/decompress) | Full | All |
+---------------------------------+---------------+--------------------------+
| Zbf (Bit-field place) | Balanced/Full | All |
+---------------------------------+---------------+--------------------------+
@@ -97,8 +97,6 @@
+---------------------------------+---------------+--------------------------+
| Zbt (Ternary) | Balanced/Full | All |
+---------------------------------+---------------+--------------------------+
- | Zb_tmp (Temporary) [#B_zb_tmp]_ | Balanced/Full | None |
- +---------------------------------+---------------+--------------------------+
The implementation of the B-extension comes with an area overhead of 1.8 to 3.0 kGE for the balanced version and 6.0 to 8.7 kGE for the full version.
That corresponds to an approximate percentage increase in area of 9 to 14 % and 25 to 30 % for the balanced and full versions respectively.
@@ -178,6 +176,3 @@
Ibex will be updated to match future versions of the specification.
Prior to ratification this may involve backwards incompatible changes.
Additionally, neither GCC or Clang have committed to maintaining support upstream for unratified versions of the specification.
-
-.. [#B_zb_tmp] The sign-extend instructions `sext.b/sext.h` are defined but not unambiguously categorized in draft version 0.92 of the extension.
- Temporarily, they have been assigned a separate Z-extension (Zb_tmp) both in Ibex and the RISCV-DV random instruction generator used to verify the bit manipulation instructions in Ibex.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
index a169298..0898fc1 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/load_store_unit.rst
@@ -58,7 +58,7 @@
----------------------
The core can optionally generate and verify check bits sent alongside the data for memory accesses.
-Checkbits are generated and checked using a 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv`).
+Checkbits are generated and checked using an inverted 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv`).
When this feature is used, any mismatch in checkbits will generate a major alert.
This feature is only used if the core is configured with the SecureIbex parameter set.
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
index 5f41df1..167ec48 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
@@ -26,6 +26,10 @@
* Early completion of multiplication by zero/one is removed
* Early completion of divide by zero is removed
+Note that data memory operations to unaligned addresses might result in multiple bus accesses being made.
+This in turn could expose information about the address as a timing side-channel.
+It is therefore recommended to stick to aligned memory accesses when using this feature for critical code regions.
+
Dummy Instruction Insertion
---------------------------
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
index 4ec4186..e1a00ce 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.cc
@@ -6,37 +6,59 @@
#include <iostream>
#include "ibex_pcounts.h"
+#include "ibex_simple_system.h"
#include "verilated_toplevel.h"
#include "verilator_memutil.h"
#include "verilator_sim_ctrl.h"
-int main(int argc, char **argv) {
- ibex_simple_system top;
- VerilatorMemUtil memutil;
- VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
- simctrl.SetTop(&top, &top.IO_CLK, &top.IO_RST_N,
- VerilatorSimCtrlFlags::ResetPolarityNegative);
+SimpleSystem::SimpleSystem(const char *ram_hier_path, int ram_size_words)
+ : _ram(ram_hier_path, ram_size_words, 4) {}
- MemArea ram("TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
- 1024 * 1024 / 4, 4);
+int SimpleSystem::Main(int argc, char **argv) {
+ bool exit_app;
+ int ret_code = Setup(argc, argv, exit_app);
- memutil.RegisterMemoryArea("ram", 0x0, &ram);
- simctrl.RegisterExtension(&memutil);
-
- bool exit_app = false;
- int ret_code = simctrl.ParseCommandArgs(argc, argv, exit_app);
if (exit_app) {
return ret_code;
}
+ Run();
+
+ if (!Finish()) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int SimpleSystem::Setup(int argc, char **argv, bool &exit_app) {
+ VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+
+ simctrl.SetTop(&_top, &_top.IO_CLK, &_top.IO_RST_N,
+ VerilatorSimCtrlFlags::ResetPolarityNegative);
+
+ _memutil.RegisterMemoryArea("ram", 0x0, &_ram);
+ simctrl.RegisterExtension(&_memutil);
+
+ exit_app = false;
+ return simctrl.ParseCommandArgs(argc, argv, exit_app);
+}
+
+void SimpleSystem::Run() {
+ VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+
std::cout << "Simulation of Ibex" << std::endl
<< "==================" << std::endl
<< std::endl;
simctrl.RunSimulation();
+}
+
+bool SimpleSystem::Finish() {
+ VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
if (!simctrl.WasSimulationSuccessful()) {
- return 1;
+ return false;
}
// Set the scope to the root scope, the ibex_pcount_string function otherwise
@@ -51,5 +73,5 @@
std::ofstream pcount_csv("ibex_simple_system_pcount.csv");
pcount_csv << ibex_pcount_string(true);
- return 0;
+ return true;
}
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
index c585a09..1813bab 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
@@ -5,26 +5,12 @@
name: "lowrisc:ibex:ibex_simple_system"
description: "Generic simple system for running binaries on ibex using verilator"
filesets:
- files_sim:
+ files_simple_system:
depend:
- - lowrisc:ibex:ibex_top_tracing
- - lowrisc:ibex:sim_shared
+ - lowrisc:ibex:ibex_simple_system_core
files:
- - rtl/ibex_simple_system.sv
- file_type: systemVerilogSource
-
- files_verilator:
- depend:
- - lowrisc:dv_verilator:memutil_verilator
- - lowrisc:dv_verilator:simutil_verilator
- - lowrisc:dv_verilator:ibex_pcounts
- files:
- - ibex_simple_system.cc: { file_type: cppSource }
- - lint/verilator_waiver.vlt: {file_type: vlt}
-
- files_lint_verible:
- files:
- - lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
+ - ibex_simple_system_main.cc
+ file_type: cppSource
parameters:
RV32E:
@@ -113,9 +99,7 @@
targets:
default: &default_target
filesets:
- - tool_verilator ? (files_verilator)
- - tool_veriblelint ? (files_lint_verible)
- - files_sim
+ - files_simple_system
toplevel: ibex_simple_system
parameters:
- RV32E
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h
new file mode 100644
index 0000000..e8d0919
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.h
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "verilated_toplevel.h"
+#include "verilator_memutil.h"
+
+class SimpleSystem {
+ public:
+ SimpleSystem(const char *ram_hier_path, int ram_size_words);
+ virtual ~SimpleSystem() {}
+ virtual int Main(int argc, char **argv);
+
+ protected:
+ ibex_simple_system _top;
+ VerilatorMemUtil _memutil;
+ MemArea _ram;
+
+ virtual int Setup(int argc, char **argv, bool &exit_app);
+ virtual void Run();
+ virtual bool Finish();
+};
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core
new file mode 100644
index 0000000..84c298a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_core.core
@@ -0,0 +1,36 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:ibex:ibex_simple_system_core"
+description: "Generic simple system for running binaries on ibex using verilator"
+filesets:
+ files_sim:
+ depend:
+ - lowrisc:ibex:ibex_top_tracing
+ - lowrisc:ibex:sim_shared
+ files:
+ - rtl/ibex_simple_system.sv
+ file_type: systemVerilogSource
+
+ files_verilator:
+ depend:
+ - lowrisc:dv_verilator:memutil_verilator
+ - lowrisc:dv_verilator:simutil_verilator
+ - lowrisc:dv_verilator:ibex_pcounts
+ files:
+ - ibex_simple_system.cc: { file_type: cppSource }
+ - ibex_simple_system.h: { file_type: cppSource, is_include_file: true}
+ - lint/verilator_waiver.vlt: {file_type: vlt}
+
+ files_lint_verible:
+ files:
+ - lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
+
+targets:
+ default:
+ filesets:
+ - tool_verilator ? (files_verilator)
+ - tool_veriblelint ? (files_lint_verible)
+ - files_sim
+ - files_verilator
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc
new file mode 100644
index 0000000..25dbbed
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system_main.cc
@@ -0,0 +1,13 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "ibex_simple_system.h"
+
+int main(int argc, char **argv) {
+ SimpleSystem simple_system(
+ "TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
+ 1024 * 1024);
+
+ return simple_system.Main(argc, argv);
+}
diff --git a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
index e32431d..d394515 100644
--- a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
+++ b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.c
@@ -174,7 +174,9 @@
Target specific final code
*/
void portable_fini(core_portable *p) {
+#ifndef SUPPRESS_PCOUNT_DUMP
dump_pcounts();
+#endif
CORE_TICKS elapsed = get_time();
float coremark_mhz;
diff --git a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
index 9ef33bb..c9ae957 100755
--- a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
+++ b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex/core_portme.mak
@@ -5,6 +5,7 @@
# SPDX-License-Identifier: Apache-2.0
RV_ISA = rv32im
+SUPPRESS_PCOUNT_DUMP = 0
OUTFILES = $(OPATH)coremark.dis $(OPATH)coremark.map $(OPATH)coremark.vmem
@@ -36,6 +37,10 @@
-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
-DPERFORMANCE_RUN=1
+ifeq ($(SUPPRESS_PCOUNT_DUMP),1)
+ PORT_CFLAGS += -DSUPPRESS_PCOUNT_DUMP
+endif
+
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS += $(PORT_CFLAGS) $(XCFLAGS) -I$(SIMPLE_SYSTEM_COMMON) -I$(PORT_DIR) -I.
#Flag : LFLAGS_END
diff --git a/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv b/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
index 0095e2f..73849f2 100644
--- a/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
+++ b/hw/vendor/lowrisc_ibex/formal/icache/formal_tb.sv
@@ -111,9 +111,9 @@
f_addr_valid <= 1'b0;
end else begin
if (branch_i) begin
- f_addr_valid = 1'b1;
+ f_addr_valid <= 1'b1;
end else if (valid_o & ready_i & err_o) begin
- f_addr_valid = 1'b0;
+ f_addr_valid <= 1'b0;
end
end
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
index 695eb82..ad796e2 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv
@@ -9,27 +9,27 @@
module ibex_alu #(
parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone
) (
- input ibex_pkg::alu_op_e operator_i,
- input logic [31:0] operand_a_i,
- input logic [31:0] operand_b_i,
+ input ibex_pkg::alu_op_e operator_i,
+ input logic [31:0] operand_a_i,
+ input logic [31:0] operand_b_i,
- input logic instr_first_cycle_i,
+ input logic instr_first_cycle_i,
- input logic [32:0] multdiv_operand_a_i,
- input logic [32:0] multdiv_operand_b_i,
+ input logic [32:0] multdiv_operand_a_i,
+ input logic [32:0] multdiv_operand_b_i,
- input logic multdiv_sel_i,
+ input logic multdiv_sel_i,
- input logic [31:0] imd_val_q_i[2],
- output logic [31:0] imd_val_d_o[2],
- output logic [1:0] imd_val_we_o,
+ input logic [31:0] imd_val_q_i[2],
+ output logic [31:0] imd_val_d_o[2],
+ output logic [1:0] imd_val_we_o,
- output logic [31:0] adder_result_o,
- output logic [33:0] adder_result_ext_o,
+ output logic [31:0] adder_result_o,
+ output logic [33:0] adder_result_ext_o,
- output logic [31:0] result_o,
- output logic comparison_result_o,
- output logic is_equal_result_o
+ output logic [31:0] result_o,
+ output logic comparison_result_o,
+ output logic is_equal_result_o
);
import ibex_pkg::*;
@@ -45,11 +45,17 @@
// Adder //
///////////
+ logic adder_op_a_shift1;
+ logic adder_op_a_shift2;
+ logic adder_op_a_shift3;
logic adder_op_b_negate;
logic [32:0] adder_in_a, adder_in_b;
logic [31:0] adder_result;
always_comb begin
+ adder_op_a_shift1 = 1'b0;
+ adder_op_a_shift2 = 1'b0;
+ adder_op_a_shift3 = 1'b0;
adder_op_b_negate = 1'b0;
unique case (operator_i)
// Adder OPs
@@ -65,20 +71,33 @@
ALU_MIN, ALU_MINU,
ALU_MAX, ALU_MAXU: adder_op_b_negate = 1'b1;
+ // Address Calculation OPs (RV32B Ops)
+ ALU_SH1ADD: if (RV32B != RV32BNone) adder_op_a_shift1 = 1'b1;
+ ALU_SH2ADD: if (RV32B != RV32BNone) adder_op_a_shift2 = 1'b1;
+ ALU_SH3ADD: if (RV32B != RV32BNone) adder_op_a_shift3 = 1'b1;
+
default:;
endcase
end
// prepare operand a
- assign adder_in_a = multdiv_sel_i ? multdiv_operand_a_i : {operand_a_i,1'b1};
+ always_comb begin
+ unique case(1'b1)
+ multdiv_sel_i: adder_in_a = multdiv_operand_a_i;
+ adder_op_a_shift1: adder_in_a = {operand_a_i[30:0],2'b01};
+ adder_op_a_shift2: adder_in_a = {operand_a_i[29:0],3'b001};
+ adder_op_a_shift3: adder_in_a = {operand_a_i[28:0],4'b0001};
+ default: adder_in_a = {operand_a_i,1'b1};
+ endcase
+ end
// prepare operand b
assign operand_b_neg = {operand_b_i,1'b0} ^ {33{1'b1}};
always_comb begin
- unique case(1'b1)
+ unique case (1'b1)
multdiv_sel_i: adder_in_b = multdiv_operand_b_i;
adder_op_b_negate: adder_in_b = operand_b_neg;
- default : adder_in_b = {operand_b_i, 1'b0};
+ default: adder_in_b = {operand_b_i, 1'b0};
endcase
end
@@ -208,12 +227,12 @@
// =======================
// Single bit instructions operate on bit operand_b_i[4:0] of operand_a_i.
- // The operations sbset, sbclr and sbinv are implemented by generation of a bit-mask using the
+ // The operations bset, bclr and binv are implemented by generation of a bit-mask using the
// shifter structure. This is done by left-shifting the operand 32'h1 by the required amount.
// The signal shift_sbmode multiplexes the shifter input and sets the signal shift_left.
// Further processing is taken care of by a separate structure.
//
- // For sbext, the bit defined by operand_b_i[4:0] is to be returned. This is done by simply
+ // For bext, the bit defined by operand_b_i[4:0] is to be returned. This is done by simply
// shifting operand_a_i to the right by the required amount and returning bit [0] of the result.
//
// Bit-Field Place
@@ -248,7 +267,7 @@
assign bfp_len = {~(|operand_b_i[27:24]), operand_b_i[27:24]}; // len = 0 encodes for len = 16
assign bfp_off = operand_b_i[20:16];
assign bfp_mask = (RV32B != RV32BNone) ? ~(32'hffff_ffff << bfp_len) : '0;
- for (genvar i=0; i<32; i++) begin : gen_rev_bfp_mask
+ for (genvar i = 0; i < 32; i++) begin : gen_rev_bfp_mask
assign bfp_mask_rev[i] = bfp_mask[31-i];
end
@@ -262,7 +281,7 @@
always_comb begin
if (bfp_op) begin
- shift_amt[4:0] = bfp_off ; // length field of bfp control word
+ shift_amt[4:0] = bfp_off; // length field of bfp control word
end else begin
shift_amt[4:0] = instr_first_cycle_i ?
(operand_b_i[5] && shift_funnel ? shift_amt_compl[4:0] : operand_b_i[4:0]) :
@@ -272,7 +291,7 @@
// single-bit mode: shift
assign shift_sbmode = (RV32B != RV32BNone) ?
- (operator_i == ALU_SBSET) | (operator_i == ALU_SBCLR) | (operator_i == ALU_SBINV) : 1'b0;
+ (operator_i == ALU_BSET) | (operator_i == ALU_BCLR) | (operator_i == ALU_BINV) : 1'b0;
// left shift if this is:
// * a standard left shift (slo, sll)
@@ -280,12 +299,12 @@
// * a ror in the second cycle
// * fsl: without word-swap bit: first cycle, else: second cycle
// * fsr: without word-swap bit: second cycle, else: first cycle
- // * a single-bit instruction: sbclr, sbset, sbinv (excluding sbext)
+ // * a single-bit instruction: bclr, bset, binv (excluding bext)
// * bfp: bfp_mask << bfp_off
always_comb begin
unique case (operator_i)
ALU_SLL: shift_left = 1'b1;
- ALU_SLO,
+ ALU_SLO: shift_left = (RV32B == RV32BFull) ? 1'b1 : 1'b0;
ALU_BFP: shift_left = (RV32B != RV32BNone) ? 1'b1 : 1'b0;
ALU_ROL: shift_left = (RV32B != RV32BNone) ? instr_first_cycle_i : 0;
ALU_ROR: shift_left = (RV32B != RV32BNone) ? ~instr_first_cycle_i : 0;
@@ -302,7 +321,7 @@
assign shift_arith = (operator_i == ALU_SRA);
assign shift_ones =
- (RV32B != RV32BNone) ? (operator_i == ALU_SLO) | (operator_i == ALU_SRO) : 1'b0;
+ (RV32B == RV32BFull) ? (operator_i == ALU_SLO) | (operator_i == ALU_SRO) : 1'b0;
assign shift_funnel =
(RV32B != RV32BNone) ? (operator_i == ALU_FSL) | (operator_i == ALU_FSR) : 1'b0;
@@ -327,7 +346,7 @@
shift_result = shift_result_ext[31:0];
unused_shift_result_ext = shift_result_ext[32];
- for (int unsigned i=0; i<32; i++) begin
+ for (int unsigned i = 0; i < 32; i++) begin
shift_result_rev[i] = shift_result[31-i];
end
@@ -384,6 +403,7 @@
logic [31:0] singlebit_result;
logic [31:0] rev_result;
logic [31:0] shuffle_result;
+ logic [31:0] xperm_result;
logic [31:0] butterfly_result;
logic [31:0] invbutterfly_result;
logic [31:0] clmul_result;
@@ -396,9 +416,9 @@
/////////////////
// The bit-counter structure computes the number of set bits in its operand. Partial results
- // (from left to right) are needed to compute the control masks for computation of bext/bdep
- // by the butterfly network, if implemented.
- // For pcnt, clz and ctz, only the end result is used.
+ // (from left to right) are needed to compute the control masks for computation of
+ // bcompress/bdecompress by the butterfly network, if implemented.
+ // For cpop, clz and ctz, only the end result is used.
logic zbe_op;
logic bitcnt_ctz;
@@ -433,13 +453,13 @@
bitcnt_bit_mask = ~bitcnt_bit_mask;
end
- assign zbe_op = (operator_i == ALU_BEXT) | (operator_i == ALU_BDEP);
+ assign zbe_op = (operator_i == ALU_BCOMPRESS) | (operator_i == ALU_BDECOMPRESS);
always_comb begin
- case(1'b1)
+ case (1'b1)
zbe_op: bitcnt_bits = operand_b_i;
bitcnt_cz: bitcnt_bits = bitcnt_bit_mask & ~bitcnt_mask_op; // clz / ctz
- default: bitcnt_bits = operand_a_i; // pcnt
+ default: bitcnt_bits = operand_a_i; // cpop
endcase
end
@@ -487,19 +507,19 @@
always_comb begin
bitcnt_partial = '{default: '0};
// stage 1
- for (int unsigned i=1; i<32; i+=2) begin
+ for (int unsigned i = 1; i < 32; i += 2) begin
bitcnt_partial[i] = {5'h0, bitcnt_bits[i]} + {5'h0, bitcnt_bits[i-1]};
end
// stage 2
- for (int unsigned i=3; i<32; i+=4) begin
+ for (int unsigned i = 3; i < 32; i += 4) begin
bitcnt_partial[i] = bitcnt_partial[i-2] + bitcnt_partial[i];
end
// stage 3
- for (int unsigned i=7; i<32; i+=8) begin
+ for (int unsigned i = 7; i < 32; i += 8) begin
bitcnt_partial[i] = bitcnt_partial[i-4] + bitcnt_partial[i];
end
// stage 4
- for (int unsigned i=15; i <32; i+=16) begin
+ for (int unsigned i = 15; i < 32; i += 16) begin
bitcnt_partial[i] = bitcnt_partial[i-8] + bitcnt_partial[i];
end
// stage 5
@@ -510,17 +530,17 @@
bitcnt_partial[23] = bitcnt_partial[15] + bitcnt_partial[23];
// stage 6
- for (int unsigned i=11; i<32; i+=8) begin
+ for (int unsigned i = 11; i < 32; i += 8) begin
bitcnt_partial[i] = bitcnt_partial[i-4] + bitcnt_partial[i];
end
// stage 7
- for (int unsigned i=5; i<32; i+=4) begin
+ for (int unsigned i = 5; i < 32; i += 4) begin
bitcnt_partial[i] = bitcnt_partial[i-2] + bitcnt_partial[i];
end
// stage 8
bitcnt_partial[0] = {5'h0, bitcnt_bits[0]};
- for (int unsigned i=2; i<32; i+=2) begin
+ for (int unsigned i = 2; i < 32; i += 2) begin
bitcnt_partial[i] = bitcnt_partial[i-1] + {5'h0, bitcnt_bits[i]};
end
end
@@ -561,10 +581,10 @@
always_comb begin
unique case (operator_i)
- ALU_SBSET: singlebit_result = operand_a_i | shift_result;
- ALU_SBCLR: singlebit_result = operand_a_i & ~shift_result;
- ALU_SBINV: singlebit_result = operand_a_i ^ shift_result;
- default: singlebit_result = {31'h0, shift_result[0]}; // ALU_SBEXT
+ ALU_BSET: singlebit_result = operand_a_i | shift_result;
+ ALU_BCLR: singlebit_result = operand_a_i & ~shift_result;
+ ALU_BINV: singlebit_result = operand_a_i ^ shift_result;
+ default: singlebit_result = {31'h0, shift_result[0]}; // ALU_BEXT
endcase
end
@@ -572,16 +592,16 @@
// General Reverse and Or-combine //
////////////////////////////////////
- // Only a subset of the General reverse and or-combine instructions are implemented in the
- // balanced version of the B extension. Currently rev, rev8 and orc.b are supported in the
- // base extension.
+ // Only a subset of the general reverse and or-combine instructions are implemented in the
+ // balanced version of the B extension. Currently rev8 (shift_amt = 5'b11000) and orc.b
+ // (shift_amt = 5'b00111) are supported in the base extension.
logic [4:0] zbp_shift_amt;
logic gorc_op;
assign gorc_op = (operator_i == ALU_GORC);
- assign zbp_shift_amt[2:0] = (RV32B == RV32BFull) ? shift_amt[2:0] : {3{&shift_amt[2:0]}};
- assign zbp_shift_amt[4:3] = (RV32B == RV32BFull) ? shift_amt[4:3] : {2{&shift_amt[4:3]}};
+ assign zbp_shift_amt[2:0] = (RV32B == RV32BFull) ? shift_amt[2:0] : {3{shift_amt[0]}};
+ assign zbp_shift_amt[4:3] = (RV32B == RV32BFull) ? shift_amt[4:3] : {2{shift_amt[3]}};
always_comb begin
rev_result = operand_a_i;
@@ -705,25 +725,115 @@
end
end
+ //////////////
+ // Crossbar //
+ //////////////
+ // The crossbar permutation instructions xperm.[nbh] (Zbp) can be implemented using 8
+ // parallel 4-bit-wide, 8-input crossbars. Basically, we permute the 8 nibbles of operand_a_i
+ // based on operand_b_i.
+
+ // Generate selector indices and valid signals.
+ // - sel_n[x] indicates which nibble of operand_a_i is selected for output nibble x.
+ // - vld_n[x] indicates if the selection is valid.
+ logic [7:0][2:0] sel_n; // nibbles
+ logic [7:0] vld_n; // nibbles
+ logic [3:0][1:0] sel_b; // bytes
+ logic [3:0] vld_b; // bytes
+ logic [1:0][0:0] sel_h; // half words
+ logic [1:0] vld_h; // half words
+
+ // Per nibble, 3 bits are needed for the selection. Other bits must be zero.
+ // sel_n bit mask: 32'b0111_0111_0111_0111_0111_0111_0111_0111
+ // vld_n bit mask: 32'b1000_1000_1000_1000_1000_1000_1000_1000
+ for (genvar i = 0; i < 8; i++) begin : gen_sel_vld_n
+ assign sel_n[i] = operand_b_i[i*4 +: 3];
+ assign vld_n[i] = ~|operand_b_i[i*4 + 3 +: 1];
+ end
+
+ // Per byte, 2 bits are needed for the selection. Other bits must be zero.
+ // sel_b bit mask: 32'b0000_0011_0000_0011_0000_0011_0000_0011
+ // vld_b bit mask: 32'b1111_1100_1111_1100_1111_1100_1111_1100
+ for (genvar i = 0; i < 4; i++) begin : gen_sel_vld_b
+ assign sel_b[i] = operand_b_i[i*8 +: 2];
+ assign vld_b[i] = ~|operand_b_i[i*8 + 2 +: 6];
+ end
+
+ // Per half word, 1 bit is needed for the selection only. All other bits must be zero.
+ // sel_h bit mask: 32'b0000_0000_0000_0001_0000_0000_0000_0001
+ // vld_h bit mask: 32'b1111_1111_1111_1110_1111_1111_1111_1110
+ for (genvar i = 0; i < 2; i++) begin : gen_sel_vld_h
+ assign sel_h[i] = operand_b_i[i*16 +: 1];
+ assign vld_h[i] = ~|operand_b_i[i*16 + 1 +: 15];
+ end
+
+ // Convert selector indices and valid signals to control the nibble-based
+ // crossbar logic.
+ logic [7:0][2:0] sel;
+ logic [7:0] vld;
+ always_comb begin
+ unique case (operator_i)
+ ALU_XPERM_N: begin
+ // No conversion needed.
+ sel = sel_n;
+ vld = vld_n;
+ end
+
+ ALU_XPERM_B: begin
+ // Convert byte to nibble indicies.
+ for (int b = 0; b < 4; b++) begin
+ sel[b*2 + 0] = {sel_b[b], 1'b0};
+ sel[b*2 + 1] = {sel_b[b], 1'b1};
+ vld[b*2 +: 2] = {2{vld_b[b]}};
+ end
+ end
+
+ ALU_XPERM_H: begin
+ // Convert half-word to nibble indices.
+ for (int h = 0; h < 2; h++) begin
+ sel[h*4 + 0] = {sel_h[h], 2'b00};
+ sel[h*4 + 1] = {sel_h[h], 2'b01};
+ sel[h*4 + 2] = {sel_h[h], 2'b10};
+ sel[h*4 + 3] = {sel_h[h], 2'b11};
+ vld[h*4 +: 4] = {4{vld_h[h]}};
+ end
+ end
+
+ default: begin
+ // Tie valid to zero to disable the crossbar unless we need it.
+ sel = sel_n;
+ vld = '0;
+ end
+ endcase
+ end
+
+ // The actual nibble-based crossbar logic.
+ logic [7:0][3:0] val_n;
+ logic [7:0][3:0] xperm_n;
+ assign val_n = operand_a_i;
+ for (genvar i = 0; i < 8; i++) begin : gen_xperm_n
+ assign xperm_n[i] = vld[i] ? val_n[sel[i]] : '0;
+ end
+ assign xperm_result = xperm_n;
+
///////////////
// Butterfly //
///////////////
- // The butterfly / inverse butterfly network executing bext/bdep (zbe) instructions.
- // For bdep, the control bits mask of a local left region is generated by
- // the inverse of a n-bit left rotate and complement upon wrap (LROTC) operation by the number
- // of ones in the deposit bitmask to the right of the segment. n hereby denotes the width
- // of the according segment. The bitmask for a pertaining local right region is equal to the
- // corresponding local left region. Bext uses an analogue inverse process.
+ // The butterfly / inverse butterfly network executing bcompress/bdecompress (zbe)
+ // instructions. For bdecompress, the control bits mask of a local left region is generated
+ // by the inverse of a n-bit left rotate and complement upon wrap (LROTC) operation by the
+ // number of ones in the deposit bitmask to the right of the segment. n hereby denotes the
+ // width of the according segment. The bitmask for a pertaining local right region is equal
+ // to the corresponding local left region. Bcompress uses an analogue inverse process.
// Consider the following 8-bit example. For details, see Hilewitz et al. "Fast Bit Gather,
// Bit Scatter and Bit Permuation Instructions for Commodity Microprocessors", (2008).
//
- // The bext/bdep instructions are completed in 2 cycles. In the first cycle, the control
- // bitmask is prepared by executing the parallel prefix bit count. In the second cycle,
- // the bit swapping is executed according to the control masks.
+ // The bcompress/bdecompress instructions are completed in 2 cycles. In the first cycle, the
+ // control bitmask is prepared by executing the parallel prefix bit count. In the second
+ // cycle, the bit swapping is executed according to the control masks.
// 8-bit example: (Hilewitz et al.)
- // Consider the instruction bdep operand_a_i deposit_mask
+ // Consider the instruction bdecompress operand_a_i deposit_mask
// Let operand_a_i = 8'babcd_efgh
// deposit_mask = 8'b1010_1101
//
@@ -761,23 +871,23 @@
// first cycle
// Store partial bitcnts
- for (genvar i=0; i<32; i++) begin : gen_bitcnt_reg_in_lsb
+ for (genvar i = 0; i < 32; i++) begin : gen_bitcnt_reg_in_lsb
assign bitcnt_partial_lsb_d[i] = bitcnt_partial[i][0];
end
- for (genvar i=0; i<16; i++) begin : gen_bitcnt_reg_in_b1
+ for (genvar i = 0; i < 16; i++) begin : gen_bitcnt_reg_in_b1
assign bitcnt_partial_msb_d[i] = bitcnt_partial[2*i+1][1];
end
- for (genvar i=0; i<8; i++) begin : gen_bitcnt_reg_in_b2
+ for (genvar i = 0; i < 8; i++) begin : gen_bitcnt_reg_in_b2
assign bitcnt_partial_msb_d[16+i] = bitcnt_partial[4*i+3][2];
end
- for (genvar i=0; i<4; i++) begin : gen_bitcnt_reg_in_b3
+ for (genvar i = 0; i < 4; i++) begin : gen_bitcnt_reg_in_b3
assign bitcnt_partial_msb_d[24+i] = bitcnt_partial[8*i+7][3];
end
- for (genvar i=0; i<2; i++) begin : gen_bitcnt_reg_in_b4
+ for (genvar i = 0; i < 2; i++) begin : gen_bitcnt_reg_in_b4
assign bitcnt_partial_msb_d[28+i] = bitcnt_partial[16*i+15][4];
end
@@ -789,23 +899,23 @@
always_comb begin
bitcnt_partial_q = '{default: '0};
- for (int unsigned i=0; i<32; i++) begin : gen_bitcnt_reg_out_lsb
+ for (int unsigned i = 0; i < 32; i++) begin : gen_bitcnt_reg_out_lsb
bitcnt_partial_q[i][0] = imd_val_q_i[0][i];
end
- for (int unsigned i=0; i<16; i++) begin : gen_bitcnt_reg_out_b1
+ for (int unsigned i = 0; i < 16; i++) begin : gen_bitcnt_reg_out_b1
bitcnt_partial_q[2*i+1][1] = imd_val_q_i[1][i];
end
- for (int unsigned i=0; i<8; i++) begin : gen_bitcnt_reg_out_b2
+ for (int unsigned i = 0; i < 8; i++) begin : gen_bitcnt_reg_out_b2
bitcnt_partial_q[4*i+3][2] = imd_val_q_i[1][16+i];
end
- for (int unsigned i=0; i<4; i++) begin : gen_bitcnt_reg_out_b3
+ for (int unsigned i = 0; i < 4; i++) begin : gen_bitcnt_reg_out_b3
bitcnt_partial_q[8*i+7][3] = imd_val_q_i[1][24+i];
end
- for (int unsigned i=0; i<2; i++) begin : gen_bitcnt_reg_out_b4
+ for (int unsigned i = 0; i < 2; i++) begin : gen_bitcnt_reg_out_b4
bitcnt_partial_q[16*i+15][4] = imd_val_q_i[1][28+i];
end
@@ -820,8 +930,8 @@
// number of bits in local r = 32 / 2**(stage + 1) = 16/2**stage
`define _N(stg) (16 >> stg)
- // bext / bdep control bit generation
- for (genvar stg=0; stg<5; stg++) begin : gen_butterfly_ctrl_stage
+ // bcompress / bdecompress control bit generation
+ for (genvar stg = 0; stg < 5; stg++) begin : gen_butterfly_ctrl_stage
// number of segs: 2** stg
for (genvar seg=0; seg<2**stg; seg++) begin : gen_butterfly_ctrl
@@ -841,7 +951,7 @@
end
`undef _N
- for (genvar stg=0; stg<5; stg++) begin : gen_butterfly_not
+ for (genvar stg = 0; stg < 5; stg++) begin : gen_butterfly_not
assign butterfly_mask_not[stg] =
~(butterfly_mask_l[stg] | butterfly_mask_r[stg]);
end
@@ -970,7 +1080,7 @@
logic [31:0] clmul_result_raw;
- for (genvar i=0; i<32; i++) begin: gen_rev_operand_b
+ for (genvar i = 0; i < 32; i++) begin : gen_rev_operand_b
assign operand_b_rev[i] = operand_b_i[31-i];
end
@@ -1007,7 +1117,7 @@
assign crc_mu_rev = crc_cpoly ? CRC32C_MU_REV : CRC32_MU_REV;
always_comb begin
- unique case(1'b1)
+ unique case (1'b1)
crc_bmode: crc_operand = {operand_a_i[7:0], 24'h0};
crc_hmode: crc_operand = {operand_a_i[15:0], 16'h0};
default: crc_operand = operand_a_i;
@@ -1025,36 +1135,36 @@
end
end
- for (genvar i=0; i<32; i++) begin : gen_clmul_and_op
+ for (genvar i = 0; i < 32; i++) begin : gen_clmul_and_op
assign clmul_and_stage[i] = clmul_op_b[i] ? clmul_op_a << i : '0;
end
- for (genvar i=0; i<16; i++) begin : gen_clmul_xor_op_l1
+ for (genvar i = 0; i < 16; i++) begin : gen_clmul_xor_op_l1
assign clmul_xor_stage1[i] = clmul_and_stage[2*i] ^ clmul_and_stage[2*i+1];
end
- for (genvar i=0; i<8; i++) begin : gen_clmul_xor_op_l2
+ for (genvar i = 0; i < 8; i++) begin : gen_clmul_xor_op_l2
assign clmul_xor_stage2[i] = clmul_xor_stage1[2*i] ^ clmul_xor_stage1[2*i+1];
end
- for (genvar i=0; i<4; i++) begin : gen_clmul_xor_op_l3
+ for (genvar i = 0; i < 4; i++) begin : gen_clmul_xor_op_l3
assign clmul_xor_stage3[i] = clmul_xor_stage2[2*i] ^ clmul_xor_stage2[2*i+1];
end
- for (genvar i=0; i<2; i++) begin : gen_clmul_xor_op_l4
+ for (genvar i = 0; i < 2; i++) begin : gen_clmul_xor_op_l4
assign clmul_xor_stage4[i] = clmul_xor_stage3[2*i] ^ clmul_xor_stage3[2*i+1];
end
assign clmul_result_raw = clmul_xor_stage4[0] ^ clmul_xor_stage4[1];
- for (genvar i=0; i<32; i++) begin : gen_rev_clmul_result
+ for (genvar i = 0; i < 32; i++) begin : gen_rev_clmul_result
assign clmul_result_rev[i] = clmul_result_raw[31-i];
end
// clmulr_result = rev(clmul(rev(a), rev(b)))
// clmulh_result = clmulr_result >> 1
always_comb begin
- case(1'b1)
+ case (1'b1)
clmul_rmode: clmul_result = clmul_result_rev;
clmul_hmode: clmul_result = {1'b0, clmul_result_rev[31:1]};
default: clmul_result = clmul_result_raw;
@@ -1064,6 +1174,7 @@
logic [31:0] unused_imd_val_q_1;
assign unused_imd_val_q_1 = imd_val_q_i[1];
assign shuffle_result = '0;
+ assign xperm_result = '0;
assign butterfly_result = '0;
assign invbutterfly_result = '0;
assign clmul_result = '0;
@@ -1078,7 +1189,7 @@
//////////////////////////////////////
// Multicycle Bitmanip Instructions //
//////////////////////////////////////
- // Ternary instructions + Shift Rotations + Bit extract/deposit + CRC
+ // Ternary instructions + Shift Rotations + Bit Compress/Decompress + CRC
// For ternary instructions (zbt), operand_a_i is tied to rs1 in the first cycle and rs3 in the
// second cycle. operand_b_i is always tied to rs2.
@@ -1123,7 +1234,7 @@
ALU_CRC32_H, ALU_CRC32C_H,
ALU_CRC32_B, ALU_CRC32C_B: begin
if (RV32B == RV32BFull) begin
- unique case(1'b1)
+ unique case (1'b1)
crc_bmode: multicycle_result = clmul_result_rev ^ (operand_a_i >> 8);
crc_hmode: multicycle_result = clmul_result_rev ^ (operand_a_i >> 16);
default: multicycle_result = clmul_result_rev;
@@ -1141,9 +1252,10 @@
end
end
- ALU_BEXT, ALU_BDEP: begin
+ ALU_BCOMPRESS, ALU_BDECOMPRESS: begin
if (RV32B == RV32BFull) begin
- multicycle_result = (operator_i == ALU_BDEP) ? butterfly_result : invbutterfly_result;
+ multicycle_result = (operator_i == ALU_BDECOMPRESS) ? butterfly_result :
+ invbutterfly_result;
imd_val_d_o = '{bitcnt_partial_lsb_d, bitcnt_partial_msb_d};
if (instr_first_cycle_i) begin
imd_val_we_o = 2'b11;
@@ -1181,6 +1293,7 @@
assign singlebit_result = '0;
assign rev_result = '0;
assign shuffle_result = '0;
+ assign xperm_result = '0;
assign butterfly_result = '0;
assign invbutterfly_result = '0;
assign clmul_result = '0;
@@ -1204,7 +1317,10 @@
ALU_AND, ALU_ANDN: result_o = bwlogic_result;
// Adder Operations
- ALU_ADD, ALU_SUB: result_o = adder_result;
+ ALU_ADD, ALU_SUB,
+ // RV32B
+ ALU_SH1ADD, ALU_SH2ADD,
+ ALU_SH3ADD: result_o = adder_result;
// Shift Operations
ALU_SLL, ALU_SRL,
@@ -1215,6 +1331,9 @@
// Shuffle Operations (RV32B)
ALU_SHFL, ALU_UNSHFL: result_o = shuffle_result;
+ // Crossbar Permutation Operations (RV32B)
+ ALU_XPERM_N, ALU_XPERM_B, ALU_XPERM_H: result_o = xperm_result;
+
// Comparison Operations
ALU_EQ, ALU_NE,
ALU_GE, ALU_GEU,
@@ -1227,7 +1346,7 @@
// Bitcount Operations (RV32B)
ALU_CLZ, ALU_CTZ,
- ALU_PCNT: result_o = {26'h0, bitcnt_result};
+ ALU_CPOP: result_o = {26'h0, bitcnt_result};
// Pack Operations (RV32B)
ALU_PACK, ALU_PACKH,
@@ -1245,12 +1364,12 @@
ALU_CRC32_W, ALU_CRC32C_W,
ALU_CRC32_H, ALU_CRC32C_H,
ALU_CRC32_B, ALU_CRC32C_B,
- // Bit Extract / Deposit (RV32B)
- ALU_BEXT, ALU_BDEP: result_o = multicycle_result;
+ // Bit Compress / Decompress (RV32B)
+ ALU_BCOMPRESS, ALU_BDECOMPRESS: result_o = multicycle_result;
// Single-Bit Bitmanip Operations (RV32B)
- ALU_SBSET, ALU_SBCLR,
- ALU_SBINV, ALU_SBEXT: result_o = singlebit_result;
+ ALU_BSET, ALU_BCLR,
+ ALU_BINV, ALU_BEXT: result_o = singlebit_result;
// General Reverse / Or-combine (RV32B)
ALU_GREV, ALU_GORC: result_o = rev_result;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
index ec694f5..e3c6aa5 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv
@@ -14,13 +14,13 @@
`include "prim_assert.sv"
module ibex_compressed_decoder (
- input logic clk_i,
- input logic rst_ni,
- input logic valid_i,
- input logic [31:0] instr_i,
- output logic [31:0] instr_o,
- output logic is_compressed_o,
- output logic illegal_instr_o
+ input logic clk_i,
+ input logic rst_ni,
+ input logic valid_i,
+ input logic [31:0] instr_i,
+ output logic [31:0] instr_o,
+ output logic is_compressed_o,
+ output logic illegal_instr_o
);
import ibex_pkg::*;
@@ -229,7 +229,7 @@
end else begin
// c.jr -> jalr x0, rd/rs1, 0
instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, {OPCODE_JALR}};
- if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
+ if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
end
end else begin
if (instr_i[6:2] != 5'b0) begin
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index 1a6523c..8641253 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -11,103 +11,101 @@
`include "dv_fcov_macros.svh"
module ibex_controller #(
- parameter bit WritebackStage = 0,
- parameter bit BranchPredictor = 0
+ parameter bit WritebackStage = 0,
+ parameter bit BranchPredictor = 0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- output logic ctrl_busy_o, // core is busy processing instrs
+ output logic ctrl_busy_o, // core is busy processing instrs
- // decoder related signals
- input logic illegal_insn_i, // decoder has an invalid instr
- input logic ecall_insn_i, // decoder has ECALL instr
- input logic mret_insn_i, // decoder has MRET instr
- input logic dret_insn_i, // decoder has DRET instr
- input logic wfi_insn_i, // decoder has WFI instr
- input logic ebrk_insn_i, // decoder has EBREAK instr
- input logic csr_pipe_flush_i, // do CSR-related pipeline flush
+ // decoder related signals
+ input logic illegal_insn_i, // decoder has an invalid instr
+ input logic ecall_insn_i, // decoder has ECALL instr
+ input logic mret_insn_i, // decoder has MRET instr
+ input logic dret_insn_i, // decoder has DRET instr
+ input logic wfi_insn_i, // decoder has WFI instr
+ input logic ebrk_insn_i, // decoder has EBREAK instr
+ input logic csr_pipe_flush_i, // do CSR-related pipeline flush
- // instr from IF-ID pipeline stage
- input logic instr_valid_i, // instr is valid
- input logic [31:0] instr_i, // uncompressed instr data for mtval
- input logic [15:0] instr_compressed_i, // instr compressed data for mtval
- input logic instr_is_compressed_i, // instr is compressed
- input logic instr_bp_taken_i, // instr was predicted taken branch
- input logic instr_fetch_err_i, // instr has error
- input logic instr_fetch_err_plus2_i, // instr error is x32
- input logic [31:0] pc_id_i, // instr address
+ // instr from IF-ID pipeline stage
+ input logic instr_valid_i, // instr is valid
+ input logic [31:0] instr_i, // uncompressed instr data for mtval
+ input logic [15:0] instr_compressed_i, // instr compressed data for mtval
+ input logic instr_is_compressed_i, // instr is compressed
+ input logic instr_bp_taken_i, // instr was predicted taken branch
+ input logic instr_fetch_err_i, // instr has error
+ input logic instr_fetch_err_plus2_i, // instr error is x32
+ input logic [31:0] pc_id_i, // instr address
- // to IF-ID pipeline stage
- output logic instr_valid_clear_o, // kill instr in IF-ID reg
- output logic id_in_ready_o, // ID stage is ready for new instr
- output logic controller_run_o, // Controller is in standard instruction
- // run mode
+ // to IF-ID pipeline stage
+ output logic instr_valid_clear_o, // kill instr in IF-ID reg
+ output logic id_in_ready_o, // ID stage is ready for new instr
+ output logic controller_run_o, // Controller is in standard instruction
+ // run mode
- // to prefetcher
- output logic instr_req_o, // start fetching instructions
- output logic pc_set_o, // jump to address set by pc_mux
- output logic pc_set_spec_o, // speculative branch
- output ibex_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector
- // (boot, normal, exception...)
- output logic nt_branch_mispredict_o, // Not-taken branch in ID/EX was
- // mispredicted (predicted taken)
- output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC
- output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs
+ // to prefetcher
+ output logic instr_req_o, // start fetching instructions
+ output logic pc_set_o, // jump to address set by pc_mux
+ output ibex_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector
+ // (boot, normal, exception...)
+ output logic nt_branch_mispredict_o, // Not-taken branch in ID/EX was
+ // mispredicted (predicted taken)
+ output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC
+ output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs
- // LSU
- input logic [31:0] lsu_addr_last_i, // for mtval
- input logic load_err_i,
- input logic store_err_i,
- output logic wb_exception_o, // Instruction in WB taking an exception
+ // LSU
+ input logic [31:0] lsu_addr_last_i, // for mtval
+ input logic load_err_i,
+ input logic store_err_i,
+ output logic wb_exception_o, // Instruction in WB taking an exception
+ output logic id_exception_o, // Instruction in ID taking an exception
- // jump/branch signals
- input logic branch_set_i, // branch set signal (branch definitely
- // taken)
- input logic branch_set_spec_i, // speculative branch signal (branch
- // may be taken)
- input logic branch_not_set_i, // branch is definitely not taken
- input logic jump_set_i, // jump taken set signal
+ // jump/branch signals
+ input logic branch_set_i, // branch set signal (branch definitely
+ // taken)
+ input logic branch_not_set_i, // branch is definitely not taken
+ input logic jump_set_i, // jump taken set signal
- // interrupt signals
- input logic csr_mstatus_mie_i, // M-mode interrupt enable bit
- input logic irq_pending_i, // interrupt request pending
- input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with
- // mie CSR
- input logic irq_nm_i, // non-maskeable interrupt
- output logic nmi_mode_o, // core executing NMI handler
+ // interrupt signals
+ input logic csr_mstatus_mie_i, // M-mode interrupt enable bit
+ input logic irq_pending_i, // interrupt request pending
+ input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with
+ // mie CSR
+ input logic irq_nm_i, // non-maskeable interrupt
+ output logic nmi_mode_o, // core executing NMI handler
- // debug signals
- input logic debug_req_i,
- output ibex_pkg::dbg_cause_e debug_cause_o,
- output logic debug_csr_save_o,
- output logic debug_mode_o,
- input logic debug_single_step_i,
- input logic debug_ebreakm_i,
- input logic debug_ebreaku_i,
- input logic trigger_match_i,
+ // debug signals
+ input logic debug_req_i,
+ output ibex_pkg::dbg_cause_e debug_cause_o,
+ output logic debug_csr_save_o,
+ output logic debug_mode_o,
+ input logic debug_single_step_i,
+ input logic debug_ebreakm_i,
+ input logic debug_ebreaku_i,
+ input logic trigger_match_i,
- output logic csr_save_if_o,
- output logic csr_save_id_o,
- output logic csr_save_wb_o,
- output logic csr_restore_mret_id_o,
- output logic csr_restore_dret_id_o,
- output logic csr_save_cause_o,
- output logic [31:0] csr_mtval_o,
- input ibex_pkg::priv_lvl_e priv_mode_i,
- input logic csr_mstatus_tw_i,
+ output logic csr_save_if_o,
+ output logic csr_save_id_o,
+ output logic csr_save_wb_o,
+ output logic csr_restore_mret_id_o,
+ output logic csr_restore_dret_id_o,
+ output logic csr_save_cause_o,
+ output logic [31:0] csr_mtval_o,
+ input ibex_pkg::priv_lvl_e priv_mode_i,
+ input logic csr_mstatus_tw_i,
- // stall & flush signals
- input logic stall_id_i,
- input logic stall_wb_i,
- output logic flush_id_o,
- input logic ready_wb_i,
+ // stall & flush signals
+ input logic stall_id_i,
+ input logic stall_wb_i,
+ output logic flush_id_o,
+ input logic ready_wb_i,
- // performance monitors
- output logic perf_jump_o, // we are executing a jump
- // instruction (j, jr, jal, jalr)
- output logic perf_tbranch_o // we are executing a taken branch
- // instruction
+ // performance monitors
+ output logic perf_jump_o, // we are executing a jump
+ // instruction (j, jr, jal, jalr)
+ output logic perf_tbranch_o // we are executing a taken branch
+ // instruction
);
import ibex_pkg::*;
@@ -222,6 +220,7 @@
// LSU exception requests
assign exc_req_lsu = store_err_i | load_err_i;
+ assign id_exception_o = exc_req_d;
// special requests: special instructions, pipeline flushes, exceptions...
// All terms in these expressions are qualified by instr_valid_i except exc_req_lsu which can come
@@ -347,23 +346,15 @@
assign handle_irq = ~debug_mode_q & ~nmi_mode_q &
(irq_nm_i | (irq_pending_i & csr_mstatus_mie_i));
- // generate ID of fast interrupts, highest priority to highest ID
+ // generate ID of fast interrupts, highest priority to lowest ID
always_comb begin : gen_mfip_id
- if (irqs_i.irq_fast[14]) mfip_id = 4'd14;
- else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
- else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
- else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
- else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
- else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
- else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
- else if (irqs_i.irq_fast[ 7]) mfip_id = 4'd7;
- else if (irqs_i.irq_fast[ 6]) mfip_id = 4'd6;
- else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
- else if (irqs_i.irq_fast[ 4]) mfip_id = 4'd4;
- else if (irqs_i.irq_fast[ 3]) mfip_id = 4'd3;
- else if (irqs_i.irq_fast[ 2]) mfip_id = 4'd2;
- else if (irqs_i.irq_fast[ 1]) mfip_id = 4'd1;
- else mfip_id = 4'd0;
+ mfip_id = 4'd0;
+
+ for (int i = 14; i >= 0; i--) begin
+ if (irqs_i.irq_fast[i]) begin
+ mfip_id = i[3:0];
+ end
+ end
end
assign unused_irq_timer = irqs_i.irq_timer;
@@ -390,7 +381,6 @@
// helping timing.
pc_mux_o = PC_BOOT;
pc_set_o = 1'b0;
- pc_set_spec_o = 1'b0;
nt_branch_mispredict_o = 1'b0;
exc_pc_mux_o = EXC_PC_IRQ;
@@ -419,7 +409,6 @@
instr_req_o = 1'b0;
pc_mux_o = PC_BOOT;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
ctrl_fsm_ns = BOOT_SET;
end
@@ -428,7 +417,6 @@
instr_req_o = 1'b1;
pc_mux_o = PC_BOOT;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
ctrl_fsm_ns = FIRST_FETCH;
end
@@ -532,13 +520,6 @@
end
end
- // pc_set signal excluding branch taken condition
- if (branch_set_spec_i || jump_set_i) begin
- // Only speculatively set the PC if the branch predictor hasn't already done the branch
- // for us
- pc_set_spec_o = BranchPredictor ? ~instr_bp_taken_i : 1'b1;
- end
-
// If entering debug mode or handling an IRQ the core needs to wait until any instruction in
// ID or WB has finished executing. Stall IF during that time.
if ((enter_debug_mode || handle_irq) && (stall || id_wb_pending)) begin
@@ -572,7 +553,6 @@
if (handle_irq) begin
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
csr_save_if_o = 1'b1;
csr_save_cause_o = 1'b1;
@@ -607,7 +587,6 @@
// jump to debug exception handler in debug memory
flush_id = 1'b1;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
csr_save_if_o = 1'b1;
debug_csr_save_o = 1'b1;
@@ -638,7 +617,6 @@
flush_id = 1'b1;
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
exc_pc_mux_o = EXC_PC_DBD;
// update dcsr and dpc
@@ -672,7 +650,6 @@
// exc_req_lsu is high for one clock cycle only (in DECODE)
if (exc_req_q || store_err_q || load_err_q) begin
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
pc_mux_o = PC_EXC;
exc_pc_mux_o = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC;
@@ -691,8 +668,8 @@
// Exception/fault prioritisation logic will have set exactly 1 X_prio signal
unique case (1'b1)
instr_fetch_err_prio: begin
- exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
- csr_mtval_o = instr_fetch_err_plus2_i ? (pc_id_i + 32'd2) : pc_id_i;
+ exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
+ csr_mtval_o = instr_fetch_err_plus2_i ? (pc_id_i + 32'd2) : pc_id_i;
end
illegal_insn_prio: begin
exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
@@ -718,7 +695,6 @@
* [Debug Spec v0.13.2, p.42]
*/
pc_set_o = 1'b0;
- pc_set_spec_o = 1'b0;
csr_save_id_o = 1'b0;
csr_save_cause_o = 1'b0;
ctrl_fsm_ns = DBG_TAKEN_ID;
@@ -751,7 +727,6 @@
if (mret_insn) begin
pc_mux_o = PC_ERET;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
csr_restore_mret_id_o = 1'b1;
if (nmi_mode_q) begin
nmi_mode_d = 1'b0; // exit NMI mode
@@ -759,7 +734,6 @@
end else if (dret_insn) begin
pc_mux_o = PC_DRET;
pc_set_o = 1'b1;
- pc_set_spec_o = 1'b1;
debug_mode_d = 1'b0;
csr_restore_dret_id_o = 1'b1;
end else if (wfi_insn) begin
@@ -866,9 +840,6 @@
RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH,
IRQ_TAKEN, DBG_TAKEN_IF, DBG_TAKEN_ID})
- // The speculative branch signal should be set whenever the actual branch signal is set
- `ASSERT(IbexSpecImpliesSetPC, pc_set_o |-> pc_set_spec_o)
-
`ifdef INC_ASSERT
// If something that causes a jump into an exception handler is seen that jump must occur before
// the next instruction executes. The logic tracks whether a jump into an exception handler is
@@ -942,4 +913,12 @@
`ASSERT(IbexNoPCSetOnSpecialReqIfNotExpected,
exception_req_pending && !expect_exception_pc_set |-> ~pc_set_o)
`endif
+
+ `ifdef RVFI
+ // Workaround for internal verilator error when using hierarchical refers to calcuate this
+ // directly in ibex_core
+ logic rvfi_flush_next;
+
+ assign rvfi_flush_next = ctrl_fsm_ns == FLUSH;
+ `endif
endmodule
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 9cf1a0c..136648d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -13,139 +13,138 @@
* Top level module of the ibex RISC-V core
*/
module ibex_core import ibex_pkg::*; #(
- parameter bit PMPEnable = 1'b0,
- parameter int unsigned PMPGranularity = 0,
- parameter int unsigned PMPNumRegions = 4,
- parameter int unsigned MHPMCounterNum = 0,
- parameter int unsigned MHPMCounterWidth = 40,
- parameter bit RV32E = 1'b0,
- parameter rv32m_e RV32M = RV32MFast,
- parameter rv32b_e RV32B = RV32BNone,
- parameter bit BranchTargetALU = 1'b0,
- parameter bit WritebackStage = 1'b0,
- parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0,
- parameter int unsigned BusSizeECC = BUS_SIZE,
- parameter int unsigned TagSizeECC = IC_TAG_SIZE,
- parameter int unsigned LineSizeECC = IC_LINE_SIZE,
- parameter bit BranchPredictor = 1'b0,
- parameter bit DbgTriggerEn = 1'b0,
- parameter int unsigned DbgHwBreakNum = 1,
- parameter bit ResetAll = 1'b0,
- parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
- parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
- parameter bit SecureIbex = 1'b0,
- parameter bit DummyInstructions = 1'b0,
- parameter bit RegFileECC = 1'b0,
- parameter int unsigned RegFileDataWidth = 32,
- parameter int unsigned DmHaltAddr = 32'h1A110800,
- parameter int unsigned DmExceptionAddr = 32'h1A110808
+ parameter bit PMPEnable = 1'b0,
+ parameter int unsigned PMPGranularity = 0,
+ parameter int unsigned PMPNumRegions = 4,
+ parameter int unsigned MHPMCounterNum = 0,
+ parameter int unsigned MHPMCounterWidth = 40,
+ parameter bit RV32E = 1'b0,
+ parameter rv32m_e RV32M = RV32MFast,
+ parameter rv32b_e RV32B = RV32BNone,
+ parameter bit BranchTargetALU = 1'b0,
+ parameter bit WritebackStage = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter bit ICacheECC = 1'b0,
+ parameter int unsigned BusSizeECC = BUS_SIZE,
+ parameter int unsigned TagSizeECC = IC_TAG_SIZE,
+ parameter int unsigned LineSizeECC = IC_LINE_SIZE,
+ parameter bit BranchPredictor = 1'b0,
+ parameter bit DbgTriggerEn = 1'b0,
+ parameter int unsigned DbgHwBreakNum = 1,
+ parameter bit ResetAll = 1'b0,
+ parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
+ parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter bit SecureIbex = 1'b0,
+ parameter bit DummyInstructions = 1'b0,
+ parameter bit RegFileECC = 1'b0,
+ parameter int unsigned RegFileDataWidth = 32,
+ parameter int unsigned DmHaltAddr = 32'h1A110800,
+ parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- input logic [31:0] hart_id_i,
- input logic [31:0] boot_addr_i,
+ input logic [31:0] hart_id_i,
+ input logic [31:0] boot_addr_i,
- // Instruction memory interface
- output logic instr_req_o,
- input logic instr_gnt_i,
- input logic instr_rvalid_i,
- output logic [31:0] instr_addr_o,
- input logic [31:0] instr_rdata_i,
- input logic instr_err_i,
+ // Instruction memory interface
+ output logic instr_req_o,
+ input logic instr_gnt_i,
+ input logic instr_rvalid_i,
+ output logic [31:0] instr_addr_o,
+ input logic [31:0] instr_rdata_i,
+ input logic instr_err_i,
- // Data memory interface
- output logic data_req_o,
- input logic data_gnt_i,
- input logic data_rvalid_i,
- output logic data_we_o,
- output logic [3:0] data_be_o,
- output logic [31:0] data_addr_o,
- output logic [31:0] data_wdata_o,
- input logic [31:0] data_rdata_i,
- input logic data_err_i,
+ // Data memory interface
+ output logic data_req_o,
+ input logic data_gnt_i,
+ input logic data_rvalid_i,
+ output logic data_we_o,
+ output logic [3:0] data_be_o,
+ output logic [31:0] data_addr_o,
+ output logic [31:0] data_wdata_o,
+ input logic [31:0] data_rdata_i,
+ input logic data_err_i,
- // Register file interface
- output logic dummy_instr_id_o,
- output logic [4:0] rf_raddr_a_o,
- output logic [4:0] rf_raddr_b_o,
- output logic [4:0] rf_waddr_wb_o,
- output logic rf_we_wb_o,
- output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o,
- input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i,
- input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i,
+ // Register file interface
+ output logic dummy_instr_id_o,
+ output logic [4:0] rf_raddr_a_o,
+ output logic [4:0] rf_raddr_b_o,
+ output logic [4:0] rf_waddr_wb_o,
+ output logic rf_we_wb_o,
+ output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o,
+ input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i,
+ input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i,
- // RAMs interface
- output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
- output logic ic_tag_write_o,
- output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
- output logic [TagSizeECC-1:0] ic_tag_wdata_o,
- input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
- output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
- output logic ic_data_write_o,
- output logic [IC_INDEX_W-1:0] ic_data_addr_o,
- output logic [LineSizeECC-1:0] ic_data_wdata_o,
- input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
+ // RAMs interface
+ output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
+ output logic ic_tag_write_o,
+ output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
+ output logic [TagSizeECC-1:0] ic_tag_wdata_o,
+ input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
+ output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
+ output logic ic_data_write_o,
+ output logic [IC_INDEX_W-1:0] ic_data_addr_o,
+ output logic [LineSizeECC-1:0] ic_data_wdata_o,
+ input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
- // Interrupt inputs
- input logic irq_software_i,
- input logic irq_timer_i,
- input logic irq_external_i,
- input logic [14:0] irq_fast_i,
- input logic irq_nm_i, // non-maskeable interrupt
- output logic irq_pending_o,
+ // Interrupt inputs
+ input logic irq_software_i,
+ input logic irq_timer_i,
+ input logic irq_external_i,
+ input logic [14:0] irq_fast_i,
+ input logic irq_nm_i, // non-maskeable interrupt
+ output logic irq_pending_o,
- // Debug Interface
- input logic debug_req_i,
- output crash_dump_t crash_dump_o,
+ // Debug Interface
+ input logic debug_req_i,
+ output crash_dump_t crash_dump_o,
- // RISC-V Formal Interface
- // Does not comply with the coding standards of _i/_o suffixes, but follows
- // the convention of RISC-V Formal Interface Specification.
+ // RISC-V Formal Interface
+ // Does not comply with the coding standards of _i/_o suffixes, but follows
+ // the convention of RISC-V Formal Interface Specification.
`ifdef RVFI
- output logic rvfi_valid,
- output logic [63:0] rvfi_order,
- output logic [31:0] rvfi_insn,
- output logic rvfi_trap,
- output logic rvfi_halt,
- output logic rvfi_intr,
- output logic [ 1:0] rvfi_mode,
- output logic [ 1:0] rvfi_ixl,
- output logic [ 4:0] rvfi_rs1_addr,
- output logic [ 4:0] rvfi_rs2_addr,
- output logic [ 4:0] rvfi_rs3_addr,
- output logic [31:0] rvfi_rs1_rdata,
- output logic [31:0] rvfi_rs2_rdata,
- output logic [31:0] rvfi_rs3_rdata,
- output logic [ 4:0] rvfi_rd_addr,
- output logic [31:0] rvfi_rd_wdata,
- output logic [31:0] rvfi_pc_rdata,
- output logic [31:0] rvfi_pc_wdata,
- output logic [31:0] rvfi_mem_addr,
- output logic [ 3:0] rvfi_mem_rmask,
- output logic [ 3:0] rvfi_mem_wmask,
- output logic [31:0] rvfi_mem_rdata,
- output logic [31:0] rvfi_mem_wdata,
+ output logic rvfi_valid,
+ output logic [63:0] rvfi_order,
+ output logic [31:0] rvfi_insn,
+ output logic rvfi_trap,
+ output logic rvfi_halt,
+ output logic rvfi_intr,
+ output logic [ 1:0] rvfi_mode,
+ output logic [ 1:0] rvfi_ixl,
+ output logic [ 4:0] rvfi_rs1_addr,
+ output logic [ 4:0] rvfi_rs2_addr,
+ output logic [ 4:0] rvfi_rs3_addr,
+ output logic [31:0] rvfi_rs1_rdata,
+ output logic [31:0] rvfi_rs2_rdata,
+ output logic [31:0] rvfi_rs3_rdata,
+ output logic [ 4:0] rvfi_rd_addr,
+ output logic [31:0] rvfi_rd_wdata,
+ output logic [31:0] rvfi_pc_rdata,
+ output logic [31:0] rvfi_pc_wdata,
+ output logic [31:0] rvfi_mem_addr,
+ output logic [ 3:0] rvfi_mem_rmask,
+ output logic [ 3:0] rvfi_mem_wmask,
+ output logic [31:0] rvfi_mem_rdata,
+ output logic [31:0] rvfi_mem_wdata,
+ output logic [31:0] rvfi_ext_mip,
+ output logic rvfi_ext_nmi,
+ output logic rvfi_ext_debug_req,
+ output logic [63:0] rvfi_ext_mcycle,
`endif
- // CPU Control Signals
- input logic fetch_enable_i,
- output logic alert_minor_o,
- output logic alert_major_o,
- output logic core_busy_o
+ // CPU Control Signals
+ input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
+ output logic core_busy_o
);
- localparam int unsigned PMP_NUM_CHAN = 2;
+ localparam int unsigned PMP_NUM_CHAN = 3;
localparam bit DataIndTiming = SecureIbex;
localparam bit PCIncrCheck = SecureIbex;
localparam bit ShadowCSR = 1'b0;
- // Speculative branch option, trades-off performance against timing.
- // Setting this to 1 eases branch target critical paths significantly but reduces performance
- // by ~3% (based on CoreMark/MHz score).
- // Set by default in the max PMP config which has the tightest budget for branch target timing.
- localparam bit SpecBranch = PMPEnable & (PMPNumRegions == 16);
// IF/ID signals
logic dummy_instr_id;
@@ -181,8 +180,8 @@
logic instr_first_cycle_id;
logic instr_valid_clear;
logic pc_set;
- logic pc_set_spec;
logic nt_branch_mispredict;
+ logic [31:0] nt_branch_addr;
pc_sel_e pc_mux_id; // Mux selector for next PC
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
exc_cause_e exc_cause; // Exception cause
@@ -297,7 +296,6 @@
pmp_cfg_t csr_pmp_cfg [PMPNumRegions];
pmp_mseccfg_t csr_pmp_mseccfg;
logic pmp_req_err [PMP_NUM_CHAN];
- logic instr_req_out;
logic data_req_out;
logic csr_save_if;
@@ -311,7 +309,6 @@
logic [31:0] csr_mtval;
logic csr_mstatus_tw;
priv_lvl_e priv_mode_id;
- priv_lvl_e priv_mode_if;
priv_lvl_e priv_mode_lsu;
// debug mode and dcsr configuration
@@ -330,6 +327,8 @@
logic perf_instr_ret_wb;
logic perf_instr_ret_compressed_wb;
+ logic perf_instr_ret_wb_spec;
+ logic perf_instr_ret_compressed_wb_spec;
logic perf_iside_wait;
logic perf_dside_wait;
logic perf_mul_wait;
@@ -343,40 +342,6 @@
// for RVFI
logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction
- // RISC-V Formal Interface signals
-`ifdef RVFI
- logic rvfi_instr_new_wb;
- logic rvfi_intr_d;
- logic rvfi_intr_q;
- logic rvfi_set_trap_pc_d;
- logic rvfi_set_trap_pc_q;
- logic [31:0] rvfi_insn_id;
- logic [4:0] rvfi_rs1_addr_d;
- logic [4:0] rvfi_rs1_addr_q;
- logic [4:0] rvfi_rs2_addr_d;
- logic [4:0] rvfi_rs2_addr_q;
- logic [4:0] rvfi_rs3_addr_d;
- logic [31:0] rvfi_rs1_data_d;
- logic [31:0] rvfi_rs1_data_q;
- logic [31:0] rvfi_rs2_data_d;
- logic [31:0] rvfi_rs2_data_q;
- logic [31:0] rvfi_rs3_data_d;
- logic [4:0] rvfi_rd_addr_wb;
- logic [4:0] rvfi_rd_addr_q;
- logic [4:0] rvfi_rd_addr_d;
- logic [31:0] rvfi_rd_wdata_wb;
- logic [31:0] rvfi_rd_wdata_d;
- logic [31:0] rvfi_rd_wdata_q;
- logic rvfi_rd_we_wb;
- logic [3:0] rvfi_mem_mask_int;
- logic [31:0] rvfi_mem_rdata_d;
- logic [31:0] rvfi_mem_rdata_q;
- logic [31:0] rvfi_mem_wdata_d;
- logic [31:0] rvfi_mem_wdata_q;
- logic [31:0] rvfi_mem_addr_d;
- logic [31:0] rvfi_mem_addr_q;
-`endif
-
//////////////////////
// Clock management //
//////////////////////
@@ -390,99 +355,97 @@
//////////////
ibex_if_stage #(
- .DmHaltAddr ( DmHaltAddr ),
- .DmExceptionAddr ( DmExceptionAddr ),
- .DummyInstructions ( DummyInstructions ),
- .ICache ( ICache ),
- .ICacheECC ( ICacheECC ),
- .BusSizeECC ( BusSizeECC ),
- .TagSizeECC ( TagSizeECC ),
- .LineSizeECC ( LineSizeECC ),
- .PCIncrCheck ( PCIncrCheck ),
- .ResetAll ( ResetAll ),
- .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
- .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
- .BranchPredictor ( BranchPredictor )
+ .DmHaltAddr (DmHaltAddr),
+ .DmExceptionAddr (DmExceptionAddr),
+ .DummyInstructions(DummyInstructions),
+ .ICache (ICache),
+ .ICacheECC (ICacheECC),
+ .BusSizeECC (BusSizeECC),
+ .TagSizeECC (TagSizeECC),
+ .LineSizeECC (LineSizeECC),
+ .PCIncrCheck (PCIncrCheck),
+ .ResetAll ( ResetAll ),
+ .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
+ .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
+ .BranchPredictor (BranchPredictor)
) if_stage_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- .boot_addr_i ( boot_addr_i ),
- .req_i ( instr_req_gated ), // instruction request control
+ .boot_addr_i(boot_addr_i),
+ .req_i (instr_req_gated), // instruction request control
- // instruction cache interface
- .instr_req_o ( instr_req_out ),
- .instr_addr_o ( instr_addr_o ),
- .instr_gnt_i ( instr_gnt_i ),
- .instr_rvalid_i ( instr_rvalid_i ),
- .instr_rdata_i ( instr_rdata_i ),
- .instr_err_i ( instr_err_i ),
- .instr_pmp_err_i ( pmp_req_err[PMP_I] ),
+ // instruction cache interface
+ .instr_req_o (instr_req_o),
+ .instr_addr_o (instr_addr_o),
+ .instr_gnt_i (instr_gnt_i),
+ .instr_rvalid_i (instr_rvalid_i),
+ .instr_rdata_i (instr_rdata_i),
+ .instr_err_i (instr_err_i),
- .ic_tag_req_o ( ic_tag_req_o ),
- .ic_tag_write_o ( ic_tag_write_o ),
- .ic_tag_addr_o ( ic_tag_addr_o ),
- .ic_tag_wdata_o ( ic_tag_wdata_o ),
- .ic_tag_rdata_i ( ic_tag_rdata_i ),
- .ic_data_req_o ( ic_data_req_o ),
- .ic_data_write_o ( ic_data_write_o ),
- .ic_data_addr_o ( ic_data_addr_o ),
- .ic_data_wdata_o ( ic_data_wdata_o ),
- .ic_data_rdata_i ( ic_data_rdata_i ),
+ .ic_tag_req_o (ic_tag_req_o),
+ .ic_tag_write_o (ic_tag_write_o),
+ .ic_tag_addr_o (ic_tag_addr_o),
+ .ic_tag_wdata_o (ic_tag_wdata_o),
+ .ic_tag_rdata_i (ic_tag_rdata_i),
+ .ic_data_req_o (ic_data_req_o),
+ .ic_data_write_o(ic_data_write_o),
+ .ic_data_addr_o (ic_data_addr_o),
+ .ic_data_wdata_o(ic_data_wdata_o),
+ .ic_data_rdata_i(ic_data_rdata_i),
- // outputs to ID stage
- .instr_valid_id_o ( instr_valid_id ),
- .instr_new_id_o ( instr_new_id ),
- .instr_rdata_id_o ( instr_rdata_id ),
- .instr_rdata_alu_id_o ( instr_rdata_alu_id ),
- .instr_rdata_c_id_o ( instr_rdata_c_id ),
- .instr_is_compressed_id_o ( instr_is_compressed_id ),
- .instr_bp_taken_o ( instr_bp_taken_id ),
- .instr_fetch_err_o ( instr_fetch_err ),
- .instr_fetch_err_plus2_o ( instr_fetch_err_plus2 ),
- .illegal_c_insn_id_o ( illegal_c_insn_id ),
- .dummy_instr_id_o ( dummy_instr_id ),
- .pc_if_o ( pc_if ),
- .pc_id_o ( pc_id ),
+ // outputs to ID stage
+ .instr_valid_id_o (instr_valid_id),
+ .instr_new_id_o (instr_new_id),
+ .instr_rdata_id_o (instr_rdata_id),
+ .instr_rdata_alu_id_o (instr_rdata_alu_id),
+ .instr_rdata_c_id_o (instr_rdata_c_id),
+ .instr_is_compressed_id_o(instr_is_compressed_id),
+ .instr_bp_taken_o (instr_bp_taken_id),
+ .instr_fetch_err_o (instr_fetch_err),
+ .instr_fetch_err_plus2_o (instr_fetch_err_plus2),
+ .illegal_c_insn_id_o (illegal_c_insn_id),
+ .dummy_instr_id_o (dummy_instr_id),
+ .pc_if_o (pc_if),
+ .pc_id_o (pc_id),
+ .pmp_err_if_i (pmp_req_err[PMP_I]),
+ .pmp_err_if_plus2_i (pmp_req_err[PMP_I2]),
- // control signals
- .instr_valid_clear_i ( instr_valid_clear ),
- .pc_set_i ( pc_set ),
- .pc_set_spec_i ( pc_set_spec ),
- .pc_mux_i ( pc_mux_id ),
- .nt_branch_mispredict_i ( nt_branch_mispredict ),
- .exc_pc_mux_i ( exc_pc_mux_id ),
- .exc_cause ( exc_cause ),
- .dummy_instr_en_i ( dummy_instr_en ),
- .dummy_instr_mask_i ( dummy_instr_mask ),
- .dummy_instr_seed_en_i ( dummy_instr_seed_en ),
- .dummy_instr_seed_i ( dummy_instr_seed ),
- .icache_enable_i ( icache_enable ),
- .icache_inval_i ( icache_inval ),
+ // control signals
+ .instr_valid_clear_i (instr_valid_clear),
+ .pc_set_i (pc_set),
+ .pc_mux_i (pc_mux_id),
+ .nt_branch_mispredict_i(nt_branch_mispredict),
+ .exc_pc_mux_i (exc_pc_mux_id),
+ .exc_cause (exc_cause),
+ .dummy_instr_en_i (dummy_instr_en),
+ .dummy_instr_mask_i (dummy_instr_mask),
+ .dummy_instr_seed_en_i (dummy_instr_seed_en),
+ .dummy_instr_seed_i (dummy_instr_seed),
+ .icache_enable_i (icache_enable),
+ .icache_inval_i (icache_inval),
- // branch targets
- .branch_target_ex_i ( branch_target_ex ),
+ // branch targets
+ .branch_target_ex_i(branch_target_ex),
+ .nt_branch_addr_i (nt_branch_addr),
- // CSRs
- .csr_mepc_i ( csr_mepc ), // exception return address
- .csr_depc_i ( csr_depc ), // debug return address
- .csr_mtvec_i ( csr_mtvec ), // trap-vector base address
- .csr_mtvec_init_o ( csr_mtvec_init ),
+ // CSRs
+ .csr_mepc_i (csr_mepc), // exception return address
+ .csr_depc_i (csr_depc), // debug return address
+ .csr_mtvec_i (csr_mtvec), // trap-vector base address
+ .csr_mtvec_init_o(csr_mtvec_init),
- // pipeline stalls
- .id_in_ready_i ( id_in_ready ),
+ // pipeline stalls
+ .id_in_ready_i(id_in_ready),
- .pc_mismatch_alert_o ( pc_mismatch_alert ),
- .if_busy_o ( if_busy )
+ .pc_mismatch_alert_o(pc_mismatch_alert),
+ .if_busy_o (if_busy)
);
// Core is waiting for the ISide when ID/EX stage is ready for a new instruction but none are
// available
assign perf_iside_wait = id_in_ready & ~instr_valid_id;
- // Qualify the instruction request with PMP error
- assign instr_req_o = instr_req_out & ~pmp_req_err[PMP_I];
-
// fetch_enable_i can be used to stop the core fetching new instructions
assign instr_req_gated = instr_req_int & fetch_enable_i;
@@ -491,207 +454,206 @@
//////////////
ibex_id_stage #(
- .RV32E ( RV32E ),
- .RV32M ( RV32M ),
- .RV32B ( RV32B ),
- .BranchTargetALU ( BranchTargetALU ),
- .DataIndTiming ( DataIndTiming ),
- .SpecBranch ( SpecBranch ),
- .WritebackStage ( WritebackStage ),
- .BranchPredictor ( BranchPredictor )
+ .RV32E (RV32E),
+ .RV32M (RV32M),
+ .RV32B (RV32B),
+ .BranchTargetALU(BranchTargetALU),
+ .DataIndTiming (DataIndTiming),
+ .WritebackStage (WritebackStage),
+ .BranchPredictor(BranchPredictor)
) id_stage_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- // Processor Enable
- .ctrl_busy_o ( ctrl_busy ),
- .illegal_insn_o ( illegal_insn_id ),
+ // Processor Enable
+ .ctrl_busy_o (ctrl_busy),
+ .illegal_insn_o(illegal_insn_id),
- // from/to IF-ID pipeline register
- .instr_valid_i ( instr_valid_id ),
- .instr_rdata_i ( instr_rdata_id ),
- .instr_rdata_alu_i ( instr_rdata_alu_id ),
- .instr_rdata_c_i ( instr_rdata_c_id ),
- .instr_is_compressed_i ( instr_is_compressed_id ),
- .instr_bp_taken_i ( instr_bp_taken_id ),
+ // from/to IF-ID pipeline register
+ .instr_valid_i (instr_valid_id),
+ .instr_rdata_i (instr_rdata_id),
+ .instr_rdata_alu_i (instr_rdata_alu_id),
+ .instr_rdata_c_i (instr_rdata_c_id),
+ .instr_is_compressed_i(instr_is_compressed_id),
+ .instr_bp_taken_i (instr_bp_taken_id),
- // Jumps and branches
- .branch_decision_i ( branch_decision ),
+ // Jumps and branches
+ .branch_decision_i(branch_decision),
- // IF and ID control signals
- .instr_first_cycle_id_o ( instr_first_cycle_id ),
- .instr_valid_clear_o ( instr_valid_clear ),
- .id_in_ready_o ( id_in_ready ),
- .instr_req_o ( instr_req_int ),
- .pc_set_o ( pc_set ),
- .pc_set_spec_o ( pc_set_spec ),
- .pc_mux_o ( pc_mux_id ),
- .nt_branch_mispredict_o ( nt_branch_mispredict ),
- .exc_pc_mux_o ( exc_pc_mux_id ),
- .exc_cause_o ( exc_cause ),
- .icache_inval_o ( icache_inval ),
+ // IF and ID control signals
+ .instr_first_cycle_id_o(instr_first_cycle_id),
+ .instr_valid_clear_o (instr_valid_clear),
+ .id_in_ready_o (id_in_ready),
+ .instr_req_o (instr_req_int),
+ .pc_set_o (pc_set),
+ .pc_mux_o (pc_mux_id),
+ .nt_branch_mispredict_o(nt_branch_mispredict),
+ .nt_branch_addr_o (nt_branch_addr),
+ .exc_pc_mux_o (exc_pc_mux_id),
+ .exc_cause_o (exc_cause),
+ .icache_inval_o (icache_inval),
- .instr_fetch_err_i ( instr_fetch_err ),
- .instr_fetch_err_plus2_i ( instr_fetch_err_plus2 ),
- .illegal_c_insn_i ( illegal_c_insn_id ),
+ .instr_fetch_err_i (instr_fetch_err),
+ .instr_fetch_err_plus2_i(instr_fetch_err_plus2),
+ .illegal_c_insn_i (illegal_c_insn_id),
- .pc_id_i ( pc_id ),
+ .pc_id_i(pc_id),
- // Stalls
- .ex_valid_i ( ex_valid ),
- .lsu_resp_valid_i ( lsu_resp_valid ),
+ // Stalls
+ .ex_valid_i (ex_valid),
+ .lsu_resp_valid_i(lsu_resp_valid),
- .alu_operator_ex_o ( alu_operator_ex ),
- .alu_operand_a_ex_o ( alu_operand_a_ex ),
- .alu_operand_b_ex_o ( alu_operand_b_ex ),
+ .alu_operator_ex_o (alu_operator_ex),
+ .alu_operand_a_ex_o(alu_operand_a_ex),
+ .alu_operand_b_ex_o(alu_operand_b_ex),
- .imd_val_q_ex_o ( imd_val_q_ex ),
- .imd_val_d_ex_i ( imd_val_d_ex ),
- .imd_val_we_ex_i ( imd_val_we_ex ),
+ .imd_val_q_ex_o (imd_val_q_ex),
+ .imd_val_d_ex_i (imd_val_d_ex),
+ .imd_val_we_ex_i(imd_val_we_ex),
- .bt_a_operand_o ( bt_a_operand ),
- .bt_b_operand_o ( bt_b_operand ),
+ .bt_a_operand_o(bt_a_operand),
+ .bt_b_operand_o(bt_b_operand),
- .mult_en_ex_o ( mult_en_ex ),
- .div_en_ex_o ( div_en_ex ),
- .mult_sel_ex_o ( mult_sel_ex ),
- .div_sel_ex_o ( div_sel_ex ),
- .multdiv_operator_ex_o ( multdiv_operator_ex ),
- .multdiv_signed_mode_ex_o ( multdiv_signed_mode_ex ),
- .multdiv_operand_a_ex_o ( multdiv_operand_a_ex ),
- .multdiv_operand_b_ex_o ( multdiv_operand_b_ex ),
- .multdiv_ready_id_o ( multdiv_ready_id ),
+ .mult_en_ex_o (mult_en_ex),
+ .div_en_ex_o (div_en_ex),
+ .mult_sel_ex_o (mult_sel_ex),
+ .div_sel_ex_o (div_sel_ex),
+ .multdiv_operator_ex_o (multdiv_operator_ex),
+ .multdiv_signed_mode_ex_o(multdiv_signed_mode_ex),
+ .multdiv_operand_a_ex_o (multdiv_operand_a_ex),
+ .multdiv_operand_b_ex_o (multdiv_operand_b_ex),
+ .multdiv_ready_id_o (multdiv_ready_id),
- // CSR ID/EX
- .csr_access_o ( csr_access ),
- .csr_op_o ( csr_op ),
- .csr_op_en_o ( csr_op_en ),
- .csr_save_if_o ( csr_save_if ), // control signal to save PC
- .csr_save_id_o ( csr_save_id ), // control signal to save PC
- .csr_save_wb_o ( csr_save_wb ), // control signal to save PC
- .csr_restore_mret_id_o ( csr_restore_mret_id ), // restore mstatus upon MRET
- .csr_restore_dret_id_o ( csr_restore_dret_id ), // restore mstatus upon MRET
- .csr_save_cause_o ( csr_save_cause ),
- .csr_mtval_o ( csr_mtval ),
- .priv_mode_i ( priv_mode_id ),
- .csr_mstatus_tw_i ( csr_mstatus_tw ),
- .illegal_csr_insn_i ( illegal_csr_insn_id ),
- .data_ind_timing_i ( data_ind_timing ),
+ // CSR ID/EX
+ .csr_access_o (csr_access),
+ .csr_op_o (csr_op),
+ .csr_op_en_o (csr_op_en),
+ .csr_save_if_o (csr_save_if), // control signal to save PC
+ .csr_save_id_o (csr_save_id), // control signal to save PC
+ .csr_save_wb_o (csr_save_wb), // control signal to save PC
+ .csr_restore_mret_id_o(csr_restore_mret_id), // restore mstatus upon MRET
+ .csr_restore_dret_id_o(csr_restore_dret_id), // restore mstatus upon MRET
+ .csr_save_cause_o (csr_save_cause),
+ .csr_mtval_o (csr_mtval),
+ .priv_mode_i (priv_mode_id),
+ .csr_mstatus_tw_i (csr_mstatus_tw),
+ .illegal_csr_insn_i (illegal_csr_insn_id),
+ .data_ind_timing_i (data_ind_timing),
- // LSU
- .lsu_req_o ( lsu_req ), // to load store unit
- .lsu_we_o ( lsu_we ), // to load store unit
- .lsu_type_o ( lsu_type ), // to load store unit
- .lsu_sign_ext_o ( lsu_sign_ext ), // to load store unit
- .lsu_wdata_o ( lsu_wdata ), // to load store unit
- .lsu_req_done_i ( lsu_req_done ), // from load store unit
+ // LSU
+ .lsu_req_o (lsu_req), // to load store unit
+ .lsu_we_o (lsu_we), // to load store unit
+ .lsu_type_o (lsu_type), // to load store unit
+ .lsu_sign_ext_o(lsu_sign_ext), // to load store unit
+ .lsu_wdata_o (lsu_wdata), // to load store unit
+ .lsu_req_done_i(lsu_req_done), // from load store unit
- .lsu_addr_incr_req_i ( lsu_addr_incr_req ),
- .lsu_addr_last_i ( lsu_addr_last ),
+ .lsu_addr_incr_req_i(lsu_addr_incr_req),
+ .lsu_addr_last_i (lsu_addr_last),
- .lsu_load_err_i ( lsu_load_err ),
- .lsu_store_err_i ( lsu_store_err ),
+ .lsu_load_err_i (lsu_load_err),
+ .lsu_store_err_i(lsu_store_err),
- // Interrupt Signals
- .csr_mstatus_mie_i ( csr_mstatus_mie ),
- .irq_pending_i ( irq_pending_o ),
- .irqs_i ( irqs ),
- .irq_nm_i ( irq_nm_i ),
- .nmi_mode_o ( nmi_mode ),
+ // Interrupt Signals
+ .csr_mstatus_mie_i(csr_mstatus_mie),
+ .irq_pending_i (irq_pending_o),
+ .irqs_i (irqs),
+ .irq_nm_i (irq_nm_i),
+ .nmi_mode_o (nmi_mode),
- // Debug Signal
- .debug_mode_o ( debug_mode ),
- .debug_cause_o ( debug_cause ),
- .debug_csr_save_o ( debug_csr_save ),
- .debug_req_i ( debug_req_i ),
- .debug_single_step_i ( debug_single_step ),
- .debug_ebreakm_i ( debug_ebreakm ),
- .debug_ebreaku_i ( debug_ebreaku ),
- .trigger_match_i ( trigger_match ),
+ // Debug Signal
+ .debug_mode_o (debug_mode),
+ .debug_cause_o (debug_cause),
+ .debug_csr_save_o (debug_csr_save),
+ .debug_req_i (debug_req_i),
+ .debug_single_step_i(debug_single_step),
+ .debug_ebreakm_i (debug_ebreakm),
+ .debug_ebreaku_i (debug_ebreaku),
+ .trigger_match_i (trigger_match),
- // write data to commit in the register file
- .result_ex_i ( result_ex ),
- .csr_rdata_i ( csr_rdata ),
+ // write data to commit in the register file
+ .result_ex_i(result_ex),
+ .csr_rdata_i(csr_rdata),
- .rf_raddr_a_o ( rf_raddr_a ),
- .rf_rdata_a_i ( rf_rdata_a ),
- .rf_raddr_b_o ( rf_raddr_b ),
- .rf_rdata_b_i ( rf_rdata_b ),
- .rf_ren_a_o ( rf_ren_a ),
- .rf_ren_b_o ( rf_ren_b ),
- .rf_waddr_id_o ( rf_waddr_id ),
- .rf_wdata_id_o ( rf_wdata_id ),
- .rf_we_id_o ( rf_we_id ),
- .rf_rd_a_wb_match_o ( rf_rd_a_wb_match ),
- .rf_rd_b_wb_match_o ( rf_rd_b_wb_match ),
+ .rf_raddr_a_o (rf_raddr_a),
+ .rf_rdata_a_i (rf_rdata_a),
+ .rf_raddr_b_o (rf_raddr_b),
+ .rf_rdata_b_i (rf_rdata_b),
+ .rf_ren_a_o (rf_ren_a),
+ .rf_ren_b_o (rf_ren_b),
+ .rf_waddr_id_o (rf_waddr_id),
+ .rf_wdata_id_o (rf_wdata_id),
+ .rf_we_id_o (rf_we_id),
+ .rf_rd_a_wb_match_o(rf_rd_a_wb_match),
+ .rf_rd_b_wb_match_o(rf_rd_b_wb_match),
- .rf_waddr_wb_i ( rf_waddr_wb ),
- .rf_wdata_fwd_wb_i ( rf_wdata_fwd_wb ),
- .rf_write_wb_i ( rf_write_wb ),
+ .rf_waddr_wb_i (rf_waddr_wb),
+ .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb),
+ .rf_write_wb_i (rf_write_wb),
- .en_wb_o ( en_wb ),
- .instr_type_wb_o ( instr_type_wb ),
- .instr_perf_count_id_o ( instr_perf_count_id ),
- .ready_wb_i ( ready_wb ),
- .outstanding_load_wb_i ( outstanding_load_wb ),
- .outstanding_store_wb_i ( outstanding_store_wb ),
+ .en_wb_o (en_wb),
+ .instr_type_wb_o (instr_type_wb),
+ .instr_perf_count_id_o (instr_perf_count_id),
+ .ready_wb_i (ready_wb),
+ .outstanding_load_wb_i (outstanding_load_wb),
+ .outstanding_store_wb_i(outstanding_store_wb),
- // Performance Counters
- .perf_jump_o ( perf_jump ),
- .perf_branch_o ( perf_branch ),
- .perf_tbranch_o ( perf_tbranch ),
- .perf_dside_wait_o ( perf_dside_wait ),
- .perf_mul_wait_o ( perf_mul_wait ),
- .perf_div_wait_o ( perf_div_wait ),
- .instr_id_done_o ( instr_id_done )
+ // Performance Counters
+ .perf_jump_o (perf_jump),
+ .perf_branch_o (perf_branch),
+ .perf_tbranch_o (perf_tbranch),
+ .perf_dside_wait_o(perf_dside_wait),
+ .perf_mul_wait_o (perf_mul_wait),
+ .perf_div_wait_o (perf_div_wait),
+ .instr_id_done_o (instr_id_done)
);
// for RVFI only
assign unused_illegal_insn_id = illegal_insn_id;
ibex_ex_block #(
- .RV32M ( RV32M ),
- .RV32B ( RV32B ),
- .BranchTargetALU ( BranchTargetALU )
+ .RV32M (RV32M),
+ .RV32B (RV32B),
+ .BranchTargetALU(BranchTargetALU)
) ex_block_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- // ALU signal from ID stage
- .alu_operator_i ( alu_operator_ex ),
- .alu_operand_a_i ( alu_operand_a_ex ),
- .alu_operand_b_i ( alu_operand_b_ex ),
- .alu_instr_first_cycle_i ( instr_first_cycle_id ),
+ // ALU signal from ID stage
+ .alu_operator_i (alu_operator_ex),
+ .alu_operand_a_i (alu_operand_a_ex),
+ .alu_operand_b_i (alu_operand_b_ex),
+ .alu_instr_first_cycle_i(instr_first_cycle_id),
- // Branch target ALU signal from ID stage
- .bt_a_operand_i ( bt_a_operand ),
- .bt_b_operand_i ( bt_b_operand ),
+ // Branch target ALU signal from ID stage
+ .bt_a_operand_i(bt_a_operand),
+ .bt_b_operand_i(bt_b_operand),
- // Multipler/Divider signal from ID stage
- .multdiv_operator_i ( multdiv_operator_ex ),
- .mult_en_i ( mult_en_ex ),
- .div_en_i ( div_en_ex ),
- .mult_sel_i ( mult_sel_ex ),
- .div_sel_i ( div_sel_ex ),
- .multdiv_signed_mode_i ( multdiv_signed_mode_ex ),
- .multdiv_operand_a_i ( multdiv_operand_a_ex ),
- .multdiv_operand_b_i ( multdiv_operand_b_ex ),
- .multdiv_ready_id_i ( multdiv_ready_id ),
- .data_ind_timing_i ( data_ind_timing ),
+ // Multipler/Divider signal from ID stage
+ .multdiv_operator_i (multdiv_operator_ex),
+ .mult_en_i (mult_en_ex),
+ .div_en_i (div_en_ex),
+ .mult_sel_i (mult_sel_ex),
+ .div_sel_i (div_sel_ex),
+ .multdiv_signed_mode_i(multdiv_signed_mode_ex),
+ .multdiv_operand_a_i (multdiv_operand_a_ex),
+ .multdiv_operand_b_i (multdiv_operand_b_ex),
+ .multdiv_ready_id_i (multdiv_ready_id),
+ .data_ind_timing_i (data_ind_timing),
- // Intermediate value register
- .imd_val_we_o ( imd_val_we_ex ),
- .imd_val_d_o ( imd_val_d_ex ),
- .imd_val_q_i ( imd_val_q_ex ),
+ // Intermediate value register
+ .imd_val_we_o(imd_val_we_ex),
+ .imd_val_d_o (imd_val_d_ex),
+ .imd_val_q_i (imd_val_q_ex),
- // Outputs
- .alu_adder_result_ex_o ( alu_adder_result_ex ), // to LSU
- .result_ex_o ( result_ex ), // to ID
+ // Outputs
+ .alu_adder_result_ex_o(alu_adder_result_ex), // to LSU
+ .result_ex_o (result_ex), // to ID
- .branch_target_o ( branch_target_ex ), // to IF
- .branch_decision_o ( branch_decision ), // to ID
+ .branch_target_o (branch_target_ex), // to IF
+ .branch_decision_o(branch_decision), // to ID
- .ex_valid_o ( ex_valid )
+ .ex_valid_o(ex_valid)
);
/////////////////////
@@ -702,88 +664,90 @@
assign lsu_resp_err = lsu_load_err | lsu_store_err;
ibex_load_store_unit load_store_unit_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- // data interface
- .data_req_o ( data_req_out ),
- .data_gnt_i ( data_gnt_i ),
- .data_rvalid_i ( data_rvalid_i ),
- .data_err_i ( data_err_i ),
- .data_pmp_err_i ( pmp_req_err[PMP_D] ),
+ // data interface
+ .data_req_o (data_req_out),
+ .data_gnt_i (data_gnt_i),
+ .data_rvalid_i (data_rvalid_i),
+ .data_err_i (data_err_i),
+ .data_pmp_err_i(pmp_req_err[PMP_D]),
- .data_addr_o ( data_addr_o ),
- .data_we_o ( data_we_o ),
- .data_be_o ( data_be_o ),
- .data_wdata_o ( data_wdata_o ),
- .data_rdata_i ( data_rdata_i ),
+ .data_addr_o (data_addr_o),
+ .data_we_o (data_we_o),
+ .data_be_o (data_be_o),
+ .data_wdata_o(data_wdata_o),
+ .data_rdata_i(data_rdata_i),
- // signals to/from ID/EX stage
- .lsu_we_i ( lsu_we ),
- .lsu_type_i ( lsu_type ),
- .lsu_wdata_i ( lsu_wdata ),
- .lsu_sign_ext_i ( lsu_sign_ext ),
+ // signals to/from ID/EX stage
+ .lsu_we_i (lsu_we),
+ .lsu_type_i (lsu_type),
+ .lsu_wdata_i (lsu_wdata),
+ .lsu_sign_ext_i(lsu_sign_ext),
- .lsu_rdata_o ( rf_wdata_lsu ),
- .lsu_rdata_valid_o ( rf_we_lsu ),
- .lsu_req_i ( lsu_req ),
- .lsu_req_done_o ( lsu_req_done ),
+ .lsu_rdata_o (rf_wdata_lsu),
+ .lsu_rdata_valid_o(rf_we_lsu),
+ .lsu_req_i (lsu_req),
+ .lsu_req_done_o (lsu_req_done),
- .adder_result_ex_i ( alu_adder_result_ex ),
+ .adder_result_ex_i(alu_adder_result_ex),
- .addr_incr_req_o ( lsu_addr_incr_req ),
- .addr_last_o ( lsu_addr_last ),
+ .addr_incr_req_o(lsu_addr_incr_req),
+ .addr_last_o (lsu_addr_last),
- .lsu_resp_valid_o ( lsu_resp_valid ),
+ .lsu_resp_valid_o(lsu_resp_valid),
- // exception signals
- .load_err_o ( lsu_load_err ),
- .store_err_o ( lsu_store_err ),
+ // exception signals
+ .load_err_o (lsu_load_err),
+ .store_err_o(lsu_store_err),
- .busy_o ( lsu_busy ),
+ .busy_o(lsu_busy),
- .perf_load_o ( perf_load ),
- .perf_store_o ( perf_store )
+ .perf_load_o (perf_load),
+ .perf_store_o(perf_store)
);
ibex_wb_stage #(
.ResetAll ( ResetAll ),
- .WritebackStage ( WritebackStage )
+ .WritebackStage(WritebackStage)
) wb_stage_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .en_wb_i ( en_wb ),
- .instr_type_wb_i ( instr_type_wb ),
- .pc_id_i ( pc_id ),
- .instr_is_compressed_id_i ( instr_is_compressed_id ),
- .instr_perf_count_id_i ( instr_perf_count_id ),
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .en_wb_i (en_wb),
+ .instr_type_wb_i (instr_type_wb),
+ .pc_id_i (pc_id),
+ .instr_is_compressed_id_i(instr_is_compressed_id),
+ .instr_perf_count_id_i (instr_perf_count_id),
- .ready_wb_o ( ready_wb ),
- .rf_write_wb_o ( rf_write_wb ),
- .outstanding_load_wb_o ( outstanding_load_wb ),
- .outstanding_store_wb_o ( outstanding_store_wb ),
- .pc_wb_o ( pc_wb ),
- .perf_instr_ret_wb_o ( perf_instr_ret_wb ),
- .perf_instr_ret_compressed_wb_o ( perf_instr_ret_compressed_wb ),
+ .ready_wb_o (ready_wb),
+ .rf_write_wb_o (rf_write_wb),
+ .outstanding_load_wb_o (outstanding_load_wb),
+ .outstanding_store_wb_o (outstanding_store_wb),
+ .pc_wb_o (pc_wb),
+ .perf_instr_ret_wb_o (perf_instr_ret_wb),
+ .perf_instr_ret_compressed_wb_o (perf_instr_ret_compressed_wb),
+ .perf_instr_ret_wb_spec_o (perf_instr_ret_wb_spec),
+ .perf_instr_ret_compressed_wb_spec_o(perf_instr_ret_compressed_wb_spec),
- .rf_waddr_id_i ( rf_waddr_id ),
- .rf_wdata_id_i ( rf_wdata_id ),
- .rf_we_id_i ( rf_we_id ),
+ .rf_waddr_id_i(rf_waddr_id),
+ .rf_wdata_id_i(rf_wdata_id),
+ .rf_we_id_i (rf_we_id),
- .rf_wdata_lsu_i ( rf_wdata_lsu ),
- .rf_we_lsu_i ( rf_we_lsu ),
+ .rf_wdata_lsu_i(rf_wdata_lsu),
+ .rf_we_lsu_i (rf_we_lsu),
- .rf_wdata_fwd_wb_o ( rf_wdata_fwd_wb ),
+ .rf_wdata_fwd_wb_o(rf_wdata_fwd_wb),
- .rf_waddr_wb_o ( rf_waddr_wb ),
- .rf_wdata_wb_o ( rf_wdata_wb ),
- .rf_we_wb_o ( rf_we_wb ),
+ .rf_waddr_wb_o(rf_waddr_wb),
+ .rf_wdata_wb_o(rf_wdata_wb),
+ .rf_we_wb_o (rf_we_wb),
- .lsu_resp_valid_i ( lsu_resp_valid ),
- .lsu_resp_err_i ( lsu_resp_err ),
+ .lsu_resp_valid_i(lsu_resp_valid),
+ .lsu_resp_err_i (lsu_resp_err),
- .instr_done_wb_o ( instr_done_wb )
+ .instr_done_wb_o(instr_done_wb)
);
/////////////////////////////
@@ -802,23 +766,23 @@
logic rf_ecc_err_a_id, rf_ecc_err_b_id;
// ECC checkbit generation for regiter file wdata
- prim_secded_39_32_enc regfile_ecc_enc (
- .data_i (rf_wdata_wb),
- .data_o (rf_wdata_wb_ecc_o)
+ prim_secded_inv_39_32_enc regfile_ecc_enc (
+ .data_i(rf_wdata_wb),
+ .data_o(rf_wdata_wb_ecc_o)
);
// ECC checking on register file rdata
- prim_secded_39_32_dec regfile_ecc_dec_a (
- .data_i (rf_rdata_a_ecc_i),
- .data_o (),
- .syndrome_o (),
- .err_o (rf_ecc_err_a)
+ prim_secded_inv_39_32_dec regfile_ecc_dec_a (
+ .data_i (rf_rdata_a_ecc_i),
+ .data_o (),
+ .syndrome_o(),
+ .err_o (rf_ecc_err_a)
);
- prim_secded_39_32_dec regfile_ecc_dec_b (
- .data_i (rf_rdata_b_ecc_i),
- .data_o (),
- .syndrome_o (),
- .err_o (rf_ecc_err_b)
+ prim_secded_inv_39_32_dec regfile_ecc_dec_b (
+ .data_i (rf_rdata_b_ecc_i),
+ .data_o (),
+ .syndrome_o(),
+ .err_o (rf_ecc_err_b)
);
// Assign read outputs - no error correction, just trigger an alert
@@ -909,9 +873,6 @@
// RF (Register File) //
////////////////////////
`ifdef RVFI
- assign rvfi_rd_addr_wb = rf_waddr_wb;
- assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
- assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu;
`endif
@@ -923,104 +884,105 @@
assign csr_addr = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0);
ibex_cs_registers #(
- .DbgTriggerEn ( DbgTriggerEn ),
- .DbgHwBreakNum ( DbgHwBreakNum ),
- .DataIndTiming ( DataIndTiming ),
- .DummyInstructions ( DummyInstructions ),
- .ShadowCSR ( ShadowCSR ),
- .ICache ( ICache ),
- .MHPMCounterNum ( MHPMCounterNum ),
- .MHPMCounterWidth ( MHPMCounterWidth ),
- .PMPEnable ( PMPEnable ),
- .PMPGranularity ( PMPGranularity ),
- .PMPNumRegions ( PMPNumRegions ),
- .RV32E ( RV32E ),
- .RV32M ( RV32M ),
- .RV32B ( RV32B )
+ .DbgTriggerEn (DbgTriggerEn),
+ .DbgHwBreakNum (DbgHwBreakNum),
+ .DataIndTiming (DataIndTiming),
+ .DummyInstructions(DummyInstructions),
+ .ShadowCSR (ShadowCSR),
+ .ICache (ICache),
+ .MHPMCounterNum (MHPMCounterNum),
+ .MHPMCounterWidth (MHPMCounterWidth),
+ .PMPEnable (PMPEnable),
+ .PMPGranularity (PMPGranularity),
+ .PMPNumRegions (PMPNumRegions),
+ .RV32E (RV32E),
+ .RV32M (RV32M),
+ .RV32B (RV32B)
) cs_registers_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- // Hart ID from outside
- .hart_id_i ( hart_id_i ),
- .priv_mode_id_o ( priv_mode_id ),
- .priv_mode_if_o ( priv_mode_if ),
- .priv_mode_lsu_o ( priv_mode_lsu ),
+ // Hart ID from outside
+ .hart_id_i (hart_id_i),
+ .priv_mode_id_o (priv_mode_id),
+ .priv_mode_lsu_o(priv_mode_lsu),
- // mtvec
- .csr_mtvec_o ( csr_mtvec ),
- .csr_mtvec_init_i ( csr_mtvec_init ),
- .boot_addr_i ( boot_addr_i ),
+ // mtvec
+ .csr_mtvec_o (csr_mtvec),
+ .csr_mtvec_init_i(csr_mtvec_init),
+ .boot_addr_i (boot_addr_i),
- // Interface to CSRs ( SRAM like )
- .csr_access_i ( csr_access ),
- .csr_addr_i ( csr_addr ),
- .csr_wdata_i ( csr_wdata ),
- .csr_op_i ( csr_op ),
- .csr_op_en_i ( csr_op_en ),
- .csr_rdata_o ( csr_rdata ),
+ // Interface to CSRs ( SRAM like )
+ .csr_access_i(csr_access),
+ .csr_addr_i (csr_addr),
+ .csr_wdata_i (csr_wdata),
+ .csr_op_i (csr_op),
+ .csr_op_en_i (csr_op_en),
+ .csr_rdata_o (csr_rdata),
- // Interrupt related control signals
- .irq_software_i ( irq_software_i ),
- .irq_timer_i ( irq_timer_i ),
- .irq_external_i ( irq_external_i ),
- .irq_fast_i ( irq_fast_i ),
- .nmi_mode_i ( nmi_mode ),
- .irq_pending_o ( irq_pending_o ),
- .irqs_o ( irqs ),
- .csr_mstatus_mie_o ( csr_mstatus_mie ),
- .csr_mstatus_tw_o ( csr_mstatus_tw ),
- .csr_mepc_o ( csr_mepc ),
+ // Interrupt related control signals
+ .irq_software_i (irq_software_i),
+ .irq_timer_i (irq_timer_i),
+ .irq_external_i (irq_external_i),
+ .irq_fast_i (irq_fast_i),
+ .nmi_mode_i (nmi_mode),
+ .irq_pending_o (irq_pending_o),
+ .irqs_o (irqs),
+ .csr_mstatus_mie_o(csr_mstatus_mie),
+ .csr_mstatus_tw_o (csr_mstatus_tw),
+ .csr_mepc_o (csr_mepc),
- // PMP
- .csr_pmp_cfg_o ( csr_pmp_cfg ),
- .csr_pmp_addr_o ( csr_pmp_addr ),
- .csr_pmp_mseccfg_o ( csr_pmp_mseccfg ),
+ // PMP
+ .csr_pmp_cfg_o (csr_pmp_cfg),
+ .csr_pmp_addr_o (csr_pmp_addr),
+ .csr_pmp_mseccfg_o(csr_pmp_mseccfg),
- // debug
- .csr_depc_o ( csr_depc ),
- .debug_mode_i ( debug_mode ),
- .debug_cause_i ( debug_cause ),
- .debug_csr_save_i ( debug_csr_save ),
- .debug_single_step_o ( debug_single_step ),
- .debug_ebreakm_o ( debug_ebreakm ),
- .debug_ebreaku_o ( debug_ebreaku ),
- .trigger_match_o ( trigger_match ),
+ // debug
+ .csr_depc_o (csr_depc),
+ .debug_mode_i (debug_mode),
+ .debug_cause_i (debug_cause),
+ .debug_csr_save_i (debug_csr_save),
+ .debug_single_step_o(debug_single_step),
+ .debug_ebreakm_o (debug_ebreakm),
+ .debug_ebreaku_o (debug_ebreaku),
+ .trigger_match_o (trigger_match),
- .pc_if_i ( pc_if ),
- .pc_id_i ( pc_id ),
- .pc_wb_i ( pc_wb ),
+ .pc_if_i(pc_if),
+ .pc_id_i(pc_id),
+ .pc_wb_i(pc_wb),
- .data_ind_timing_o ( data_ind_timing ),
- .dummy_instr_en_o ( dummy_instr_en ),
- .dummy_instr_mask_o ( dummy_instr_mask ),
- .dummy_instr_seed_en_o ( dummy_instr_seed_en ),
- .dummy_instr_seed_o ( dummy_instr_seed ),
- .icache_enable_o ( icache_enable ),
- .csr_shadow_err_o ( csr_shadow_err ),
+ .data_ind_timing_o (data_ind_timing),
+ .dummy_instr_en_o (dummy_instr_en),
+ .dummy_instr_mask_o (dummy_instr_mask),
+ .dummy_instr_seed_en_o(dummy_instr_seed_en),
+ .dummy_instr_seed_o (dummy_instr_seed),
+ .icache_enable_o (icache_enable),
+ .csr_shadow_err_o (csr_shadow_err),
- .csr_save_if_i ( csr_save_if ),
- .csr_save_id_i ( csr_save_id ),
- .csr_save_wb_i ( csr_save_wb ),
- .csr_restore_mret_i ( csr_restore_mret_id ),
- .csr_restore_dret_i ( csr_restore_dret_id ),
- .csr_save_cause_i ( csr_save_cause ),
- .csr_mcause_i ( exc_cause ),
- .csr_mtval_i ( csr_mtval ),
- .illegal_csr_insn_o ( illegal_csr_insn_id ),
+ .csr_save_if_i (csr_save_if),
+ .csr_save_id_i (csr_save_id),
+ .csr_save_wb_i (csr_save_wb),
+ .csr_restore_mret_i(csr_restore_mret_id),
+ .csr_restore_dret_i(csr_restore_dret_id),
+ .csr_save_cause_i (csr_save_cause),
+ .csr_mcause_i (exc_cause),
+ .csr_mtval_i (csr_mtval),
+ .illegal_csr_insn_o(illegal_csr_insn_id),
- // performance counter related signals
- .instr_ret_i ( perf_instr_ret_wb ),
- .instr_ret_compressed_i ( perf_instr_ret_compressed_wb ),
- .iside_wait_i ( perf_iside_wait ),
- .jump_i ( perf_jump ),
- .branch_i ( perf_branch ),
- .branch_taken_i ( perf_tbranch ),
- .mem_load_i ( perf_load ),
- .mem_store_i ( perf_store ),
- .dside_wait_i ( perf_dside_wait ),
- .mul_wait_i ( perf_mul_wait ),
- .div_wait_i ( perf_div_wait )
+ // performance counter related signals
+ .instr_ret_i (perf_instr_ret_wb),
+ .instr_ret_compressed_i (perf_instr_ret_compressed_wb),
+ .instr_ret_spec_i (perf_instr_ret_wb_spec),
+ .instr_ret_compressed_spec_i(perf_instr_ret_compressed_wb_spec),
+ .iside_wait_i (perf_iside_wait),
+ .jump_i (perf_jump),
+ .branch_i (perf_branch),
+ .branch_taken_i (perf_tbranch),
+ .mem_load_i (perf_load),
+ .mem_store_i (perf_store),
+ .dside_wait_i (perf_dside_wait),
+ .mul_wait_i (perf_mul_wait),
+ .div_wait_i (perf_div_wait)
);
// These assertions are in top-level as instr_valid_id required as the enable term
@@ -1037,45 +999,48 @@
pmp_req_e pmp_req_type [PMP_NUM_CHAN];
priv_lvl_e pmp_priv_lvl [PMP_NUM_CHAN];
- assign pmp_req_addr[PMP_I] = {2'b00,instr_addr_o[31:0]};
- assign pmp_req_type[PMP_I] = PMP_ACC_EXEC;
- assign pmp_priv_lvl[PMP_I] = priv_mode_if;
- assign pmp_req_addr[PMP_D] = {2'b00,data_addr_o[31:0]};
- assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ;
- assign pmp_priv_lvl[PMP_D] = priv_mode_lsu;
+ assign pmp_req_addr[PMP_I] = {2'b00, pc_if};
+ assign pmp_req_type[PMP_I] = PMP_ACC_EXEC;
+ assign pmp_priv_lvl[PMP_I] = priv_mode_id;
+ assign pmp_req_addr[PMP_I2] = {2'b00, (pc_if + 32'd2)};
+ assign pmp_req_type[PMP_I2] = PMP_ACC_EXEC;
+ assign pmp_priv_lvl[PMP_I2] = priv_mode_id;
+ assign pmp_req_addr[PMP_D] = {2'b00, data_addr_o[31:0]};
+ assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ;
+ assign pmp_priv_lvl[PMP_D] = priv_mode_lsu;
ibex_pmp #(
- .PMPGranularity ( PMPGranularity ),
- .PMPNumChan ( PMP_NUM_CHAN ),
- .PMPNumRegions ( PMPNumRegions )
+ .PMPGranularity(PMPGranularity),
+ .PMPNumChan (PMP_NUM_CHAN),
+ .PMPNumRegions (PMPNumRegions)
) pmp_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- // Interface to CSRs
- .csr_pmp_cfg_i ( csr_pmp_cfg ),
- .csr_pmp_addr_i ( csr_pmp_addr ),
- .csr_pmp_mseccfg_i ( csr_pmp_mseccfg ),
- .priv_mode_i ( pmp_priv_lvl ),
- // Access checking channels
- .pmp_req_addr_i ( pmp_req_addr ),
- .pmp_req_type_i ( pmp_req_type ),
- .pmp_req_err_o ( pmp_req_err )
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ // Interface to CSRs
+ .csr_pmp_cfg_i (csr_pmp_cfg),
+ .csr_pmp_addr_i (csr_pmp_addr),
+ .csr_pmp_mseccfg_i(csr_pmp_mseccfg),
+ .priv_mode_i (pmp_priv_lvl),
+ // Access checking channels
+ .pmp_req_addr_i (pmp_req_addr),
+ .pmp_req_type_i (pmp_req_type),
+ .pmp_req_err_o (pmp_req_err)
);
end else begin : g_no_pmp
// Unused signal tieoff
- priv_lvl_e unused_priv_lvl_if, unused_priv_lvl_ls;
+ priv_lvl_e unused_priv_lvl_ls;
logic [33:0] unused_csr_pmp_addr [PMPNumRegions];
pmp_cfg_t unused_csr_pmp_cfg [PMPNumRegions];
pmp_mseccfg_t unused_csr_pmp_mseccfg;
- assign unused_priv_lvl_if = priv_mode_if;
assign unused_priv_lvl_ls = priv_mode_lsu;
assign unused_csr_pmp_addr = csr_pmp_addr;
assign unused_csr_pmp_cfg = csr_pmp_cfg;
assign unused_csr_pmp_mseccfg = csr_pmp_mseccfg;
// Output tieoff
- assign pmp_req_err[PMP_I] = 1'b0;
- assign pmp_req_err[PMP_D] = 1'b0;
+ assign pmp_req_err[PMP_I] = 1'b0;
+ assign pmp_req_err[PMP_I2] = 1'b0;
+ assign pmp_req_err[PMP_D] = 1'b0;
end
`ifdef RVFI
@@ -1111,6 +1076,59 @@
logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES];
logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES];
+ logic rvfi_instr_new_wb;
+ logic rvfi_intr_d;
+ logic rvfi_intr_q;
+ logic rvfi_set_trap_pc_d;
+ logic rvfi_set_trap_pc_q;
+ logic [31:0] rvfi_insn_id;
+ logic [4:0] rvfi_rs1_addr_d;
+ logic [4:0] rvfi_rs1_addr_q;
+ logic [4:0] rvfi_rs2_addr_d;
+ logic [4:0] rvfi_rs2_addr_q;
+ logic [4:0] rvfi_rs3_addr_d;
+ logic [31:0] rvfi_rs1_data_d;
+ logic [31:0] rvfi_rs1_data_q;
+ logic [31:0] rvfi_rs2_data_d;
+ logic [31:0] rvfi_rs2_data_q;
+ logic [31:0] rvfi_rs3_data_d;
+ logic [4:0] rvfi_rd_addr_wb;
+ logic [4:0] rvfi_rd_addr_q;
+ logic [4:0] rvfi_rd_addr_d;
+ logic [31:0] rvfi_rd_wdata_wb;
+ logic [31:0] rvfi_rd_wdata_d;
+ logic [31:0] rvfi_rd_wdata_q;
+ logic rvfi_rd_we_wb;
+ logic [3:0] rvfi_mem_mask_int;
+ logic [31:0] rvfi_mem_rdata_d;
+ logic [31:0] rvfi_mem_rdata_q;
+ logic [31:0] rvfi_mem_wdata_d;
+ logic [31:0] rvfi_mem_wdata_q;
+ logic [31:0] rvfi_mem_addr_d;
+ logic [31:0] rvfi_mem_addr_q;
+ logic rvfi_trap_id;
+ logic rvfi_trap_wb;
+ logic [63:0] rvfi_stage_order_d;
+ logic rvfi_id_done;
+ logic rvfi_wb_done;
+
+ logic new_debug_req;
+ logic new_nmi;
+ logic new_irq;
+ ibex_pkg::irqs_t captured_mip;
+ logic captured_nmi;
+ logic captured_debug_req;
+ logic captured_valid;
+
+ // RVFI extension for co-simulation support
+ // debug_req and MIP captured at IF -> ID transition so one extra stage
+ ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1];
+ logic rvfi_ext_stage_nmi [RVFI_STAGES+1];
+ logic rvfi_ext_stage_debug_req [RVFI_STAGES+1];
+ logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES];
+
+
+
logic rvfi_stage_valid_d [RVFI_STAGES];
assign rvfi_valid = rvfi_stage_valid [RVFI_STAGES-1];
@@ -1137,6 +1155,34 @@
assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1];
assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1];
+ assign rvfi_rd_addr_wb = rf_waddr_wb;
+ assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
+ assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu;
+
+ always_comb begin
+ // Use always_comb instead of continuous assign so first assign can set 0 as default everywhere
+ // that is overridden by more specific settings.
+ rvfi_ext_mip = '0;
+ rvfi_ext_mip[CSR_MSIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_software;
+ rvfi_ext_mip[CSR_MTIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_timer;
+ rvfi_ext_mip[CSR_MEIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_external;
+ rvfi_ext_mip[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = rvfi_ext_stage_mip[RVFI_STAGES].irq_fast;
+ end
+
+ assign rvfi_ext_nmi = rvfi_ext_stage_nmi[RVFI_STAGES];
+ assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req[RVFI_STAGES];
+ assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle[RVFI_STAGES-1];
+
+ // When an instruction takes a trap the `rvfi_trap` signal will be set. Instructions that take
+ // traps flush the pipeline so ordinarily wouldn't be seen to be retire. The RVFI tracking
+ // pipeline is kept going for flushed instructions that trapped so they are still visible on the
+ // RVFI interface.
+
+ // Factor in exceptions taken in ID so RVFI tracking picks up flushed instructions that took
+ // a trap
+ assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next &
+ id_stage_i.controller_i.id_exception_o);
+
if (WritebackStage) begin : gen_rvfi_wb_stage
logic unused_instr_new_id;
@@ -1146,91 +1192,181 @@
// awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB
// So first stage becomes valid when instruction leaves ID/EX stage and remains valid until
// instruction leaves WB
- assign rvfi_stage_valid_d[0] = (instr_id_done & ~dummy_instr_id) |
- (rvfi_stage_valid[0] & ~instr_done_wb);
+ assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) |
+ (rvfi_stage_valid[0] & ~rvfi_wb_done);
// Second stage is output stage so simple valid cycle after instruction leaves WB (and so has
// retired)
- assign rvfi_stage_valid_d[1] = instr_done_wb;
+ assign rvfi_stage_valid_d[1] = rvfi_wb_done;
// Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB)
logic rvfi_instr_new_wb_q;
- assign rvfi_instr_new_wb = rvfi_instr_new_wb_q;
+ // Signal new instruction in WB either when one has just entered or when a trap is progressing
+ // through the tracking pipeline
+ assign rvfi_instr_new_wb = rvfi_instr_new_wb_q | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
always_ff @(posedge clk_i or negedge rst_ni) begin
- if (~rst_ni) begin
+ if (!rst_ni) begin
rvfi_instr_new_wb_q <= 0;
end else begin
- rvfi_instr_new_wb_q <= instr_id_done;
+ rvfi_instr_new_wb_q <= rvfi_id_done;
end
end
+
+ assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o;
+ assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu;
+ // WB is instantly done in the tracking pipeline when a trap is progress through the pipeline
+ assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
end else begin : gen_rvfi_no_wb_stage
// Without writeback stage first RVFI stage is output stage so simply valid the cycle after
// instruction leaves ID/EX (and so has retired)
- assign rvfi_stage_valid_d[0] = instr_id_done & ~dummy_instr_id;
+ assign rvfi_stage_valid_d[0] = rvfi_id_done & ~dummy_instr_id;
// Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly
// setup register write signals
assign rvfi_instr_new_wb = instr_new_id;
+ assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu;
+ assign rvfi_trap_wb = 1'b0;
+ assign rvfi_wb_done = instr_done_wb;
end
- for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
+ assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order[0] : rvfi_stage_order[0] + 64'd1;
+
+ // For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID
+ // finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV
+ // environment with information about the irq/debug_req/nmi state that applies to a particular
+ // instruction.
+ //
+ // When a irq/debug_req/nmi appears the ID stage will finish whatever instruction it is currently
+ // executing (if any) then take the trap the cycle after that instruction leaves the ID stage. The
+ // trap taken depends upon the state of irq/debug_req/nmi on that cycle. In the cycles following
+ // that before the first instruction of the trap handler enters the ID stage the state of
+ // irq/debug_req/nmi could change but this has no effect on the trap handler (e.g. a higher
+ // priority interrupt might appear but this wouldn't stop the lower priority interrupt trap
+ // handler executing first as it's already being fetched). To provide the DV environment with the
+ // correct information for it to verify execution we need to capture the irq/debug_req/nmi state
+ // the cycle the trap decision is made. Which the captured_X signals below do.
+ //
+ // The new_X signals take the raw irq/debug_req/nmi inputs and factor in the enable terms required
+ // to determine if a trap will actually happen.
+ //
+ // These signals and the comment above are referred to in the documentation (cosim.rst). If
+ // altering the names or meanings of these signals or this comment please adjust the documentation
+ // appropriately.
+ assign new_debug_req = (debug_req_i & ~debug_mode);
+ assign new_nmi = irq_nm_i & ~nmi_mode & ~debug_mode;
+ assign new_irq = irq_pending_o & csr_mstatus_mie & ~nmi_mode & ~debug_mode;
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ captured_valid <= 1'b0;
+ captured_mip <= '0;
+ captured_nmi <= 1'b0;
+ captured_debug_req <= 1'b0;
+ end else begin
+ // Capture when ID stage has emptied out and something occurs that will cause a trap and we
+ // haven't yet captured
+ if (~instr_valid_id & (new_debug_req | new_irq | new_nmi) & ~captured_valid) begin
+ captured_valid <= 1'b1;
+ captured_nmi <= irq_nm_i;
+ captured_mip <= cs_registers_i.mip;
+ captured_debug_req <= debug_req_i;
+ end
+
+ // Capture cleared out as soon as a new instruction appears in ID
+ if (if_stage_i.instr_valid_id_d) begin
+ captured_valid <= 1'b0;
+ end
+ end
+ end
+
+ // Pass the captured irq/debug_req/nmi state to the rvfi_ext interface tracking pipeline.
+ //
+ // To correctly capture we need to factor in various enable terms, should there be a fault in this
+ // logic we won't tell the DV environment about a trap that should have been taken. So if there's
+ // no valid capture we grab the raw values of the irq/debug_req/nmi inputs whatever they are and
+ // the DV environment will see if a trap should have been taken but wasn't.
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ rvfi_ext_stage_mip[0] <= '0;
+ rvfi_ext_stage_nmi[0] <= '0;
+ rvfi_ext_stage_debug_req[0] <= '0;
+ end else if (if_stage_i.instr_valid_id_d & if_stage_i.instr_new_id_d) begin
+ rvfi_ext_stage_mip[0] <= instr_valid_id | ~captured_valid ? cs_registers_i.mip :
+ captured_mip;
+ rvfi_ext_stage_nmi[0] <= instr_valid_id | ~captured_valid ? irq_nm_i :
+ captured_nmi;
+ rvfi_ext_stage_debug_req[0] <= instr_valid_id | ~captured_valid ? debug_req_i :
+ captured_debug_req;
+ end
+ end
+
+ for (genvar i = 0; i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- rvfi_stage_halt[i] <= '0;
- rvfi_stage_trap[i] <= '0;
- rvfi_stage_intr[i] <= '0;
- rvfi_stage_order[i] <= '0;
- rvfi_stage_insn[i] <= '0;
- rvfi_stage_mode[i] <= {PRIV_LVL_M};
- rvfi_stage_ixl[i] <= CSR_MISA_MXL;
- rvfi_stage_rs1_addr[i] <= '0;
- rvfi_stage_rs2_addr[i] <= '0;
- rvfi_stage_rs3_addr[i] <= '0;
- rvfi_stage_pc_rdata[i] <= '0;
- rvfi_stage_pc_wdata[i] <= '0;
- rvfi_stage_mem_rmask[i] <= '0;
- rvfi_stage_mem_wmask[i] <= '0;
- rvfi_stage_valid[i] <= '0;
- rvfi_stage_rs1_rdata[i] <= '0;
- rvfi_stage_rs2_rdata[i] <= '0;
- rvfi_stage_rs3_rdata[i] <= '0;
- rvfi_stage_rd_wdata[i] <= '0;
- rvfi_stage_rd_addr[i] <= '0;
- rvfi_stage_mem_rdata[i] <= '0;
- rvfi_stage_mem_wdata[i] <= '0;
- rvfi_stage_mem_addr[i] <= '0;
+ rvfi_stage_halt[i] <= '0;
+ rvfi_stage_trap[i] <= '0;
+ rvfi_stage_intr[i] <= '0;
+ rvfi_stage_order[i] <= '0;
+ rvfi_stage_insn[i] <= '0;
+ rvfi_stage_mode[i] <= {PRIV_LVL_M};
+ rvfi_stage_ixl[i] <= CSR_MISA_MXL;
+ rvfi_stage_rs1_addr[i] <= '0;
+ rvfi_stage_rs2_addr[i] <= '0;
+ rvfi_stage_rs3_addr[i] <= '0;
+ rvfi_stage_pc_rdata[i] <= '0;
+ rvfi_stage_pc_wdata[i] <= '0;
+ rvfi_stage_mem_rmask[i] <= '0;
+ rvfi_stage_mem_wmask[i] <= '0;
+ rvfi_stage_valid[i] <= '0;
+ rvfi_stage_rs1_rdata[i] <= '0;
+ rvfi_stage_rs2_rdata[i] <= '0;
+ rvfi_stage_rs3_rdata[i] <= '0;
+ rvfi_stage_rd_wdata[i] <= '0;
+ rvfi_stage_rd_addr[i] <= '0;
+ rvfi_stage_mem_rdata[i] <= '0;
+ rvfi_stage_mem_wdata[i] <= '0;
+ rvfi_stage_mem_addr[i] <= '0;
+ rvfi_ext_stage_mip[i+1] <= '0;
+ rvfi_ext_stage_nmi[i+1] <= '0;
+ rvfi_ext_stage_debug_req[i+1] <= '0;
+ rvfi_ext_stage_mcycle[i] <= '0;
end else begin
rvfi_stage_valid[i] <= rvfi_stage_valid_d[i];
if (i == 0) begin
- if(instr_id_done) begin
+ if (rvfi_id_done) begin
rvfi_stage_halt[i] <= '0;
- rvfi_stage_trap[i] <= illegal_insn_id;
- rvfi_stage_intr[i] <= rvfi_intr_d;
- rvfi_stage_order[i] <= rvfi_stage_order[i] + 64'(rvfi_stage_valid_d[i]);
- rvfi_stage_insn[i] <= rvfi_insn_id;
- rvfi_stage_mode[i] <= {priv_mode_id};
- rvfi_stage_ixl[i] <= CSR_MISA_MXL;
- rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d;
- rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d;
- rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d;
- rvfi_stage_pc_rdata[i] <= pc_id;
- rvfi_stage_pc_wdata[i] <= pc_set ? branch_target_ex : pc_if;
- rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
- rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
- rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
- rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
- rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
- rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
- rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
- rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
- rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
- rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
+ // TODO: Sort this out for writeback stage
+ rvfi_stage_trap[i] <= rvfi_trap_id;
+ rvfi_stage_intr[i] <= rvfi_intr_d;
+ rvfi_stage_order[i] <= rvfi_stage_order_d;
+ rvfi_stage_insn[i] <= rvfi_insn_id;
+ rvfi_stage_mode[i] <= {priv_mode_id};
+ rvfi_stage_ixl[i] <= CSR_MISA_MXL;
+ rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d;
+ rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d;
+ rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d;
+ rvfi_stage_pc_rdata[i] <= pc_id;
+ rvfi_stage_pc_wdata[i] <= pc_set ? branch_target_ex : pc_if;
+ rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
+ rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
+ rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
+ rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
+ rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
+ rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
+ rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
+ rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
+ rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
+ rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
+ rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
+ rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
+ rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
+ rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
end
end else begin
- if(instr_done_wb) begin
+ if (rvfi_wb_done) begin
rvfi_stage_halt[i] <= rvfi_stage_halt[i-1];
- rvfi_stage_trap[i] <= rvfi_stage_trap[i-1];
+ rvfi_stage_trap[i] <= rvfi_stage_trap[i-1] | rvfi_trap_wb;
rvfi_stage_intr[i] <= rvfi_stage_intr[i-1];
rvfi_stage_order[i] <= rvfi_stage_order[i-1];
rvfi_stage_insn[i] <= rvfi_stage_insn[i-1];
@@ -1256,6 +1392,11 @@
rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
+
+ rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
+ rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
+ rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
+ rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1];
end
end
end
@@ -1347,16 +1488,16 @@
end
always_comb begin
- if(rvfi_rd_we_wb) begin
+ if (rvfi_rd_we_wb) begin
// Capture address/data of write to register file
- rvfi_rd_addr_d = rvfi_rd_addr_wb;
+ rvfi_rd_addr_d = rvfi_rd_addr_wb;
// If writing to x0 zero write data as required by RVFI specification
- if(rvfi_rd_addr_wb == 5'b0) begin
+ if (rvfi_rd_addr_wb == 5'b0) begin
rvfi_rd_wdata_d = '0;
end else begin
rvfi_rd_wdata_d = rvfi_rd_wdata_wb;
end
- end else if(rvfi_instr_new_wb) begin
+ end else if (rvfi_instr_new_wb) begin
// If no RF write but new instruction in Writeback (when present) or ID/EX (when no writeback
// stage present) then zero RF write address/data as required by RVFI specification
rvfi_rd_addr_d = '0;
@@ -1392,7 +1533,7 @@
(exc_pc_mux_id == EXC_PC_EXC || exc_pc_mux_id == EXC_PC_IRQ)) begin
// PC is set to enter a trap handler
rvfi_set_trap_pc_d = 1'b1;
- end else if (rvfi_set_trap_pc_q && instr_id_done) begin
+ end else if (rvfi_set_trap_pc_q && rvfi_id_done) begin
// first instruction has been executed after PC is set to trap handler
rvfi_set_trap_pc_d = 1'b0;
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
index 0091d5a..a6187b7 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv
@@ -1,5 +1,9 @@
module ibex_counter #(
- parameter int CounterWidth = 32
+ parameter int CounterWidth = 32,
+ // When set `counter_val_upd_o` provides an incremented version of the counter value, otherwise
+ // the output is hard-wired to 0. This is required to allow Xilinx DSP inference to work
+ // correctly. When `ProvideValUpd` is set no DSPs are inferred.
+ parameter bit ProvideValUpd = 0
) (
input logic clk_i,
input logic rst_ni,
@@ -8,7 +12,8 @@
input logic counterh_we_i,
input logic counter_we_i,
input logic [31:0] counter_val_i,
- output logic [63:0] counter_val_o
+ output logic [63:0] counter_val_o,
+ output logic [63:0] counter_val_upd_o
);
logic [63:0] counter;
@@ -17,9 +22,11 @@
logic we;
logic [CounterWidth-1:0] counter_d;
+ // Increment
+ assign counter_upd = counter[CounterWidth-1:0] + {{CounterWidth - 1{1'b0}}, 1'b1};
+
// Update
always_comb begin
-
// Write
we = counter_we_i | counterh_we_i;
counter_load[63:32] = counter[63:32];
@@ -29,13 +36,10 @@
counter_load[31:0] = counter[31:0];
end
- // Increment
- counter_upd = counter[CounterWidth-1:0] + {{CounterWidth-1{1'b0}},1'b1};
-
// Next value logic
if (we) begin
counter_d = counter_load[CounterWidth-1:0];
- end else if (counter_inc_i)begin
+ end else if (counter_inc_i) begin
counter_d = counter_upd[CounterWidth-1:0];
end else begin
counter_d = counter[CounterWidth-1:0];
@@ -44,7 +48,7 @@
`ifdef FPGA_XILINX
// Set DSP pragma for supported xilinx FPGAs
- localparam int DspPragma = CounterWidth < 49 ? "yes" : "no";
+ localparam int DspPragma = CounterWidth < 49 ? "yes" : "no";
(* use_dsp = DspPragma *) logic [CounterWidth-1:0] counter_q;
// DSP output register requires synchronous reset.
@@ -67,11 +71,24 @@
if (CounterWidth < 64) begin : g_counter_narrow
logic [63:CounterWidth] unused_counter_load;
- assign counter[CounterWidth-1:0] = counter_q;
- assign counter[63:CounterWidth] = '0;
- assign unused_counter_load = counter_load[63:CounterWidth];
+ assign counter[CounterWidth-1:0] = counter_q;
+ assign counter[63:CounterWidth] = '0;
+
+ if (ProvideValUpd) begin : g_counter_val_upd_o
+ assign counter_val_upd_o[CounterWidth-1:0] = counter_upd;
+ end else begin : g_no_counter_val_upd_o
+ assign counter_val_upd_o[CounterWidth-1:0] = '0;
+ end
+ assign counter_val_upd_o[63:CounterWidth] = '0;
+ assign unused_counter_load = counter_load[63:CounterWidth];
end else begin : g_counter_full
- assign counter = counter_q;
+ assign counter = counter_q;
+
+ if (ProvideValUpd) begin : g_counter_val_upd_o
+ assign counter_val_upd_o = counter_upd;
+ end else begin : g_no_counter_val_upd_o
+ assign counter_val_upd_o = '0;
+ end
end
assign counter_val_o = counter;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index 75ef2e5..559e607 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -13,110 +13,111 @@
`include "prim_assert.sv"
module ibex_cs_registers #(
- parameter bit DbgTriggerEn = 0,
- parameter int unsigned DbgHwBreakNum = 1,
- parameter bit DataIndTiming = 1'b0,
- parameter bit DummyInstructions = 1'b0,
- parameter bit ShadowCSR = 1'b0,
- parameter bit ICache = 1'b0,
- parameter int unsigned MHPMCounterNum = 10,
- parameter int unsigned MHPMCounterWidth = 40,
- parameter bit PMPEnable = 0,
- parameter int unsigned PMPGranularity = 0,
- parameter int unsigned PMPNumRegions = 4,
- parameter bit RV32E = 0,
- parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
- parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone
+ parameter bit DbgTriggerEn = 0,
+ parameter int unsigned DbgHwBreakNum = 1,
+ parameter bit DataIndTiming = 1'b0,
+ parameter bit DummyInstructions = 1'b0,
+ parameter bit ShadowCSR = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter int unsigned MHPMCounterNum = 10,
+ parameter int unsigned MHPMCounterWidth = 40,
+ parameter bit PMPEnable = 0,
+ parameter int unsigned PMPGranularity = 0,
+ parameter int unsigned PMPNumRegions = 4,
+ parameter bit RV32E = 0,
+ parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
+ parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- // Hart ID
- input logic [31:0] hart_id_i,
+ // Hart ID
+ input logic [31:0] hart_id_i,
- // Privilege mode
- output ibex_pkg::priv_lvl_e priv_mode_id_o,
- output ibex_pkg::priv_lvl_e priv_mode_if_o,
- output ibex_pkg::priv_lvl_e priv_mode_lsu_o,
- output logic csr_mstatus_tw_o,
+ // Privilege mode
+ output ibex_pkg::priv_lvl_e priv_mode_id_o,
+ output ibex_pkg::priv_lvl_e priv_mode_lsu_o,
+ output logic csr_mstatus_tw_o,
- // mtvec
- output logic [31:0] csr_mtvec_o,
- input logic csr_mtvec_init_i,
- input logic [31:0] boot_addr_i,
+ // mtvec
+ output logic [31:0] csr_mtvec_o,
+ input logic csr_mtvec_init_i,
+ input logic [31:0] boot_addr_i,
- // Interface to registers (SRAM like)
- input logic csr_access_i,
- input ibex_pkg::csr_num_e csr_addr_i,
- input logic [31:0] csr_wdata_i,
- input ibex_pkg::csr_op_e csr_op_i,
- input csr_op_en_i,
- output logic [31:0] csr_rdata_o,
+ // Interface to registers (SRAM like)
+ input logic csr_access_i,
+ input ibex_pkg::csr_num_e csr_addr_i,
+ input logic [31:0] csr_wdata_i,
+ input ibex_pkg::csr_op_e csr_op_i,
+ input csr_op_en_i,
+ output logic [31:0] csr_rdata_o,
- // interrupts
- input logic irq_software_i,
- input logic irq_timer_i,
- input logic irq_external_i,
- input logic [14:0] irq_fast_i,
- input logic nmi_mode_i,
- output logic irq_pending_o, // interrupt request pending
- output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie
- output logic csr_mstatus_mie_o,
- output logic [31:0] csr_mepc_o,
+ // interrupts
+ input logic irq_software_i,
+ input logic irq_timer_i,
+ input logic irq_external_i,
+ input logic [14:0] irq_fast_i,
+ input logic nmi_mode_i,
+ output logic irq_pending_o, // interrupt request pending
+ output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie
+ output logic csr_mstatus_mie_o,
+ output logic [31:0] csr_mepc_o,
- // PMP
- output ibex_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions],
- output logic [33:0] csr_pmp_addr_o [PMPNumRegions],
- output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o,
+ // PMP
+ output ibex_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions],
+ output logic [33:0] csr_pmp_addr_o [PMPNumRegions],
+ output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o,
- // debug
- input logic debug_mode_i,
- input ibex_pkg::dbg_cause_e debug_cause_i,
- input logic debug_csr_save_i,
- output logic [31:0] csr_depc_o,
- output logic debug_single_step_o,
- output logic debug_ebreakm_o,
- output logic debug_ebreaku_o,
- output logic trigger_match_o,
+ // debug
+ input logic debug_mode_i,
+ input ibex_pkg::dbg_cause_e debug_cause_i,
+ input logic debug_csr_save_i,
+ output logic [31:0] csr_depc_o,
+ output logic debug_single_step_o,
+ output logic debug_ebreakm_o,
+ output logic debug_ebreaku_o,
+ output logic trigger_match_o,
- input logic [31:0] pc_if_i,
- input logic [31:0] pc_id_i,
- input logic [31:0] pc_wb_i,
+ input logic [31:0] pc_if_i,
+ input logic [31:0] pc_id_i,
+ input logic [31:0] pc_wb_i,
- // CPU control bits
- output logic data_ind_timing_o,
- output logic dummy_instr_en_o,
- output logic [2:0] dummy_instr_mask_o,
- output logic dummy_instr_seed_en_o,
- output logic [31:0] dummy_instr_seed_o,
- output logic icache_enable_o,
- output logic csr_shadow_err_o,
+ // CPU control bits
+ output logic data_ind_timing_o,
+ output logic dummy_instr_en_o,
+ output logic [2:0] dummy_instr_mask_o,
+ output logic dummy_instr_seed_en_o,
+ output logic [31:0] dummy_instr_seed_o,
+ output logic icache_enable_o,
+ output logic csr_shadow_err_o,
- // Exception save/restore
- input logic csr_save_if_i,
- input logic csr_save_id_i,
- input logic csr_save_wb_i,
- input logic csr_restore_mret_i,
- input logic csr_restore_dret_i,
- input logic csr_save_cause_i,
- input ibex_pkg::exc_cause_e csr_mcause_i,
- input logic [31:0] csr_mtval_i,
- output logic illegal_csr_insn_o, // access to non-existent CSR,
- // with wrong priviledge level, or
- // missing write permissions
- // Performance Counters
- input logic instr_ret_i, // instr retired in ID/EX stage
- input logic instr_ret_compressed_i, // compressed instr retired
- input logic iside_wait_i, // core waiting for the iside
- input logic jump_i, // jump instr seen (j, jr, jal, jalr)
- input logic branch_i, // branch instr seen (bf, bnf)
- input logic branch_taken_i, // branch was taken
- input logic mem_load_i, // load from memory in this cycle
- input logic mem_store_i, // store to memory in this cycle
- input logic dside_wait_i, // core waiting for the dside
- input logic mul_wait_i, // core waiting for multiply
- input logic div_wait_i // core waiting for divide
+ // Exception save/restore
+ input logic csr_save_if_i,
+ input logic csr_save_id_i,
+ input logic csr_save_wb_i,
+ input logic csr_restore_mret_i,
+ input logic csr_restore_dret_i,
+ input logic csr_save_cause_i,
+ input ibex_pkg::exc_cause_e csr_mcause_i,
+ input logic [31:0] csr_mtval_i,
+ output logic illegal_csr_insn_o, // access to non-existent CSR,
+ // with wrong priviledge level, or
+ // missing write permissions
+ // Performance Counters
+ input logic instr_ret_i, // instr retired in ID/EX stage
+ input logic instr_ret_compressed_i, // compressed instr retired
+ input logic instr_ret_spec_i, // speculative instr_ret_i
+ input logic instr_ret_compressed_spec_i, // speculative instr_ret_compressed_i
+ input logic iside_wait_i, // core waiting for the iside
+ input logic jump_i, // jump instr seen (j, jr, jal, jalr)
+ input logic branch_i, // branch instr seen (bf, bnf)
+ input logic branch_taken_i, // branch was taken
+ input logic mem_load_i, // load from memory in this cycle
+ input logic mem_store_i, // store to memory in this cycle
+ input logic dside_wait_i, // core waiting for the dside
+ input logic mul_wait_i, // core waiting for multiply
+ input logic div_wait_i // core waiting for divide
);
import ibex_pkg::*;
@@ -242,6 +243,8 @@
logic unused_mhpmcounterh_we_1;
logic unused_mhpmcounter_incr_1;
+ logic [63:0] minstret_next, minstret_raw;
+
// Debug / trigger registers
logic [31:0] tselect_rdata;
logic [31:0] tmatch_control_rdata;
@@ -294,6 +297,12 @@
illegal_csr = 1'b0;
unique case (csr_addr_i)
+ // mvendorid: encoding of manufacturer/provider
+ CSR_MVENDORID: csr_rdata_int = CSR_MVENDORID_VALUE;
+ // marchid: encoding of base microarchitecture
+ CSR_MARCHID: csr_rdata_int = CSR_MARCHID_VALUE;
+ // mimpid: encoding of processor implementation version
+ CSR_MIMPID: csr_rdata_int = CSR_MIMPID_VALUE;
// mhartid: unique hardware thread id
CSR_MHARTID: csr_rdata_int = hart_id_i;
@@ -476,7 +485,7 @@
// Custom CSR for controlling CPU features
CSR_CPUCTRL: begin
- csr_rdata_int = {{32-$bits(cpu_ctrl_t){1'b0}},cpuctrl_q};
+ csr_rdata_int = {{32 - $bits(cpu_ctrl_t) {1'b0}}, cpuctrl_q};
end
// Custom CSR for LFSR re-seeding (cannot be read)
@@ -719,8 +728,6 @@
// Send current priv level to the decoder
assign priv_mode_id_o = priv_lvl_q;
- // New instruction fetches need to account for updates to priv_lvl_q this cycle
- assign priv_mode_if_o = priv_lvl_d;
// Load/store instructions must factor in MPRV for PMP checking
assign priv_mode_lsu_o = mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q;
@@ -769,30 +776,30 @@
mprv: 1'b0,
tw: 1'b0};
ibex_csr #(
- .Width ($bits(status_t)),
- .ShadowCopy (ShadowCSR),
- .ResetValue ({MSTATUS_RST_VAL})
+ .Width ($bits(status_t)),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue({MSTATUS_RST_VAL})
) u_mstatus_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({mstatus_d}),
- .wr_en_i (mstatus_en),
- .rd_data_o (mstatus_q),
- .rd_error_o (mstatus_err)
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({mstatus_d}),
+ .wr_en_i (mstatus_en),
+ .rd_data_o (mstatus_q),
+ .rd_error_o(mstatus_err)
);
// MEPC
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mepc_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mepc_d),
- .wr_en_i (mepc_en),
- .rd_data_o (mepc_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mepc_d),
+ .wr_en_i (mepc_en),
+ .rd_data_o (mepc_q),
+ .rd_error_o()
);
// MIE
@@ -801,180 +808,177 @@
assign mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT];
assign mie_d.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW];
ibex_csr #(
- .Width ($bits(irqs_t)),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width ($bits(irqs_t)),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mie_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({mie_d}),
- .wr_en_i (mie_en),
- .rd_data_o (mie_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({mie_d}),
+ .wr_en_i (mie_en),
+ .rd_data_o (mie_q),
+ .rd_error_o()
);
// MSCRATCH
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mscratch_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (csr_wdata_int),
- .wr_en_i (mscratch_en),
- .rd_data_o (mscratch_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (csr_wdata_int),
+ .wr_en_i (mscratch_en),
+ .rd_data_o (mscratch_q),
+ .rd_error_o()
);
// MCAUSE
ibex_csr #(
- .Width (6),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (6),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mcause_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mcause_d),
- .wr_en_i (mcause_en),
- .rd_data_o (mcause_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mcause_d),
+ .wr_en_i (mcause_en),
+ .rd_data_o (mcause_q),
+ .rd_error_o()
);
// MTVAL
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mtval_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mtval_d),
- .wr_en_i (mtval_en),
- .rd_data_o (mtval_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mtval_d),
+ .wr_en_i (mtval_en),
+ .rd_data_o (mtval_q),
+ .rd_error_o()
);
// MTVEC
ibex_csr #(
- .Width (32),
- .ShadowCopy (ShadowCSR),
- .ResetValue (32'd1)
+ .Width (32),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue(32'd1)
) u_mtvec_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mtvec_d),
- .wr_en_i (mtvec_en),
- .rd_data_o (mtvec_q),
- .rd_error_o (mtvec_err)
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mtvec_d),
+ .wr_en_i (mtvec_en),
+ .rd_data_o (mtvec_q),
+ .rd_error_o(mtvec_err)
);
// DCSR
localparam dcsr_t DCSR_RESET_VAL = '{
xdebugver: XDEBUGVER_STD,
- cause: DBG_CAUSE_NONE, // 3'h0
- prv: PRIV_LVL_M,
- default: '0
+ cause: DBG_CAUSE_NONE, // 3'h0
+ prv: PRIV_LVL_M,
+ default: '0
};
ibex_csr #(
- .Width ($bits(dcsr_t)),
- .ShadowCopy (1'b0),
- .ResetValue ({DCSR_RESET_VAL})
+ .Width ($bits(dcsr_t)),
+ .ShadowCopy(1'b0),
+ .ResetValue({DCSR_RESET_VAL})
) u_dcsr_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({dcsr_d}),
- .wr_en_i (dcsr_en),
- .rd_data_o (dcsr_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({dcsr_d}),
+ .wr_en_i (dcsr_en),
+ .rd_data_o (dcsr_q),
+ .rd_error_o()
);
// DEPC
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_depc_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (depc_d),
- .wr_en_i (depc_en),
- .rd_data_o (depc_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (depc_d),
+ .wr_en_i (depc_en),
+ .rd_data_o (depc_q),
+ .rd_error_o()
);
// DSCRATCH0
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_dscratch0_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (csr_wdata_int),
- .wr_en_i (dscratch0_en),
- .rd_data_o (dscratch0_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (csr_wdata_int),
+ .wr_en_i (dscratch0_en),
+ .rd_data_o (dscratch0_q),
+ .rd_error_o()
);
// DSCRATCH1
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_dscratch1_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (csr_wdata_int),
- .wr_en_i (dscratch1_en),
- .rd_data_o (dscratch1_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (csr_wdata_int),
+ .wr_en_i (dscratch1_en),
+ .rd_data_o (dscratch1_q),
+ .rd_error_o()
);
// MSTACK
- localparam status_stk_t MSTACK_RESET_VAL = '{
- mpie: 1'b1,
- mpp: PRIV_LVL_U
- };
+ localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U};
ibex_csr #(
- .Width ($bits(status_stk_t)),
- .ShadowCopy (1'b0),
- .ResetValue ({MSTACK_RESET_VAL})
+ .Width ($bits(status_stk_t)),
+ .ShadowCopy(1'b0),
+ .ResetValue({MSTACK_RESET_VAL})
) u_mstack_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({mstack_d}),
- .wr_en_i (mstack_en),
- .rd_data_o (mstack_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({mstack_d}),
+ .wr_en_i (mstack_en),
+ .rd_data_o (mstack_q),
+ .rd_error_o()
);
// MSTACK_EPC
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mstack_epc_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mstack_epc_d),
- .wr_en_i (mstack_en),
- .rd_data_o (mstack_epc_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mstack_epc_d),
+ .wr_en_i (mstack_en),
+ .rd_data_o (mstack_epc_q),
+ .rd_error_o()
);
// MSTACK_CAUSE
ibex_csr #(
- .Width (6),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (6),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_mstack_cause_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (mstack_cause_d),
- .wr_en_i (mstack_en),
- .rd_data_o (mstack_cause_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (mstack_cause_d),
+ .wr_en_i (mstack_en),
+ .rd_data_o (mstack_cause_q),
+ .rd_error_o()
);
// -----------------
@@ -1021,7 +1025,7 @@
// For G >= 2, bits are masked to one or zero depending on the mode
always_comb begin
// In NAPOT mode, bits [G-2:0] must read as one
- pmp_addr_rdata[i] = {pmp_addr[i], {PMPGranularity-1{1'b1}}};
+ pmp_addr_rdata[i] = {pmp_addr[i], {PMPGranularity - 1{1'b1}}};
if ((pmp_cfg[i].mode == PMP_MODE_OFF) || (pmp_cfg[i].mode == PMP_MODE_TOR)) begin
// In TOR or OFF mode, bits [G-1:0] must read as zero
@@ -1066,16 +1070,16 @@
assign pmp_cfg_wdata[i].read = csr_wdata_int[(i%4)*PMP_CFG_W];
ibex_csr #(
- .Width ($bits(pmp_cfg_t)),
- .ShadowCopy (ShadowCSR),
- .ResetValue ('0)
+ .Width ($bits(pmp_cfg_t)),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue('0)
) u_pmp_cfg_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({pmp_cfg_wdata[i]}),
- .wr_en_i (pmp_cfg_we[i]),
- .rd_data_o (pmp_cfg[i]),
- .rd_error_o (pmp_cfg_err[i])
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({pmp_cfg_wdata[i]}),
+ .wr_en_i (pmp_cfg_we[i]),
+ .rd_data_o (pmp_cfg[i]),
+ .rd_error_o(pmp_cfg_err[i])
);
// MSECCFG.RLB allows the lock bit to be bypassed (allowing cfg writes when MSECCFG.RLB is
@@ -1095,16 +1099,16 @@
end
ibex_csr #(
- .Width (PMPAddrWidth),
- .ShadowCopy (ShadowCSR),
- .ResetValue ('0)
+ .Width (PMPAddrWidth),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue('0)
) u_pmp_addr_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (csr_wdata_int[31-:PMPAddrWidth]),
- .wr_en_i (pmp_addr_we[i]),
- .rd_data_o (pmp_addr[i]),
- .rd_error_o (pmp_addr_err[i])
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (csr_wdata_int[31-:PMPAddrWidth]),
+ .wr_en_i (pmp_addr_we[i]),
+ .rd_data_o (pmp_addr[i]),
+ .rd_error_o(pmp_addr_err[i])
);
assign csr_pmp_cfg_o[i] = pmp_cfg[i];
@@ -1126,16 +1130,16 @@
assign pmp_mseccfg_d.rlb = any_pmp_entry_locked ? 1'b0 : csr_wdata_int[CSR_MSECCFG_RLB_BIT];
ibex_csr #(
- .Width ($bits(pmp_mseccfg_t)),
- .ShadowCopy (ShadowCSR),
- .ResetValue ('0)
+ .Width ($bits(pmp_mseccfg_t)),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue('0)
) u_pmp_mseccfg (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (pmp_mseccfg_d),
- .wr_en_i (pmp_mseccfg_we),
- .rd_data_o (pmp_mseccfg_q),
- .rd_error_o (pmp_mseccfg_err)
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (pmp_mseccfg_d),
+ .wr_en_i (pmp_mseccfg_we),
+ .rd_data_o (pmp_mseccfg_q),
+ .rd_error_o(pmp_mseccfg_err)
);
assign pmp_csr_err = (|pmp_cfg_err) | (|pmp_addr_err) | pmp_mseccfg_err;
@@ -1175,7 +1179,7 @@
always_comb begin : gen_mhpmcounter_incr
// Assign inactive counters (first to prevent latch inference)
- for (int unsigned i=0; i<32; i++) begin : gen_mhpmcounter_incr_inactive
+ for (int unsigned i = 0; i < 32; i++) begin : gen_mhpmcounter_incr_inactive
mhpmcounter_incr[i] = 1'b0;
end
@@ -1203,14 +1207,14 @@
always_comb begin : gen_mhpmevent
// activate all
- for (int i=0; i<32; i++) begin : gen_mhpmevent_active
+ for (int i = 0; i < 32; i++) begin : gen_mhpmevent_active
mhpmevent[i] = '0;
mhpmevent[i][i] = 1'b1;
end
// deactivate
mhpmevent[1] = '0; // not existing, reserved
- for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmevent_inactive
+ for (int unsigned i = 3 + MHPMCounterNum; i < 32; i++) begin : gen_mhpmevent_inactive
mhpmevent[i] = '0;
end
end
@@ -1225,12 +1229,15 @@
.counterh_we_i(mhpmcounterh_we[0]),
.counter_we_i(mhpmcounter_we[0]),
.counter_val_i(csr_wdata_int),
- .counter_val_o(mhpmcounter[0])
+ .counter_val_o(mhpmcounter[0]),
+ .counter_val_upd_o()
);
+
// minstret
ibex_counter #(
- .CounterWidth(64)
+ .CounterWidth(64),
+ .ProvideValUpd(1)
) minstret_counter_i (
.clk_i(clk_i),
.rst_ni(rst_ni),
@@ -1238,39 +1245,74 @@
.counterh_we_i(mhpmcounterh_we[2]),
.counter_we_i(mhpmcounter_we[2]),
.counter_val_i(csr_wdata_int),
- .counter_val_o(mhpmcounter[2])
+ .counter_val_o(minstret_raw),
+ .counter_val_upd_o(minstret_next)
);
+ // Where the writeback stage is present instruction in ID observing value of minstret must take
+ // into account any instruction in the writeback stage. If one is present the incremented value of
+ // minstret is used. A speculative version of the signal is used to aid timing. When the writeback
+ // stage sees an exception (so the speculative signal is incorrect) the ID stage will be flushed
+ // so the incorrect value doesn't matter. A similar behaviour is required for the compressed
+ // instruction retired counter below. When the writeback stage isn't present the speculative
+ // signals are always 0.
+ assign mhpmcounter[2] = instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw;
+
// reserved:
assign mhpmcounter[1] = '0;
assign unused_mhpmcounter_we_1 = mhpmcounter_we[1];
assign unused_mhpmcounterh_we_1 = mhpmcounterh_we[1];
assign unused_mhpmcounter_incr_1 = mhpmcounter_incr[1];
- for (genvar cnt=0; cnt < 29; cnt++) begin : gen_cntrs
- if (cnt < MHPMCounterNum) begin : gen_imp
+ // Iterate through optionally included counters (MHPMCounterNum controls how many are included)
+ for (genvar i = 0; i < 29; i++) begin : gen_cntrs
+ localparam int Cnt = i + 3;
+
+ if (i < MHPMCounterNum) begin : gen_imp
+ logic [63:0] mhpmcounter_raw, mhpmcounter_next;
+
ibex_counter #(
- .CounterWidth(MHPMCounterWidth)
+ .CounterWidth(MHPMCounterWidth),
+ .ProvideValUpd(Cnt == 10)
) mcounters_variable_i (
.clk_i(clk_i),
.rst_ni(rst_ni),
- .counter_inc_i(mhpmcounter_incr[cnt+3] & ~mcountinhibit[cnt+3]),
- .counterh_we_i(mhpmcounterh_we[cnt+3]),
- .counter_we_i(mhpmcounter_we[cnt+3]),
+ .counter_inc_i(mhpmcounter_incr[Cnt] & ~mcountinhibit[Cnt]),
+ .counterh_we_i(mhpmcounterh_we[Cnt]),
+ .counter_we_i(mhpmcounter_we[Cnt]),
.counter_val_i(csr_wdata_int),
- .counter_val_o(mhpmcounter[cnt+3])
+ .counter_val_o(mhpmcounter_raw),
+ .counter_val_upd_o(mhpmcounter_next)
);
+
+ if (Cnt == 10) begin : gen_compressed_instr_cnt
+ // Special behaviour for reading compressed instruction retired counter, see comment on
+ // `mhpmcounter[2]` above for further information.
+ assign mhpmcounter[Cnt] =
+ instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next:
+ mhpmcounter_raw;
+ end else begin : gen_other_cnts
+ logic [63:0] unused_mhpmcounter_next;
+ // All other counters just see the raw counter value directly.
+ assign mhpmcounter[Cnt] = mhpmcounter_raw;
+ assign unused_mhpmcounter_next = mhpmcounter_next;
+ end
end else begin : gen_unimp
- assign mhpmcounter[cnt+3] = '0;
+ assign mhpmcounter[Cnt] = '0;
+
+ if (Cnt == 10) begin : gen_no_compressed_instr_cnt
+ logic unused_instr_ret_compressed_spec_i;
+ assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i;
+ end
end
end
- if(MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
+ if (MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
logic [29-MHPMCounterNum-1:0] unused_mhphcounter_we;
logic [29-MHPMCounterNum-1:0] unused_mhphcounterh_we;
logic [29-MHPMCounterNum-1:0] unused_mhphcounter_incr;
- assign mcountinhibit = {{29-MHPMCounterNum{1'b1}}, mcountinhibit_q};
+ assign mcountinhibit = {{29 - MHPMCounterNum{1'b1}}, mcountinhibit_q};
// Lint tieoffs for unused bits
assign unused_mhphcounter_we = mhpmcounter_we[31:MHPMCounterNum+3];
assign unused_mhphcounterh_we = mhpmcounterh_we[31:MHPMCounterNum+3];
@@ -1331,43 +1373,43 @@
// Registers
ibex_csr #(
- .Width (DbgHwNumLen),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (DbgHwNumLen),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_tselect_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (tselect_d),
- .wr_en_i (tselect_we),
- .rd_data_o (tselect_q),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (tselect_d),
+ .wr_en_i (tselect_we),
+ .rd_data_o (tselect_q),
+ .rd_error_o()
);
for (genvar i = 0; i < DbgHwBreakNum; i++) begin : g_dbg_tmatch_reg
ibex_csr #(
- .Width (1),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (1),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_tmatch_control_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (tmatch_control_d),
- .wr_en_i (tmatch_control_we[i]),
- .rd_data_o (tmatch_control_q[i]),
- .rd_error_o ()
- );
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (tmatch_control_d),
+ .wr_en_i (tmatch_control_we[i]),
+ .rd_data_o (tmatch_control_q[i]),
+ .rd_error_o()
+ );
ibex_csr #(
- .Width (32),
- .ShadowCopy (1'b0),
- .ResetValue ('0)
+ .Width (32),
+ .ShadowCopy(1'b0),
+ .ResetValue('0)
) u_tmatch_value_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i (tmatch_value_d),
- .wr_en_i (tmatch_value_we[i]),
- .rd_data_o (tmatch_value_q[i]),
- .rd_error_o ()
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i (tmatch_value_d),
+ .wr_en_i (tmatch_value_we[i]),
+ .rd_data_o (tmatch_value_q[i]),
+ .rd_error_o()
);
end
@@ -1483,16 +1525,16 @@
assign icache_enable_o = cpuctrl_q.icache_enable;
ibex_csr #(
- .Width ($bits(cpu_ctrl_t)),
- .ShadowCopy (ShadowCSR),
- .ResetValue ('0)
+ .Width ($bits(cpu_ctrl_t)),
+ .ShadowCopy(ShadowCSR),
+ .ResetValue('0)
) u_cpuctrl_csr (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
- .wr_data_i ({cpuctrl_d}),
- .wr_en_i (cpuctrl_we),
- .rd_data_o (cpuctrl_q),
- .rd_error_o (cpuctrl_err)
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .wr_data_i ({cpuctrl_d}),
+ .wr_en_i (cpuctrl_we),
+ .rd_data_o (cpuctrl_q),
+ .rd_error_o(cpuctrl_err)
);
assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
index 8623fa5..309a325 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv
@@ -9,18 +9,18 @@
`include "prim_assert.sv"
module ibex_csr #(
- parameter int unsigned Width = 32,
- parameter bit ShadowCopy = 1'b0,
- parameter bit [Width-1:0] ResetValue = '0
+ parameter int unsigned Width = 32,
+ parameter bit ShadowCopy = 1'b0,
+ parameter bit [Width-1:0] ResetValue = '0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- input logic [Width-1:0] wr_data_i,
- input logic wr_en_i,
- output logic [Width-1:0] rd_data_o,
+ input logic [Width-1:0] wr_data_i,
+ input logic wr_en_i,
+ output logic [Width-1:0] rd_data_o,
- output logic rd_error_o
+ output logic rd_error_o
);
logic [Width-1:0] rdata_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
index 0f10608..fbc754a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
@@ -14,87 +14,87 @@
`include "prim_assert.sv"
module ibex_decoder #(
- parameter bit RV32E = 0,
- parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
- parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
- parameter bit BranchTargetALU = 0
+ parameter bit RV32E = 0,
+ parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
+ parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
+ parameter bit BranchTargetALU = 0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- // to/from controller
- output logic illegal_insn_o, // illegal instr encountered
- output logic ebrk_insn_o, // trap instr encountered
- output logic mret_insn_o, // return from exception instr
- // encountered
- output logic dret_insn_o, // return from debug instr encountered
- output logic ecall_insn_o, // syscall instr encountered
- output logic wfi_insn_o, // wait for interrupt instr encountered
- output logic jump_set_o, // jump taken set signal
- input logic branch_taken_i, // registered branch decision
- output logic icache_inval_o,
+ // to/from controller
+ output logic illegal_insn_o, // illegal instr encountered
+ output logic ebrk_insn_o, // trap instr encountered
+ output logic mret_insn_o, // return from exception instr
+ // encountered
+ output logic dret_insn_o, // return from debug instr encountered
+ output logic ecall_insn_o, // syscall instr encountered
+ output logic wfi_insn_o, // wait for interrupt instr encountered
+ output logic jump_set_o, // jump taken set signal
+ input logic branch_taken_i, // registered branch decision
+ output logic icache_inval_o,
- // from IF-ID pipeline register
- input logic instr_first_cycle_i, // instruction read is in its first cycle
- input logic [31:0] instr_rdata_i, // instruction read from memory/cache
- input logic [31:0] instr_rdata_alu_i, // instruction read from memory/cache
- // replicated to ease fan-out)
+ // from IF-ID pipeline register
+ input logic instr_first_cycle_i, // instruction read is in its first cycle
+ input logic [31:0] instr_rdata_i, // instruction read from memory/cache
+ input logic [31:0] instr_rdata_alu_i, // instruction read from memory/cache
+ // replicated to ease fan-out)
- input logic illegal_c_insn_i, // compressed instruction decode failed
+ input logic illegal_c_insn_i, // compressed instruction decode failed
- // immediates
- output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
- output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
- output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a
- output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b
- output logic [31:0] imm_i_type_o,
- output logic [31:0] imm_s_type_o,
- output logic [31:0] imm_b_type_o,
- output logic [31:0] imm_u_type_o,
- output logic [31:0] imm_j_type_o,
- output logic [31:0] zimm_rs1_type_o,
+ // immediates
+ output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
+ output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
+ output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a
+ output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b
+ output logic [31:0] imm_i_type_o,
+ output logic [31:0] imm_s_type_o,
+ output logic [31:0] imm_b_type_o,
+ output logic [31:0] imm_u_type_o,
+ output logic [31:0] imm_j_type_o,
+ output logic [31:0] zimm_rs1_type_o,
- // register file
- output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection
- output logic rf_we_o, // write enable for regfile
- output logic [4:0] rf_raddr_a_o,
- output logic [4:0] rf_raddr_b_o,
- output logic [4:0] rf_waddr_o,
- output logic rf_ren_a_o, // Instruction reads from RF addr A
- output logic rf_ren_b_o, // Instruction reads from RF addr B
+ // register file
+ output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection
+ output logic rf_we_o, // write enable for regfile
+ output logic [4:0] rf_raddr_a_o,
+ output logic [4:0] rf_raddr_b_o,
+ output logic [4:0] rf_waddr_o,
+ output logic rf_ren_a_o, // Instruction reads from RF addr A
+ output logic rf_ren_b_o, // Instruction reads from RF addr B
- // ALU
- output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection
- output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC,
- // immediate or zero
- output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
- // immediate
- output logic alu_multicycle_o, // ternary bitmanip instruction
+ // ALU
+ output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection
+ output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC,
+ // immediate or zero
+ output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
+ // immediate
+ output logic alu_multicycle_o, // ternary bitmanip instruction
- // MULT & DIV
- output logic mult_en_o, // perform integer multiplication
- output logic div_en_o, // perform integer division or remainder
- output logic mult_sel_o, // as above but static, for data muxes
- output logic div_sel_o, // as above but static, for data muxes
+ // MULT & DIV
+ output logic mult_en_o, // perform integer multiplication
+ output logic div_en_o, // perform integer division or remainder
+ output logic mult_sel_o, // as above but static, for data muxes
+ output logic div_sel_o, // as above but static, for data muxes
- output ibex_pkg::md_op_e multdiv_operator_o,
- output logic [1:0] multdiv_signed_mode_o,
+ output ibex_pkg::md_op_e multdiv_operator_o,
+ output logic [1:0] multdiv_signed_mode_o,
- // CSRs
- output logic csr_access_o, // access to CSR
- output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR
+ // CSRs
+ output logic csr_access_o, // access to CSR
+ output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR
- // LSU
- output logic data_req_o, // start transaction to data memory
- output logic data_we_o, // write enable
- output logic [1:0] data_type_o, // size of transaction: byte, half
- // word or word
- output logic data_sign_extension_o, // sign extension for data read from
- // memory
+ // LSU
+ output logic data_req_o, // start transaction to data memory
+ output logic data_we_o, // write enable
+ output logic [1:0] data_type_o, // size of transaction: byte, half
+ // word or word
+ output logic data_sign_extension_o, // sign extension for data read from
+ // memory
- // jump/branches
- output logic jump_in_dec_o, // jump is being calculated in ALU
- output logic branch_in_dec_o
+ // jump/branches
+ output logic jump_in_dec_o, // jump is being calculated in ALU
+ output logic branch_in_dec_o
);
import ibex_pkg::*;
@@ -362,10 +362,10 @@
3'b001: begin
unique case (instr[31:27])
5'b0_0000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1; // slli
- 5'b0_0100, // sloi
- 5'b0_1001, // sbclri
- 5'b0_0101, // sbseti
- 5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // sbinvi
+ 5'b0_0100: illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1; // sloi
+ 5'b0_1001, // bclri
+ 5'b0_0101, // bseti
+ 5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // binvi
5'b0_0001: if (instr[26] == 1'b0) begin
illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1; // shfl
end else begin
@@ -375,7 +375,7 @@
unique case(instr[26:20])
7'b000_0000, // clz
7'b000_0001, // ctz
- 7'b000_0010, // pcnt
+ 7'b000_0010, // cpop
7'b000_0100, // sext.b
7'b000_0101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // sext.h
7'b001_0000, // crc32.b
@@ -400,20 +400,17 @@
5'b0_0000, // srli
5'b0_1000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1; // srai
- 5'b0_0100, // sroi
+ 5'b0_0100: illegal_insn = (RV32B == RV32BFull) ? 1'b0 : 1'b1; // sroi
5'b0_1100, // rori
- 5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // sbexti
+ 5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // bexti
5'b0_1101: begin
if ((RV32B == RV32BFull)) begin
illegal_insn = 1'b0; // grevi
+ end else if (RV32B == RV32BBalanced) begin
+ illegal_insn = (instr[24:20] == 5'b11000) ? 1'b0 : 1'b1; // rev8
end else begin
- unique case (instr[24:20])
- 5'b11111, // rev
- 5'b11000: illegal_insn = (RV32B == RV32BBalanced) ? 1'b0 : 1'b1; // rev8
-
- default: illegal_insn = 1'b1;
- endcase
+ illegal_insn = 1'b1;
end
end
5'b0_0101: begin
@@ -462,36 +459,43 @@
{7'b000_0000, 3'b101},
{7'b010_0000, 3'b101}: illegal_insn = 1'b0;
+ // RV32B zba
+ {7'b001_0000, 3'b010}, // sh1add
+ {7'b001_0000, 3'b100}, // sh2add
+ {7'b001_0000, 3'b110}, // sh3add
// RV32B zbb
{7'b010_0000, 3'b111}, // andn
{7'b010_0000, 3'b110}, // orn
{7'b010_0000, 3'b100}, // xnor
- {7'b001_0000, 3'b001}, // slo
- {7'b001_0000, 3'b101}, // sro
{7'b011_0000, 3'b001}, // rol
{7'b011_0000, 3'b101}, // ror
{7'b000_0101, 3'b100}, // min
- {7'b000_0101, 3'b101}, // max
- {7'b000_0101, 3'b110}, // minu
+ {7'b000_0101, 3'b110}, // max
+ {7'b000_0101, 3'b101}, // minu
{7'b000_0101, 3'b111}, // maxu
{7'b000_0100, 3'b100}, // pack
{7'b010_0100, 3'b100}, // packu
{7'b000_0100, 3'b111}, // packh
// RV32B zbs
- {7'b010_0100, 3'b001}, // sbclr
- {7'b001_0100, 3'b001}, // sbset
- {7'b011_0100, 3'b001}, // sbinv
- {7'b010_0100, 3'b101}, // sbext
+ {7'b010_0100, 3'b001}, // bclr
+ {7'b001_0100, 3'b001}, // bset
+ {7'b011_0100, 3'b001}, // binv
+ {7'b010_0100, 3'b101}, // bext
// RV32B zbf
{7'b010_0100, 3'b111}: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // bfp
// RV32B zbe
- {7'b010_0100, 3'b110}, // bdep
- {7'b000_0100, 3'b110}, // bext
+ {7'b010_0100, 3'b110}, // bdecompress
+ {7'b000_0100, 3'b110}, // bcompress
// RV32B zbp
{7'b011_0100, 3'b101}, // grev
{7'b001_0100, 3'b101}, // gorc
{7'b000_0100, 3'b001}, // shfl
{7'b000_0100, 3'b101}, // unshfl
+ {7'b001_0100, 3'b010}, // xperm.n
+ {7'b001_0100, 3'b100}, // xperm.b
+ {7'b001_0100, 3'b110}, // xperm.h
+ {7'b001_0000, 3'b001}, // slo
+ {7'b001_0000, 3'b101}, // sro
// RV32B zbc
{7'b000_0101, 3'b001}, // clmul
{7'b000_0101, 3'b010}, // clmulr
@@ -819,17 +823,18 @@
if (RV32B != RV32BNone) begin
unique case (instr_alu[31:27])
5'b0_0000: alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate
- 5'b0_0100: alu_operator_o = ALU_SLO; // Shift Left Ones by Immediate
- 5'b0_1001: alu_operator_o = ALU_SBCLR; // Clear bit specified by immediate
- 5'b0_0101: alu_operator_o = ALU_SBSET; // Set bit specified by immediate
- 5'b0_1101: alu_operator_o = ALU_SBINV; // Invert bit specified by immediate.
+ // Shift Left Ones by Immediate
+ 5'b0_0100: if (RV32B == RV32BFull) alu_operator_o = ALU_SLO;
+ 5'b0_1001: alu_operator_o = ALU_BCLR; // Clear bit specified by immediate
+ 5'b0_0101: alu_operator_o = ALU_BSET; // Set bit specified by immediate
+ 5'b0_1101: alu_operator_o = ALU_BINV; // Invert bit specified by immediate.
// Shuffle with Immediate Control Value
5'b0_0001: if (instr_alu[26] == 0) alu_operator_o = ALU_SHFL;
5'b0_1100: begin
unique case (instr_alu[26:20])
7'b000_0000: alu_operator_o = ALU_CLZ; // clz
7'b000_0001: alu_operator_o = ALU_CTZ; // ctz
- 7'b000_0010: alu_operator_o = ALU_PCNT; // pcnt
+ 7'b000_0010: alu_operator_o = ALU_CPOP; // cpop
7'b000_0100: alu_operator_o = ALU_SEXTB; // sext.b
7'b000_0101: alu_operator_o = ALU_SEXTH; // sext.h
7'b001_0000: begin
@@ -893,8 +898,9 @@
unique case (instr_alu[31:27])
5'b0_0000: alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
5'b0_1000: alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
- 5'b0_0100: alu_operator_o = ALU_SRO; // Shift Right Ones by Immediate
- 5'b0_1001: alu_operator_o = ALU_SBEXT; // Extract bit specified by immediate.
+ // Shift Right Ones by Immediate
+ 5'b0_0100: if (RV32B == RV32BFull) alu_operator_o = ALU_SRO;
+ 5'b0_1001: alu_operator_o = ALU_BEXT; // Extract bit specified by immediate.
5'b0_1100: begin
alu_operator_o = ALU_ROR; // Rotate Right by Immediate
alu_multicycle_o = 1'b1;
@@ -985,8 +991,6 @@
{7'b010_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic
// RV32B ALU Operations
- {7'b001_0000, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SLO; // slo
- {7'b001_0000, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_SRO; // sro
{7'b011_0000, 3'b001}: begin
if (RV32B != RV32BNone) begin
alu_operator_o = ALU_ROL; // rol
@@ -1001,8 +1005,8 @@
end
{7'b000_0101, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_MIN; // min
- {7'b000_0101, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAX; // max
- {7'b000_0101, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_MINU; // minu
+ {7'b000_0101, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAX; // max
+ {7'b000_0101, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_MINU; // minu
{7'b000_0101, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_MAXU; // maxu
{7'b000_0100, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_PACK; // pack
@@ -1013,20 +1017,30 @@
{7'b010_0000, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_ORN; // orn
{7'b010_0000, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_ANDN; // andn
+ // RV32B zba
+ {7'b001_0000, 3'b010}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH1ADD; // sh1add
+ {7'b001_0000, 3'b100}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH2ADD; // sh2add
+ {7'b001_0000, 3'b110}: if (RV32B != RV32BNone) alu_operator_o = ALU_SH3ADD; // sh3add
+
// RV32B zbs
- {7'b010_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBCLR; // sbclr
- {7'b001_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBSET; // sbset
- {7'b011_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBINV; // sbinv
- {7'b010_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_SBEXT; // sbext
+ {7'b010_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BCLR; // bclr
+ {7'b001_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BSET; // bset
+ {7'b011_0100, 3'b001}: if (RV32B != RV32BNone) alu_operator_o = ALU_BINV; // binv
+ {7'b010_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_BEXT; // bext
// RV32B zbf
{7'b010_0100, 3'b111}: if (RV32B != RV32BNone) alu_operator_o = ALU_BFP; // bfp
// RV32B zbp
- {7'b011_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GREV; // grev
- {7'b001_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GORC; // grev
- {7'b000_0100, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SHFL; // shfl
- {7'b000_0100, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_UNSHFL; // unshfl
+ {7'b011_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GREV; // grev
+ {7'b001_0100, 3'b101}: if (RV32B != RV32BNone) alu_operator_o = ALU_GORC; // gorc
+ {7'b000_0100, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SHFL; // shfl
+ {7'b000_0100, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_UNSHFL; // unshfl
+ {7'b001_0100, 3'b010}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_N; // xperm.n
+ {7'b001_0100, 3'b100}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_B; // xperm.b
+ {7'b001_0100, 3'b110}: if (RV32B == RV32BFull) alu_operator_o = ALU_XPERM_H; // xperm.h
+ {7'b001_0000, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_SLO; // slo
+ {7'b001_0000, 3'b101}: if (RV32B == RV32BFull) alu_operator_o = ALU_SRO; // sro
// RV32B zbc
{7'b000_0101, 3'b001}: if (RV32B == RV32BFull) alu_operator_o = ALU_CLMUL; // clmul
@@ -1036,13 +1050,13 @@
// RV32B zbe
{7'b010_0100, 3'b110}: begin
if (RV32B == RV32BFull) begin
- alu_operator_o = ALU_BDEP; // bdep
+ alu_operator_o = ALU_BDECOMPRESS; // bdecompress
alu_multicycle_o = 1'b1;
end
end
{7'b000_0100, 3'b110}: begin
if (RV32B == RV32BFull) begin
- alu_operator_o = ALU_BEXT; // bext
+ alu_operator_o = ALU_BCOMPRESS; // bcompress
alu_multicycle_o = 1'b1;
end
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
index cae665a..979ea93 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
@@ -12,21 +12,21 @@
parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
) (
- // Clock and reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and reset
+ input logic clk_i,
+ input logic rst_ni,
- // Interface to CSRs
- input logic dummy_instr_en_i,
- input logic [2:0] dummy_instr_mask_i,
- input logic dummy_instr_seed_en_i,
- input logic [31:0] dummy_instr_seed_i,
+ // Interface to CSRs
+ input logic dummy_instr_en_i,
+ input logic [2:0] dummy_instr_mask_i,
+ input logic dummy_instr_seed_en_i,
+ input logic [31:0] dummy_instr_seed_i,
- // Interface to IF stage
- input logic fetch_valid_i,
- input logic id_in_ready_i,
- output logic insert_dummy_instr_o,
- output logic [31:0] dummy_instr_data_o
+ // Interface to IF stage
+ input logic fetch_valid_i,
+ input logic id_in_ready_i,
+ output logic insert_dummy_instr_o,
+ output logic [31:0] dummy_instr_data_o
);
localparam int unsigned TIMEOUT_CNT_W = 5;
@@ -116,31 +116,31 @@
// Encode instruction
always_comb begin
unique case (lfsr_data.instr_type)
- DUMMY_ADD : begin
+ DUMMY_ADD: begin
dummy_set = 7'b0000000;
dummy_opcode = 3'b000;
end
- DUMMY_MUL : begin
+ DUMMY_MUL: begin
dummy_set = 7'b0000001;
dummy_opcode = 3'b000;
end
- DUMMY_DIV : begin
+ DUMMY_DIV: begin
dummy_set = 7'b0000001;
dummy_opcode = 3'b100;
end
- DUMMY_AND : begin
+ DUMMY_AND: begin
dummy_set = 7'b0000000;
dummy_opcode = 3'b111;
end
- default : begin
+ default: begin
dummy_set = 7'b0000000;
dummy_opcode = 3'b000;
end
endcase
end
- // SET RS2 RS1 OP RD
- assign dummy_instr = {dummy_set,lfsr_data.op_b,lfsr_data.op_a,dummy_opcode,5'h00,7'h33};
+ // SET RS2 RS1 OP RD
+ assign dummy_instr = {dummy_set, lfsr_data.op_b, lfsr_data.op_a, dummy_opcode, 5'h00, 7'h33};
// Assign outputs
assign insert_dummy_instr_o = insert_dummy_instr;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
index 62e0396..ee90016 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv
@@ -9,48 +9,48 @@
* Execution block: Hosts ALU and MUL/DIV unit
*/
module ibex_ex_block #(
- parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
- parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
- parameter bit BranchTargetALU = 0
+ parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
+ parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
+ parameter bit BranchTargetALU = 0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- // ALU
- input ibex_pkg::alu_op_e alu_operator_i,
- input logic [31:0] alu_operand_a_i,
- input logic [31:0] alu_operand_b_i,
- input logic alu_instr_first_cycle_i,
+ // ALU
+ input ibex_pkg::alu_op_e alu_operator_i,
+ input logic [31:0] alu_operand_a_i,
+ input logic [31:0] alu_operand_b_i,
+ input logic alu_instr_first_cycle_i,
- // Branch Target ALU
- // All of these signals are unusued when BranchTargetALU == 0
- input logic [31:0] bt_a_operand_i,
- input logic [31:0] bt_b_operand_i,
+ // Branch Target ALU
+ // All of these signals are unusued when BranchTargetALU == 0
+ input logic [31:0] bt_a_operand_i,
+ input logic [31:0] bt_b_operand_i,
- // Multiplier/Divider
- input ibex_pkg::md_op_e multdiv_operator_i,
- input logic mult_en_i, // dynamic enable signal, for FSM control
- input logic div_en_i, // dynamic enable signal, for FSM control
- input logic mult_sel_i, // static decoder output, for data muxes
- input logic div_sel_i, // static decoder output, for data muxes
- input logic [1:0] multdiv_signed_mode_i,
- input logic [31:0] multdiv_operand_a_i,
- input logic [31:0] multdiv_operand_b_i,
- input logic multdiv_ready_id_i,
- input logic data_ind_timing_i,
+ // Multiplier/Divider
+ input ibex_pkg::md_op_e multdiv_operator_i,
+ input logic mult_en_i, // dynamic enable signal, for FSM control
+ input logic div_en_i, // dynamic enable signal, for FSM control
+ input logic mult_sel_i, // static decoder output, for data muxes
+ input logic div_sel_i, // static decoder output, for data muxes
+ input logic [1:0] multdiv_signed_mode_i,
+ input logic [31:0] multdiv_operand_a_i,
+ input logic [31:0] multdiv_operand_b_i,
+ input logic multdiv_ready_id_i,
+ input logic data_ind_timing_i,
- // intermediate val reg
- output logic [1:0] imd_val_we_o,
- output logic [33:0] imd_val_d_o[2],
- input logic [33:0] imd_val_q_i[2],
+ // intermediate val reg
+ output logic [1:0] imd_val_we_o,
+ output logic [33:0] imd_val_d_o[2],
+ input logic [33:0] imd_val_q_i[2],
- // Outputs
- output logic [31:0] alu_adder_result_ex_o, // to LSU
- output logic [31:0] result_ex_o,
- output logic [31:0] branch_target_o, // to IF
- output logic branch_decision_o, // to ID
+ // Outputs
+ output logic [31:0] alu_adder_result_ex_o, // to LSU
+ output logic [31:0] result_ex_o,
+ output logic [31:0] branch_target_o, // to IF
+ output logic branch_decision_o, // to ID
- output logic ex_valid_o // EX has valid output
+ output logic ex_valid_o // EX has valid output
);
import ibex_pkg::*;
@@ -115,22 +115,22 @@
ibex_alu #(
.RV32B(RV32B)
- ) alu_i (
- .operator_i ( alu_operator_i ),
- .operand_a_i ( alu_operand_a_i ),
- .operand_b_i ( alu_operand_b_i ),
- .instr_first_cycle_i ( alu_instr_first_cycle_i ),
- .imd_val_q_i ( alu_imd_val_q ),
- .imd_val_we_o ( alu_imd_val_we ),
- .imd_val_d_o ( alu_imd_val_d ),
- .multdiv_operand_a_i ( multdiv_alu_operand_a ),
- .multdiv_operand_b_i ( multdiv_alu_operand_b ),
- .multdiv_sel_i ( multdiv_sel ),
- .adder_result_o ( alu_adder_result_ex_o ),
- .adder_result_ext_o ( alu_adder_result_ext ),
- .result_o ( alu_result ),
- .comparison_result_o ( alu_cmp_result ),
- .is_equal_result_o ( alu_is_equal_result )
+ ) alu_i (
+ .operator_i (alu_operator_i),
+ .operand_a_i (alu_operand_a_i),
+ .operand_b_i (alu_operand_b_i),
+ .instr_first_cycle_i(alu_instr_first_cycle_i),
+ .imd_val_q_i (alu_imd_val_q),
+ .imd_val_we_o (alu_imd_val_we),
+ .imd_val_d_o (alu_imd_val_d),
+ .multdiv_operand_a_i(multdiv_alu_operand_a),
+ .multdiv_operand_b_i(multdiv_alu_operand_b),
+ .multdiv_sel_i (multdiv_sel),
+ .adder_result_o (alu_adder_result_ex_o),
+ .adder_result_ext_o (alu_adder_result_ext),
+ .result_o (alu_result),
+ .comparison_result_o(alu_cmp_result),
+ .is_equal_result_o (alu_is_equal_result)
);
////////////////
@@ -139,55 +139,55 @@
if (RV32M == RV32MSlow) begin : gen_multdiv_slow
ibex_multdiv_slow multdiv_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .mult_en_i ( mult_en_i ),
- .div_en_i ( div_en_i ),
- .mult_sel_i ( mult_sel_i ),
- .div_sel_i ( div_sel_i ),
- .operator_i ( multdiv_operator_i ),
- .signed_mode_i ( multdiv_signed_mode_i ),
- .op_a_i ( multdiv_operand_a_i ),
- .op_b_i ( multdiv_operand_b_i ),
- .alu_adder_ext_i ( alu_adder_result_ext ),
- .alu_adder_i ( alu_adder_result_ex_o ),
- .equal_to_zero_i ( alu_is_equal_result ),
- .data_ind_timing_i ( data_ind_timing_i ),
- .valid_o ( multdiv_valid ),
- .alu_operand_a_o ( multdiv_alu_operand_a ),
- .alu_operand_b_o ( multdiv_alu_operand_b ),
- .imd_val_q_i ( imd_val_q_i ),
- .imd_val_d_o ( multdiv_imd_val_d ),
- .imd_val_we_o ( multdiv_imd_val_we ),
- .multdiv_ready_id_i ( multdiv_ready_id_i ),
- .multdiv_result_o ( multdiv_result )
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .mult_en_i (mult_en_i),
+ .div_en_i (div_en_i),
+ .mult_sel_i (mult_sel_i),
+ .div_sel_i (div_sel_i),
+ .operator_i (multdiv_operator_i),
+ .signed_mode_i (multdiv_signed_mode_i),
+ .op_a_i (multdiv_operand_a_i),
+ .op_b_i (multdiv_operand_b_i),
+ .alu_adder_ext_i (alu_adder_result_ext),
+ .alu_adder_i (alu_adder_result_ex_o),
+ .equal_to_zero_i (alu_is_equal_result),
+ .data_ind_timing_i (data_ind_timing_i),
+ .valid_o (multdiv_valid),
+ .alu_operand_a_o (multdiv_alu_operand_a),
+ .alu_operand_b_o (multdiv_alu_operand_b),
+ .imd_val_q_i (imd_val_q_i),
+ .imd_val_d_o (multdiv_imd_val_d),
+ .imd_val_we_o (multdiv_imd_val_we),
+ .multdiv_ready_id_i(multdiv_ready_id_i),
+ .multdiv_result_o (multdiv_result)
);
end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast
- ibex_multdiv_fast # (
- .RV32M ( RV32M )
- ) multdiv_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .mult_en_i ( mult_en_i ),
- .div_en_i ( div_en_i ),
- .mult_sel_i ( mult_sel_i ),
- .div_sel_i ( div_sel_i ),
- .operator_i ( multdiv_operator_i ),
- .signed_mode_i ( multdiv_signed_mode_i ),
- .op_a_i ( multdiv_operand_a_i ),
- .op_b_i ( multdiv_operand_b_i ),
- .alu_operand_a_o ( multdiv_alu_operand_a ),
- .alu_operand_b_o ( multdiv_alu_operand_b ),
- .alu_adder_ext_i ( alu_adder_result_ext ),
- .alu_adder_i ( alu_adder_result_ex_o ),
- .equal_to_zero_i ( alu_is_equal_result ),
- .data_ind_timing_i ( data_ind_timing_i ),
- .imd_val_q_i ( imd_val_q_i ),
- .imd_val_d_o ( multdiv_imd_val_d ),
- .imd_val_we_o ( multdiv_imd_val_we ),
- .multdiv_ready_id_i ( multdiv_ready_id_i ),
- .valid_o ( multdiv_valid ),
- .multdiv_result_o ( multdiv_result )
+ ibex_multdiv_fast #(
+ .RV32M(RV32M)
+ ) multdiv_i (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .mult_en_i (mult_en_i),
+ .div_en_i (div_en_i),
+ .mult_sel_i (mult_sel_i),
+ .div_sel_i (div_sel_i),
+ .operator_i (multdiv_operator_i),
+ .signed_mode_i (multdiv_signed_mode_i),
+ .op_a_i (multdiv_operand_a_i),
+ .op_b_i (multdiv_operand_b_i),
+ .alu_operand_a_o (multdiv_alu_operand_a),
+ .alu_operand_b_o (multdiv_alu_operand_b),
+ .alu_adder_ext_i (alu_adder_result_ext),
+ .alu_adder_i (alu_adder_result_ex_o),
+ .equal_to_zero_i (alu_is_equal_result),
+ .data_ind_timing_i (data_ind_timing_i),
+ .imd_val_q_i (imd_val_q_i),
+ .imd_val_d_o (multdiv_imd_val_d),
+ .imd_val_we_o (multdiv_imd_val_we),
+ .multdiv_ready_id_i(multdiv_ready_id_i),
+ .valid_o (multdiv_valid),
+ .multdiv_result_o (multdiv_result)
);
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
index 98fb287..61179ed 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv
@@ -16,27 +16,26 @@
parameter int unsigned NUM_REQS = 2,
parameter bit ResetAll = 1'b0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- // control signals
- input logic clear_i, // clears the contents of the FIFO
- output logic [NUM_REQS-1:0] busy_o,
+ // control signals
+ input logic clear_i, // clears the contents of the FIFO
+ output logic [NUM_REQS-1:0] busy_o,
- // input port
- input logic in_valid_i,
- input logic [31:0] in_addr_i,
- input logic [31:0] in_rdata_i,
- input logic in_err_i,
+ // input port
+ input logic in_valid_i,
+ input logic [31:0] in_addr_i,
+ input logic [31:0] in_rdata_i,
+ input logic in_err_i,
- // output port
- output logic out_valid_o,
- input logic out_ready_i,
- output logic [31:0] out_addr_o,
- output logic [31:0] out_addr_next_o,
- output logic [31:0] out_rdata_o,
- output logic out_err_o,
- output logic out_err_plus2_o
+ // output port
+ output logic out_valid_o,
+ input logic out_ready_i,
+ output logic [31:0] out_addr_o,
+ output logic [31:0] out_rdata_o,
+ output logic out_err_o,
+ output logic out_err_plus2_o
);
localparam int unsigned DEPTH = NUM_REQS+1;
@@ -166,10 +165,7 @@
end
end
- // Output both PC of current instruction and instruction following. PC of instruction following is
- // required for the branch predictor. It's used to fetch the instruction following a branch that
- // was not-taken but (mis)predicted taken.
- assign out_addr_next_o = {instr_addr_next, 1'b0};
+ // Output PC of current instruction
assign out_addr_o = {instr_addr_q, 1'b0};
// The LSB of the address is unused, since all addresses are halfword aligned
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
index 202c721..f5e6a95 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
@@ -11,7 +11,6 @@
`include "prim_assert.sv"
module ibex_icache import ibex_pkg::*; #(
- parameter bit BranchPredictor = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter bit ResetAll = 1'b0,
parameter int unsigned BusSizeECC = BUS_SIZE,
@@ -20,53 +19,51 @@
// Only cache branch targets
parameter bit BranchCache = 1'b0
) (
- // Clock and reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and reset
+ input logic clk_i,
+ input logic rst_ni,
- // Signal that the core would like instructions
- input logic req_i,
+ // Signal that the core would like instructions
+ input logic req_i,
- // Set the cache's address counter
- input logic branch_i,
- input logic branch_spec_i,
- input logic predicted_branch_i,
- input logic branch_mispredict_i,
- input logic [31:0] addr_i,
+ // Set the cache's address counter
+ input logic branch_i,
+ input logic branch_mispredict_i,
+ input logic [31:0] mispredict_addr_i,
+ input logic [31:0] addr_i,
- // IF stage interface: Pass fetched instructions to the core
- input logic ready_i,
- output logic valid_o,
- output logic [31:0] rdata_o,
- output logic [31:0] addr_o,
- output logic err_o,
- output logic err_plus2_o,
+ // IF stage interface: Pass fetched instructions to the core
+ input logic ready_i,
+ output logic valid_o,
+ output logic [31:0] rdata_o,
+ output logic [31:0] addr_o,
+ output logic err_o,
+ output logic err_plus2_o,
- // Instruction memory / interconnect interface: Fetch instruction data from memory
- output logic instr_req_o,
- input logic instr_gnt_i,
- output logic [31:0] instr_addr_o,
- input logic [BUS_SIZE-1:0] instr_rdata_i,
- input logic instr_err_i,
- input logic instr_pmp_err_i,
- input logic instr_rvalid_i,
+ // Instruction memory / interconnect interface: Fetch instruction data from memory
+ output logic instr_req_o,
+ input logic instr_gnt_i,
+ output logic [31:0] instr_addr_o,
+ input logic [BUS_SIZE-1:0] instr_rdata_i,
+ input logic instr_err_i,
+ input logic instr_rvalid_i,
- // RAM IO
- output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
- output logic ic_tag_write_o,
- output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
- output logic [TagSizeECC-1:0] ic_tag_wdata_o,
- input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
- output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
- output logic ic_data_write_o,
- output logic [IC_INDEX_W-1:0] ic_data_addr_o,
- output logic [LineSizeECC-1:0] ic_data_wdata_o,
- input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
+ // RAM IO
+ output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
+ output logic ic_tag_write_o,
+ output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
+ output logic [TagSizeECC-1:0] ic_tag_wdata_o,
+ input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
+ output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
+ output logic ic_data_write_o,
+ output logic [IC_INDEX_W-1:0] ic_data_addr_o,
+ output logic [LineSizeECC-1:0] ic_data_wdata_o,
+ input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
- // Cache status
- input logic icache_enable_i,
- input logic icache_inval_i,
- output logic busy_o
+ // Cache status
+ input logic icache_enable_i,
+ input logic icache_inval_i,
+ output logic busy_o
);
// Number of fill buffers (must be >= 2)
@@ -76,12 +73,10 @@
// Prefetch signals
logic [ADDR_W-1:0] lookup_addr_aligned;
- logic [ADDR_W-1:0] branch_mispredict_addr;
logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q;
logic prefetch_addr_en;
logic branch_or_mispredict;
// Cache pipelipe IC0 signals
- logic branch_suppress;
logic lookup_throttle;
logic lookup_req_ic0;
logic [ADDR_W-1:0] lookup_addr_ic0;
@@ -121,7 +116,6 @@
logic [IC_NUM_WAYS-1:0] ecc_write_ways;
logic [IC_INDEX_W-1:0] ecc_write_index;
// Fill buffer signals
- logic gnt_or_pmp_err, gnt_not_pmp_err;
logic [$clog2(NUM_FB)-1:0] fb_fill_level;
logic fill_cache_new;
logic fill_new_alloc;
@@ -198,41 +192,6 @@
// Instruction prefetch //
//////////////////////////
- if (BranchPredictor) begin : g_branch_predictor
- // Where the branch predictor is present record what address followed a predicted branch. If
- // that branch is predicted taken but mispredicted (so not-taken) this is used to resume on
- // the not-taken code path.
- logic [31:0] branch_mispredict_addr_q;
- logic branch_mispredict_addr_en;
-
- assign branch_mispredict_addr_en = branch_i & predicted_branch_i;
-
- if (ResetAll) begin : g_branch_misp_ra
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- branch_mispredict_addr_q <= '0;
- end else if (branch_mispredict_addr_en) begin
- branch_mispredict_addr_q <= {output_addr_incr, 1'b0};
- end
- end
- end else begin : g_branch_misp_nr
- always_ff @(posedge clk_i) begin
- if (branch_mispredict_addr_en) begin
- branch_mispredict_addr_q <= {output_addr_incr, 1'b0};
- end
- end
- end
-
- assign branch_mispredict_addr = branch_mispredict_addr_q;
-
- end else begin : g_no_branch_predictor
- logic unused_predicted_branch;
-
- assign unused_predicted_branch = predicted_branch_i;
-
- assign branch_mispredict_addr = '0;
- end
-
assign branch_or_mispredict = branch_i | branch_mispredict_i;
assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}};
@@ -247,7 +206,7 @@
lookup_grant_ic0 ? (lookup_addr_aligned +
{{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) :
branch_i ? addr_i :
- branch_mispredict_addr;
+ mispredict_addr_i;
assign prefetch_addr_en = branch_or_mispredict | lookup_grant_ic0;
@@ -276,8 +235,8 @@
assign lookup_req_ic0 = req_i & ~&fill_busy_q & (branch_or_mispredict | ~lookup_throttle) &
~ecc_write_req;
- assign lookup_addr_ic0 = branch_spec_i ? addr_i :
- branch_mispredict_i ? branch_mispredict_addr :
+ assign lookup_addr_ic0 = branch_i ? addr_i :
+ branch_mispredict_i ? mispredict_addr_i :
prefetch_addr_q;
assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W];
@@ -288,12 +247,9 @@
fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]};
assign fill_wdata_ic0 = fill_ram_req_data;
- // Suppress a new lookup on a not-taken branch (as the address will be incorrect)
- assign branch_suppress = branch_spec_i & ~branch_i;
-
// Arbitrated signals - lookups have highest priority
- assign lookup_grant_ic0 = lookup_req_ic0 & ~branch_suppress;
- assign fill_grant_ic0 = fill_req_ic0 & (~lookup_req_ic0 | branch_suppress) & ~inval_prog_q &
+ assign lookup_grant_ic0 = lookup_req_ic0;
+ assign fill_grant_ic0 = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q &
~ecc_write_req;
// Qualified lookup grant to mask ram signals in IC1 if access was not made
assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & ~start_inval;
@@ -322,12 +278,12 @@
// Reuse the same ecc encoding module for larger cache sizes by padding with zeros
logic [21:0] tag_ecc_input_padded;
logic [27:0] tag_ecc_output_padded;
- logic [22-IC_TAG_SIZE:0] tag_ecc_output_unused;
+ logic [22-IC_TAG_SIZE:0] unused_tag_ecc_output;
assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0};
- assign tag_ecc_output_unused = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
+ assign unused_tag_ecc_output = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
- prim_secded_28_22_enc tag_ecc_enc (
+ prim_secded_inv_28_22_enc tag_ecc_enc (
.data_i (tag_ecc_input_padded),
.data_o (tag_ecc_output_padded)
);
@@ -336,7 +292,7 @@
// Dataram ECC
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
- prim_secded_39_32_enc data_ecc_enc (
+ prim_secded_inv_39_32_enc data_ecc_enc (
.data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
.data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
);
@@ -458,7 +414,7 @@
{22-IC_TAG_SIZE{1'b0}},
tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
- prim_secded_28_22_dec data_ecc_dec (
+ prim_secded_inv_28_22_dec data_ecc_dec (
.data_i (tag_rdata_padded_ic1),
.data_o (),
.syndrome_o (),
@@ -470,7 +426,7 @@
// Data ECC checking
// Note - could generate for all ways and mux after
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
- prim_secded_39_32_dec data_ecc_dec (
+ prim_secded_inv_39_32_dec data_ecc_dec (
.data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
.data_o (),
.syndrome_o (),
@@ -590,21 +546,18 @@
fb_fill_level = '0;
for (int i = 0; i < NUM_FB; i++) begin
if (fill_busy_q[i] & ~fill_stale_q[i]) begin
- fb_fill_level += {{$clog2(NUM_FB)-1{1'b0}},1'b1};
+ fb_fill_level += {{$clog2(NUM_FB) - 1{1'b0}}, 1'b1};
end
end
end
- // PMP errors might not / don't need to be granted (since the external request is masked)
- assign gnt_or_pmp_err = instr_gnt_i | instr_pmp_err_i;
- assign gnt_not_pmp_err = instr_gnt_i & ~instr_pmp_err_i;
// Allocate a new buffer for every granted lookup
assign fill_new_alloc = lookup_grant_ic0;
// Track whether a speculative external request was made from IC0, and whether it was granted
// Speculative requests are only made for branches, or if the cache is disabled
assign fill_spec_req = (~icache_enable_i | branch_or_mispredict) & ~|fill_ext_req;
- assign fill_spec_done = fill_spec_req & gnt_not_pmp_err;
- assign fill_spec_hold = fill_spec_req & ~gnt_or_pmp_err;
+ assign fill_spec_done = fill_spec_req & instr_gnt_i;
+ assign fill_spec_hold = fill_spec_req & ~instr_gnt_i;
for (genvar fb = 0; fb < NUM_FB; fb++) begin : gen_fbs
@@ -658,20 +611,17 @@
assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done_d[fb];
// Count the number of completed external requests (each line requires IC_LINE_BEATS requests)
- // Don't count fake PMP error grants here since they will never receive an rvalid response
assign fill_ext_cnt_d[fb] = fill_alloc[fb] ?
{{IC_LINE_BEATS_W{1'b0}},fill_spec_done} :
(fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}},
- fill_ext_arb[fb] & gnt_not_pmp_err});
+ fill_ext_arb[fb] & instr_gnt_i});
// External request must be held until granted
assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) |
- (fill_ext_arb[fb] & ~gnt_or_pmp_err);
+ (fill_ext_arb[fb] & ~instr_gnt_i);
// External requests are completed when the counter is filled or when the request is cancelled
assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] |
// external requests are considered complete if the request hit
fill_hit_ic1[fb] | fill_hit_q[fb] |
- // external requests will stop once any PMP error is received
- fill_err_q[fb][fill_ext_off[fb]] |
// cancel if the line won't be cached and, it is stale
(~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] |
// or we're already at the end of the line
@@ -696,12 +646,10 @@
// data output, and have data available to send.
// Data is available if:
// - The request hit in the cache
- // - The current beat is an error (since a PMP error might not actually receive any data)
// - Buffered data is available (fill_rvd_cnt_q is ahead of fill_out_cnt_q)
// - Data is available from the bus this cycle (fill_rvd_arb)
assign fill_out_req[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] &
(fill_hit_ic1[fb] | fill_hit_q[fb] |
- (fill_err_q[fb][fill_out_cnt_q[fb][IC_LINE_BEATS_W-1:0]]) |
(fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]);
// Calculate when a beat of data is output. Any ECC error squashes the output that cycle.
@@ -859,15 +807,7 @@
for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf
// Error tracking (per beat)
- // Either a PMP error on a speculative request,
- assign fill_err_d[fb][b] = (instr_pmp_err_i & fill_alloc[fb] & fill_spec_req &
- (lookup_addr_ic0[IC_LINE_W-1:BUS_W] ==
- b[IC_LINE_BEATS_W-1:0])) |
- // a PMP error on a fill buffer ext req
- (instr_pmp_err_i & fill_ext_arb[fb] &
- (fill_ext_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
- // Or a data error with instr_rvalid_i
- (fill_rvd_arb[fb] & instr_err_i &
+ assign fill_err_d[fb][b] = (fill_rvd_arb[fb] & instr_err_i &
(fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
// Hold the error once recorded
(fill_busy_q[fb] & fill_err_q[fb][b]);
@@ -971,7 +911,7 @@
always_comb begin
line_data_muxed = '0;
line_err_muxed = 1'b0;
- for (int i = 0; i < IC_LINE_BEATS; i++) begin
+ for (int unsigned i = 0; i < IC_LINE_BEATS; i++) begin
// When data has been skidded, the output address is behind by one
if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) ==
i[IC_LINE_BEATS_W-1:0]) begin
@@ -1047,7 +987,7 @@
// Signal that valid data is available to the IF stage
// Note that if the first half of an unaligned instruction reports an error, we do not need
- // to wait for the second half (and for PMP errors we might not have fetched the second half)
+ // to wait for the second half
// Compressed instruction completely satisfied by skid buffer
assign output_valid = skid_complete_instr |
// Output data available and, output stream aligned, or skid data available,
@@ -1068,7 +1008,7 @@
// Redirect the address on branches or mispredicts
assign output_addr_d = branch_i ? addr_i[31:1] :
- branch_mispredict_i ? branch_mispredict_addr[31:1] :
+ branch_mispredict_i ? mispredict_addr_i[31:1] :
output_addr_incr;
if (ResetAll) begin : g_output_addr_ra
@@ -1094,7 +1034,7 @@
// 31 15 0 31 15 0
always_comb begin
output_data_lo = '0;
- for (int i = 0; i < IC_OUTPUT_BEATS; i++) begin
+ for (int unsigned i = 0; i < IC_OUTPUT_BEATS; i++) begin
if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
output_data_lo |= output_data[i*16+:16];
end
@@ -1103,7 +1043,7 @@
always_comb begin
output_data_hi = '0;
- for (int i = 0; i < IC_OUTPUT_BEATS-1; i++) begin
+ for (int unsigned i = 0; i < IC_OUTPUT_BEATS - 1; i++) begin
if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
output_data_hi |= output_data[(i+1)*16+:16];
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index 7107ee6..2e79573 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -18,170 +18,169 @@
`include "dv_fcov_macros.svh"
module ibex_id_stage #(
- parameter bit RV32E = 0,
- parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
- parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
- parameter bit DataIndTiming = 1'b0,
- parameter bit BranchTargetALU = 0,
- parameter bit SpecBranch = 0,
- parameter bit WritebackStage = 0,
- parameter bit BranchPredictor = 0
+ parameter bit RV32E = 0,
+ parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
+ parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
+ parameter bit DataIndTiming = 1'b0,
+ parameter bit BranchTargetALU = 0,
+ parameter bit WritebackStage = 0,
+ parameter bit BranchPredictor = 0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- output logic ctrl_busy_o,
- output logic illegal_insn_o,
+ output logic ctrl_busy_o,
+ output logic illegal_insn_o,
- // Interface to IF stage
- input logic instr_valid_i,
- input logic [31:0] instr_rdata_i, // from IF-ID pipeline registers
- input logic [31:0] instr_rdata_alu_i, // from IF-ID pipeline registers
- input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers
- input logic instr_is_compressed_i,
- input logic instr_bp_taken_i,
- output logic instr_req_o,
- output logic instr_first_cycle_id_o,
- output logic instr_valid_clear_o, // kill instr in IF-ID reg
- output logic id_in_ready_o, // ID stage is ready for next instr
- output logic icache_inval_o,
+ // Interface to IF stage
+ input logic instr_valid_i,
+ input logic [31:0] instr_rdata_i, // from IF-ID pipeline registers
+ input logic [31:0] instr_rdata_alu_i, // from IF-ID pipeline registers
+ input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers
+ input logic instr_is_compressed_i,
+ input logic instr_bp_taken_i,
+ output logic instr_req_o,
+ output logic instr_first_cycle_id_o,
+ output logic instr_valid_clear_o, // kill instr in IF-ID reg
+ output logic id_in_ready_o, // ID stage is ready for next instr
+ output logic icache_inval_o,
- // Jumps and branches
- input logic branch_decision_i,
+ // Jumps and branches
+ input logic branch_decision_i,
- // IF and ID stage signals
- output logic pc_set_o,
- output logic pc_set_spec_o,
- output ibex_pkg::pc_sel_e pc_mux_o,
- output logic nt_branch_mispredict_o,
- output ibex_pkg::exc_pc_sel_e exc_pc_mux_o,
- output ibex_pkg::exc_cause_e exc_cause_o,
+ // IF and ID stage signals
+ output logic pc_set_o,
+ output ibex_pkg::pc_sel_e pc_mux_o,
+ output logic nt_branch_mispredict_o,
+ output logic [31:0] nt_branch_addr_o,
+ output ibex_pkg::exc_pc_sel_e exc_pc_mux_o,
+ output ibex_pkg::exc_cause_e exc_cause_o,
- input logic illegal_c_insn_i,
- input logic instr_fetch_err_i,
- input logic instr_fetch_err_plus2_i,
+ input logic illegal_c_insn_i,
+ input logic instr_fetch_err_i,
+ input logic instr_fetch_err_plus2_i,
- input logic [31:0] pc_id_i,
+ input logic [31:0] pc_id_i,
- // Stalls
- input logic ex_valid_i, // EX stage has valid output
- input logic lsu_resp_valid_i, // LSU has valid output, or is done
- // ALU
- output ibex_pkg::alu_op_e alu_operator_ex_o,
- output logic [31:0] alu_operand_a_ex_o,
- output logic [31:0] alu_operand_b_ex_o,
+ // Stalls
+ input logic ex_valid_i, // EX stage has valid output
+ input logic lsu_resp_valid_i, // LSU has valid output, or is done
+ // ALU
+ output ibex_pkg::alu_op_e alu_operator_ex_o,
+ output logic [31:0] alu_operand_a_ex_o,
+ output logic [31:0] alu_operand_b_ex_o,
- // Multicycle Operation Stage Register
- input logic [1:0] imd_val_we_ex_i,
- input logic [33:0] imd_val_d_ex_i[2],
- output logic [33:0] imd_val_q_ex_o[2],
+ // Multicycle Operation Stage Register
+ input logic [1:0] imd_val_we_ex_i,
+ input logic [33:0] imd_val_d_ex_i[2],
+ output logic [33:0] imd_val_q_ex_o[2],
- // Branch target ALU
- output logic [31:0] bt_a_operand_o,
- output logic [31:0] bt_b_operand_o,
+ // Branch target ALU
+ output logic [31:0] bt_a_operand_o,
+ output logic [31:0] bt_b_operand_o,
- // MUL, DIV
- output logic mult_en_ex_o,
- output logic div_en_ex_o,
- output logic mult_sel_ex_o,
- output logic div_sel_ex_o,
- output ibex_pkg::md_op_e multdiv_operator_ex_o,
- output logic [1:0] multdiv_signed_mode_ex_o,
- output logic [31:0] multdiv_operand_a_ex_o,
- output logic [31:0] multdiv_operand_b_ex_o,
- output logic multdiv_ready_id_o,
+ // MUL, DIV
+ output logic mult_en_ex_o,
+ output logic div_en_ex_o,
+ output logic mult_sel_ex_o,
+ output logic div_sel_ex_o,
+ output ibex_pkg::md_op_e multdiv_operator_ex_o,
+ output logic [1:0] multdiv_signed_mode_ex_o,
+ output logic [31:0] multdiv_operand_a_ex_o,
+ output logic [31:0] multdiv_operand_b_ex_o,
+ output logic multdiv_ready_id_o,
- // CSR
- output logic csr_access_o,
- output ibex_pkg::csr_op_e csr_op_o,
- output logic csr_op_en_o,
- output logic csr_save_if_o,
- output logic csr_save_id_o,
- output logic csr_save_wb_o,
- output logic csr_restore_mret_id_o,
- output logic csr_restore_dret_id_o,
- output logic csr_save_cause_o,
- output logic [31:0] csr_mtval_o,
- input ibex_pkg::priv_lvl_e priv_mode_i,
- input logic csr_mstatus_tw_i,
- input logic illegal_csr_insn_i,
- input logic data_ind_timing_i,
+ // CSR
+ output logic csr_access_o,
+ output ibex_pkg::csr_op_e csr_op_o,
+ output logic csr_op_en_o,
+ output logic csr_save_if_o,
+ output logic csr_save_id_o,
+ output logic csr_save_wb_o,
+ output logic csr_restore_mret_id_o,
+ output logic csr_restore_dret_id_o,
+ output logic csr_save_cause_o,
+ output logic [31:0] csr_mtval_o,
+ input ibex_pkg::priv_lvl_e priv_mode_i,
+ input logic csr_mstatus_tw_i,
+ input logic illegal_csr_insn_i,
+ input logic data_ind_timing_i,
- // Interface to load store unit
- output logic lsu_req_o,
- output logic lsu_we_o,
- output logic [1:0] lsu_type_o,
- output logic lsu_sign_ext_o,
- output logic [31:0] lsu_wdata_o,
+ // Interface to load store unit
+ output logic lsu_req_o,
+ output logic lsu_we_o,
+ output logic [1:0] lsu_type_o,
+ output logic lsu_sign_ext_o,
+ output logic [31:0] lsu_wdata_o,
- input logic lsu_req_done_i, // Data req to LSU is complete and
- // instruction can move to writeback
- // (only relevant where writeback stage is
- // present)
+ input logic lsu_req_done_i, // Data req to LSU is complete and
+ // instruction can move to writeback
+ // (only relevant where writeback stage is
+ // present)
- input logic lsu_addr_incr_req_i,
- input logic [31:0] lsu_addr_last_i,
+ input logic lsu_addr_incr_req_i,
+ input logic [31:0] lsu_addr_last_i,
- // Interrupt signals
- input logic csr_mstatus_mie_i,
- input logic irq_pending_i,
- input ibex_pkg::irqs_t irqs_i,
- input logic irq_nm_i,
- output logic nmi_mode_o,
+ // Interrupt signals
+ input logic csr_mstatus_mie_i,
+ input logic irq_pending_i,
+ input ibex_pkg::irqs_t irqs_i,
+ input logic irq_nm_i,
+ output logic nmi_mode_o,
- input logic lsu_load_err_i,
- input logic lsu_store_err_i,
+ input logic lsu_load_err_i,
+ input logic lsu_store_err_i,
- // Debug Signal
- output logic debug_mode_o,
- output ibex_pkg::dbg_cause_e debug_cause_o,
- output logic debug_csr_save_o,
- input logic debug_req_i,
- input logic debug_single_step_i,
- input logic debug_ebreakm_i,
- input logic debug_ebreaku_i,
- input logic trigger_match_i,
+ // Debug Signal
+ output logic debug_mode_o,
+ output ibex_pkg::dbg_cause_e debug_cause_o,
+ output logic debug_csr_save_o,
+ input logic debug_req_i,
+ input logic debug_single_step_i,
+ input logic debug_ebreakm_i,
+ input logic debug_ebreaku_i,
+ input logic trigger_match_i,
- // Write back signal
- input logic [31:0] result_ex_i,
- input logic [31:0] csr_rdata_i,
+ // Write back signal
+ input logic [31:0] result_ex_i,
+ input logic [31:0] csr_rdata_i,
- // Register file read
- output logic [4:0] rf_raddr_a_o,
- input logic [31:0] rf_rdata_a_i,
- output logic [4:0] rf_raddr_b_o,
- input logic [31:0] rf_rdata_b_i,
- output logic rf_ren_a_o,
- output logic rf_ren_b_o,
+ // Register file read
+ output logic [4:0] rf_raddr_a_o,
+ input logic [31:0] rf_rdata_a_i,
+ output logic [4:0] rf_raddr_b_o,
+ input logic [31:0] rf_rdata_b_i,
+ output logic rf_ren_a_o,
+ output logic rf_ren_b_o,
- // Register file write (via writeback)
- output logic [4:0] rf_waddr_id_o,
- output logic [31:0] rf_wdata_id_o,
- output logic rf_we_id_o,
- output logic rf_rd_a_wb_match_o,
- output logic rf_rd_b_wb_match_o,
+ // Register file write (via writeback)
+ output logic [4:0] rf_waddr_id_o,
+ output logic [31:0] rf_wdata_id_o,
+ output logic rf_we_id_o,
+ output logic rf_rd_a_wb_match_o,
+ output logic rf_rd_b_wb_match_o,
- // Register write information from writeback (for resolving data hazards)
- input logic [4:0] rf_waddr_wb_i,
- input logic [31:0] rf_wdata_fwd_wb_i,
- input logic rf_write_wb_i,
+ // Register write information from writeback (for resolving data hazards)
+ input logic [4:0] rf_waddr_wb_i,
+ input logic [31:0] rf_wdata_fwd_wb_i,
+ input logic rf_write_wb_i,
- output logic en_wb_o,
- output ibex_pkg::wb_instr_type_e instr_type_wb_o,
- output logic instr_perf_count_id_o,
- input logic ready_wb_i,
- input logic outstanding_load_wb_i,
- input logic outstanding_store_wb_i,
+ output logic en_wb_o,
+ output ibex_pkg::wb_instr_type_e instr_type_wb_o,
+ output logic instr_perf_count_id_o,
+ input logic ready_wb_i,
+ input logic outstanding_load_wb_i,
+ input logic outstanding_store_wb_i,
- // Performance Counters
- output logic perf_jump_o, // executing a jump instr
- output logic perf_branch_o, // executing a branch instr
- output logic perf_tbranch_o, // executing a taken branch instr
- output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory
- // access to finish before proceeding
- output logic perf_mul_wait_o,
- output logic perf_div_wait_o,
- output logic instr_id_done_o
+ // Performance Counters
+ output logic perf_jump_o, // executing a jump instr
+ output logic perf_branch_o, // executing a branch instr
+ output logic perf_tbranch_o, // executing a taken branch instr
+ output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory
+ // access to finish before proceeding
+ output logic perf_mul_wait_o,
+ output logic perf_div_wait_o,
+ output logic instr_id_done_o
);
import ibex_pkg::*;
@@ -195,9 +194,9 @@
logic wfi_insn_dec;
logic wb_exception;
+ logic id_exception;
logic branch_in_dec;
- logic branch_spec, branch_set_spec, branch_set_raw_spec;
logic branch_set, branch_set_raw, branch_set_raw_d;
logic branch_jump_set_done_q, branch_jump_set_done_d;
logic branch_not_set;
@@ -388,7 +387,7 @@
// Multicycle Operation Stage Register //
/////////////////////////////////////////
- for (genvar i=0; i<2; i++) begin : gen_intermediate_val_reg
+ for (genvar i = 0; i < 2; i++) begin : gen_intermediate_val_reg
always_ff @(posedge clk_i or negedge rst_ni) begin : intermediate_val_reg
if (!rst_ni) begin
imd_val_q[i] <= '0;
@@ -421,81 +420,81 @@
/////////////
ibex_decoder #(
- .RV32E ( RV32E ),
- .RV32M ( RV32M ),
- .RV32B ( RV32B ),
- .BranchTargetALU ( BranchTargetALU )
+ .RV32E (RV32E),
+ .RV32M (RV32M),
+ .RV32B (RV32B),
+ .BranchTargetALU(BranchTargetALU)
) decoder_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- // controller
- .illegal_insn_o ( illegal_insn_dec ),
- .ebrk_insn_o ( ebrk_insn ),
- .mret_insn_o ( mret_insn_dec ),
- .dret_insn_o ( dret_insn_dec ),
- .ecall_insn_o ( ecall_insn_dec ),
- .wfi_insn_o ( wfi_insn_dec ),
- .jump_set_o ( jump_set_dec ),
- .branch_taken_i ( branch_taken ),
- .icache_inval_o ( icache_inval_o ),
+ // controller
+ .illegal_insn_o(illegal_insn_dec),
+ .ebrk_insn_o (ebrk_insn),
+ .mret_insn_o (mret_insn_dec),
+ .dret_insn_o (dret_insn_dec),
+ .ecall_insn_o (ecall_insn_dec),
+ .wfi_insn_o (wfi_insn_dec),
+ .jump_set_o (jump_set_dec),
+ .branch_taken_i(branch_taken),
+ .icache_inval_o(icache_inval_o),
- // from IF-ID pipeline register
- .instr_first_cycle_i ( instr_first_cycle ),
- .instr_rdata_i ( instr_rdata_i ),
- .instr_rdata_alu_i ( instr_rdata_alu_i ),
- .illegal_c_insn_i ( illegal_c_insn_i ),
+ // from IF-ID pipeline register
+ .instr_first_cycle_i(instr_first_cycle),
+ .instr_rdata_i (instr_rdata_i),
+ .instr_rdata_alu_i (instr_rdata_alu_i),
+ .illegal_c_insn_i (illegal_c_insn_i),
- // immediates
- .imm_a_mux_sel_o ( imm_a_mux_sel ),
- .imm_b_mux_sel_o ( imm_b_mux_sel_dec ),
- .bt_a_mux_sel_o ( bt_a_mux_sel ),
- .bt_b_mux_sel_o ( bt_b_mux_sel ),
+ // immediates
+ .imm_a_mux_sel_o(imm_a_mux_sel),
+ .imm_b_mux_sel_o(imm_b_mux_sel_dec),
+ .bt_a_mux_sel_o (bt_a_mux_sel),
+ .bt_b_mux_sel_o (bt_b_mux_sel),
- .imm_i_type_o ( imm_i_type ),
- .imm_s_type_o ( imm_s_type ),
- .imm_b_type_o ( imm_b_type ),
- .imm_u_type_o ( imm_u_type ),
- .imm_j_type_o ( imm_j_type ),
- .zimm_rs1_type_o ( zimm_rs1_type ),
+ .imm_i_type_o (imm_i_type),
+ .imm_s_type_o (imm_s_type),
+ .imm_b_type_o (imm_b_type),
+ .imm_u_type_o (imm_u_type),
+ .imm_j_type_o (imm_j_type),
+ .zimm_rs1_type_o(zimm_rs1_type),
- // register file
- .rf_wdata_sel_o ( rf_wdata_sel ),
- .rf_we_o ( rf_we_dec ),
+ // register file
+ .rf_wdata_sel_o(rf_wdata_sel),
+ .rf_we_o (rf_we_dec),
- .rf_raddr_a_o ( rf_raddr_a_o ),
- .rf_raddr_b_o ( rf_raddr_b_o ),
- .rf_waddr_o ( rf_waddr_id_o ),
- .rf_ren_a_o ( rf_ren_a_dec ),
- .rf_ren_b_o ( rf_ren_b_dec ),
+ .rf_raddr_a_o(rf_raddr_a_o),
+ .rf_raddr_b_o(rf_raddr_b_o),
+ .rf_waddr_o (rf_waddr_id_o),
+ .rf_ren_a_o (rf_ren_a_dec),
+ .rf_ren_b_o (rf_ren_b_dec),
- // ALU
- .alu_operator_o ( alu_operator ),
- .alu_op_a_mux_sel_o ( alu_op_a_mux_sel_dec ),
- .alu_op_b_mux_sel_o ( alu_op_b_mux_sel_dec ),
- .alu_multicycle_o ( alu_multicycle_dec ),
+ // ALU
+ .alu_operator_o (alu_operator),
+ .alu_op_a_mux_sel_o(alu_op_a_mux_sel_dec),
+ .alu_op_b_mux_sel_o(alu_op_b_mux_sel_dec),
+ .alu_multicycle_o (alu_multicycle_dec),
- // MULT & DIV
- .mult_en_o ( mult_en_dec ),
- .div_en_o ( div_en_dec ),
- .mult_sel_o ( mult_sel_ex_o ),
- .div_sel_o ( div_sel_ex_o ),
- .multdiv_operator_o ( multdiv_operator ),
- .multdiv_signed_mode_o ( multdiv_signed_mode ),
+ // MULT & DIV
+ .mult_en_o (mult_en_dec),
+ .div_en_o (div_en_dec),
+ .mult_sel_o (mult_sel_ex_o),
+ .div_sel_o (div_sel_ex_o),
+ .multdiv_operator_o (multdiv_operator),
+ .multdiv_signed_mode_o(multdiv_signed_mode),
- // CSRs
- .csr_access_o ( csr_access_o ),
- .csr_op_o ( csr_op_o ),
+ // CSRs
+ .csr_access_o(csr_access_o),
+ .csr_op_o (csr_op_o),
- // LSU
- .data_req_o ( lsu_req_dec ),
- .data_we_o ( lsu_we ),
- .data_type_o ( lsu_type ),
- .data_sign_extension_o ( lsu_sign_ext ),
+ // LSU
+ .data_req_o (lsu_req_dec),
+ .data_we_o (lsu_we),
+ .data_type_o (lsu_type),
+ .data_sign_extension_o(lsu_sign_ext),
- // jump/branches
- .jump_in_dec_o ( jump_in_dec ),
- .branch_in_dec_o ( branch_in_dec )
+ // jump/branches
+ .jump_in_dec_o (jump_in_dec),
+ .branch_in_dec_o(branch_in_dec)
);
/////////////////////////////////
@@ -531,95 +530,94 @@
assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i);
ibex_controller #(
- .WritebackStage ( WritebackStage ),
- .BranchPredictor ( BranchPredictor )
+ .WritebackStage (WritebackStage),
+ .BranchPredictor(BranchPredictor)
) controller_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk_i),
+ .rst_ni(rst_ni),
- .ctrl_busy_o ( ctrl_busy_o ),
+ .ctrl_busy_o(ctrl_busy_o),
- // decoder related signals
- .illegal_insn_i ( illegal_insn_o ),
- .ecall_insn_i ( ecall_insn_dec ),
- .mret_insn_i ( mret_insn_dec ),
- .dret_insn_i ( dret_insn_dec ),
- .wfi_insn_i ( wfi_insn_dec ),
- .ebrk_insn_i ( ebrk_insn ),
- .csr_pipe_flush_i ( csr_pipe_flush ),
+ // decoder related signals
+ .illegal_insn_i (illegal_insn_o),
+ .ecall_insn_i (ecall_insn_dec),
+ .mret_insn_i (mret_insn_dec),
+ .dret_insn_i (dret_insn_dec),
+ .wfi_insn_i (wfi_insn_dec),
+ .ebrk_insn_i (ebrk_insn),
+ .csr_pipe_flush_i(csr_pipe_flush),
- // from IF-ID pipeline
- .instr_valid_i ( instr_valid_i ),
- .instr_i ( instr_rdata_i ),
- .instr_compressed_i ( instr_rdata_c_i ),
- .instr_is_compressed_i ( instr_is_compressed_i ),
- .instr_bp_taken_i ( instr_bp_taken_i ),
- .instr_fetch_err_i ( instr_fetch_err_i ),
- .instr_fetch_err_plus2_i ( instr_fetch_err_plus2_i ),
- .pc_id_i ( pc_id_i ),
+ // from IF-ID pipeline
+ .instr_valid_i (instr_valid_i),
+ .instr_i (instr_rdata_i),
+ .instr_compressed_i (instr_rdata_c_i),
+ .instr_is_compressed_i (instr_is_compressed_i),
+ .instr_bp_taken_i (instr_bp_taken_i),
+ .instr_fetch_err_i (instr_fetch_err_i),
+ .instr_fetch_err_plus2_i(instr_fetch_err_plus2_i),
+ .pc_id_i (pc_id_i),
- // to IF-ID pipeline
- .instr_valid_clear_o ( instr_valid_clear_o ),
- .id_in_ready_o ( id_in_ready_o ),
- .controller_run_o ( controller_run ),
+ // to IF-ID pipeline
+ .instr_valid_clear_o(instr_valid_clear_o),
+ .id_in_ready_o (id_in_ready_o),
+ .controller_run_o (controller_run),
- // to prefetcher
- .instr_req_o ( instr_req_o ),
- .pc_set_o ( pc_set_o ),
- .pc_set_spec_o ( pc_set_spec_o ),
- .pc_mux_o ( pc_mux_o ),
- .nt_branch_mispredict_o ( nt_branch_mispredict_o ),
- .exc_pc_mux_o ( exc_pc_mux_o ),
- .exc_cause_o ( exc_cause_o ),
+ // to prefetcher
+ .instr_req_o (instr_req_o),
+ .pc_set_o (pc_set_o),
+ .pc_mux_o (pc_mux_o),
+ .nt_branch_mispredict_o(nt_branch_mispredict_o),
+ .exc_pc_mux_o (exc_pc_mux_o),
+ .exc_cause_o (exc_cause_o),
- // LSU
- .lsu_addr_last_i ( lsu_addr_last_i ),
- .load_err_i ( lsu_load_err_i ),
- .store_err_i ( lsu_store_err_i ),
- .wb_exception_o ( wb_exception ),
+ // LSU
+ .lsu_addr_last_i(lsu_addr_last_i),
+ .load_err_i (lsu_load_err_i),
+ .store_err_i (lsu_store_err_i),
+ .wb_exception_o (wb_exception),
+ .id_exception_o (id_exception),
- // jump/branch control
- .branch_set_i ( branch_set ),
- .branch_set_spec_i ( branch_set_spec ),
- .branch_not_set_i ( branch_not_set ),
- .jump_set_i ( jump_set ),
+ // jump/branch control
+ .branch_set_i (branch_set),
+ .branch_not_set_i (branch_not_set),
+ .jump_set_i (jump_set),
- // interrupt signals
- .csr_mstatus_mie_i ( csr_mstatus_mie_i ),
- .irq_pending_i ( irq_pending_i ),
- .irqs_i ( irqs_i ),
- .irq_nm_i ( irq_nm_i ),
- .nmi_mode_o ( nmi_mode_o ),
+ // interrupt signals
+ .csr_mstatus_mie_i(csr_mstatus_mie_i),
+ .irq_pending_i (irq_pending_i),
+ .irqs_i (irqs_i),
+ .irq_nm_i (irq_nm_i),
+ .nmi_mode_o (nmi_mode_o),
- // CSR Controller Signals
- .csr_save_if_o ( csr_save_if_o ),
- .csr_save_id_o ( csr_save_id_o ),
- .csr_save_wb_o ( csr_save_wb_o ),
- .csr_restore_mret_id_o ( csr_restore_mret_id_o ),
- .csr_restore_dret_id_o ( csr_restore_dret_id_o ),
- .csr_save_cause_o ( csr_save_cause_o ),
- .csr_mtval_o ( csr_mtval_o ),
- .priv_mode_i ( priv_mode_i ),
- .csr_mstatus_tw_i ( csr_mstatus_tw_i ),
+ // CSR Controller Signals
+ .csr_save_if_o (csr_save_if_o),
+ .csr_save_id_o (csr_save_id_o),
+ .csr_save_wb_o (csr_save_wb_o),
+ .csr_restore_mret_id_o(csr_restore_mret_id_o),
+ .csr_restore_dret_id_o(csr_restore_dret_id_o),
+ .csr_save_cause_o (csr_save_cause_o),
+ .csr_mtval_o (csr_mtval_o),
+ .priv_mode_i (priv_mode_i),
+ .csr_mstatus_tw_i (csr_mstatus_tw_i),
- // Debug Signal
- .debug_mode_o ( debug_mode_o ),
- .debug_cause_o ( debug_cause_o ),
- .debug_csr_save_o ( debug_csr_save_o ),
- .debug_req_i ( debug_req_i ),
- .debug_single_step_i ( debug_single_step_i ),
- .debug_ebreakm_i ( debug_ebreakm_i ),
- .debug_ebreaku_i ( debug_ebreaku_i ),
- .trigger_match_i ( trigger_match_i ),
+ // Debug Signal
+ .debug_mode_o (debug_mode_o),
+ .debug_cause_o (debug_cause_o),
+ .debug_csr_save_o (debug_csr_save_o),
+ .debug_req_i (debug_req_i),
+ .debug_single_step_i(debug_single_step_i),
+ .debug_ebreakm_i (debug_ebreakm_i),
+ .debug_ebreaku_i (debug_ebreaku_i),
+ .trigger_match_i (trigger_match_i),
- .stall_id_i ( stall_id ),
- .stall_wb_i ( stall_wb ),
- .flush_id_o ( flush_id ),
- .ready_wb_i ( ready_wb_i ),
+ .stall_id_i(stall_id),
+ .stall_wb_i(stall_wb),
+ .flush_id_o(flush_id),
+ .ready_wb_i(ready_wb_i),
- // Performance Counters
- .perf_jump_o ( perf_jump_o ),
- .perf_tbranch_o ( perf_tbranch_o )
+ // Performance Counters
+ .perf_jump_o (perf_jump_o),
+ .perf_tbranch_o(perf_tbranch_o)
);
assign multdiv_en_dec = mult_en_dec | div_en_dec;
@@ -659,7 +657,6 @@
// Branch set fed straight to controller with branch target ALU
// (condition pass/fail used same cycle as generated instruction request)
assign branch_set_raw = branch_set_raw_d;
- assign branch_set_raw_spec = branch_spec;
end else begin : g_branch_set_flop
// Branch set flopped without branch target ALU, or in fixed time execution mode
// (condition pass/fail used next cycle where branch target is calculated)
@@ -679,9 +676,6 @@
assign branch_set_raw = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d :
branch_set_raw_q;
- // Use the speculative branch signal when BTALU is enabled
- assign branch_set_raw_spec = (BranchTargetALU && !data_ind_timing_i) ? branch_spec :
- branch_set_raw_q;
end
// Track whether the current instruction in ID/EX has done a branch or jump set.
@@ -705,7 +699,6 @@
// needless extra IF flushes and fetches.
assign jump_set = jump_set_raw & ~branch_jump_set_done_q;
assign branch_set = branch_set_raw & ~branch_jump_set_done_q;
- assign branch_set_spec = branch_set_raw_spec & ~branch_jump_set_done_q;
// Branch condition is calculated in the first cycle and flopped for use in the second cycle
// (only used in fixed time execution mode to determine branch destination).
@@ -736,6 +729,16 @@
`ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set)
`ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set)
+ //////////////////////////////
+ // Branch not-taken address //
+ //////////////////////////////
+
+ if (BranchPredictor) begin : g_calc_nt_addr
+ assign nt_branch_addr_o = pc_id_i + (instr_is_compressed_i ? 32'd2 : 32'd4);
+ end else begin : g_n_calc_nt_addr
+ assign nt_branch_addr_o = 32'd0;
+ end
+
///////////////
// ID-EX FSM //
///////////////
@@ -764,7 +767,6 @@
stall_branch = 1'b0;
stall_alu = 1'b0;
branch_set_raw_d = 1'b0;
- branch_spec = 1'b0;
branch_not_set = 1'b0;
jump_set_raw = 1'b0;
perf_branch_o = 1'b0;
@@ -806,8 +808,6 @@
branch_not_set = ~branch_decision_i;
end
- // Speculative branch (excludes branch_decision_i)
- branch_spec = SpecBranch ? 1'b1 : branch_decision_i;
perf_branch_o = 1'b1;
end
jump_in_dec: begin
@@ -906,6 +906,7 @@
// - There was an error on instruction fetch
assign instr_kill = instr_fetch_err_i |
wb_exception |
+ id_exception |
~controller_run;
// With writeback stage instructions must be prevented from executing if there is:
@@ -1023,6 +1024,7 @@
logic unused_outstanding_store_wb;
logic unused_wb_exception;
logic [31:0] unused_rf_wdata_fwd_wb;
+ logic unused_id_exception;
assign unused_data_req_done_ex = lsu_req_done_i;
assign unused_rf_waddr_wb = rf_waddr_wb_i;
@@ -1031,6 +1033,7 @@
assign unused_outstanding_store_wb = outstanding_store_wb_i;
assign unused_wb_exception = wb_exception;
assign unused_rf_wdata_fwd_wb = rf_wdata_fwd_wb_i;
+ assign unused_id_exception = id_exception;
assign instr_type_wb_o = WB_INSTR_OTHER;
assign stall_wb = 1'b0;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index abd09af..7f9f4d8 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -13,102 +13,103 @@
`include "prim_assert.sv"
module ibex_if_stage import ibex_pkg::*; #(
- parameter int unsigned DmHaltAddr = 32'h1A110800,
- parameter int unsigned DmExceptionAddr = 32'h1A110808,
- parameter bit DummyInstructions = 1'b0,
- parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0,
- parameter int unsigned BusSizeECC = BUS_SIZE,
- parameter int unsigned TagSizeECC = IC_TAG_SIZE,
- parameter int unsigned LineSizeECC = IC_LINE_SIZE,
- parameter bit PCIncrCheck = 1'b0,
- parameter bit ResetAll = 1'b0,
- parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
- parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
- parameter bit BranchPredictor = 1'b0
+ parameter int unsigned DmHaltAddr = 32'h1A110800,
+ parameter int unsigned DmExceptionAddr = 32'h1A110808,
+ parameter bit DummyInstructions = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter bit ICacheECC = 1'b0,
+ parameter int unsigned BusSizeECC = BUS_SIZE,
+ parameter int unsigned TagSizeECC = IC_TAG_SIZE,
+ parameter int unsigned LineSizeECC = IC_LINE_SIZE,
+ parameter bit PCIncrCheck = 1'b0,
+ parameter bit ResetAll = 1'b0,
+ parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
+ parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter bit BranchPredictor = 1'b0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- input logic [31:0] boot_addr_i, // also used for mtvec
- input logic req_i, // instruction request control
+ input logic [31:0] boot_addr_i, // also used for mtvec
+ input logic req_i, // instruction request control
- // instruction cache interface
- output logic instr_req_o,
- output logic [31:0] instr_addr_o,
- input logic instr_gnt_i,
- input logic instr_rvalid_i,
- input logic [31:0] instr_rdata_i,
- input logic instr_err_i,
- input logic instr_pmp_err_i,
+ // instruction cache interface
+ output logic instr_req_o,
+ output logic [31:0] instr_addr_o,
+ input logic instr_gnt_i,
+ input logic instr_rvalid_i,
+ input logic [31:0] instr_rdata_i,
+ input logic instr_err_i,
- // ICache RAM IO
- output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
- output logic ic_tag_write_o,
- output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
- output logic [TagSizeECC-1:0] ic_tag_wdata_o,
- input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
- output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
- output logic ic_data_write_o,
- output logic [IC_INDEX_W-1:0] ic_data_addr_o,
- output logic [LineSizeECC-1:0] ic_data_wdata_o,
- input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
+ // ICache RAM IO
+ output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
+ output logic ic_tag_write_o,
+ output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
+ output logic [TagSizeECC-1:0] ic_tag_wdata_o,
+ input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
+ output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
+ output logic ic_data_write_o,
+ output logic [IC_INDEX_W-1:0] ic_data_addr_o,
+ output logic [LineSizeECC-1:0] ic_data_wdata_o,
+ input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
- // output of ID stage
- output logic instr_valid_id_o, // instr in IF-ID is valid
- output logic instr_new_id_o, // instr in IF-ID is new
- output logic [31:0] instr_rdata_id_o, // instr for ID stage
- output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage
- // to reduce fan-out
- output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
- // (mtval), meaningful only if
- // instr_is_compressed_id_o = 1'b1
- output logic instr_is_compressed_id_o, // compressed decoder thinks this
- // is a compressed instr
- output logic instr_bp_taken_o, // instruction was predicted to be
- // a taken branch
- output logic instr_fetch_err_o, // bus error on fetch
- output logic instr_fetch_err_plus2_o, // bus error misaligned
- output logic illegal_c_insn_id_o, // compressed decoder thinks this
- // is an invalid instr
- output logic dummy_instr_id_o, // Instruction is a dummy
- output logic [31:0] pc_if_o,
- output logic [31:0] pc_id_o,
+ // output of ID stage
+ output logic instr_valid_id_o, // instr in IF-ID is valid
+ output logic instr_new_id_o, // instr in IF-ID is new
+ output logic [31:0] instr_rdata_id_o, // instr for ID stage
+ output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage
+ // to reduce fan-out
+ output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
+ // (mtval), meaningful only if
+ // instr_is_compressed_id_o = 1'b1
+ output logic instr_is_compressed_id_o, // compressed decoder thinks this
+ // is a compressed instr
+ output logic instr_bp_taken_o, // instruction was predicted to be
+ // a taken branch
+ output logic instr_fetch_err_o, // bus error on fetch
+ output logic instr_fetch_err_plus2_o, // bus error misaligned
+ output logic illegal_c_insn_id_o, // compressed decoder thinks this
+ // is an invalid instr
+ output logic dummy_instr_id_o, // Instruction is a dummy
+ output logic [31:0] pc_if_o,
+ output logic [31:0] pc_id_o,
+ input logic pmp_err_if_i,
+ input logic pmp_err_if_plus2_i,
- // control signals
- input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
- input logic pc_set_i, // set the PC to a new value
- input logic pc_set_spec_i,
- input pc_sel_e pc_mux_i, // selector for PC multiplexer
- input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was
- // mispredicted (predicted taken)
- input exc_pc_sel_e exc_pc_mux_i, // selects ISR address
- input exc_cause_e exc_cause, // selects ISR address for
- // vectorized interrupt lines
- input logic dummy_instr_en_i,
- input logic [2:0] dummy_instr_mask_i,
- input logic dummy_instr_seed_en_i,
- input logic [31:0] dummy_instr_seed_i,
- input logic icache_enable_i,
- input logic icache_inval_i,
+ // control signals
+ input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
+ input logic pc_set_i, // set the PC to a new value
+ input pc_sel_e pc_mux_i, // selector for PC multiplexer
+ input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was
+ // mispredicted (predicted taken)
+ input logic [31:0] nt_branch_addr_i, // Not-taken branch address in ID/EX
+ input exc_pc_sel_e exc_pc_mux_i, // selects ISR address
+ input exc_cause_e exc_cause, // selects ISR address for
+ // vectorized interrupt lines
+ input logic dummy_instr_en_i,
+ input logic [2:0] dummy_instr_mask_i,
+ input logic dummy_instr_seed_en_i,
+ input logic [31:0] dummy_instr_seed_i,
+ input logic icache_enable_i,
+ input logic icache_inval_i,
- // jump and branch target
- input logic [31:0] branch_target_ex_i, // branch/jump target address
+ // jump and branch target
+ input logic [31:0] branch_target_ex_i, // branch/jump target address
- // CSRs
- input logic [31:0] csr_mepc_i, // PC to restore after handling
- // the interrupt/exception
- input logic [31:0] csr_depc_i, // PC to restore after handling
- // the debug request
- input logic [31:0] csr_mtvec_i, // base PC to jump to on exception
- output logic csr_mtvec_init_o, // tell CS regfile to init mtvec
+ // CSRs
+ input logic [31:0] csr_mepc_i, // PC to restore after handling
+ // the interrupt/exception
+ input logic [31:0] csr_depc_i, // PC to restore after handling
+ // the debug request
+ input logic [31:0] csr_mtvec_i, // base PC to jump to on exception
+ output logic csr_mtvec_init_o, // tell CS regfile to init mtvec
- // pipeline stall
- input logic id_in_ready_i, // ID stage is ready for new instr
+ // pipeline stall
+ input logic id_in_ready_i, // ID stage is ready for new instr
- // misc signals
- output logic pc_mismatch_alert_o,
- output logic if_busy_o // IF stage is busy fetching instr
+ // misc signals
+ output logic pc_mismatch_alert_o,
+ output logic if_busy_o // IF stage is busy fetching instr
);
logic instr_valid_id_d, instr_valid_id_q;
@@ -117,8 +118,6 @@
// prefetch buffer related signals
logic prefetch_busy;
logic branch_req;
- logic branch_spec;
- logic predicted_branch;
logic [31:0] fetch_addr_n;
logic unused_fetch_addr_n0;
@@ -129,10 +128,17 @@
logic fetch_err;
logic fetch_err_plus2;
+ logic [31:0] instr_decompressed;
+ logic illegal_c_insn;
+ logic instr_is_compressed;
+
logic if_instr_valid;
logic [31:0] if_instr_rdata;
logic [31:0] if_instr_addr;
+ logic if_instr_bus_err;
+ logic if_instr_pmp_err;
logic if_instr_err;
+ logic if_instr_err_plus2;
logic [31:0] exc_pc;
@@ -200,7 +206,6 @@
if (ICache) begin : gen_icache
// Full I-Cache option
ibex_icache #(
- .BranchPredictor (BranchPredictor),
.ICacheECC (ICacheECC),
.ResetAll (ResetAll),
.BusSizeECC (BusSizeECC),
@@ -213,9 +218,8 @@
.req_i ( req_i ),
.branch_i ( branch_req ),
- .branch_spec_i ( branch_spec ),
- .predicted_branch_i ( predicted_branch ),
.branch_mispredict_i ( nt_branch_mispredict_i ),
+ .mispredict_addr_i ( nt_branch_addr_i ),
.addr_i ( {fetch_addr_n[31:1], 1'b0} ),
.ready_i ( fetch_ready ),
@@ -231,7 +235,6 @@
.instr_rvalid_i ( instr_rvalid_i ),
.instr_rdata_i ( instr_rdata_i ),
.instr_err_i ( instr_err_i ),
- .instr_pmp_err_i ( instr_pmp_err_i ),
.ic_tag_req_o ( ic_tag_req_o ),
.ic_tag_write_o ( ic_tag_write_o ),
@@ -251,7 +254,6 @@
end else begin : gen_prefetch_buffer
// prefetch buffer, caches a fixed number of instructions
ibex_prefetch_buffer #(
- .BranchPredictor (BranchPredictor),
.ResetAll (ResetAll)
) prefetch_buffer_i (
.clk_i ( clk_i ),
@@ -260,9 +262,8 @@
.req_i ( req_i ),
.branch_i ( branch_req ),
- .branch_spec_i ( branch_spec ),
- .predicted_branch_i ( predicted_branch ),
.branch_mispredict_i ( nt_branch_mispredict_i ),
+ .mispredict_addr_i ( nt_branch_addr_i ),
.addr_i ( {fetch_addr_n[31:1], 1'b0} ),
.ready_i ( fetch_ready ),
@@ -278,7 +279,6 @@
.instr_rvalid_i ( instr_rvalid_i ),
.instr_rdata_i ( instr_rdata_i ),
.instr_err_i ( instr_err_i ),
- .instr_pmp_err_i ( instr_pmp_err_i ),
.busy_o ( prefetch_busy )
);
@@ -303,28 +303,36 @@
assign unused_fetch_addr_n0 = fetch_addr_n[0];
assign branch_req = pc_set_i | predict_branch_taken;
- assign branch_spec = pc_set_spec_i | predict_branch_taken;
assign pc_if_o = if_instr_addr;
assign if_busy_o = prefetch_busy;
+ // PMP errors
+ // An error can come from the instruction address, or the next instruction address for unaligned,
+ // uncompressed instructions.
+ assign if_instr_pmp_err = pmp_err_if_i |
+ (if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i);
+
+ // Combine bus errors and pmp errors
+ assign if_instr_err = if_instr_bus_err | if_instr_pmp_err;
+
+ // Capture the second half of the address for errors on the second part of an instruction
+ assign if_instr_err_plus2 = ((if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) |
+ fetch_err_plus2) & ~pmp_err_if_i;
+
// compressed instruction decoding, or more precisely compressed instruction
// expander
//
// since it does not matter where we decompress instructions, we do it here
// to ease timing closure
- logic [31:0] instr_decompressed;
- logic illegal_c_insn;
- logic instr_is_compressed;
-
ibex_compressed_decoder compressed_decoder_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .valid_i ( fetch_valid & ~fetch_err ),
- .instr_i ( if_instr_rdata ),
- .instr_o ( instr_decompressed ),
- .is_compressed_o ( instr_is_compressed ),
- .illegal_instr_o ( illegal_c_insn )
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .valid_i (fetch_valid & ~fetch_err),
+ .instr_i (if_instr_rdata),
+ .instr_o (instr_decompressed),
+ .is_compressed_o(instr_is_compressed),
+ .illegal_instr_o(illegal_c_insn)
);
// Dummy instruction insertion
@@ -336,16 +344,16 @@
.RndCnstLfsrSeed (RndCnstLfsrSeed),
.RndCnstLfsrPerm (RndCnstLfsrPerm)
) dummy_instr_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .dummy_instr_en_i ( dummy_instr_en_i ),
- .dummy_instr_mask_i ( dummy_instr_mask_i ),
- .dummy_instr_seed_en_i ( dummy_instr_seed_en_i ),
- .dummy_instr_seed_i ( dummy_instr_seed_i ),
- .fetch_valid_i ( fetch_valid ),
- .id_in_ready_i ( id_in_ready_i ),
- .insert_dummy_instr_o ( insert_dummy_instr ),
- .dummy_instr_data_o ( dummy_instr_data )
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .dummy_instr_en_i (dummy_instr_en_i),
+ .dummy_instr_mask_i (dummy_instr_mask_i),
+ .dummy_instr_seed_en_i(dummy_instr_seed_en_i),
+ .dummy_instr_seed_i (dummy_instr_seed_i),
+ .fetch_valid_i (fetch_valid),
+ .id_in_ready_i (id_in_ready_i),
+ .insert_dummy_instr_o (insert_dummy_instr),
+ .dummy_instr_data_o (dummy_instr_data)
);
// Mux between actual instructions and dummy instructions
@@ -426,7 +434,7 @@
// To reduce fan-out and help timing from the instr_rdata_id flops they are replicated.
instr_rdata_alu_id_o <= instr_out;
instr_fetch_err_o <= instr_err_out;
- instr_fetch_err_plus2_o <= fetch_err_plus2;
+ instr_fetch_err_plus2_o <= if_instr_err_plus2;
instr_rdata_c_id_o <= if_instr_rdata[15:0];
instr_is_compressed_id_o <= instr_is_compressed_out;
illegal_c_insn_id_o <= illegal_c_instr_out;
@@ -440,7 +448,7 @@
// To reduce fan-out and help timing from the instr_rdata_id flops they are replicated.
instr_rdata_alu_id_o <= instr_out;
instr_fetch_err_o <= instr_err_out;
- instr_fetch_err_plus2_o <= fetch_err_plus2;
+ instr_fetch_err_plus2_o <= if_instr_err_plus2;
instr_rdata_c_id_o <= if_instr_rdata[15:0];
instr_is_compressed_id_o <= instr_is_compressed_out;
illegal_c_insn_id_o <= illegal_c_instr_out;
@@ -457,7 +465,7 @@
// Do not check for sequential increase after a branch, jump, exception, interrupt or debug
// request, all of which will set branch_req. Also do not check after reset or for dummys.
assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) &
- ~branch_req & ~stall_dummy_instr;
+ ~branch_req & ~if_instr_err & ~stall_dummy_instr;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@@ -467,8 +475,7 @@
end
end
- assign prev_instr_addr_incr = pc_id_o + ((instr_is_compressed_id_o && !instr_fetch_err_o) ?
- 32'd2 : 32'd4);
+ assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4);
// Check that the address equals the previous address +2/+4
assign pc_mismatch_alert_o = prev_instr_seq_q & (pc_if_o != prev_instr_addr_incr);
@@ -512,7 +519,7 @@
// data_gnt_i -> instr_req_o (which needs to be avoided as for some interconnects this will
// result in a combinational loop).
- assign instr_skid_en = predicted_branch & ~id_in_ready_i & ~instr_skid_valid_q;
+ assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q;
assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr) |
instr_skid_en;
@@ -548,14 +555,14 @@
end
ibex_branch_predict branch_predict_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .fetch_rdata_i ( fetch_rdata ),
- .fetch_pc_i ( fetch_addr ),
- .fetch_valid_i ( fetch_valid ),
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .fetch_rdata_i(fetch_rdata),
+ .fetch_pc_i (fetch_addr),
+ .fetch_valid_i(fetch_valid),
- .predict_branch_taken_o ( predict_branch_taken_raw ),
- .predict_branch_pc_o ( predict_branch_pc )
+ .predict_branch_taken_o(predict_branch_taken_raw),
+ .predict_branch_pc_o (predict_branch_pc)
);
// If there is an instruction in the skid buffer there must be no branch prediction.
@@ -564,16 +571,13 @@
// Do not branch predict on instruction errors.
assign predict_branch_taken = predict_branch_taken_raw & ~instr_skid_valid_q & ~fetch_err;
- // pc_set_i takes precendence over branch prediction
- assign predicted_branch = predict_branch_taken & ~pc_set_i;
-
- assign if_instr_valid = fetch_valid | instr_skid_valid_q;
+ assign if_instr_valid = fetch_valid | (instr_skid_valid_q & ~nt_branch_mispredict_i);
assign if_instr_rdata = instr_skid_valid_q ? instr_skid_data_q : fetch_rdata;
assign if_instr_addr = instr_skid_valid_q ? instr_skid_addr_q : fetch_addr;
// Don't branch predict on instruction error so only instructions without errors end up in the
// skid buffer.
- assign if_instr_err = ~instr_skid_valid_q & fetch_err;
+ assign if_instr_bus_err = ~instr_skid_valid_q & fetch_err;
assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken;
assign fetch_ready = id_in_ready_i & ~stall_dummy_instr & ~instr_skid_valid_q;
@@ -585,13 +589,12 @@
end else begin : g_no_branch_predictor
assign instr_bp_taken_o = 1'b0;
assign predict_branch_taken = 1'b0;
- assign predicted_branch = 1'b0;
assign predict_branch_pc = 32'b0;
assign if_instr_valid = fetch_valid;
assign if_instr_rdata = fetch_rdata;
assign if_instr_addr = fetch_addr;
- assign if_instr_err = fetch_err;
+ assign if_instr_bus_err = fetch_err;
assign fetch_ready = id_in_ready_i & ~stall_dummy_instr;
end
@@ -638,6 +641,11 @@
assign next_pc = fetch_addr + (instr_is_compressed_out ? 32'd2 : 32'd4);
+ logic predicted_branch;
+
+ // pc_set_i takes precendence over branch prediction
+ assign predicted_branch = predict_branch_taken & ~pc_set_i;
+
always_comb begin
predicted_branch_live_d = predicted_branch_live_q;
mispredicted_d = mispredicted_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
index 907bf61..14de33b 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv
@@ -16,54 +16,54 @@
module ibex_load_store_unit
(
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- // data interface
- output logic data_req_o,
- input logic data_gnt_i,
- input logic data_rvalid_i,
- input logic data_err_i,
- input logic data_pmp_err_i,
+ // data interface
+ output logic data_req_o,
+ input logic data_gnt_i,
+ input logic data_rvalid_i,
+ input logic data_err_i,
+ input logic data_pmp_err_i,
- output logic [31:0] data_addr_o,
- output logic data_we_o,
- output logic [3:0] data_be_o,
- output logic [31:0] data_wdata_o,
- input logic [31:0] data_rdata_i,
+ output logic [31:0] data_addr_o,
+ output logic data_we_o,
+ output logic [3:0] data_be_o,
+ output logic [31:0] data_wdata_o,
+ input logic [31:0] data_rdata_i,
- // signals to/from ID/EX stage
- input logic lsu_we_i, // write enable -> from ID/EX
- input logic [1:0] lsu_type_i, // data type: word, half word, byte -> from ID/EX
- input logic [31:0] lsu_wdata_i, // data to write to memory -> from ID/EX
- input logic lsu_sign_ext_i, // sign extension -> from ID/EX
+ // signals to/from ID/EX stage
+ input logic lsu_we_i, // write enable -> from ID/EX
+ input logic [1:0] lsu_type_i, // data type: word, half word, byte -> from ID/EX
+ input logic [31:0] lsu_wdata_i, // data to write to memory -> from ID/EX
+ input logic lsu_sign_ext_i, // sign extension -> from ID/EX
- output logic [31:0] lsu_rdata_o, // requested data -> to ID/EX
- output logic lsu_rdata_valid_o,
- input logic lsu_req_i, // data request -> from ID/EX
+ output logic [31:0] lsu_rdata_o, // requested data -> to ID/EX
+ output logic lsu_rdata_valid_o,
+ input logic lsu_req_i, // data request -> from ID/EX
- input logic [31:0] adder_result_ex_i, // address computed in ALU -> from ID/EX
+ input logic [31:0] adder_result_ex_i, // address computed in ALU -> from ID/EX
- output logic addr_incr_req_o, // request address increment for
- // misaligned accesses -> to ID/EX
- output logic [31:0] addr_last_o, // address of last transaction -> to controller
- // -> mtval
- // -> AGU for misaligned accesses
+ output logic addr_incr_req_o, // request address increment for
+ // misaligned accesses -> to ID/EX
+ output logic [31:0] addr_last_o, // address of last transaction -> to controller
+ // -> mtval
+ // -> AGU for misaligned accesses
- output logic lsu_req_done_o, // Signals that data request is complete
- // (only need to await final data
- // response) -> to ID/EX
+ output logic lsu_req_done_o, // Signals that data request is complete
+ // (only need to await final data
+ // response) -> to ID/EX
- output logic lsu_resp_valid_o, // LSU has response from transaction -> to ID/EX
+ output logic lsu_resp_valid_o, // LSU has response from transaction -> to ID/EX
- // exception signals
- output logic load_err_o,
- output logic store_err_o,
+ // exception signals
+ output logic load_err_o,
+ output logic store_err_o,
- output logic busy_o,
+ output logic busy_o,
- output logic perf_load_o,
- output logic perf_store_o
+ output logic perf_load_o,
+ output logic perf_store_o
);
logic [31:0] data_addr;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
index a95ef49..3d1e20f 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
@@ -7,97 +7,97 @@
// those from the main core. The second core runs synchronously with the main core, delayed by
// LockstepOffset cycles.
module ibex_lockstep import ibex_pkg::*; #(
- parameter int unsigned LockstepOffset = 2,
- parameter bit PMPEnable = 1'b0,
- parameter int unsigned PMPGranularity = 0,
- parameter int unsigned PMPNumRegions = 4,
- parameter int unsigned MHPMCounterNum = 0,
- parameter int unsigned MHPMCounterWidth = 40,
- parameter bit RV32E = 1'b0,
- parameter rv32m_e RV32M = RV32MFast,
- parameter rv32b_e RV32B = RV32BNone,
- parameter bit BranchTargetALU = 1'b0,
- parameter bit WritebackStage = 1'b0,
- parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0,
- parameter int unsigned BusSizeECC = BUS_SIZE,
- parameter int unsigned TagSizeECC = IC_TAG_SIZE,
- parameter int unsigned LineSizeECC = IC_LINE_SIZE,
- parameter bit BranchPredictor = 1'b0,
- parameter bit DbgTriggerEn = 1'b0,
- parameter int unsigned DbgHwBreakNum = 1,
- parameter bit ResetAll = 1'b0,
- parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
- parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
- parameter bit SecureIbex = 1'b0,
- parameter bit DummyInstructions = 1'b0,
- parameter bit RegFileECC = 1'b0,
- parameter int unsigned RegFileDataWidth = 32,
- parameter int unsigned DmHaltAddr = 32'h1A110800,
- parameter int unsigned DmExceptionAddr = 32'h1A110808
+ parameter int unsigned LockstepOffset = 2,
+ parameter bit PMPEnable = 1'b0,
+ parameter int unsigned PMPGranularity = 0,
+ parameter int unsigned PMPNumRegions = 4,
+ parameter int unsigned MHPMCounterNum = 0,
+ parameter int unsigned MHPMCounterWidth = 40,
+ parameter bit RV32E = 1'b0,
+ parameter rv32m_e RV32M = RV32MFast,
+ parameter rv32b_e RV32B = RV32BNone,
+ parameter bit BranchTargetALU = 1'b0,
+ parameter bit WritebackStage = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter bit ICacheECC = 1'b0,
+ parameter int unsigned BusSizeECC = BUS_SIZE,
+ parameter int unsigned TagSizeECC = IC_TAG_SIZE,
+ parameter int unsigned LineSizeECC = IC_LINE_SIZE,
+ parameter bit BranchPredictor = 1'b0,
+ parameter bit DbgTriggerEn = 1'b0,
+ parameter int unsigned DbgHwBreakNum = 1,
+ parameter bit ResetAll = 1'b0,
+ parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
+ parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter bit SecureIbex = 1'b0,
+ parameter bit DummyInstructions = 1'b0,
+ parameter bit RegFileECC = 1'b0,
+ parameter int unsigned RegFileDataWidth = 32,
+ parameter int unsigned DmHaltAddr = 32'h1A110800,
+ parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- input logic [31:0] hart_id_i,
- input logic [31:0] boot_addr_i,
+ input logic [31:0] hart_id_i,
+ input logic [31:0] boot_addr_i,
- input logic instr_req_i,
- input logic instr_gnt_i,
- input logic instr_rvalid_i,
- input logic [31:0] instr_addr_i,
- input logic [31:0] instr_rdata_i,
- input logic [6:0] instr_rdata_intg_i,
- input logic instr_err_i,
+ input logic instr_req_i,
+ input logic instr_gnt_i,
+ input logic instr_rvalid_i,
+ input logic [31:0] instr_addr_i,
+ input logic [31:0] instr_rdata_i,
+ input logic [6:0] instr_rdata_intg_i,
+ input logic instr_err_i,
- input logic data_req_i,
- input logic data_gnt_i,
- input logic data_rvalid_i,
- input logic data_we_i,
- input logic [3:0] data_be_i,
- input logic [31:0] data_addr_i,
- input logic [31:0] data_wdata_i,
- output logic [6:0] data_wdata_intg_o,
- input logic [31:0] data_rdata_i,
- input logic [6:0] data_rdata_intg_i,
- input logic data_err_i,
+ input logic data_req_i,
+ input logic data_gnt_i,
+ input logic data_rvalid_i,
+ input logic data_we_i,
+ input logic [3:0] data_be_i,
+ input logic [31:0] data_addr_i,
+ input logic [31:0] data_wdata_i,
+ output logic [6:0] data_wdata_intg_o,
+ input logic [31:0] data_rdata_i,
+ input logic [6:0] data_rdata_intg_i,
+ input logic data_err_i,
- input logic dummy_instr_id_i,
- input logic [4:0] rf_raddr_a_i,
- input logic [4:0] rf_raddr_b_i,
- input logic [4:0] rf_waddr_wb_i,
- input logic rf_we_wb_i,
- input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i,
- input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i,
- input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i,
+ input logic dummy_instr_id_i,
+ input logic [4:0] rf_raddr_a_i,
+ input logic [4:0] rf_raddr_b_i,
+ input logic [4:0] rf_waddr_wb_i,
+ input logic rf_we_wb_i,
+ input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i,
+ input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i,
+ input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i,
- input logic [IC_NUM_WAYS-1:0] ic_tag_req_i,
- input logic ic_tag_write_i,
- input logic [IC_INDEX_W-1:0] ic_tag_addr_i,
- input logic [TagSizeECC-1:0] ic_tag_wdata_i,
- input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
- input logic [IC_NUM_WAYS-1:0] ic_data_req_i,
- input logic ic_data_write_i,
- input logic [IC_INDEX_W-1:0] ic_data_addr_i,
- input logic [LineSizeECC-1:0] ic_data_wdata_i,
- input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
+ input logic [IC_NUM_WAYS-1:0] ic_tag_req_i,
+ input logic ic_tag_write_i,
+ input logic [IC_INDEX_W-1:0] ic_tag_addr_i,
+ input logic [TagSizeECC-1:0] ic_tag_wdata_i,
+ input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
+ input logic [IC_NUM_WAYS-1:0] ic_data_req_i,
+ input logic ic_data_write_i,
+ input logic [IC_INDEX_W-1:0] ic_data_addr_i,
+ input logic [LineSizeECC-1:0] ic_data_wdata_i,
+ input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
- input logic irq_software_i,
- input logic irq_timer_i,
- input logic irq_external_i,
- input logic [14:0] irq_fast_i,
- input logic irq_nm_i,
- input logic irq_pending_i,
+ input logic irq_software_i,
+ input logic irq_timer_i,
+ input logic irq_external_i,
+ input logic [14:0] irq_fast_i,
+ input logic irq_nm_i,
+ input logic irq_pending_i,
- input logic debug_req_i,
- input crash_dump_t crash_dump_i,
+ input logic debug_req_i,
+ input crash_dump_t crash_dump_i,
- input logic fetch_enable_i,
- output logic alert_minor_o,
- output logic alert_major_o,
- input logic core_busy_i,
- input logic test_en_i,
- input logic scan_rst_ni
+ input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
+ input logic core_busy_i,
+ input logic test_en_i,
+ input logic scan_rst_ni
);
localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset);
@@ -190,13 +190,13 @@
data_rdata_intg_q <= '0;
for (int unsigned i = 0; i < LockstepOffset; i++) begin
shadow_inputs_q[i] <= delayed_inputs_t'('0);
- shadow_tag_rdata_q[i] <= '{default:0};
- shadow_data_rdata_q[i] <= '{default:0};
+ shadow_tag_rdata_q[i] <= '{default: 0};
+ shadow_data_rdata_q[i] <= '{default: 0};
end
end else begin
instr_rdata_intg_q <= instr_rdata_intg_i;
data_rdata_intg_q <= data_rdata_intg_i;
- for (int unsigned i = 0; i < LockstepOffset-1; i++) begin
+ for (int unsigned i = 0; i < LockstepOffset - 1; i++) begin
shadow_inputs_q[i] <= shadow_inputs_q[i+1];
shadow_tag_rdata_q[i] <= shadow_tag_rdata_q[i+1];
shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1];
@@ -216,14 +216,14 @@
logic [31:0] unused_wdata;
// Checks on incoming data
- prim_secded_39_32_dec u_instr_intg_dec (
+ prim_secded_inv_39_32_dec u_instr_intg_dec (
.data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}),
.data_o (),
.syndrome_o (),
.err_o (instr_intg_err)
);
- prim_secded_39_32_dec u_data_intg_dec (
+ prim_secded_inv_39_32_dec u_data_intg_dec (
.data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}),
.data_o (),
.syndrome_o (),
@@ -234,7 +234,7 @@
(shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err);
// Generate integrity bits
- prim_secded_39_32_enc u_data_gen (
+ prim_secded_inv_39_32_enc u_data_gen (
.data_i (data_wdata_i),
.data_o ({data_wdata_intg_o, unused_wdata})
);
@@ -302,7 +302,7 @@
// Delay the outputs
always_ff @(posedge clk_i) begin
- for (int unsigned i = 0; i < OutputsOffset-1; i++) begin
+ for (int unsigned i = 0; i < OutputsOffset - 1; i++) begin
core_outputs_q[i] <= core_outputs_q[i+1];
end
core_outputs_q[OutputsOffset-1] <= core_outputs_in;
@@ -397,29 +397,33 @@
.crash_dump_o (shadow_outputs_d.crash_dump),
`ifdef RVFI
- .rvfi_valid (),
- .rvfi_order (),
- .rvfi_insn (),
- .rvfi_trap (),
- .rvfi_halt (),
- .rvfi_intr (),
- .rvfi_mode (),
- .rvfi_ixl (),
- .rvfi_rs1_addr (),
- .rvfi_rs2_addr (),
- .rvfi_rs3_addr (),
- .rvfi_rs1_rdata (),
- .rvfi_rs2_rdata (),
- .rvfi_rs3_rdata (),
- .rvfi_rd_addr (),
- .rvfi_rd_wdata (),
- .rvfi_pc_rdata (),
- .rvfi_pc_wdata (),
- .rvfi_mem_addr (),
- .rvfi_mem_rmask (),
- .rvfi_mem_wmask (),
- .rvfi_mem_rdata (),
- .rvfi_mem_wdata (),
+ .rvfi_valid (),
+ .rvfi_order (),
+ .rvfi_insn (),
+ .rvfi_trap (),
+ .rvfi_halt (),
+ .rvfi_intr (),
+ .rvfi_mode (),
+ .rvfi_ixl (),
+ .rvfi_rs1_addr (),
+ .rvfi_rs2_addr (),
+ .rvfi_rs3_addr (),
+ .rvfi_rs1_rdata (),
+ .rvfi_rs2_rdata (),
+ .rvfi_rs3_rdata (),
+ .rvfi_rd_addr (),
+ .rvfi_rd_wdata (),
+ .rvfi_pc_rdata (),
+ .rvfi_pc_wdata (),
+ .rvfi_mem_addr (),
+ .rvfi_mem_rmask (),
+ .rvfi_mem_wmask (),
+ .rvfi_mem_rdata (),
+ .rvfi_mem_wdata (),
+ .rvfi_ext_mip (),
+ .rvfi_ext_nmi (),
+ .rvfi_ext_debug_req (),
+ .rvfi_ext_mcycle (),
`endif
.fetch_enable_i (shadow_inputs_q[0].fetch_enable),
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
index 4da8f0d..79ed5bc 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
@@ -15,34 +15,34 @@
`include "prim_assert.sv"
module ibex_multdiv_fast #(
- parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
+ parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
) (
- input logic clk_i,
- input logic rst_ni,
- input logic mult_en_i, // dynamic enable signal, for FSM control
- input logic div_en_i, // dynamic enable signal, for FSM control
- input logic mult_sel_i, // static decoder output, for data muxes
- input logic div_sel_i, // static decoder output, for data muxes
- input ibex_pkg::md_op_e operator_i,
- input logic [1:0] signed_mode_i,
- input logic [31:0] op_a_i,
- input logic [31:0] op_b_i,
- input logic [33:0] alu_adder_ext_i,
- input logic [31:0] alu_adder_i,
- input logic equal_to_zero_i,
- input logic data_ind_timing_i,
+ input logic clk_i,
+ input logic rst_ni,
+ input logic mult_en_i, // dynamic enable signal, for FSM control
+ input logic div_en_i, // dynamic enable signal, for FSM control
+ input logic mult_sel_i, // static decoder output, for data muxes
+ input logic div_sel_i, // static decoder output, for data muxes
+ input ibex_pkg::md_op_e operator_i,
+ input logic [1:0] signed_mode_i,
+ input logic [31:0] op_a_i,
+ input logic [31:0] op_b_i,
+ input logic [33:0] alu_adder_ext_i,
+ input logic [31:0] alu_adder_i,
+ input logic equal_to_zero_i,
+ input logic data_ind_timing_i,
- output logic [32:0] alu_operand_a_o,
- output logic [32:0] alu_operand_b_o,
+ output logic [32:0] alu_operand_a_o,
+ output logic [32:0] alu_operand_b_o,
- input logic [33:0] imd_val_q_i[2],
- output logic [33:0] imd_val_d_o[2],
- output logic [1:0] imd_val_we_o,
+ input logic [33:0] imd_val_q_i[2],
+ output logic [33:0] imd_val_d_o[2],
+ output logic [1:0] imd_val_we_o,
- input logic multdiv_ready_id_i,
+ input logic multdiv_ready_id_i,
- output logic [31:0] multdiv_result_o,
- output logic valid_o
+ output logic [31:0] multdiv_result_o,
+ output logic valid_o
);
import ibex_pkg::*;
@@ -415,7 +415,7 @@
div_hold = 1'b0;
div_by_zero_d = div_by_zero_q;
- unique case(md_state_q)
+ unique case (md_state_q)
MD_IDLE: begin
if (operator_i == MD_OP_DIV) begin
// Check if the Denominator is 0
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
index a8d60b4..b184c5a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
@@ -13,33 +13,33 @@
module ibex_multdiv_slow
(
- input logic clk_i,
- input logic rst_ni,
- input logic mult_en_i, // dynamic enable signal, for FSM control
- input logic div_en_i, // dynamic enable signal, for FSM control
- input logic mult_sel_i, // static decoder output, for data muxes
- input logic div_sel_i, // static decoder output, for data muxes
- input ibex_pkg::md_op_e operator_i,
- input logic [1:0] signed_mode_i,
- input logic [31:0] op_a_i,
- input logic [31:0] op_b_i,
- input logic [33:0] alu_adder_ext_i,
- input logic [31:0] alu_adder_i,
- input logic equal_to_zero_i,
- input logic data_ind_timing_i,
+ input logic clk_i,
+ input logic rst_ni,
+ input logic mult_en_i, // dynamic enable signal, for FSM control
+ input logic div_en_i, // dynamic enable signal, for FSM control
+ input logic mult_sel_i, // static decoder output, for data muxes
+ input logic div_sel_i, // static decoder output, for data muxes
+ input ibex_pkg::md_op_e operator_i,
+ input logic [1:0] signed_mode_i,
+ input logic [31:0] op_a_i,
+ input logic [31:0] op_b_i,
+ input logic [33:0] alu_adder_ext_i,
+ input logic [31:0] alu_adder_i,
+ input logic equal_to_zero_i,
+ input logic data_ind_timing_i,
- output logic [32:0] alu_operand_a_o,
- output logic [32:0] alu_operand_b_o,
+ output logic [32:0] alu_operand_a_o,
+ output logic [32:0] alu_operand_b_o,
- input logic [33:0] imd_val_q_i[2],
- output logic [33:0] imd_val_d_o[2],
- output logic [1:0] imd_val_we_o,
+ input logic [33:0] imd_val_q_i[2],
+ output logic [33:0] imd_val_d_o[2],
+ output logic [1:0] imd_val_we_o,
- input logic multdiv_ready_id_i,
+ input logic multdiv_ready_id_i,
- output logic [31:0] multdiv_result_o,
+ output logic [31:0] multdiv_result_o,
- output logic valid_o
+ output logic valid_o
);
import ibex_pkg::*;
@@ -96,7 +96,7 @@
always_comb begin
alu_operand_a_o = accum_window_q;
- unique case(operator_i)
+ unique case (operator_i)
MD_OP_MULL: begin
alu_operand_b_o = op_a_bw_pp;
@@ -108,7 +108,7 @@
MD_OP_DIV,
MD_OP_REM: begin
- unique case(md_state_q)
+ unique case (md_state_q)
MD_IDLE: begin
// 0 - B = 0 iff B == 0
alu_operand_a_o = {32'h0 , 1'b1};
@@ -181,9 +181,9 @@
multdiv_hold = 1'b0;
div_by_zero_d = div_by_zero_q;
if (mult_sel_i || div_sel_i) begin
- unique case(md_state_q)
+ unique case (md_state_q)
MD_IDLE: begin
- unique case(operator_i)
+ unique case (operator_i)
MD_OP_MULL: begin
op_a_shift_d = op_a_ext << 1;
accum_window_d = { ~(op_a_ext[32] & op_b_i[0]),
@@ -233,15 +233,15 @@
MD_ABS_B: begin
// remainder
- accum_window_d = {32'h0,op_numerator_q[31]};
+ accum_window_d = {32'h0, op_numerator_q[31]};
// B abs value
- op_b_shift_d = sign_b ? {1'b0,alu_adder_i} : {1'b0,op_b_i};
+ op_b_shift_d = sign_b ? {1'b0, alu_adder_i} : {1'b0, op_b_i};
md_state_d = MD_COMP;
end
MD_COMP: begin
multdiv_count_d = multdiv_count_q - 5'h1;
- unique case(operator_i)
+ unique case (operator_i)
MD_OP_MULL: begin
accum_window_d = res_adder_l;
op_a_shift_d = op_a_shift_q << 1;
@@ -268,7 +268,7 @@
end
MD_LAST: begin
- unique case(operator_i)
+ unique case (operator_i)
MD_OP_MULL: begin
accum_window_d = res_adder_l;
@@ -301,7 +301,7 @@
MD_CHANGE_SIGN: begin
md_state_d = MD_FINISH;
- unique case(operator_i)
+ unique case (operator_i)
MD_OP_DIV:
accum_window_d = div_change_sign ? {1'b0,alu_adder_i} : accum_window_q;
MD_OP_REM:
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
index 6d60ed2..33d2245 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv
@@ -8,565 +8,595 @@
*/
package ibex_pkg;
-////////////////
-// IO Structs //
-////////////////
+ ////////////////
+ // IO Structs //
+ ////////////////
-typedef struct packed {
- logic [31:0] current_pc;
- logic [31:0] next_pc;
- logic [31:0] last_data_addr;
- logic [31:0] exception_addr;
-} crash_dump_t;
+ typedef struct packed {
+ logic [31:0] current_pc;
+ logic [31:0] next_pc;
+ logic [31:0] last_data_addr;
+ logic [31:0] exception_addr;
+ } crash_dump_t;
-typedef struct packed {
- logic dummy_instr_id;
- logic [4:0] raddr_a;
- logic [4:0] waddr_a;
- logic we_a;
- logic [4:0] raddr_b;
-} core2rf_t;
+ typedef struct packed {
+ logic dummy_instr_id;
+ logic [4:0] raddr_a;
+ logic [4:0] waddr_a;
+ logic we_a;
+ logic [4:0] raddr_b;
+ } core2rf_t;
-/////////////////////
-// Parameter Enums //
-/////////////////////
+ /////////////////////
+ // Parameter Enums //
+ /////////////////////
-typedef enum integer {
- RegFileFF = 0,
- RegFileFPGA = 1,
- RegFileLatch = 2
-} regfile_e;
+ typedef enum integer {
+ RegFileFF = 0,
+ RegFileFPGA = 1,
+ RegFileLatch = 2
+ } regfile_e;
-typedef enum integer {
- RV32MNone = 0,
- RV32MSlow = 1,
- RV32MFast = 2,
- RV32MSingleCycle = 3
-} rv32m_e;
+ typedef enum integer {
+ RV32MNone = 0,
+ RV32MSlow = 1,
+ RV32MFast = 2,
+ RV32MSingleCycle = 3
+ } rv32m_e;
-typedef enum integer {
- RV32BNone = 0,
- RV32BBalanced = 1,
- RV32BFull = 2
-} rv32b_e;
+ typedef enum integer {
+ RV32BNone = 0,
+ RV32BBalanced = 1,
+ RV32BFull = 2
+ } rv32b_e;
-/////////////
-// Opcodes //
-/////////////
+ /////////////
+ // Opcodes //
+ /////////////
-typedef enum logic [6:0] {
- OPCODE_LOAD = 7'h03,
- OPCODE_MISC_MEM = 7'h0f,
- OPCODE_OP_IMM = 7'h13,
- OPCODE_AUIPC = 7'h17,
- OPCODE_STORE = 7'h23,
- OPCODE_OP = 7'h33,
- OPCODE_LUI = 7'h37,
- OPCODE_BRANCH = 7'h63,
- OPCODE_JALR = 7'h67,
- OPCODE_JAL = 7'h6f,
- OPCODE_SYSTEM = 7'h73
-} opcode_e;
+ typedef enum logic [6:0] {
+ OPCODE_LOAD = 7'h03,
+ OPCODE_MISC_MEM = 7'h0f,
+ OPCODE_OP_IMM = 7'h13,
+ OPCODE_AUIPC = 7'h17,
+ OPCODE_STORE = 7'h23,
+ OPCODE_OP = 7'h33,
+ OPCODE_LUI = 7'h37,
+ OPCODE_BRANCH = 7'h63,
+ OPCODE_JALR = 7'h67,
+ OPCODE_JAL = 7'h6f,
+ OPCODE_SYSTEM = 7'h73
+ } opcode_e;
-////////////////////
-// ALU operations //
-////////////////////
+ ////////////////////
+ // ALU operations //
+ ////////////////////
-typedef enum logic [5:0] {
- // Arithmetics
- ALU_ADD,
- ALU_SUB,
+ typedef enum logic [6:0] {
+ // Arithmetics
+ ALU_ADD,
+ ALU_SUB,
- // Logics
- ALU_XOR,
- ALU_OR,
- ALU_AND,
- // RV32B
- ALU_XNOR,
- ALU_ORN,
- ALU_ANDN,
+ // Logics
+ ALU_XOR,
+ ALU_OR,
+ ALU_AND,
+ // RV32B
+ ALU_XNOR,
+ ALU_ORN,
+ ALU_ANDN,
- // Shifts
- ALU_SRA,
- ALU_SRL,
- ALU_SLL,
- // RV32B
- ALU_SRO,
- ALU_SLO,
- ALU_ROR,
- ALU_ROL,
- ALU_GREV,
- ALU_GORC,
- ALU_SHFL,
- ALU_UNSHFL,
+ // Shifts
+ ALU_SRA,
+ ALU_SRL,
+ ALU_SLL,
+ // RV32B
+ ALU_SRO,
+ ALU_SLO,
+ ALU_ROR,
+ ALU_ROL,
+ ALU_GREV,
+ ALU_GORC,
+ ALU_SHFL,
+ ALU_UNSHFL,
+ ALU_XPERM_N,
+ ALU_XPERM_B,
+ ALU_XPERM_H,
- // Comparisons
- ALU_LT,
- ALU_LTU,
- ALU_GE,
- ALU_GEU,
- ALU_EQ,
- ALU_NE,
- // RV32B
- ALU_MIN,
- ALU_MINU,
- ALU_MAX,
- ALU_MAXU,
+ // Address Calculations
+ // RV32B
+ ALU_SH1ADD,
+ ALU_SH2ADD,
+ ALU_SH3ADD,
- // Pack
- // RV32B
- ALU_PACK,
- ALU_PACKU,
- ALU_PACKH,
+ // Comparisons
+ ALU_LT,
+ ALU_LTU,
+ ALU_GE,
+ ALU_GEU,
+ ALU_EQ,
+ ALU_NE,
+ // RV32B
+ ALU_MIN,
+ ALU_MINU,
+ ALU_MAX,
+ ALU_MAXU,
- // Sign-Extend
- // RV32B
- ALU_SEXTB,
- ALU_SEXTH,
+ // Pack
+ // RV32B
+ ALU_PACK,
+ ALU_PACKU,
+ ALU_PACKH,
- // Bitcounting
- // RV32B
- ALU_CLZ,
- ALU_CTZ,
- ALU_PCNT,
+ // Sign-Extend
+ // RV32B
+ ALU_SEXTB,
+ ALU_SEXTH,
- // Set lower than
- ALU_SLT,
- ALU_SLTU,
+ // Bitcounting
+ // RV32B
+ ALU_CLZ,
+ ALU_CTZ,
+ ALU_CPOP,
- // Ternary Bitmanip Operations
- // RV32B
- ALU_CMOV,
- ALU_CMIX,
- ALU_FSL,
- ALU_FSR,
+ // Set lower than
+ ALU_SLT,
+ ALU_SLTU,
- // Single-Bit Operations
- // RV32B
- ALU_SBSET,
- ALU_SBCLR,
- ALU_SBINV,
- ALU_SBEXT,
+ // Ternary Bitmanip Operations
+ // RV32B
+ ALU_CMOV,
+ ALU_CMIX,
+ ALU_FSL,
+ ALU_FSR,
- // Bit Extract / Deposit
- // RV32B
- ALU_BEXT,
- ALU_BDEP,
+ // Single-Bit Operations
+ // RV32B
+ ALU_BSET,
+ ALU_BCLR,
+ ALU_BINV,
+ ALU_BEXT,
- // Bit Field Place
- // RV32B
- ALU_BFP,
+ // Bit Compress / Decompress
+ // RV32B
+ ALU_BCOMPRESS,
+ ALU_BDECOMPRESS,
- // Carry-less Multiply
- // RV32B
- ALU_CLMUL,
- ALU_CLMULR,
- ALU_CLMULH,
+ // Bit Field Place
+ // RV32B
+ ALU_BFP,
- // Cyclic Redundancy Check
- ALU_CRC32_B,
- ALU_CRC32C_B,
- ALU_CRC32_H,
- ALU_CRC32C_H,
- ALU_CRC32_W,
- ALU_CRC32C_W
-} alu_op_e;
+ // Carry-less Multiply
+ // RV32B
+ ALU_CLMUL,
+ ALU_CLMULR,
+ ALU_CLMULH,
-typedef enum logic [1:0] {
- // Multiplier/divider
- MD_OP_MULL,
- MD_OP_MULH,
- MD_OP_DIV,
- MD_OP_REM
-} md_op_e;
+ // Cyclic Redundancy Check
+ ALU_CRC32_B,
+ ALU_CRC32C_B,
+ ALU_CRC32_H,
+ ALU_CRC32C_H,
+ ALU_CRC32_W,
+ ALU_CRC32C_W
+ } alu_op_e;
+ typedef enum logic [1:0] {
+ // Multiplier/divider
+ MD_OP_MULL,
+ MD_OP_MULH,
+ MD_OP_DIV,
+ MD_OP_REM
+ } md_op_e;
-//////////////////////////////////
-// Control and status registers //
-//////////////////////////////////
-// CSR operations
-typedef enum logic [1:0] {
- CSR_OP_READ,
- CSR_OP_WRITE,
- CSR_OP_SET,
- CSR_OP_CLEAR
-} csr_op_e;
+ //////////////////////////////////
+ // Control and status registers //
+ //////////////////////////////////
-// Privileged mode
-typedef enum logic[1:0] {
- PRIV_LVL_M = 2'b11,
- PRIV_LVL_H = 2'b10,
- PRIV_LVL_S = 2'b01,
- PRIV_LVL_U = 2'b00
-} priv_lvl_e;
+ // CSR operations
+ typedef enum logic [1:0] {
+ CSR_OP_READ,
+ CSR_OP_WRITE,
+ CSR_OP_SET,
+ CSR_OP_CLEAR
+ } csr_op_e;
-// Constants for the dcsr.xdebugver fields
-typedef enum logic[3:0] {
- XDEBUGVER_NO = 4'd0, // no external debug support
- XDEBUGVER_STD = 4'd4, // external debug according to RISC-V debug spec
- XDEBUGVER_NONSTD = 4'd15 // debug not conforming to RISC-V debug spec
-} x_debug_ver_e;
+ // Privileged mode
+ typedef enum logic[1:0] {
+ PRIV_LVL_M = 2'b11,
+ PRIV_LVL_H = 2'b10,
+ PRIV_LVL_S = 2'b01,
+ PRIV_LVL_U = 2'b00
+ } priv_lvl_e;
-//////////////
-// WB stage //
-//////////////
+ // Constants for the dcsr.xdebugver fields
+ typedef enum logic[3:0] {
+ XDEBUGVER_NO = 4'd0, // no external debug support
+ XDEBUGVER_STD = 4'd4, // external debug according to RISC-V debug spec
+ XDEBUGVER_NONSTD = 4'd15 // debug not conforming to RISC-V debug spec
+ } x_debug_ver_e;
-// Type of instruction present in writeback stage
-typedef enum logic[1:0] {
- WB_INSTR_LOAD, // Instruction is awaiting load data
- WB_INSTR_STORE, // Instruction is awaiting store response
- WB_INSTR_OTHER // Instruction doesn't fit into above categories
-} wb_instr_type_e;
+ //////////////
+ // WB stage //
+ //////////////
-//////////////
-// ID stage //
-//////////////
+ // Type of instruction present in writeback stage
+ typedef enum logic[1:0] {
+ WB_INSTR_LOAD, // Instruction is awaiting load data
+ WB_INSTR_STORE, // Instruction is awaiting store response
+ WB_INSTR_OTHER // Instruction doesn't fit into above categories
+ } wb_instr_type_e;
-// Operand a selection
-typedef enum logic[1:0] {
- OP_A_REG_A,
- OP_A_FWD,
- OP_A_CURRPC,
- OP_A_IMM
-} op_a_sel_e;
+ //////////////
+ // ID stage //
+ //////////////
-// Immediate a selection
-typedef enum logic {
- IMM_A_Z,
- IMM_A_ZERO
-} imm_a_sel_e;
+ // Operand a selection
+ typedef enum logic[1:0] {
+ OP_A_REG_A,
+ OP_A_FWD,
+ OP_A_CURRPC,
+ OP_A_IMM
+ } op_a_sel_e;
-// Operand b selection
-typedef enum logic {
- OP_B_REG_B,
- OP_B_IMM
-} op_b_sel_e;
+ // Immediate a selection
+ typedef enum logic {
+ IMM_A_Z,
+ IMM_A_ZERO
+ } imm_a_sel_e;
-// Immediate b selection
-typedef enum logic [2:0] {
- IMM_B_I,
- IMM_B_S,
- IMM_B_B,
- IMM_B_U,
- IMM_B_J,
- IMM_B_INCR_PC,
- IMM_B_INCR_ADDR
-} imm_b_sel_e;
+ // Operand b selection
+ typedef enum logic {
+ OP_B_REG_B,
+ OP_B_IMM
+ } op_b_sel_e;
-// Regfile write data selection
-typedef enum logic {
- RF_WD_EX,
- RF_WD_CSR
-} rf_wd_sel_e;
+ // Immediate b selection
+ typedef enum logic [2:0] {
+ IMM_B_I,
+ IMM_B_S,
+ IMM_B_B,
+ IMM_B_U,
+ IMM_B_J,
+ IMM_B_INCR_PC,
+ IMM_B_INCR_ADDR
+ } imm_b_sel_e;
-//////////////
-// IF stage //
-//////////////
+ // Regfile write data selection
+ typedef enum logic {
+ RF_WD_EX,
+ RF_WD_CSR
+ } rf_wd_sel_e;
-// PC mux selection
-typedef enum logic [2:0] {
- PC_BOOT,
- PC_JUMP,
- PC_EXC,
- PC_ERET,
- PC_DRET,
- PC_BP
-} pc_sel_e;
+ //////////////
+ // IF stage //
+ //////////////
-// Exception PC mux selection
-typedef enum logic [1:0] {
- EXC_PC_EXC,
- EXC_PC_IRQ,
- EXC_PC_DBD,
- EXC_PC_DBG_EXC // Exception while in debug mode
-} exc_pc_sel_e;
+ // PC mux selection
+ typedef enum logic [2:0] {
+ PC_BOOT,
+ PC_JUMP,
+ PC_EXC,
+ PC_ERET,
+ PC_DRET,
+ PC_BP
+ } pc_sel_e;
+
+ // Exception PC mux selection
+ typedef enum logic [1:0] {
+ EXC_PC_EXC,
+ EXC_PC_IRQ,
+ EXC_PC_DBD,
+ EXC_PC_DBG_EXC // Exception while in debug mode
+ } exc_pc_sel_e;
+
+ // Interrupt requests
+ typedef struct packed {
+ logic irq_software;
+ logic irq_timer;
+ logic irq_external;
+ logic [14:0] irq_fast; // 15 fast interrupts,
+ // one interrupt is reserved for NMI (not visible through mip/mie)
+ } irqs_t;
+
+ // Exception cause
+ typedef enum logic [5:0] {
+ EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03},
+ EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07},
+ EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11},
+ // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16},
+ // EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30},
+ EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15
+ EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00},
+ EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01},
+ EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd02},
+ EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03},
+ EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05},
+ EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
+ EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08},
+ EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11}
+ } exc_cause_e;
+
+ // Debug cause
+ typedef enum logic [2:0] {
+ DBG_CAUSE_NONE = 3'h0,
+ DBG_CAUSE_EBREAK = 3'h1,
+ DBG_CAUSE_TRIGGER = 3'h2,
+ DBG_CAUSE_HALTREQ = 3'h3,
+ DBG_CAUSE_STEP = 3'h4
+ } dbg_cause_e;
-// Interrupt requests
-typedef struct packed {
- logic irq_software;
- logic irq_timer;
- logic irq_external;
- logic [14:0] irq_fast; // 15 fast interrupts,
- // one interrupt is reserved for NMI (not visible through mip/mie)
-} irqs_t;
+ // ICache constants
+ parameter int unsigned ADDR_W = 32;
+ parameter int unsigned BUS_SIZE = 32;
+ parameter int unsigned BUS_BYTES = BUS_SIZE/8;
+ parameter int unsigned BUS_W = $clog2(BUS_BYTES);
+ parameter int unsigned IC_SIZE_BYTES = 4096;
+ parameter int unsigned IC_NUM_WAYS = 2;
+ parameter int unsigned IC_LINE_SIZE = 64;
+ parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8;
+ parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES);
+ parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
+ parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES;
+ parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
+ parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES);
+ parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1;
+ parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
+ parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
-// Exception cause
-typedef enum logic [5:0] {
- EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03},
- EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07},
- EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11},
- // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16},
- // EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30},
- EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15
- EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00},
- EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01},
- EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd02},
- EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03},
- EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05},
- EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
- EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08},
- EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11}
-} exc_cause_e;
+ // PMP constants
+ parameter int unsigned PMP_MAX_REGIONS = 16;
+ parameter int unsigned PMP_CFG_W = 8;
-// Debug cause
-typedef enum logic [2:0] {
- DBG_CAUSE_NONE = 3'h0,
- DBG_CAUSE_EBREAK = 3'h1,
- DBG_CAUSE_TRIGGER = 3'h2,
- DBG_CAUSE_HALTREQ = 3'h3,
- DBG_CAUSE_STEP = 3'h4
-} dbg_cause_e;
+ // PMP acces type
+ parameter int unsigned PMP_I = 0;
+ parameter int unsigned PMP_I2 = 1;
+ parameter int unsigned PMP_D = 2;
-// ICache constants
-parameter int unsigned ADDR_W = 32;
-parameter int unsigned BUS_SIZE = 32;
-parameter int unsigned BUS_BYTES = BUS_SIZE/8;
-parameter int unsigned BUS_W = $clog2(BUS_BYTES);
-parameter int unsigned IC_SIZE_BYTES = 4096;
-parameter int unsigned IC_NUM_WAYS = 2;
-parameter int unsigned IC_LINE_SIZE = 64;
-parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8;
-parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES);
-parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
-parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES;
-parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
-parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES);
-parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1;
-parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
-parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
+ typedef enum logic [1:0] {
+ PMP_ACC_EXEC = 2'b00,
+ PMP_ACC_WRITE = 2'b01,
+ PMP_ACC_READ = 2'b10
+ } pmp_req_e;
-// PMP constants
-parameter int unsigned PMP_MAX_REGIONS = 16;
-parameter int unsigned PMP_CFG_W = 8;
+ // PMP cfg structures
+ typedef enum logic [1:0] {
+ PMP_MODE_OFF = 2'b00,
+ PMP_MODE_TOR = 2'b01,
+ PMP_MODE_NA4 = 2'b10,
+ PMP_MODE_NAPOT = 2'b11
+ } pmp_cfg_mode_e;
-// PMP acces type
-parameter int unsigned PMP_I = 0;
-parameter int unsigned PMP_D = 1;
+ typedef struct packed {
+ logic lock;
+ pmp_cfg_mode_e mode;
+ logic exec;
+ logic write;
+ logic read;
+ } pmp_cfg_t;
-typedef enum logic [1:0] {
- PMP_ACC_EXEC = 2'b00,
- PMP_ACC_WRITE = 2'b01,
- PMP_ACC_READ = 2'b10
-} pmp_req_e;
+ // Machine Security Configuration (ePMP)
+ typedef struct packed {
+ logic rlb; // Rule Locking Bypass
+ logic mmwp; // Machine Mode Whitelist Policy
+ logic mml; // Machine Mode Lockdown
+ } pmp_mseccfg_t;
-// PMP cfg structures
-typedef enum logic [1:0] {
- PMP_MODE_OFF = 2'b00,
- PMP_MODE_TOR = 2'b01,
- PMP_MODE_NA4 = 2'b10,
- PMP_MODE_NAPOT = 2'b11
-} pmp_cfg_mode_e;
+ // CSRs
+ typedef enum logic[11:0] {
+ // Machine information
+ CSR_MVENDORID = 12'hF11,
+ CSR_MARCHID = 12'hF12,
+ CSR_MIMPID = 12'hF13,
+ CSR_MHARTID = 12'hF14,
-typedef struct packed {
- logic lock;
- pmp_cfg_mode_e mode;
- logic exec;
- logic write;
- logic read;
-} pmp_cfg_t;
+ // Machine trap setup
+ CSR_MSTATUS = 12'h300,
+ CSR_MISA = 12'h301,
+ CSR_MIE = 12'h304,
+ CSR_MTVEC = 12'h305,
+ CSR_MCOUNTEREN= 12'h306,
-// Machine Security Configuration (ePMP)
-typedef struct packed {
- logic rlb; // Rule Locking Bypass
- logic mmwp; // Machine Mode Whitelist Policy
- logic mml; // Machine Mode Lockdown
-} pmp_mseccfg_t;
+ // Machine trap handling
+ CSR_MSCRATCH = 12'h340,
+ CSR_MEPC = 12'h341,
+ CSR_MCAUSE = 12'h342,
+ CSR_MTVAL = 12'h343,
+ CSR_MIP = 12'h344,
-// CSRs
-typedef enum logic[11:0] {
- // Machine information
- CSR_MHARTID = 12'hF14,
+ // Physical memory protection
+ CSR_PMPCFG0 = 12'h3A0,
+ CSR_PMPCFG1 = 12'h3A1,
+ CSR_PMPCFG2 = 12'h3A2,
+ CSR_PMPCFG3 = 12'h3A3,
+ CSR_PMPADDR0 = 12'h3B0,
+ CSR_PMPADDR1 = 12'h3B1,
+ CSR_PMPADDR2 = 12'h3B2,
+ CSR_PMPADDR3 = 12'h3B3,
+ CSR_PMPADDR4 = 12'h3B4,
+ CSR_PMPADDR5 = 12'h3B5,
+ CSR_PMPADDR6 = 12'h3B6,
+ CSR_PMPADDR7 = 12'h3B7,
+ CSR_PMPADDR8 = 12'h3B8,
+ CSR_PMPADDR9 = 12'h3B9,
+ CSR_PMPADDR10 = 12'h3BA,
+ CSR_PMPADDR11 = 12'h3BB,
+ CSR_PMPADDR12 = 12'h3BC,
+ CSR_PMPADDR13 = 12'h3BD,
+ CSR_PMPADDR14 = 12'h3BE,
+ CSR_PMPADDR15 = 12'h3BF,
- // Machine trap setup
- CSR_MSTATUS = 12'h300,
- CSR_MISA = 12'h301,
- CSR_MIE = 12'h304,
- CSR_MTVEC = 12'h305,
- CSR_MCOUNTEREN= 12'h306,
+ // ePMP control
+ CSR_MSECCFG = 12'h747,
+ CSR_MSECCFGH = 12'h757,
- // Machine trap handling
- CSR_MSCRATCH = 12'h340,
- CSR_MEPC = 12'h341,
- CSR_MCAUSE = 12'h342,
- CSR_MTVAL = 12'h343,
- CSR_MIP = 12'h344,
+ // Debug trigger
+ CSR_TSELECT = 12'h7A0,
+ CSR_TDATA1 = 12'h7A1,
+ CSR_TDATA2 = 12'h7A2,
+ CSR_TDATA3 = 12'h7A3,
+ CSR_MCONTEXT = 12'h7A8,
+ CSR_SCONTEXT = 12'h7AA,
- // Physical memory protection
- CSR_PMPCFG0 = 12'h3A0,
- CSR_PMPCFG1 = 12'h3A1,
- CSR_PMPCFG2 = 12'h3A2,
- CSR_PMPCFG3 = 12'h3A3,
- CSR_PMPADDR0 = 12'h3B0,
- CSR_PMPADDR1 = 12'h3B1,
- CSR_PMPADDR2 = 12'h3B2,
- CSR_PMPADDR3 = 12'h3B3,
- CSR_PMPADDR4 = 12'h3B4,
- CSR_PMPADDR5 = 12'h3B5,
- CSR_PMPADDR6 = 12'h3B6,
- CSR_PMPADDR7 = 12'h3B7,
- CSR_PMPADDR8 = 12'h3B8,
- CSR_PMPADDR9 = 12'h3B9,
- CSR_PMPADDR10 = 12'h3BA,
- CSR_PMPADDR11 = 12'h3BB,
- CSR_PMPADDR12 = 12'h3BC,
- CSR_PMPADDR13 = 12'h3BD,
- CSR_PMPADDR14 = 12'h3BE,
- CSR_PMPADDR15 = 12'h3BF,
+ // Debug/trace
+ CSR_DCSR = 12'h7b0,
+ CSR_DPC = 12'h7b1,
- // ePMP control
- CSR_MSECCFG = 12'h747,
- CSR_MSECCFGH = 12'h757,
+ // Debug
+ CSR_DSCRATCH0 = 12'h7b2, // optional
+ CSR_DSCRATCH1 = 12'h7b3, // optional
- // Debug trigger
- CSR_TSELECT = 12'h7A0,
- CSR_TDATA1 = 12'h7A1,
- CSR_TDATA2 = 12'h7A2,
- CSR_TDATA3 = 12'h7A3,
- CSR_MCONTEXT = 12'h7A8,
- CSR_SCONTEXT = 12'h7AA,
+ // Machine Counter/Timers
+ CSR_MCOUNTINHIBIT = 12'h320,
+ CSR_MHPMEVENT3 = 12'h323,
+ CSR_MHPMEVENT4 = 12'h324,
+ CSR_MHPMEVENT5 = 12'h325,
+ CSR_MHPMEVENT6 = 12'h326,
+ CSR_MHPMEVENT7 = 12'h327,
+ CSR_MHPMEVENT8 = 12'h328,
+ CSR_MHPMEVENT9 = 12'h329,
+ CSR_MHPMEVENT10 = 12'h32A,
+ CSR_MHPMEVENT11 = 12'h32B,
+ CSR_MHPMEVENT12 = 12'h32C,
+ CSR_MHPMEVENT13 = 12'h32D,
+ CSR_MHPMEVENT14 = 12'h32E,
+ CSR_MHPMEVENT15 = 12'h32F,
+ CSR_MHPMEVENT16 = 12'h330,
+ CSR_MHPMEVENT17 = 12'h331,
+ CSR_MHPMEVENT18 = 12'h332,
+ CSR_MHPMEVENT19 = 12'h333,
+ CSR_MHPMEVENT20 = 12'h334,
+ CSR_MHPMEVENT21 = 12'h335,
+ CSR_MHPMEVENT22 = 12'h336,
+ CSR_MHPMEVENT23 = 12'h337,
+ CSR_MHPMEVENT24 = 12'h338,
+ CSR_MHPMEVENT25 = 12'h339,
+ CSR_MHPMEVENT26 = 12'h33A,
+ CSR_MHPMEVENT27 = 12'h33B,
+ CSR_MHPMEVENT28 = 12'h33C,
+ CSR_MHPMEVENT29 = 12'h33D,
+ CSR_MHPMEVENT30 = 12'h33E,
+ CSR_MHPMEVENT31 = 12'h33F,
+ CSR_MCYCLE = 12'hB00,
+ CSR_MINSTRET = 12'hB02,
+ CSR_MHPMCOUNTER3 = 12'hB03,
+ CSR_MHPMCOUNTER4 = 12'hB04,
+ CSR_MHPMCOUNTER5 = 12'hB05,
+ CSR_MHPMCOUNTER6 = 12'hB06,
+ CSR_MHPMCOUNTER7 = 12'hB07,
+ CSR_MHPMCOUNTER8 = 12'hB08,
+ CSR_MHPMCOUNTER9 = 12'hB09,
+ CSR_MHPMCOUNTER10 = 12'hB0A,
+ CSR_MHPMCOUNTER11 = 12'hB0B,
+ CSR_MHPMCOUNTER12 = 12'hB0C,
+ CSR_MHPMCOUNTER13 = 12'hB0D,
+ CSR_MHPMCOUNTER14 = 12'hB0E,
+ CSR_MHPMCOUNTER15 = 12'hB0F,
+ CSR_MHPMCOUNTER16 = 12'hB10,
+ CSR_MHPMCOUNTER17 = 12'hB11,
+ CSR_MHPMCOUNTER18 = 12'hB12,
+ CSR_MHPMCOUNTER19 = 12'hB13,
+ CSR_MHPMCOUNTER20 = 12'hB14,
+ CSR_MHPMCOUNTER21 = 12'hB15,
+ CSR_MHPMCOUNTER22 = 12'hB16,
+ CSR_MHPMCOUNTER23 = 12'hB17,
+ CSR_MHPMCOUNTER24 = 12'hB18,
+ CSR_MHPMCOUNTER25 = 12'hB19,
+ CSR_MHPMCOUNTER26 = 12'hB1A,
+ CSR_MHPMCOUNTER27 = 12'hB1B,
+ CSR_MHPMCOUNTER28 = 12'hB1C,
+ CSR_MHPMCOUNTER29 = 12'hB1D,
+ CSR_MHPMCOUNTER30 = 12'hB1E,
+ CSR_MHPMCOUNTER31 = 12'hB1F,
+ CSR_MCYCLEH = 12'hB80,
+ CSR_MINSTRETH = 12'hB82,
+ CSR_MHPMCOUNTER3H = 12'hB83,
+ CSR_MHPMCOUNTER4H = 12'hB84,
+ CSR_MHPMCOUNTER5H = 12'hB85,
+ CSR_MHPMCOUNTER6H = 12'hB86,
+ CSR_MHPMCOUNTER7H = 12'hB87,
+ CSR_MHPMCOUNTER8H = 12'hB88,
+ CSR_MHPMCOUNTER9H = 12'hB89,
+ CSR_MHPMCOUNTER10H = 12'hB8A,
+ CSR_MHPMCOUNTER11H = 12'hB8B,
+ CSR_MHPMCOUNTER12H = 12'hB8C,
+ CSR_MHPMCOUNTER13H = 12'hB8D,
+ CSR_MHPMCOUNTER14H = 12'hB8E,
+ CSR_MHPMCOUNTER15H = 12'hB8F,
+ CSR_MHPMCOUNTER16H = 12'hB90,
+ CSR_MHPMCOUNTER17H = 12'hB91,
+ CSR_MHPMCOUNTER18H = 12'hB92,
+ CSR_MHPMCOUNTER19H = 12'hB93,
+ CSR_MHPMCOUNTER20H = 12'hB94,
+ CSR_MHPMCOUNTER21H = 12'hB95,
+ CSR_MHPMCOUNTER22H = 12'hB96,
+ CSR_MHPMCOUNTER23H = 12'hB97,
+ CSR_MHPMCOUNTER24H = 12'hB98,
+ CSR_MHPMCOUNTER25H = 12'hB99,
+ CSR_MHPMCOUNTER26H = 12'hB9A,
+ CSR_MHPMCOUNTER27H = 12'hB9B,
+ CSR_MHPMCOUNTER28H = 12'hB9C,
+ CSR_MHPMCOUNTER29H = 12'hB9D,
+ CSR_MHPMCOUNTER30H = 12'hB9E,
+ CSR_MHPMCOUNTER31H = 12'hB9F,
+ CSR_CPUCTRL = 12'h7C0,
+ CSR_SECURESEED = 12'h7C1
+ } csr_num_e;
- // Debug/trace
- CSR_DCSR = 12'h7b0,
- CSR_DPC = 12'h7b1,
+ // CSR pmp-related offsets
+ parameter logic [11:0] CSR_OFF_PMP_CFG = 12'h3A0; // pmp_cfg @ 12'h3a0 - 12'h3a3
+ parameter logic [11:0] CSR_OFF_PMP_ADDR = 12'h3B0; // pmp_addr @ 12'h3b0 - 12'h3bf
- // Debug
- CSR_DSCRATCH0 = 12'h7b2, // optional
- CSR_DSCRATCH1 = 12'h7b3, // optional
+ // CSR status bits
+ parameter int unsigned CSR_MSTATUS_MIE_BIT = 3;
+ parameter int unsigned CSR_MSTATUS_MPIE_BIT = 7;
+ parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW = 11;
+ parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12;
+ parameter int unsigned CSR_MSTATUS_MPRV_BIT = 17;
+ parameter int unsigned CSR_MSTATUS_TW_BIT = 21;
- // Machine Counter/Timers
- CSR_MCOUNTINHIBIT = 12'h320,
- CSR_MHPMEVENT3 = 12'h323,
- CSR_MHPMEVENT4 = 12'h324,
- CSR_MHPMEVENT5 = 12'h325,
- CSR_MHPMEVENT6 = 12'h326,
- CSR_MHPMEVENT7 = 12'h327,
- CSR_MHPMEVENT8 = 12'h328,
- CSR_MHPMEVENT9 = 12'h329,
- CSR_MHPMEVENT10 = 12'h32A,
- CSR_MHPMEVENT11 = 12'h32B,
- CSR_MHPMEVENT12 = 12'h32C,
- CSR_MHPMEVENT13 = 12'h32D,
- CSR_MHPMEVENT14 = 12'h32E,
- CSR_MHPMEVENT15 = 12'h32F,
- CSR_MHPMEVENT16 = 12'h330,
- CSR_MHPMEVENT17 = 12'h331,
- CSR_MHPMEVENT18 = 12'h332,
- CSR_MHPMEVENT19 = 12'h333,
- CSR_MHPMEVENT20 = 12'h334,
- CSR_MHPMEVENT21 = 12'h335,
- CSR_MHPMEVENT22 = 12'h336,
- CSR_MHPMEVENT23 = 12'h337,
- CSR_MHPMEVENT24 = 12'h338,
- CSR_MHPMEVENT25 = 12'h339,
- CSR_MHPMEVENT26 = 12'h33A,
- CSR_MHPMEVENT27 = 12'h33B,
- CSR_MHPMEVENT28 = 12'h33C,
- CSR_MHPMEVENT29 = 12'h33D,
- CSR_MHPMEVENT30 = 12'h33E,
- CSR_MHPMEVENT31 = 12'h33F,
- CSR_MCYCLE = 12'hB00,
- CSR_MINSTRET = 12'hB02,
- CSR_MHPMCOUNTER3 = 12'hB03,
- CSR_MHPMCOUNTER4 = 12'hB04,
- CSR_MHPMCOUNTER5 = 12'hB05,
- CSR_MHPMCOUNTER6 = 12'hB06,
- CSR_MHPMCOUNTER7 = 12'hB07,
- CSR_MHPMCOUNTER8 = 12'hB08,
- CSR_MHPMCOUNTER9 = 12'hB09,
- CSR_MHPMCOUNTER10 = 12'hB0A,
- CSR_MHPMCOUNTER11 = 12'hB0B,
- CSR_MHPMCOUNTER12 = 12'hB0C,
- CSR_MHPMCOUNTER13 = 12'hB0D,
- CSR_MHPMCOUNTER14 = 12'hB0E,
- CSR_MHPMCOUNTER15 = 12'hB0F,
- CSR_MHPMCOUNTER16 = 12'hB10,
- CSR_MHPMCOUNTER17 = 12'hB11,
- CSR_MHPMCOUNTER18 = 12'hB12,
- CSR_MHPMCOUNTER19 = 12'hB13,
- CSR_MHPMCOUNTER20 = 12'hB14,
- CSR_MHPMCOUNTER21 = 12'hB15,
- CSR_MHPMCOUNTER22 = 12'hB16,
- CSR_MHPMCOUNTER23 = 12'hB17,
- CSR_MHPMCOUNTER24 = 12'hB18,
- CSR_MHPMCOUNTER25 = 12'hB19,
- CSR_MHPMCOUNTER26 = 12'hB1A,
- CSR_MHPMCOUNTER27 = 12'hB1B,
- CSR_MHPMCOUNTER28 = 12'hB1C,
- CSR_MHPMCOUNTER29 = 12'hB1D,
- CSR_MHPMCOUNTER30 = 12'hB1E,
- CSR_MHPMCOUNTER31 = 12'hB1F,
- CSR_MCYCLEH = 12'hB80,
- CSR_MINSTRETH = 12'hB82,
- CSR_MHPMCOUNTER3H = 12'hB83,
- CSR_MHPMCOUNTER4H = 12'hB84,
- CSR_MHPMCOUNTER5H = 12'hB85,
- CSR_MHPMCOUNTER6H = 12'hB86,
- CSR_MHPMCOUNTER7H = 12'hB87,
- CSR_MHPMCOUNTER8H = 12'hB88,
- CSR_MHPMCOUNTER9H = 12'hB89,
- CSR_MHPMCOUNTER10H = 12'hB8A,
- CSR_MHPMCOUNTER11H = 12'hB8B,
- CSR_MHPMCOUNTER12H = 12'hB8C,
- CSR_MHPMCOUNTER13H = 12'hB8D,
- CSR_MHPMCOUNTER14H = 12'hB8E,
- CSR_MHPMCOUNTER15H = 12'hB8F,
- CSR_MHPMCOUNTER16H = 12'hB90,
- CSR_MHPMCOUNTER17H = 12'hB91,
- CSR_MHPMCOUNTER18H = 12'hB92,
- CSR_MHPMCOUNTER19H = 12'hB93,
- CSR_MHPMCOUNTER20H = 12'hB94,
- CSR_MHPMCOUNTER21H = 12'hB95,
- CSR_MHPMCOUNTER22H = 12'hB96,
- CSR_MHPMCOUNTER23H = 12'hB97,
- CSR_MHPMCOUNTER24H = 12'hB98,
- CSR_MHPMCOUNTER25H = 12'hB99,
- CSR_MHPMCOUNTER26H = 12'hB9A,
- CSR_MHPMCOUNTER27H = 12'hB9B,
- CSR_MHPMCOUNTER28H = 12'hB9C,
- CSR_MHPMCOUNTER29H = 12'hB9D,
- CSR_MHPMCOUNTER30H = 12'hB9E,
- CSR_MHPMCOUNTER31H = 12'hB9F,
- CSR_CPUCTRL = 12'h7C0,
- CSR_SECURESEED = 12'h7C1
-} csr_num_e;
+ // CSR machine ISA
+ parameter logic [1:0] CSR_MISA_MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32
-// CSR pmp-related offsets
-parameter logic [11:0] CSR_OFF_PMP_CFG = 12'h3A0; // pmp_cfg @ 12'h3a0 - 12'h3a3
-parameter logic [11:0] CSR_OFF_PMP_ADDR = 12'h3B0; // pmp_addr @ 12'h3b0 - 12'h3bf
+ // CSR interrupt pending/enable bits
+ parameter int unsigned CSR_MSIX_BIT = 3;
+ parameter int unsigned CSR_MTIX_BIT = 7;
+ parameter int unsigned CSR_MEIX_BIT = 11;
+ parameter int unsigned CSR_MFIX_BIT_LOW = 16;
+ parameter int unsigned CSR_MFIX_BIT_HIGH = 30;
-// CSR status bits
-parameter int unsigned CSR_MSTATUS_MIE_BIT = 3;
-parameter int unsigned CSR_MSTATUS_MPIE_BIT = 7;
-parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW = 11;
-parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12;
-parameter int unsigned CSR_MSTATUS_MPRV_BIT = 17;
-parameter int unsigned CSR_MSTATUS_TW_BIT = 21;
+ // CSR Machine Security Configuration bits
+ parameter int unsigned CSR_MSECCFG_MML_BIT = 0;
+ parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1;
+ parameter int unsigned CSR_MSECCFG_RLB_BIT = 2;
-// CSR machine ISA
-parameter logic [1:0] CSR_MISA_MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32
+ // Vendor ID
+ // No JEDEC ID has been allocated to lowRISC so the value is 0 to indicate the field is not
+ // implemented
+ localparam logic [31:0] CSR_MVENDORID_VALUE = 32'b0;
-// CSR interrupt pending/enable bits
-parameter int unsigned CSR_MSIX_BIT = 3;
-parameter int unsigned CSR_MTIX_BIT = 7;
-parameter int unsigned CSR_MEIX_BIT = 11;
-parameter int unsigned CSR_MFIX_BIT_LOW = 16;
-parameter int unsigned CSR_MFIX_BIT_HIGH = 30;
+ // Architecture ID
+ // Top bit is unset to indicate an open source project. The lower bits are an ID allocated by the
+ // RISC-V Foundation. Note this is allocated specifically to Ibex, should significant changes be
+ // made a different architecture ID should be supplied.
+ localparam logic [31:0] CSR_MARCHID_VALUE = {1'b0, 31'd22};
-// CSR Machine Security Configuration bits
-parameter int unsigned CSR_MSECCFG_MML_BIT = 0;
-parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1;
-parameter int unsigned CSR_MSECCFG_RLB_BIT = 2;
+ // Implementation ID
+ // 0 indicates this field is not implemeted. Ibex implementors may wish to indicate an RTL/netlist
+ // version here using their own unique encoding (e.g. 32 bits of the git hash of the implemented
+ // commit).
+ localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0;
-// These LFSR parameters have been generated with
-// $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix ""
-parameter int LfsrWidth = 32;
-typedef logic [LfsrWidth-1:0] lfsr_seed_t;
-typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t;
-parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4;
-parameter lfsr_perm_t RndCnstLfsrPermDefault = {
- 160'h1e35ecba467fd1b12e958152c04fa43878a8daed
-};
+ // These LFSR parameters have been generated with
+ // $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix ""
+ parameter int LfsrWidth = 32;
+ typedef logic [LfsrWidth-1:0] lfsr_seed_t;
+ typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t;
+ parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4;
+ parameter lfsr_perm_t RndCnstLfsrPermDefault = {
+ 160'h1e35ecba467fd1b12e958152c04fa43878a8daed
+ };
endpackage
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
index 3d110f6..16e806a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_pmp.sv
@@ -3,28 +3,28 @@
// SPDX-License-Identifier: Apache-2.0
module ibex_pmp #(
- // Granularity of NAPOT access,
- // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc.
- parameter int unsigned PMPGranularity = 0,
- // Number of access channels (e.g. i-side + d-side)
- parameter int unsigned PMPNumChan = 2,
- // Number of implemented regions
- parameter int unsigned PMPNumRegions = 4
+ // Granularity of NAPOT access,
+ // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc.
+ parameter int unsigned PMPGranularity = 0,
+ // Number of access channels (e.g. i-side + d-side)
+ parameter int unsigned PMPNumChan = 2,
+ // Number of implemented regions
+ parameter int unsigned PMPNumRegions = 4
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- // Interface to CSRs
- input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions],
- input logic [33:0] csr_pmp_addr_i [PMPNumRegions],
- input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i,
+ // Interface to CSRs
+ input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions],
+ input logic [33:0] csr_pmp_addr_i [PMPNumRegions],
+ input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i,
- input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan],
- // Access checking channels
- input logic [33:0] pmp_req_addr_i [PMPNumChan],
- input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan],
- output logic pmp_req_err_o [PMPNumChan]
+ input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan],
+ // Access checking channels
+ input logic [33:0] pmp_req_addr_i [PMPNumChan],
+ input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan],
+ output logic pmp_req_err_o [PMPNumChan]
);
@@ -56,7 +56,7 @@
csr_pmp_addr_i[r];
end
// Address mask for NA matching
- for (genvar b = PMPGranularity+2; b < 34; b++) begin : g_bitmask
+ for (genvar b = PMPGranularity + 2; b < 34; b++) begin : g_bitmask
if (b == 2) begin : g_bit0
// Always mask bit 2 for NAPOT
assign region_addr_mask[r][b] = (csr_pmp_cfg_i[r].mode != PMP_MODE_NAPOT);
@@ -92,14 +92,14 @@
always_comb begin
region_match_all[c][r] = 1'b0;
unique case (csr_pmp_cfg_i[r].mode)
- PMP_MODE_OFF : region_match_all[c][r] = 1'b0;
- PMP_MODE_NA4 : region_match_all[c][r] = region_match_eq[c][r];
- PMP_MODE_NAPOT : region_match_all[c][r] = region_match_eq[c][r];
- PMP_MODE_TOR : begin
+ PMP_MODE_OFF: region_match_all[c][r] = 1'b0;
+ PMP_MODE_NA4: region_match_all[c][r] = region_match_eq[c][r];
+ PMP_MODE_NAPOT: region_match_all[c][r] = region_match_eq[c][r];
+ PMP_MODE_TOR: begin
region_match_all[c][r] = (region_match_eq[c][r] | region_match_gt[c][r]) &
region_match_lt[c][r];
end
- default : region_match_all[c][r] = 1'b0;
+ default: region_match_all[c][r] = 1'b0;
endcase
end
@@ -156,7 +156,7 @@
// PMP entries are statically prioritized, from 0 to N-1
// The lowest-numbered PMP entry which matches an address determines accessability
- for (int r = PMPNumRegions-1; r >= 0; r--) begin
+ for (int r = PMPNumRegions - 1; r >= 0; r--) begin
if (region_match_all[c][r]) begin
if (csr_pmp_mseccfg_i.mml) begin
// When MSECCFG.MML is set use MML specific permission check
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
index d2b0f17..5b834ce 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv
@@ -10,61 +10,52 @@
* paths to the instruction cache.
*/
module ibex_prefetch_buffer #(
- parameter bit BranchPredictor = 1'b0,
parameter bit ResetAll = 1'b0
) (
- input logic clk_i,
- input logic rst_ni,
+ input logic clk_i,
+ input logic rst_ni,
- input logic req_i,
+ input logic req_i,
- input logic branch_i,
- input logic branch_spec_i,
- input logic predicted_branch_i,
- input logic branch_mispredict_i,
- input logic [31:0] addr_i,
+ input logic branch_i,
+ input logic branch_mispredict_i,
+ input logic [31:0] mispredict_addr_i,
+ input logic [31:0] addr_i,
- input logic ready_i,
- output logic valid_o,
- output logic [31:0] rdata_o,
- output logic [31:0] addr_o,
- output logic err_o,
- output logic err_plus2_o,
+ input logic ready_i,
+ output logic valid_o,
+ output logic [31:0] rdata_o,
+ output logic [31:0] addr_o,
+ output logic err_o,
+ output logic err_plus2_o,
+ // goes to instruction memory / instruction cache
+ output logic instr_req_o,
+ input logic instr_gnt_i,
+ output logic [31:0] instr_addr_o,
+ input logic [31:0] instr_rdata_i,
+ input logic instr_err_i,
+ input logic instr_rvalid_i,
- // goes to instruction memory / instruction cache
- output logic instr_req_o,
- input logic instr_gnt_i,
- output logic [31:0] instr_addr_o,
- input logic [31:0] instr_rdata_i,
- input logic instr_err_i,
- input logic instr_pmp_err_i,
- input logic instr_rvalid_i,
-
- // Prefetch Buffer Status
- output logic busy_o
+ // Prefetch Buffer Status
+ output logic busy_o
);
localparam int unsigned NUM_REQS = 2;
- logic branch_suppress;
logic valid_new_req, valid_req;
logic valid_req_d, valid_req_q;
logic discard_req_d, discard_req_q;
- logic gnt_or_pmp_err, rvalid_or_pmp_err;
logic [NUM_REQS-1:0] rdata_outstanding_n, rdata_outstanding_s, rdata_outstanding_q;
logic [NUM_REQS-1:0] branch_discard_n, branch_discard_s, branch_discard_q;
- logic [NUM_REQS-1:0] rdata_pmp_err_n, rdata_pmp_err_s, rdata_pmp_err_q;
logic [NUM_REQS-1:0] rdata_outstanding_rev;
logic [31:0] stored_addr_d, stored_addr_q;
logic stored_addr_en;
logic [31:0] fetch_addr_d, fetch_addr_q;
logic fetch_addr_en;
- logic [31:0] branch_mispredict_addr;
logic [31:0] instr_addr, instr_addr_w_aligned;
- logic instr_or_pmp_err;
logic fifo_valid;
logic [31:0] fifo_addr;
@@ -74,8 +65,6 @@
logic valid_raw;
- logic [31:0] addr_next;
-
logic branch_or_mispredict;
////////////////////////////
@@ -90,10 +79,6 @@
// Fetch fifo - consumes addresses and data //
//////////////////////////////////////////////
- // Instruction fetch errors are valid on the data phase of a request
- // PMP errors are generated in the address phase, and registered into a fake data phase
- assign instr_or_pmp_err = instr_err_i | rdata_pmp_err_q[0];
-
// A branch will invalidate any previously fetched instructions.
// Note that the FENCE.I instruction relies on this flushing behaviour on branch. If it is
// altered the FENCE.I implementation may require changes.
@@ -122,13 +107,12 @@
.in_valid_i ( fifo_valid ),
.in_addr_i ( fifo_addr ),
.in_rdata_i ( instr_rdata_i ),
- .in_err_i ( instr_or_pmp_err ),
+ .in_err_i ( instr_err_i ),
.out_valid_o ( valid_raw ),
.out_ready_i ( ready_i ),
.out_rdata_o ( rdata_o ),
.out_addr_o ( addr_o ),
- .out_addr_next_o ( addr_next ),
.out_err_o ( err_o ),
.out_err_plus2_o ( err_plus2_o )
);
@@ -137,25 +121,14 @@
// Requests //
//////////////
- // Suppress a new request on a not-taken branch (as the external address will be incorrect)
- assign branch_suppress = branch_spec_i & ~branch_i;
-
// Make a new request any time there is space in the FIFO, and space in the request queue
- assign valid_new_req = ~branch_suppress & req_i & (fifo_ready | branch_or_mispredict) &
+ assign valid_new_req = req_i & (fifo_ready | branch_or_mispredict) &
~rdata_outstanding_q[NUM_REQS-1];
assign valid_req = valid_req_q | valid_new_req;
- // If a request address triggers a PMP error, the external bus request is suppressed. We might
- // therefore never receive a grant for such a request. The grant is faked in this case to make
- // sure the request proceeds and the error is pushed to the FIFO.
- assign gnt_or_pmp_err = instr_gnt_i | instr_pmp_err_i;
-
- // As with the grant, the rvalid must be faked for a PMP error, since the request was suppressed.
- assign rvalid_or_pmp_err = rdata_outstanding_q[0] & (instr_rvalid_i | rdata_pmp_err_q[0]);
-
// Hold the request stable for requests that didn't get granted
- assign valid_req_d = valid_req & ~gnt_or_pmp_err;
+ assign valid_req_d = valid_req & ~instr_gnt_i;
// Record whether an outstanding bus request is cancelled by a branch
assign discard_req_d = valid_req_q & (branch_or_mispredict | discard_req_q);
@@ -177,7 +150,7 @@
// 1. stored_addr_q
// Only update stored_addr_q for new ungranted requests
- assign stored_addr_en = valid_new_req & ~valid_req_q & ~gnt_or_pmp_err;
+ assign stored_addr_en = valid_new_req & ~valid_req_q & ~instr_gnt_i;
// Store whatever address was issued on the bus
assign stored_addr_d = instr_addr;
@@ -198,50 +171,13 @@
end
end
end
-
- if (BranchPredictor) begin : g_branch_predictor
- // Where the branch predictor is present record what address followed a predicted branch. If
- // that branch is predicted taken but mispredicted (so not-taken) this is used to resume on
- // the not-taken code path.
- logic [31:0] branch_mispredict_addr_q;
- logic branch_mispredict_addr_en;
-
- assign branch_mispredict_addr_en = branch_i & predicted_branch_i;
-
- if (ResetAll) begin : g_branch_misp_addr_ra
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- branch_mispredict_addr_q <= '0;
- end else if (branch_mispredict_addr_en) begin
- branch_mispredict_addr_q <= addr_next;
- end
- end
- end else begin : g_branch_misp_addr_nr
- always_ff @(posedge clk_i) begin
- if (branch_mispredict_addr_en) begin
- branch_mispredict_addr_q <= addr_next;
- end
- end
- end
-
- assign branch_mispredict_addr = branch_mispredict_addr_q;
- end else begin : g_no_branch_predictor
- logic unused_predicted_branch;
- logic [31:0] unused_addr_next;
-
- assign unused_predicted_branch = predicted_branch_i;
- assign unused_addr_next = addr_next;
-
- assign branch_mispredict_addr = '0;
- end
-
// 2. fetch_addr_q
// Update on a branch or as soon as a request is issued
assign fetch_addr_en = branch_or_mispredict | (valid_new_req & ~valid_req_q);
assign fetch_addr_d = (branch_i ? addr_i :
- branch_mispredict_i ? {branch_mispredict_addr[31:2], 2'b00} :
+ branch_mispredict_i ? {mispredict_addr_i[31:2], 2'b00} :
{fetch_addr_q[31:2], 2'b00}) +
// Current address + 4
{{29{1'b0}},(valid_new_req & ~valid_req_q),2'b00};
@@ -264,8 +200,8 @@
// Address mux
assign instr_addr = valid_req_q ? stored_addr_q :
- branch_spec_i ? addr_i :
- branch_mispredict_i ? branch_mispredict_addr :
+ branch_i ? addr_i :
+ branch_mispredict_i ? mispredict_addr_i :
fetch_addr_q;
assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00};
@@ -279,46 +215,38 @@
if (i == 0) begin : g_req0
// A request becomes outstanding once granted, and is cleared once the rvalid is received.
// Outstanding requests shift down the queue towards entry 0.
- assign rdata_outstanding_n[i] = (valid_req & gnt_or_pmp_err) |
+ assign rdata_outstanding_n[i] = (valid_req & instr_gnt_i) |
rdata_outstanding_q[i];
// If a branch is received at any point while a request is outstanding, it must be tracked
// to ensure we discard the data once received
- assign branch_discard_n[i] = (valid_req & gnt_or_pmp_err & discard_req_d) |
+ assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d) |
(branch_or_mispredict & rdata_outstanding_q[i]) |
branch_discard_q[i];
- // Record whether this request received a PMP error
- assign rdata_pmp_err_n[i] = (valid_req & ~rdata_outstanding_q[i] & instr_pmp_err_i) |
- rdata_pmp_err_q[i];
end else begin : g_reqtop
// Entries > 0 consider the FIFO fill state to calculate their next state (by checking
// whether the previous entry is valid)
- assign rdata_outstanding_n[i] = (valid_req & gnt_or_pmp_err &
+ assign rdata_outstanding_n[i] = (valid_req & instr_gnt_i &
rdata_outstanding_q[i-1]) |
rdata_outstanding_q[i];
- assign branch_discard_n[i] = (valid_req & gnt_or_pmp_err & discard_req_d &
+ assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d &
rdata_outstanding_q[i-1]) |
(branch_or_mispredict & rdata_outstanding_q[i]) |
branch_discard_q[i];
- assign rdata_pmp_err_n[i] = (valid_req & ~rdata_outstanding_q[i] & instr_pmp_err_i &
- rdata_outstanding_q[i-1]) |
- rdata_pmp_err_q[i];
end
end
// Shift the entries down on each instr_rvalid_i
- assign rdata_outstanding_s = rvalid_or_pmp_err ? {1'b0,rdata_outstanding_n[NUM_REQS-1:1]} :
- rdata_outstanding_n;
- assign branch_discard_s = rvalid_or_pmp_err ? {1'b0,branch_discard_n[NUM_REQS-1:1]} :
- branch_discard_n;
- assign rdata_pmp_err_s = rvalid_or_pmp_err ? {1'b0,rdata_pmp_err_n[NUM_REQS-1:1]} :
- rdata_pmp_err_n;
+ assign rdata_outstanding_s = instr_rvalid_i ? {1'b0,rdata_outstanding_n[NUM_REQS-1:1]} :
+ rdata_outstanding_n;
+ assign branch_discard_s = instr_rvalid_i ? {1'b0,branch_discard_n[NUM_REQS-1:1]} :
+ branch_discard_n;
// Push a new entry to the FIFO once complete (and not cancelled by a branch)
- assign fifo_valid = rvalid_or_pmp_err & ~branch_discard_q[0];
+ assign fifo_valid = instr_rvalid_i & ~branch_discard_q[0];
- assign fifo_addr = branch_i ? addr_i : branch_mispredict_addr;
+ assign fifo_addr = branch_i ? addr_i : mispredict_addr_i;
///////////////
// Registers //
@@ -330,13 +258,11 @@
discard_req_q <= 1'b0;
rdata_outstanding_q <= 'b0;
branch_discard_q <= 'b0;
- rdata_pmp_err_q <= 'b0;
end else begin
valid_req_q <= valid_req_d;
discard_req_q <= discard_req_d;
rdata_outstanding_q <= rdata_outstanding_s;
branch_discard_q <= branch_discard_s;
- rdata_pmp_err_q <= rdata_pmp_err_s;
end
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
index 3e887b1..0cd5e6f 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -11,30 +11,31 @@
* targeting FPGA synthesis or Verilator simulation.
*/
module ibex_register_file_ff #(
- parameter bit RV32E = 0,
- parameter int unsigned DataWidth = 32,
- parameter bit DummyInstructions = 0
+ parameter bit RV32E = 0,
+ parameter int unsigned DataWidth = 32,
+ parameter bit DummyInstructions = 0,
+ parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- input logic test_en_i,
- input logic dummy_instr_id_i,
+ input logic test_en_i,
+ input logic dummy_instr_id_i,
- //Read port R1
- input logic [4:0] raddr_a_i,
- output logic [DataWidth-1:0] rdata_a_o,
+ //Read port R1
+ input logic [4:0] raddr_a_i,
+ output logic [DataWidth-1:0] rdata_a_o,
- //Read port R2
- input logic [4:0] raddr_b_i,
- output logic [DataWidth-1:0] rdata_b_o,
+ //Read port R2
+ input logic [4:0] raddr_b_i,
+ output logic [DataWidth-1:0] rdata_b_o,
- // Write port W1
- input logic [4:0] waddr_a_i,
- input logic [DataWidth-1:0] wdata_a_i,
- input logic we_a_i
+ // Write port W1
+ input logic [4:0] waddr_a_i,
+ input logic [DataWidth-1:0] wdata_a_i,
+ input logic we_a_i
);
@@ -47,7 +48,7 @@
always_comb begin : we_a_decoder
for (int unsigned i = 1; i < NUM_WORDS; i++) begin
- we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
+ we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
end
end
@@ -55,8 +56,8 @@
for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- rf_reg_q[i] <= '0;
- end else if(we_a_dec[i]) begin
+ rf_reg_q[i] <= WordZeroVal;
+ end else if (we_a_dec[i]) begin
rf_reg_q[i] <= wdata_a_i;
end
end
@@ -73,21 +74,21 @@
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- rf_r0_q <= '0;
+ rf_r0_q <= WordZeroVal;
end else if (we_r0_dummy) begin
rf_r0_q <= wdata_a_i;
end
end
// Output the dummy data for dummy instructions, otherwise R0 reads as zero
- assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0;
+ assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal;
end else begin : g_normal_r0
logic unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;
// R0 is nil
- assign rf_reg[0] = '0;
+ assign rf_reg[0] = WordZeroVal;
end
assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1];
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
index e603dc4..678549a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_fpga.sv
@@ -12,9 +12,10 @@
* FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested.
*/
module ibex_register_file_fpga #(
- parameter bit RV32E = 0,
- parameter int unsigned DataWidth = 32,
- parameter bit DummyInstructions = 0
+ parameter bit RV32E = 0,
+ parameter int unsigned DataWidth = 32,
+ parameter bit DummyInstructions = 0,
+ parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
// Clock and Reset
input logic clk_i,
@@ -36,7 +37,7 @@
);
localparam int ADDR_WIDTH = RV32E ? 4 : 5;
- localparam int NUM_WORDS = 2**ADDR_WIDTH;
+ localparam int NUM_WORDS = 2 ** ADDR_WIDTH;
logic [DataWidth-1:0] mem[NUM_WORDS];
logic we; // write enable if writing to any register other than R0
@@ -50,12 +51,24 @@
// we select
assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i;
- always_ff @(posedge clk_i) begin : sync_write
+ // Note that the SystemVerilog LRM requires variables on the LHS of assignments within
+ // "always_ff" to not be written to by any other process. However, to enable the initialization
+ // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed.
+ // Therefore, we use "always" instead of the generally preferred "always_ff" for the synchronous
+ // write procedure.
+ always @(posedge clk_i) begin : sync_write
if (we == 1'b1) begin
mem[waddr_a_i] <= wdata_a_i;
end
end : sync_write
+ // Make sure we initialize the BRAM with the correct register reset value.
+ initial begin
+ for (int k = 0; k < NUM_WORDS; k++) begin
+ mem[k] = WordZeroVal;
+ end
+ end
+
// Reset not used in this register file version
logic unused_rst_ni;
assign unused_rst_ni = rst_ni;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
index 8c5fb35..717bcaf 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -12,29 +12,30 @@
* register file when targeting ASIC synthesis or event-based simulators.
*/
module ibex_register_file_latch #(
- parameter bit RV32E = 0,
- parameter int unsigned DataWidth = 32,
- parameter bit DummyInstructions = 0
+ parameter bit RV32E = 0,
+ parameter int unsigned DataWidth = 32,
+ parameter bit DummyInstructions = 0,
+ parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- input logic test_en_i,
- input logic dummy_instr_id_i,
+ input logic test_en_i,
+ input logic dummy_instr_id_i,
- //Read port R1
- input logic [4:0] raddr_a_i,
- output logic [DataWidth-1:0] rdata_a_o,
+ //Read port R1
+ input logic [4:0] raddr_a_i,
+ output logic [DataWidth-1:0] rdata_a_o,
- //Read port R2
- input logic [4:0] raddr_b_i,
- output logic [DataWidth-1:0] rdata_b_o,
+ //Read port R2
+ input logic [4:0] raddr_b_i,
+ output logic [DataWidth-1:0] rdata_b_o,
- // Write port W1
- input logic [4:0] waddr_a_i,
- input logic [DataWidth-1:0] wdata_a_i,
- input logic we_a_i
+ // Write port W1
+ input logic [4:0] waddr_a_i,
+ input logic [DataWidth-1:0] wdata_a_i,
+ input logic we_a_i
);
@@ -78,7 +79,7 @@
// Use clk_int here, since otherwise we don't want to write anything anyway.
always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata
if (!rst_ni) begin
- wdata_a_q <= '0;
+ wdata_a_q <= WordZeroVal;
end else begin
if (we_a_i) begin
wdata_a_q <= wdata_a_i;
@@ -143,13 +144,13 @@
end
// Output the dummy data for dummy instructions, otherwise R0 reads as zero
- assign mem[0] = dummy_instr_id_i ? mem_r0 : '0;
+ assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal;
end else begin : g_normal_r0
logic unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;
- assign mem[0] = '0;
+ assign mem[0] = WordZeroVal;
end
`ifdef VERILATOR
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
index c0148ea..71bc1ba 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
@@ -13,108 +13,112 @@
* Top level module of the ibex RISC-V core
*/
module ibex_top import ibex_pkg::*; #(
- parameter bit PMPEnable = 1'b0,
- parameter int unsigned PMPGranularity = 0,
- parameter int unsigned PMPNumRegions = 4,
- parameter int unsigned MHPMCounterNum = 0,
- parameter int unsigned MHPMCounterWidth = 40,
- parameter bit RV32E = 1'b0,
- parameter rv32m_e RV32M = RV32MFast,
- parameter rv32b_e RV32B = RV32BNone,
- parameter regfile_e RegFile = RegFileFF,
- parameter bit BranchTargetALU = 1'b0,
- parameter bit WritebackStage = 1'b0,
- parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0,
- parameter bit BranchPredictor = 1'b0,
- parameter bit DbgTriggerEn = 1'b0,
- parameter int unsigned DbgHwBreakNum = 1,
- parameter bit SecureIbex = 1'b0,
- parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
- parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
- parameter int unsigned DmHaltAddr = 32'h1A110800,
- parameter int unsigned DmExceptionAddr = 32'h1A110808
+ parameter bit PMPEnable = 1'b0,
+ parameter int unsigned PMPGranularity = 0,
+ parameter int unsigned PMPNumRegions = 4,
+ parameter int unsigned MHPMCounterNum = 0,
+ parameter int unsigned MHPMCounterWidth = 40,
+ parameter bit RV32E = 1'b0,
+ parameter rv32m_e RV32M = RV32MFast,
+ parameter rv32b_e RV32B = RV32BNone,
+ parameter regfile_e RegFile = RegFileFF,
+ parameter bit BranchTargetALU = 1'b0,
+ parameter bit WritebackStage = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter bit ICacheECC = 1'b0,
+ parameter bit BranchPredictor = 1'b0,
+ parameter bit DbgTriggerEn = 1'b0,
+ parameter int unsigned DbgHwBreakNum = 1,
+ parameter bit SecureIbex = 1'b0,
+ parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
+ parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter int unsigned DmHaltAddr = 32'h1A110800,
+ parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- input logic test_en_i, // enable all clock gates for testing
- input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
+ input logic test_en_i, // enable all clock gates for testing
+ input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
- input logic [31:0] hart_id_i,
- input logic [31:0] boot_addr_i,
+ input logic [31:0] hart_id_i,
+ input logic [31:0] boot_addr_i,
- // Instruction memory interface
- output logic instr_req_o,
- input logic instr_gnt_i,
- input logic instr_rvalid_i,
- output logic [31:0] instr_addr_o,
- input logic [31:0] instr_rdata_i,
- input logic [6:0] instr_rdata_intg_i,
- input logic instr_err_i,
+ // Instruction memory interface
+ output logic instr_req_o,
+ input logic instr_gnt_i,
+ input logic instr_rvalid_i,
+ output logic [31:0] instr_addr_o,
+ input logic [31:0] instr_rdata_i,
+ input logic [6:0] instr_rdata_intg_i,
+ input logic instr_err_i,
- // Data memory interface
- output logic data_req_o,
- input logic data_gnt_i,
- input logic data_rvalid_i,
- output logic data_we_o,
- output logic [3:0] data_be_o,
- output logic [31:0] data_addr_o,
- output logic [31:0] data_wdata_o,
- output logic [6:0] data_wdata_intg_o,
- input logic [31:0] data_rdata_i,
- input logic [6:0] data_rdata_intg_i,
- input logic data_err_i,
+ // Data memory interface
+ output logic data_req_o,
+ input logic data_gnt_i,
+ input logic data_rvalid_i,
+ output logic data_we_o,
+ output logic [3:0] data_be_o,
+ output logic [31:0] data_addr_o,
+ output logic [31:0] data_wdata_o,
+ output logic [6:0] data_wdata_intg_o,
+ input logic [31:0] data_rdata_i,
+ input logic [6:0] data_rdata_intg_i,
+ input logic data_err_i,
- // Interrupt inputs
- input logic irq_software_i,
- input logic irq_timer_i,
- input logic irq_external_i,
- input logic [14:0] irq_fast_i,
- input logic irq_nm_i, // non-maskeable interrupt
+ // Interrupt inputs
+ input logic irq_software_i,
+ input logic irq_timer_i,
+ input logic irq_external_i,
+ input logic [14:0] irq_fast_i,
+ input logic irq_nm_i, // non-maskeable interrupt
- // Debug Interface
- input logic debug_req_i,
- output crash_dump_t crash_dump_o,
+ // Debug Interface
+ input logic debug_req_i,
+ output crash_dump_t crash_dump_o,
- // RISC-V Formal Interface
- // Does not comply with the coding standards of _i/_o suffixes, but follows
- // the convention of RISC-V Formal Interface Specification.
+ // RISC-V Formal Interface
+ // Does not comply with the coding standards of _i/_o suffixes, but follows
+ // the convention of RISC-V Formal Interface Specification.
`ifdef RVFI
- output logic rvfi_valid,
- output logic [63:0] rvfi_order,
- output logic [31:0] rvfi_insn,
- output logic rvfi_trap,
- output logic rvfi_halt,
- output logic rvfi_intr,
- output logic [ 1:0] rvfi_mode,
- output logic [ 1:0] rvfi_ixl,
- output logic [ 4:0] rvfi_rs1_addr,
- output logic [ 4:0] rvfi_rs2_addr,
- output logic [ 4:0] rvfi_rs3_addr,
- output logic [31:0] rvfi_rs1_rdata,
- output logic [31:0] rvfi_rs2_rdata,
- output logic [31:0] rvfi_rs3_rdata,
- output logic [ 4:0] rvfi_rd_addr,
- output logic [31:0] rvfi_rd_wdata,
- output logic [31:0] rvfi_pc_rdata,
- output logic [31:0] rvfi_pc_wdata,
- output logic [31:0] rvfi_mem_addr,
- output logic [ 3:0] rvfi_mem_rmask,
- output logic [ 3:0] rvfi_mem_wmask,
- output logic [31:0] rvfi_mem_rdata,
- output logic [31:0] rvfi_mem_wdata,
+ output logic rvfi_valid,
+ output logic [63:0] rvfi_order,
+ output logic [31:0] rvfi_insn,
+ output logic rvfi_trap,
+ output logic rvfi_halt,
+ output logic rvfi_intr,
+ output logic [ 1:0] rvfi_mode,
+ output logic [ 1:0] rvfi_ixl,
+ output logic [ 4:0] rvfi_rs1_addr,
+ output logic [ 4:0] rvfi_rs2_addr,
+ output logic [ 4:0] rvfi_rs3_addr,
+ output logic [31:0] rvfi_rs1_rdata,
+ output logic [31:0] rvfi_rs2_rdata,
+ output logic [31:0] rvfi_rs3_rdata,
+ output logic [ 4:0] rvfi_rd_addr,
+ output logic [31:0] rvfi_rd_wdata,
+ output logic [31:0] rvfi_pc_rdata,
+ output logic [31:0] rvfi_pc_wdata,
+ output logic [31:0] rvfi_mem_addr,
+ output logic [ 3:0] rvfi_mem_rmask,
+ output logic [ 3:0] rvfi_mem_wmask,
+ output logic [31:0] rvfi_mem_rdata,
+ output logic [31:0] rvfi_mem_wdata,
+ output logic [31:0] rvfi_ext_mip,
+ output logic rvfi_ext_nmi,
+ output logic rvfi_ext_debug_req,
+ output logic [63:0] rvfi_ext_mcycle,
`endif
- // CPU Control Signals
- input logic fetch_enable_i,
- output logic alert_minor_o,
- output logic alert_major_o,
- output logic core_sleep_o,
+ // CPU Control Signals
+ input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
+ output logic core_sleep_o,
- // DFT bypass controls
- input logic scan_rst_ni
+ // DFT bypass controls
+ input logic scan_rst_ni
);
localparam bit Lockstep = SecureIbex;
@@ -172,10 +176,10 @@
assign core_sleep_o = ~clock_en;
prim_clock_gating core_clock_gate_i (
- .clk_i ( clk_i ),
- .en_i ( clock_en ),
- .test_en_i ( test_en_i ),
- .clk_o ( clk )
+ .clk_i (clk_i),
+ .en_i (clock_en),
+ .test_en_i(test_en_i),
+ .clk_o (clk)
);
////////////////////////
@@ -183,35 +187,35 @@
////////////////////////
ibex_core #(
- .PMPEnable ( PMPEnable ),
- .PMPGranularity ( PMPGranularity ),
- .PMPNumRegions ( PMPNumRegions ),
- .MHPMCounterNum ( MHPMCounterNum ),
- .MHPMCounterWidth ( MHPMCounterWidth ),
- .RV32E ( RV32E ),
- .RV32M ( RV32M ),
- .RV32B ( RV32B ),
- .BranchTargetALU ( BranchTargetALU ),
- .ICache ( ICache ),
- .ICacheECC ( ICacheECC ),
- .BusSizeECC ( BusSizeECC ),
- .TagSizeECC ( TagSizeECC ),
- .LineSizeECC ( LineSizeECC ),
- .BranchPredictor ( BranchPredictor ),
- .DbgTriggerEn ( DbgTriggerEn ),
- .DbgHwBreakNum ( DbgHwBreakNum ),
- .WritebackStage ( WritebackStage ),
- .ResetAll ( ResetAll ),
- .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
- .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
- .SecureIbex ( SecureIbex ),
- .DummyInstructions ( DummyInstructions ),
- .RegFileECC ( RegFileECC ),
- .RegFileDataWidth ( RegFileDataWidth ),
- .DmHaltAddr ( DmHaltAddr ),
- .DmExceptionAddr ( DmExceptionAddr )
+ .PMPEnable (PMPEnable),
+ .PMPGranularity (PMPGranularity),
+ .PMPNumRegions (PMPNumRegions),
+ .MHPMCounterNum (MHPMCounterNum),
+ .MHPMCounterWidth (MHPMCounterWidth),
+ .RV32E (RV32E),
+ .RV32M (RV32M),
+ .RV32B (RV32B),
+ .BranchTargetALU (BranchTargetALU),
+ .ICache (ICache),
+ .ICacheECC (ICacheECC),
+ .BusSizeECC (BusSizeECC),
+ .TagSizeECC (TagSizeECC),
+ .LineSizeECC (LineSizeECC),
+ .BranchPredictor (BranchPredictor),
+ .DbgTriggerEn (DbgTriggerEn),
+ .DbgHwBreakNum (DbgHwBreakNum),
+ .WritebackStage (WritebackStage),
+ .ResetAll (ResetAll),
+ .RndCnstLfsrSeed (RndCnstLfsrSeed),
+ .RndCnstLfsrPerm (RndCnstLfsrPerm),
+ .SecureIbex (SecureIbex),
+ .DummyInstructions(DummyInstructions),
+ .RegFileECC (RegFileECC),
+ .RegFileDataWidth (RegFileDataWidth),
+ .DmHaltAddr (DmHaltAddr),
+ .DmExceptionAddr (DmExceptionAddr)
) u_ibex_core (
- .clk_i (clk),
+ .clk_i(clk),
.rst_ni,
.hart_id_i,
@@ -234,32 +238,32 @@
.data_rdata_i,
.data_err_i,
- .dummy_instr_id_o (dummy_instr_id),
- .rf_raddr_a_o (rf_raddr_a),
- .rf_raddr_b_o (rf_raddr_b),
- .rf_waddr_wb_o (rf_waddr_wb),
- .rf_we_wb_o (rf_we_wb),
- .rf_wdata_wb_ecc_o (rf_wdata_wb_ecc),
- .rf_rdata_a_ecc_i (rf_rdata_a_ecc),
- .rf_rdata_b_ecc_i (rf_rdata_b_ecc),
+ .dummy_instr_id_o (dummy_instr_id),
+ .rf_raddr_a_o (rf_raddr_a),
+ .rf_raddr_b_o (rf_raddr_b),
+ .rf_waddr_wb_o (rf_waddr_wb),
+ .rf_we_wb_o (rf_we_wb),
+ .rf_wdata_wb_ecc_o(rf_wdata_wb_ecc),
+ .rf_rdata_a_ecc_i (rf_rdata_a_ecc),
+ .rf_rdata_b_ecc_i (rf_rdata_b_ecc),
- .ic_tag_req_o (ic_tag_req),
- .ic_tag_write_o (ic_tag_write),
- .ic_tag_addr_o (ic_tag_addr),
- .ic_tag_wdata_o (ic_tag_wdata),
- .ic_tag_rdata_i (ic_tag_rdata),
- .ic_data_req_o (ic_data_req),
- .ic_data_write_o (ic_data_write),
- .ic_data_addr_o (ic_data_addr),
- .ic_data_wdata_o (ic_data_wdata),
- .ic_data_rdata_i (ic_data_rdata),
+ .ic_tag_req_o (ic_tag_req),
+ .ic_tag_write_o (ic_tag_write),
+ .ic_tag_addr_o (ic_tag_addr),
+ .ic_tag_wdata_o (ic_tag_wdata),
+ .ic_tag_rdata_i (ic_tag_rdata),
+ .ic_data_req_o (ic_data_req),
+ .ic_data_write_o(ic_data_write),
+ .ic_data_addr_o (ic_data_addr),
+ .ic_data_wdata_o(ic_data_wdata),
+ .ic_data_rdata_i(ic_data_rdata),
.irq_software_i,
.irq_timer_i,
.irq_external_i,
.irq_fast_i,
.irq_nm_i,
- .irq_pending_o (irq_pending),
+ .irq_pending_o(irq_pending),
.debug_req_i,
.crash_dump_o,
@@ -288,12 +292,16 @@
.rvfi_mem_wmask,
.rvfi_mem_rdata,
.rvfi_mem_wdata,
+ .rvfi_ext_mip,
+ .rvfi_ext_nmi,
+ .rvfi_ext_debug_req,
+ .rvfi_ext_mcycle,
`endif
.fetch_enable_i,
- .alert_minor_o (core_alert_minor),
- .alert_major_o (core_alert_major),
- .core_busy_o (core_busy_d)
+ .alert_minor_o(core_alert_minor),
+ .alert_major_o(core_alert_major),
+ .core_busy_o (core_busy_d)
);
/////////////////////////////////
@@ -302,63 +310,66 @@
if (RegFile == RegFileFF) begin : gen_regfile_ff
ibex_register_file_ff #(
- .RV32E ( RV32E ),
- .DataWidth ( RegFileDataWidth ),
- .DummyInstructions ( DummyInstructions )
+ .RV32E (RV32E),
+ .DataWidth (RegFileDataWidth),
+ .DummyInstructions(DummyInstructions),
+ .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
) register_file_i (
- .clk_i ( clk ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk),
+ .rst_ni(rst_ni),
- .test_en_i ( test_en_i ),
- .dummy_instr_id_i ( dummy_instr_id ),
+ .test_en_i (test_en_i),
+ .dummy_instr_id_i(dummy_instr_id),
- .raddr_a_i ( rf_raddr_a ),
- .rdata_a_o ( rf_rdata_a_ecc ),
- .raddr_b_i ( rf_raddr_b ),
- .rdata_b_o ( rf_rdata_b_ecc ),
- .waddr_a_i ( rf_waddr_wb ),
- .wdata_a_i ( rf_wdata_wb_ecc ),
- .we_a_i ( rf_we_wb )
+ .raddr_a_i(rf_raddr_a),
+ .rdata_a_o(rf_rdata_a_ecc),
+ .raddr_b_i(rf_raddr_b),
+ .rdata_b_o(rf_rdata_b_ecc),
+ .waddr_a_i(rf_waddr_wb),
+ .wdata_a_i(rf_wdata_wb_ecc),
+ .we_a_i (rf_we_wb)
);
end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
ibex_register_file_fpga #(
- .RV32E ( RV32E ),
- .DataWidth ( RegFileDataWidth ),
- .DummyInstructions ( DummyInstructions )
+ .RV32E (RV32E),
+ .DataWidth (RegFileDataWidth),
+ .DummyInstructions(DummyInstructions),
+ .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
) register_file_i (
- .clk_i ( clk ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk),
+ .rst_ni(rst_ni),
- .test_en_i ( test_en_i ),
- .dummy_instr_id_i ( dummy_instr_id ),
+ .test_en_i (test_en_i),
+ .dummy_instr_id_i(dummy_instr_id),
- .raddr_a_i ( rf_raddr_a ),
- .rdata_a_o ( rf_rdata_a_ecc ),
- .raddr_b_i ( rf_raddr_b ),
- .rdata_b_o ( rf_rdata_b_ecc ),
- .waddr_a_i ( rf_waddr_wb ),
- .wdata_a_i ( rf_wdata_wb_ecc ),
- .we_a_i ( rf_we_wb )
+ .raddr_a_i(rf_raddr_a),
+ .rdata_a_o(rf_rdata_a_ecc),
+ .raddr_b_i(rf_raddr_b),
+ .rdata_b_o(rf_rdata_b_ecc),
+ .waddr_a_i(rf_waddr_wb),
+ .wdata_a_i(rf_wdata_wb_ecc),
+ .we_a_i (rf_we_wb)
);
end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
ibex_register_file_latch #(
- .RV32E ( RV32E ),
- .DataWidth ( RegFileDataWidth ),
- .DummyInstructions ( DummyInstructions )
+ .RV32E (RV32E),
+ .DataWidth (RegFileDataWidth),
+ .DummyInstructions(DummyInstructions),
+ .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord))
) register_file_i (
- .clk_i ( clk ),
- .rst_ni ( rst_ni ),
+ .clk_i (clk),
+ .rst_ni(rst_ni),
- .test_en_i ( test_en_i ),
- .dummy_instr_id_i ( dummy_instr_id ),
+ .test_en_i (test_en_i),
+ .dummy_instr_id_i(dummy_instr_id),
- .raddr_a_i ( rf_raddr_a ),
- .rdata_a_o ( rf_rdata_a_ecc ),
- .raddr_b_i ( rf_raddr_b ),
- .rdata_b_o ( rf_rdata_b_ecc ),
- .waddr_a_i ( rf_waddr_wb ),
- .wdata_a_i ( rf_wdata_wb_ecc ),
- .we_a_i ( rf_we_wb )
+ .raddr_a_i(rf_raddr_a),
+ .rdata_a_o(rf_rdata_a_ecc),
+ .raddr_b_i(rf_raddr_b),
+ .rdata_b_o(rf_rdata_b_ecc),
+ .waddr_a_i(rf_waddr_wb),
+ .wdata_a_i(rf_wdata_wb_ecc),
+ .we_a_i (rf_we_wb)
);
end
@@ -371,33 +382,33 @@
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner
// Tag RAM instantiation
prim_ram_1p #(
- .Width (TagSizeECC),
- .Depth (IC_NUM_LINES),
- .DataBitsPerMask (TagSizeECC)
+ .Width (TagSizeECC),
+ .Depth (IC_NUM_LINES),
+ .DataBitsPerMask(TagSizeECC)
) tag_bank (
- .clk_i (clk_i),
- .req_i (ic_tag_req[way]),
- .cfg_i (ram_cfg_i),
- .write_i (ic_tag_write),
- .wmask_i ({TagSizeECC{1'b1}}),
- .addr_i (ic_tag_addr),
- .wdata_i (ic_tag_wdata),
- .rdata_o (ic_tag_rdata[way])
+ .clk_i (clk_i),
+ .req_i (ic_tag_req[way]),
+ .cfg_i (ram_cfg_i),
+ .write_i(ic_tag_write),
+ .wmask_i({TagSizeECC{1'b1}}),
+ .addr_i (ic_tag_addr),
+ .wdata_i(ic_tag_wdata),
+ .rdata_o(ic_tag_rdata[way])
);
// Data RAM instantiation
prim_ram_1p #(
- .Width (LineSizeECC),
- .Depth (IC_NUM_LINES),
- .DataBitsPerMask (LineSizeECC)
+ .Width (LineSizeECC),
+ .Depth (IC_NUM_LINES),
+ .DataBitsPerMask(LineSizeECC)
) data_bank (
- .clk_i (clk_i),
- .req_i (ic_data_req[way]),
- .cfg_i (ram_cfg_i),
- .write_i (ic_data_write),
- .wmask_i ({LineSizeECC{1'b1}}),
- .addr_i (ic_data_addr),
- .wdata_i (ic_data_wdata),
- .rdata_o (ic_data_rdata[way])
+ .clk_i (clk_i),
+ .req_i (ic_data_req[way]),
+ .cfg_i (ram_cfg_i),
+ .write_i(ic_data_write),
+ .wmask_i({LineSizeECC{1'b1}}),
+ .addr_i (ic_data_addr),
+ .wdata_i(ic_data_wdata),
+ .rdata_o(ic_data_rdata[way])
);
end
@@ -643,33 +654,33 @@
logic lockstep_alert_minor_local, lockstep_alert_major_local;
ibex_lockstep #(
- .PMPEnable ( PMPEnable ),
- .PMPGranularity ( PMPGranularity ),
- .PMPNumRegions ( PMPNumRegions ),
- .MHPMCounterNum ( MHPMCounterNum ),
- .MHPMCounterWidth ( MHPMCounterWidth ),
- .RV32E ( RV32E ),
- .RV32M ( RV32M ),
- .RV32B ( RV32B ),
- .BranchTargetALU ( BranchTargetALU ),
- .ICache ( ICache ),
- .ICacheECC ( ICacheECC ),
- .BusSizeECC ( BusSizeECC ),
- .TagSizeECC ( TagSizeECC ),
- .LineSizeECC ( LineSizeECC ),
- .BranchPredictor ( BranchPredictor ),
- .DbgTriggerEn ( DbgTriggerEn ),
- .DbgHwBreakNum ( DbgHwBreakNum ),
- .WritebackStage ( WritebackStage ),
- .ResetAll ( ResetAll ),
- .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
- .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
- .SecureIbex ( SecureIbex ),
- .DummyInstructions ( DummyInstructions ),
- .RegFileECC ( RegFileECC ),
- .RegFileDataWidth ( RegFileDataWidth ),
- .DmHaltAddr ( DmHaltAddr ),
- .DmExceptionAddr ( DmExceptionAddr )
+ .PMPEnable (PMPEnable),
+ .PMPGranularity (PMPGranularity),
+ .PMPNumRegions (PMPNumRegions),
+ .MHPMCounterNum (MHPMCounterNum),
+ .MHPMCounterWidth (MHPMCounterWidth),
+ .RV32E (RV32E),
+ .RV32M (RV32M),
+ .RV32B (RV32B),
+ .BranchTargetALU (BranchTargetALU),
+ .ICache (ICache),
+ .ICacheECC (ICacheECC),
+ .BusSizeECC (BusSizeECC),
+ .TagSizeECC (TagSizeECC),
+ .LineSizeECC (LineSizeECC),
+ .BranchPredictor (BranchPredictor),
+ .DbgTriggerEn (DbgTriggerEn),
+ .DbgHwBreakNum (DbgHwBreakNum),
+ .WritebackStage (WritebackStage),
+ .ResetAll (ResetAll),
+ .RndCnstLfsrSeed (RndCnstLfsrSeed),
+ .RndCnstLfsrPerm (RndCnstLfsrPerm),
+ .SecureIbex (SecureIbex),
+ .DummyInstructions(DummyInstructions),
+ .RegFileECC (RegFileECC),
+ .RegFileDataWidth (RegFileDataWidth),
+ .DmHaltAddr (DmHaltAddr),
+ .DmExceptionAddr (DmExceptionAddr)
) u_ibex_lockstep (
.clk_i (clk),
.rst_ni (rst_ni),
@@ -742,12 +753,12 @@
);
prim_buf u_prim_buf_alert_minor (
- .in_i(lockstep_alert_minor_local),
+ .in_i (lockstep_alert_minor_local),
.out_o(lockstep_alert_minor)
);
prim_buf u_prim_buf_alert_major (
- .in_i(lockstep_alert_major_local),
+ .in_i (lockstep_alert_major_local),
.out_o(lockstep_alert_major)
);
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
index 340d9ee..c08fc18 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top_tracing.sv
@@ -7,78 +7,78 @@
*/
module ibex_top_tracing import ibex_pkg::*; #(
- parameter bit PMPEnable = 1'b0,
- parameter int unsigned PMPGranularity = 0,
- parameter int unsigned PMPNumRegions = 4,
- parameter int unsigned MHPMCounterNum = 0,
- parameter int unsigned MHPMCounterWidth = 40,
- parameter bit RV32E = 1'b0,
- parameter rv32m_e RV32M = RV32MFast,
- parameter rv32b_e RV32B = RV32BNone,
- parameter regfile_e RegFile = RegFileFF,
- parameter bit BranchTargetALU = 1'b0,
- parameter bit WritebackStage = 1'b0,
- parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0,
- parameter bit BranchPredictor = 1'b0,
- parameter bit DbgTriggerEn = 1'b0,
- parameter int unsigned DbgHwBreakNum = 1,
- parameter bit SecureIbex = 1'b0,
- parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
- parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
- parameter int unsigned DmHaltAddr = 32'h1A110800,
- parameter int unsigned DmExceptionAddr = 32'h1A110808
+ parameter bit PMPEnable = 1'b0,
+ parameter int unsigned PMPGranularity = 0,
+ parameter int unsigned PMPNumRegions = 4,
+ parameter int unsigned MHPMCounterNum = 0,
+ parameter int unsigned MHPMCounterWidth = 40,
+ parameter bit RV32E = 1'b0,
+ parameter rv32m_e RV32M = RV32MFast,
+ parameter rv32b_e RV32B = RV32BNone,
+ parameter regfile_e RegFile = RegFileFF,
+ parameter bit BranchTargetALU = 1'b0,
+ parameter bit WritebackStage = 1'b0,
+ parameter bit ICache = 1'b0,
+ parameter bit ICacheECC = 1'b0,
+ parameter bit BranchPredictor = 1'b0,
+ parameter bit DbgTriggerEn = 1'b0,
+ parameter int unsigned DbgHwBreakNum = 1,
+ parameter bit SecureIbex = 1'b0,
+ parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
+ parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter int unsigned DmHaltAddr = 32'h1A110800,
+ parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
- // Clock and Reset
- input logic clk_i,
- input logic rst_ni,
+ // Clock and Reset
+ input logic clk_i,
+ input logic rst_ni,
- input logic test_en_i, // enable all clock gates for testing
- input logic scan_rst_ni,
- input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
+ input logic test_en_i, // enable all clock gates for testing
+ input logic scan_rst_ni,
+ input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
- input logic [31:0] hart_id_i,
- input logic [31:0] boot_addr_i,
+ input logic [31:0] hart_id_i,
+ input logic [31:0] boot_addr_i,
- // Instruction memory interface
- output logic instr_req_o,
- input logic instr_gnt_i,
- input logic instr_rvalid_i,
- output logic [31:0] instr_addr_o,
- input logic [31:0] instr_rdata_i,
- input logic [6:0] instr_rdata_intg_i,
- input logic instr_err_i,
+ // Instruction memory interface
+ output logic instr_req_o,
+ input logic instr_gnt_i,
+ input logic instr_rvalid_i,
+ output logic [31:0] instr_addr_o,
+ input logic [31:0] instr_rdata_i,
+ input logic [6:0] instr_rdata_intg_i,
+ input logic instr_err_i,
- // Data memory interface
- output logic data_req_o,
- input logic data_gnt_i,
- input logic data_rvalid_i,
- output logic data_we_o,
- output logic [3:0] data_be_o,
- output logic [31:0] data_addr_o,
- output logic [31:0] data_wdata_o,
- output logic [6:0] data_wdata_intg_o,
- input logic [31:0] data_rdata_i,
- input logic [6:0] data_rdata_intg_i,
- input logic data_err_i,
+ // Data memory interface
+ output logic data_req_o,
+ input logic data_gnt_i,
+ input logic data_rvalid_i,
+ output logic data_we_o,
+ output logic [3:0] data_be_o,
+ output logic [31:0] data_addr_o,
+ output logic [31:0] data_wdata_o,
+ output logic [6:0] data_wdata_intg_o,
+ input logic [31:0] data_rdata_i,
+ input logic [6:0] data_rdata_intg_i,
+ input logic data_err_i,
- // Interrupt inputs
- input logic irq_software_i,
- input logic irq_timer_i,
- input logic irq_external_i,
- input logic [14:0] irq_fast_i,
- input logic irq_nm_i, // non-maskeable interrupt
+ // Interrupt inputs
+ input logic irq_software_i,
+ input logic irq_timer_i,
+ input logic irq_external_i,
+ input logic [14:0] irq_fast_i,
+ input logic irq_nm_i, // non-maskeable interrupt
- // Debug Interface
- input logic debug_req_i,
- output crash_dump_t crash_dump_o,
+ // Debug Interface
+ input logic debug_req_i,
+ output crash_dump_t crash_dump_o,
- // CPU Control Signals
- input logic fetch_enable_i,
- output logic alert_minor_o,
- output logic alert_major_o,
- output logic core_sleep_o
+ // CPU Control Signals
+ input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
+ output logic core_sleep_o
);
@@ -110,6 +110,22 @@
logic [ 3:0] rvfi_mem_wmask;
logic [31:0] rvfi_mem_rdata;
logic [31:0] rvfi_mem_wdata;
+ logic [31:0] rvfi_ext_mip;
+ logic rvfi_ext_nmi;
+ logic rvfi_ext_debug_req;
+ logic [63:0] rvfi_ext_mcycle;
+
+ logic [31:0] unused_rvfi_ext_mip;
+ logic unused_rvfi_ext_nmi;
+ logic unused_rvfi_ext_debug_req;
+ logic [63:0] unused_rvfi_ext_mcycle;
+
+ // Tracer doesn't use these signals, though other modules may probe down into tracer to observe
+ // them.
+ assign unused_rvfi_ext_mip = rvfi_ext_mip;
+ assign unused_rvfi_ext_nmi = rvfi_ext_nmi;
+ assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req;
+ assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle;
ibex_top #(
.PMPEnable ( PMPEnable ),
@@ -129,6 +145,8 @@
.DbgHwBreakNum ( DbgHwBreakNum ),
.WritebackStage ( WritebackStage ),
.SecureIbex ( SecureIbex ),
+ .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
+ .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr )
) u_ibex_top (
@@ -194,6 +212,10 @@
.rvfi_mem_wmask,
.rvfi_mem_rdata,
.rvfi_mem_wdata,
+ .rvfi_ext_mip,
+ .rvfi_ext_nmi,
+ .rvfi_ext_debug_req,
+ .rvfi_ext_mcycle,
.fetch_enable_i,
.alert_minor_o,
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
index bbee71b..4a08446 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv
@@ -490,7 +490,7 @@
rvfi_insn[30:25], rvfi_insn[11:8], 1'b0 });
branch_target = rvfi_pc_rdata + imm;
- data_accessed = RS1 | RS2 | RD;
+ data_accessed = RS1 | RS2;
decoded_str = $sformatf("%s\tx%0d,x%0d,%0x",
mnemonic, rvfi_rs1_addr, rvfi_rs2_addr, branch_target);
endfunction
@@ -855,9 +855,12 @@
INSN_SLTIU: decode_i_insn("sltiu");
INSN_XORI: decode_i_insn("xori");
INSN_ORI: decode_i_insn("ori");
- // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
- // zext.b rd rs = andi rd, rs, 255.
- // Currently instruction set simulators don't output this pseudo-instruction.
+ // Unlike the ratified v.1.0.0 bitmanip extension, the v.0.94 draft extension continues to
+ // define the pseudo-instruction
+ // zext.b rd rs = andi rd, rs, 255.
+ // However, for now the tracer doesn't emit this due to a lack of support in the LLVM and
+ // GCC toolchains. Enabling this functionality when the time is right is tracked in
+ // https://github.com/lowRISC/ibex/issues/1228
INSN_ANDI: decode_i_insn("andi");
// INSN_ANDI:begin
// casez (rvfi_insn)
@@ -907,12 +910,12 @@
// MISC-MEM
INSN_FENCE: decode_fence();
INSN_FENCEI: decode_mnemonic("fence.i");
+ // RV32B - ZBA
+ INSN_SH1ADD: decode_r_insn("sh1add");
+ INSN_SH2ADD: decode_r_insn("sh2add");
+ INSN_SH3ADD: decode_r_insn("sh3add");
// RV32B - ZBB
- INSN_SLOI: decode_i_shift_insn("sloi");
- INSN_SROI: decode_i_shift_insn("sroi");
INSN_RORI: decode_i_shift_insn("rori");
- INSN_SLO: decode_r_insn("slo");
- INSN_SRO: decode_r_insn("sro");
INSN_ROL: decode_r_insn("rol");
INSN_ROR: decode_r_insn("ror");
INSN_MIN: decode_r_insn("min");
@@ -922,9 +925,11 @@
INSN_XNOR: decode_r_insn("xnor");
INSN_ORN: decode_r_insn("orn");
INSN_ANDN: decode_r_insn("andn");
- // Version 0.92 of the Bitmanip Extension defines the pseudo-instruction
- // zext.h rd rs = pack rd, rs, zero.
- // Currently instruction set simulators don't output this pseudo-instruction.
+ // The ratified v.1.0.0 bitmanip extension defines the pseudo-instruction
+ // zext.h rd rs = pack rd, rs, zero.
+ // However, for now the tracer doesn't emit this due to a lack of support in the LLVM and
+ // GCC toolchains. Enabling this functionality when the time is right is tracked in
+ // https://github.com/lowRISC/ibex/issues/1228
INSN_PACK: decode_r_insn("pack");
// INSN_PACK: begin
// casez (rvfi_insn)
@@ -936,21 +941,21 @@
INSN_PACKU: decode_r_insn("packu");
INSN_CLZ: decode_r1_insn("clz");
INSN_CTZ: decode_r1_insn("ctz");
- INSN_PCNT: decode_r1_insn("pcnt");
+ INSN_CPOP: decode_r1_insn("cpop");
INSN_SEXTB: decode_r1_insn("sext.b");
INSN_SEXTH: decode_r1_insn("sext.h");
// RV32B - ZBS
- INSN_SBCLRI: decode_i_insn("sbclri");
- INSN_SBSETI: decode_i_insn("sbseti");
- INSN_SBINVI: decode_i_insn("sbinvi");
- INSN_SBEXTI: decode_i_insn("sbexti");
- INSN_SBCLR: decode_r_insn("sbclr");
- INSN_SBSET: decode_r_insn("sbset");
- INSN_SBINV: decode_r_insn("sbinv");
- INSN_SBEXT: decode_r_insn("sbext");
+ INSN_BCLRI: decode_i_insn("bclri");
+ INSN_BSETI: decode_i_insn("bseti");
+ INSN_BINVI: decode_i_insn("binvi");
+ INSN_BEXTI: decode_i_insn("bexti");
+ INSN_BCLR: decode_r_insn("bclr");
+ INSN_BSET: decode_r_insn("bset");
+ INSN_BINV: decode_r_insn("binv");
+ INSN_BEXT: decode_r_insn("bext");
// RV32B - ZBE
- INSN_BDEP: decode_r_insn("bdep");
- INSN_BEXT: decode_r_insn("bext");
+ INSN_BDECOMPRESS: decode_r_insn("bdecompress");
+ INSN_BCOMPRESS: decode_r_insn("bcompress");
// RV32B - ZBP
INSN_GREV: decode_r_insn("grev");
INSN_GREVI: begin
@@ -1026,6 +1031,13 @@
default: decode_i_insn("unshfli");
endcase
end
+ INSN_XPERM_N: decode_r_insn("xperm_n");
+ INSN_XPERM_B: decode_r_insn("xperm_b");
+ INSN_XPERM_H: decode_r_insn("xperm_h");
+ INSN_SLO: decode_r_insn("slo");
+ INSN_SRO: decode_r_insn("sro");
+ INSN_SLOI: decode_i_shift_insn("sloi");
+ INSN_SROI: decode_i_shift_insn("sroi");
// RV32B - ZBT
INSN_CMIX: decode_r_cmixcmov_insn("cmix");
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
index c794786..6dbbfc9 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv
@@ -4,310 +4,332 @@
// SPDX-License-Identifier: Apache-2.0
package ibex_tracer_pkg;
-import ibex_pkg::*;
+ import ibex_pkg::*;
-parameter logic [1:0] OPCODE_C0 = 2'b00;
-parameter logic [1:0] OPCODE_C1 = 2'b01;
-parameter logic [1:0] OPCODE_C2 = 2'b10;
+ parameter logic [1:0] OPCODE_C0 = 2'b00;
+ parameter logic [1:0] OPCODE_C1 = 2'b01;
+ parameter logic [1:0] OPCODE_C2 = 2'b10;
-// instruction masks (for tracer)
-parameter logic [31:0] INSN_LUI = { 25'h?, {OPCODE_LUI } };
-parameter logic [31:0] INSN_AUIPC = { 25'h?, {OPCODE_AUIPC} };
-parameter logic [31:0] INSN_JAL = { 25'h?, {OPCODE_JAL } };
-parameter logic [31:0] INSN_JALR = { 17'h?, 3'b000, 5'h?, {OPCODE_JALR } };
+ // instruction masks (for tracer)
+ parameter logic [31:0] INSN_LUI = { 25'h?, {OPCODE_LUI } };
+ parameter logic [31:0] INSN_AUIPC = { 25'h?, {OPCODE_AUIPC} };
+ parameter logic [31:0] INSN_JAL = { 25'h?, {OPCODE_JAL } };
+ parameter logic [31:0] INSN_JALR = { 17'h?, 3'b000, 5'h?, {OPCODE_JALR } };
-// BRANCH
-parameter logic [31:0] INSN_BEQ = { 17'h?, 3'b000, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BNE = { 17'h?, 3'b001, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BLT = { 17'h?, 3'b100, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BGE = { 17'h?, 3'b101, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BLTU = { 17'h?, 3'b110, 5'h?, {OPCODE_BRANCH} };
-parameter logic [31:0] INSN_BGEU = { 17'h?, 3'b111, 5'h?, {OPCODE_BRANCH} };
+ // BRANCH
+ parameter logic [31:0] INSN_BEQ = { 17'h?, 3'b000, 5'h?, {OPCODE_BRANCH} };
+ parameter logic [31:0] INSN_BNE = { 17'h?, 3'b001, 5'h?, {OPCODE_BRANCH} };
+ parameter logic [31:0] INSN_BLT = { 17'h?, 3'b100, 5'h?, {OPCODE_BRANCH} };
+ parameter logic [31:0] INSN_BGE = { 17'h?, 3'b101, 5'h?, {OPCODE_BRANCH} };
+ parameter logic [31:0] INSN_BLTU = { 17'h?, 3'b110, 5'h?, {OPCODE_BRANCH} };
+ parameter logic [31:0] INSN_BGEU = { 17'h?, 3'b111, 5'h?, {OPCODE_BRANCH} };
-// OPIMM
-parameter logic [31:0] INSN_ADDI = { 17'h?, 3'b000, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLTI = { 17'h?, 3'b010, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLTIU = { 17'h?, 3'b011, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_XORI = { 17'h?, 3'b100, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORI = { 17'h?, 3'b110, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ANDI = { 17'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SLLI = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SRLI = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SRAI = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // OPIMM
+ parameter logic [31:0] INSN_ADDI = { 17'h?, 3'b000, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SLTI = { 17'h?, 3'b010, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SLTIU = { 17'h?, 3'b011, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_XORI = { 17'h?, 3'b100, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORI = { 17'h?, 3'b110, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ANDI = { 17'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SLLI = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SRLI = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SRAI = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// OP
-parameter logic [31:0] INSN_ADD = { 7'b0000000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SUB = { 7'b0100000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLL = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLT = { 7'b0000000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLTU = { 7'b0000000, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_XOR = { 7'b0000000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRL = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRA = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_OR = { 7'b0000000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_AND = { 7'b0000000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ // OP
+ parameter logic [31:0] INSN_ADD = { 7'b0000000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SUB = { 7'b0100000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SLL = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SLT = { 7'b0000000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SLTU = { 7'b0000000, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_XOR = { 7'b0000000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SRL = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SRA = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_OR = { 7'b0000000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_AND = { 7'b0000000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-// SYSTEM
-parameter logic [31:0] INSN_CSRRW = { 17'h?, 3'b001, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRS = { 17'h?, 3'b010, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRC = { 17'h?, 3'b011, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRWI = { 17'h?, 3'b101, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRSI = { 17'h?, 3'b110, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_CSRRCI = { 17'h?, 3'b111, 5'h?, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_ECALL = { 12'b000000000000, 13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_EBREAK = { 12'b000000000001, 13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_MRET = { 12'b001100000010, 13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_DRET = { 12'b011110110010, 13'b0, {OPCODE_SYSTEM} };
-parameter logic [31:0] INSN_WFI = { 12'b000100000101, 13'b0, {OPCODE_SYSTEM} };
+ // SYSTEM
+ parameter logic [31:0] INSN_CSRRW = { 17'h?, 3'b001, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_CSRRS = { 17'h?, 3'b010, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_CSRRC = { 17'h?, 3'b011, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_CSRRWI = { 17'h?, 3'b101, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_CSRRSI = { 17'h?, 3'b110, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_CSRRCI = { 17'h?, 3'b111, 5'h?, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_ECALL = { 12'b000000000000, 13'b0, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_EBREAK = { 12'b000000000001, 13'b0, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_MRET = { 12'b001100000010, 13'b0, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_DRET = { 12'b011110110010, 13'b0, {OPCODE_SYSTEM} };
+ parameter logic [31:0] INSN_WFI = { 12'b000100000101, 13'b0, {OPCODE_SYSTEM} };
-// RV32M
-parameter logic [31:0] INSN_DIV = { 7'b0000001, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_DIVU = { 7'b0000001, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_REM = { 7'b0000001, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_REMU = { 7'b0000001, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMUL = { 7'b0000001, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMUH = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PMULHU = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+ // RV32M
+ parameter logic [31:0] INSN_DIV = { 7'b0000001, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_DIVU = { 7'b0000001, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_REM = { 7'b0000001, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_REMU = { 7'b0000001, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PMUL = { 7'b0000001, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PMUH = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PMULHU = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
-// RV32B
-// ZBB
-parameter logic [31:0] INSN_SLOI = { 5'b00100 , 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
-// fsri.
-parameter logic [31:0] INSN_SROI = { 5'b00100 , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_RORI = { 5'b01100 , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CLZ = { 12'b011000000000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CTZ = { 12'b011000000001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_PCNT = { 12'b011000000010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SEXTB = { 12'b011000000100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SEXTH = { 12'b011000000101, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// The ZEXT.B and ZEXT.H pseudo-instructions are currently not emitted by the tracer due to a lack
-// of support in the LLVM and GCC toolchains. Enabling this functionality when the time is right is
-// tracked in https://github.com/lowRISC/ibex/issues/1228
-// sext -- pseudoinstruction: andi rd, rs 255
-// parameter logic [31:0] INSN_ZEXTB = { 4'b0000, 8'b11111111, 5'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
-// sext -- pseudoinstruction: pack rd, rs zero
-// parameter logic [31:0] INSN_ZEXTH = { 7'b0000100, 5'b00000, 5'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ // RV32B
+ // ZBA
+ parameter logic [31:0] INSN_SH1ADD = { 7'b0010000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SH2ADD = { 7'b0010000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SH3ADD = { 7'b0010000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SLO = { 7'b0010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SRO = { 7'b0010000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ROL = { 7'b0110000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ROR = { 7'b0110000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MIN = { 7'b0000101, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MAX = { 7'b0000101, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MINU = { 7'b0000101, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_MAXU = { 7'b0000101, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_XNOR = { 7'b0100000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ORN = { 7'b0100000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_ANDN = { 7'b0100000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACK = { 7'b0000100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACKU = { 7'b0100100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_PACKH = { 7'b0000100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ // ZBB
+ // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+ // instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
+ // fsri.
+ parameter logic [31:0] INSN_RORI = { 5'b01100 , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CLZ = { 12'b011000000000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CTZ = { 12'b011000000001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CPOP = { 12'b011000000010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SEXTB = { 12'b011000000100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_SEXTH = { 12'b011000000101, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// ZBS
-parameter logic [31:0] INSN_SBCLRI = { 5'b01001, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SBSETI = { 5'b00101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_SBINVI = { 5'b01101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, sbexti is instead decoded as fsri.
-parameter logic [31:0] INSN_SBEXTI = { 5'b01001, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // The zext.h and zext.b pseudo-instructions are defined in the ratified v.1.0.0 and draft v.0.94
+ // specifications of the bitmanip extension, respectively. They are currently not emitted by the
+ // tracer due to a lack of support in the LLVM and GCC toolchains. Enabling this functionality
+ // when the time is right is tracked in https://github.com/lowRISC/ibex/issues/1228
+ // zext.b -- pseudo-instruction: andi rd, rs 255
+ // parameter logic [31:0] INSN_ZEXTB =
+ // { 4'b0000, 8'b11111111, 5'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
+ // zext.h -- pseudo-instruction: pack rd, rs zero
+ // parameter logic [31:0] INSN_ZEXTH = { 7'b0000100, 5'b00000, 5'h?, 3'b100, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBCLR = { 7'b0100100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBSET = { 7'b0010100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBINV = { 7'b0110100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SBEXT = { 7'b0100100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_ROL = { 7'b0110000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_ROR = { 7'b0110000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_MIN = { 7'b0000101, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_MAX = { 7'b0000101, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_MINU = { 7'b0000101, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_MAXU = { 7'b0000101, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_XNOR = { 7'b0100000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_ORN = { 7'b0100000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_ANDN = { 7'b0100000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PACK = { 7'b0000100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PACKU = { 7'b0100100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_PACKH = { 7'b0000100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-// ZBP
-// grevi
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, grevi is instead decoded as fsri.
-parameter logic [31:0] INSN_GREVI = { 5'b01101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// grevi -- pseudo-instructions
-parameter logic [31:0] INSN_REV_P =
- { 5'b01101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_N =
- { 5'b01101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_N =
- { 5'b01101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4_B =
- { 5'b01101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_B =
- { 5'b01101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_B =
- { 5'b01101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV8_H =
- { 5'b01101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4_H =
- { 5'b01101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2_H =
- { 5'b01101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV_H =
- { 5'b01101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV16 =
- { 5'b01101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV8 =
- { 5'b01101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV4 =
- { 5'b01101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV2 =
- { 5'b01101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_REV =
- { 5'b01101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// gorci
-// Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
-// instr[24:20] are effectively used. Whenever instr[26] is set, gorci is instead decoded as fsri.
-parameter logic [31:0] INSN_GORCI = { 5'b00101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// gorci -- pseudo-instructions
-parameter logic [31:0] INSN_ORC_P =
- { 5'b00101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_N =
- { 5'b00101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_N =
- { 5'b00101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4_B =
- { 5'b00101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_B =
- { 5'b00101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_B =
- { 5'b00101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC8_H =
- { 5'b00101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4_H =
- { 5'b00101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2_H =
- { 5'b00101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC_H =
- { 5'b00101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC16 =
- { 5'b00101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC8 =
- { 5'b00101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC4 =
- { 5'b00101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC2 =
- { 5'b00101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ORC =
- { 5'b00101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// shfli
-parameter logic [31:0] INSN_SHFLI = { 6'b000010, 11'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// shfli -- pseudo-instructions
-parameter logic [31:0] INSN_ZIP_N =
- { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2_B =
- { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP_B =
- { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP4_H =
- { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2_H =
- { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP_H =
- { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP8 =
- { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP4 =
- { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP2 =
- { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_ZIP =
- { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// unshfli
-parameter logic [31:0] INSN_UNSHFLI = { 6'b000010, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// unshfli -- pseudo-instructions
-parameter logic [31:0] INSN_UNZIP_N =
- { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2_B =
- { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP_B =
- { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP4_H =
- { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2_H =
- { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP_H =
- { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP8 =
- { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP4 =
- { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP2 =
- { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_UNZIP =
- { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // ZBS
+ parameter logic [31:0] INSN_BCLRI = { 5'b01001, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_BSETI = { 5'b00101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_BINVI = { 5'b01101, 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+ // instr[24:20] are effectively used. Whenever instr[26] is set, bexti is instead decoded as fsri.
+ parameter logic [31:0] INSN_BEXTI = { 5'b01001, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_GREV = { 7'b0110100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_GORC = { 7'b0010100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_SHFL = { 7'b0000100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_UNSHFL = { 7'b0000100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_BCLR = { 7'b0100100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_BSET = { 7'b0010100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_BINV = { 7'b0110100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_BEXT = { 7'b0100100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-// ZBE
-parameter logic [31:0] INSN_BDEP = {7'b0100100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_BEXT = {7'b0000100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ // ZBP
+ // grevi
+ // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+ // instr[24:20] are effectively used. Whenever instr[26] is set, grevi is instead decoded as fsri.
+ parameter logic [31:0] INSN_GREVI = { 5'b01101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // grevi -- pseudo-instructions
+ parameter logic [31:0] INSN_REV_P =
+ { 5'b01101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV2_N =
+ { 5'b01101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV_N =
+ { 5'b01101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV4_B =
+ { 5'b01101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV2_B =
+ { 5'b01101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV_B =
+ { 5'b01101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV8_H =
+ { 5'b01101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV4_H =
+ { 5'b01101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV2_H =
+ { 5'b01101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV_H =
+ { 5'b01101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV16 =
+ { 5'b01101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV8 =
+ { 5'b01101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV4 =
+ { 5'b01101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV2 =
+ { 5'b01101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_REV =
+ { 5'b01101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // gorci
+ // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+ // instr[24:20] are effectively used. Whenever instr[26] is set, gorci is instead decoded as fsri.
+ parameter logic [31:0] INSN_GORCI = { 5'b00101, 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // gorci -- pseudo-instructions
+ parameter logic [31:0] INSN_ORC_P =
+ { 5'b00101, 1'b0, 1'b?, 5'b00001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC2_N =
+ { 5'b00101, 1'b0, 1'b?, 5'b00010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC_N =
+ { 5'b00101, 1'b0, 1'b?, 5'b00011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC4_B =
+ { 5'b00101, 1'b0, 1'b?, 5'b00100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC2_B =
+ { 5'b00101, 1'b0, 1'b?, 5'b00110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC_B =
+ { 5'b00101, 1'b0, 1'b?, 5'b00111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC8_H =
+ { 5'b00101, 1'b0, 1'b?, 5'b01000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC4_H =
+ { 5'b00101, 1'b0, 1'b?, 5'b01100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC2_H =
+ { 5'b00101, 1'b0, 1'b?, 5'b01110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC_H =
+ { 5'b00101, 1'b0, 1'b?, 5'b01111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC16 =
+ { 5'b00101, 1'b0, 1'b?, 5'b10000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC8 =
+ { 5'b00101, 1'b0, 1'b?, 5'b11000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC4 =
+ { 5'b00101, 1'b0, 1'b?, 5'b11100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC2 =
+ { 5'b00101, 1'b0, 1'b?, 5'b11110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ORC =
+ { 5'b00101, 1'b0, 1'b?, 5'b11111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // shfli
+ parameter logic [31:0] INSN_SHFLI = { 6'b000010, 11'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ // shfli -- pseudo-instructions
+ parameter logic [31:0] INSN_ZIP_N =
+ { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP2_B =
+ { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP_B =
+ { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP4_H =
+ { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP2_H =
+ { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP_H =
+ { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP8 =
+ { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP4 =
+ { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP2 =
+ { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_ZIP =
+ { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ // unshfli
+ parameter logic [31:0] INSN_UNSHFLI = { 6'b000010, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ // unshfli -- pseudo-instructions
+ parameter logic [31:0] INSN_UNZIP_N =
+ { 6'b000010, 2'h?, 4'b0001, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP2_B =
+ { 6'b000010, 2'h?, 4'b0010, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP_B =
+ { 6'b000010, 2'h?, 4'b0011, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP4_H =
+ { 6'b000010, 2'h?, 4'b0100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP2_H =
+ { 6'b000010, 2'h?, 4'b0110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP_H =
+ { 6'b000010, 2'h?, 4'b0111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP8 =
+ { 6'b000010, 2'h?, 4'b1000, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP4 =
+ { 6'b000010, 2'h?, 4'b1100, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP2 =
+ { 6'b000010, 2'h?, 4'b1110, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_UNZIP =
+ { 6'b000010, 2'h?, 4'b1111, 5'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// ZBT
-parameter logic [31:0] INSN_FSRI = { 5'h?, 1'b1, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_GREV = { 7'b0110100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_GORC = { 7'b0010100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SHFL = { 7'b0000100, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_UNSHFL = { 7'b0000100, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CMIX = {5'h?, 2'b11, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CMOV = {5'h?, 2'b11, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_FSL = {5'h?, 2'b10, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_FSR = {5'h?, 2'b10, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_XPERM_N = { 7'b0010100, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_XPERM_B = { 7'b0010100, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_XPERM_H = { 7'b0010100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-// ZBF
-parameter logic [31:0] INSN_BFP = {7'b0100100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SLO = { 7'b0010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SRO = { 7'b0010000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_SLOI = { 5'b00100 , 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ // Only log2(XLEN) bits of the immediate are used. For RV32, this means only the bits in
+ // instr[24:20] are effectively used. Whenever instr[26] is set, sroi/rori is instead decoded as
+ // fsri.
+ parameter logic [31:0] INSN_SROI = { 5'b00100 , 1'b0, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// ZBC
-parameter logic [31:0] INSN_CLMUL = {7'b0000101, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CLMULR = {7'b0000101, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
-parameter logic [31:0] INSN_CLMULH = {7'b0000101, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
+ // ZBE
+ parameter logic [31:0] INSN_BDECOMPRESS = {7'b0100100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_BCOMPRESS = {7'b0000100, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
-// ZBR
-parameter logic [31:0] INSN_CRC32_B = {7'b0110000, 5'b10000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32_H = {7'b0110000, 5'b10001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32_W = {7'b0110000, 5'b10010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_B = {7'b0110000, 5'b11000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_H = {7'b0110000, 5'b11001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-parameter logic [31:0] INSN_CRC32C_W = {7'b0110000, 5'b11010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ // ZBT
+ parameter logic [31:0] INSN_FSRI = { 5'h?, 1'b1, 11'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
-// LOAD & STORE
-parameter logic [31:0] INSN_LOAD = {25'h?, {OPCODE_LOAD } };
-parameter logic [31:0] INSN_STORE = {25'h?, {OPCODE_STORE} };
+ parameter logic [31:0] INSN_CMIX = {5'h?, 2'b11, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_CMOV = {5'h?, 2'b11, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_FSL = {5'h?, 2'b10, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_FSR = {5'h?, 2'b10, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
-// MISC-MEM
-parameter logic [31:0] INSN_FENCE = { 17'h?, 3'b000, 5'h?, {OPCODE_MISC_MEM} };
-parameter logic [31:0] INSN_FENCEI = { 17'h0, 3'b001, 5'h0, {OPCODE_MISC_MEM} };
+ // ZBF
+ parameter logic [31:0] INSN_BFP = {7'b0100100, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
-// Compressed Instructions
-// C0
-parameter logic [15:0] INSN_CADDI4SPN = { 3'b000, 11'h?, {OPCODE_C0} };
-parameter logic [15:0] INSN_CLW = { 3'b010, 11'h?, {OPCODE_C0} };
-parameter logic [15:0] INSN_CSW = { 3'b110, 11'h?, {OPCODE_C0} };
+ // ZBC
+ parameter logic [31:0] INSN_CLMUL = {7'b0000101, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_CLMULR = {7'b0000101, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
+ parameter logic [31:0] INSN_CLMULH = {7'b0000101, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
-// C1
-parameter logic [15:0] INSN_CADDI = { 3'b000, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CJAL = { 3'b001, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CJ = { 3'b101, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CLI = { 3'b010, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CLUI = { 3'b011, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CBEQZ = { 3'b110, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CBNEZ = { 3'b111, 11'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CSRLI = { 3'b100, 1'h?, 2'b00, 8'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CSRAI = { 3'b100, 1'h?, 2'b01, 8'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CANDI = { 3'b100, 1'h?, 2'b10, 8'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CSUB = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b00, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CXOR = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b01, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_COR = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b10, 3'h?, {OPCODE_C1} };
-parameter logic [15:0] INSN_CAND = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b11, 3'h?, {OPCODE_C1} };
+ // ZBR
+ parameter logic [31:0] INSN_CRC32_B =
+ {7'b0110000, 5'b10000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CRC32_H =
+ {7'b0110000, 5'b10001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CRC32_W =
+ {7'b0110000, 5'b10010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CRC32C_B =
+ {7'b0110000, 5'b11000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CRC32C_H =
+ {7'b0110000, 5'b11001, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
+ parameter logic [31:0] INSN_CRC32C_W =
+ {7'b0110000, 5'b11010, 5'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
-// C2
-parameter logic [15:0] INSN_CSLLI = { 3'b000, 11'h?, {OPCODE_C2} };
-parameter logic [15:0] INSN_CLWSP = { 3'b010, 11'h?, {OPCODE_C2} };
-parameter logic [15:0] INSN_SWSP = { 3'b110, 11'h?, {OPCODE_C2} };
-parameter logic [15:0] INSN_CMV = { 3'b100, 1'b0, 10'h?, {OPCODE_C2} };
-parameter logic [15:0] INSN_CADD = { 3'b100, 1'b1, 10'h?, {OPCODE_C2} };
-parameter logic [15:0] INSN_CEBREAK = { 3'b100, 1'b1, 5'h0, 5'h0, {OPCODE_C2} };
-parameter logic [15:0] INSN_CJR = { 3'b100, 1'b0, 5'h0, 5'h0, {OPCODE_C2} };
-parameter logic [15:0] INSN_CJALR = { 3'b100, 1'b1, 5'h?, 5'h0, {OPCODE_C2} };
+ // LOAD & STORE
+ parameter logic [31:0] INSN_LOAD = {25'h?, {OPCODE_LOAD } };
+ parameter logic [31:0] INSN_STORE = {25'h?, {OPCODE_STORE} };
+
+ // MISC-MEM
+ parameter logic [31:0] INSN_FENCE = { 17'h?, 3'b000, 5'h?, {OPCODE_MISC_MEM} };
+ parameter logic [31:0] INSN_FENCEI = { 17'h0, 3'b001, 5'h0, {OPCODE_MISC_MEM} };
+
+ // Compressed Instructions
+ // C0
+ parameter logic [15:0] INSN_CADDI4SPN = { 3'b000, 11'h?, {OPCODE_C0} };
+ parameter logic [15:0] INSN_CLW = { 3'b010, 11'h?, {OPCODE_C0} };
+ parameter logic [15:0] INSN_CSW = { 3'b110, 11'h?, {OPCODE_C0} };
+
+ // C1
+ parameter logic [15:0] INSN_CADDI = { 3'b000, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CJAL = { 3'b001, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CJ = { 3'b101, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CLI = { 3'b010, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CLUI = { 3'b011, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CBEQZ = { 3'b110, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CBNEZ = { 3'b111, 11'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CSRLI = { 3'b100, 1'h?, 2'b00, 8'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CSRAI = { 3'b100, 1'h?, 2'b01, 8'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CANDI = { 3'b100, 1'h?, 2'b10, 8'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CSUB = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b00, 3'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CXOR = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b01, 3'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_COR = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b10, 3'h?, {OPCODE_C1} };
+ parameter logic [15:0] INSN_CAND = { 3'b100, 1'b0, 2'b11, 3'h?, 2'b11, 3'h?, {OPCODE_C1} };
+
+ // C2
+ parameter logic [15:0] INSN_CSLLI = { 3'b000, 11'h?, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CLWSP = { 3'b010, 11'h?, {OPCODE_C2} };
+ parameter logic [15:0] INSN_SWSP = { 3'b110, 11'h?, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CMV = { 3'b100, 1'b0, 10'h?, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CADD = { 3'b100, 1'b1, 10'h?, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CEBREAK = { 3'b100, 1'b1, 5'h0, 5'h0, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CJR = { 3'b100, 1'b0, 5'h0, 5'h0, {OPCODE_C2} };
+ parameter logic [15:0] INSN_CJALR = { 3'b100, 1'b1, 5'h?, 5'h0, {OPCODE_C2} };
endpackage
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
index b3317c0..d0a2360 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv
@@ -34,6 +34,8 @@
output logic [31:0] pc_wb_o,
output logic perf_instr_ret_wb_o,
output logic perf_instr_ret_compressed_wb_o,
+ output logic perf_instr_ret_wb_spec_o,
+ output logic perf_instr_ret_compressed_wb_spec_o,
input logic [4:0] rf_waddr_id_i,
input logic [31:0] rf_wdata_id_i,
@@ -61,7 +63,7 @@
logic [31:0] rf_wdata_wb_mux [2];
logic [1:0] rf_wdata_wb_mux_we;
- if(WritebackStage) begin : g_writeback_stage
+ if (WritebackStage) begin : g_writeback_stage
logic [31:0] rf_wdata_wb_q;
logic rf_we_wb_q;
logic [4:0] rf_waddr_wb_q;
@@ -86,7 +88,7 @@
assign wb_done = (wb_instr_type_q == WB_INSTR_OTHER) | lsu_resp_valid_i;
always_ff @(posedge clk_i or negedge rst_ni) begin
- if(~rst_ni) begin
+ if (!rst_ni) begin
wb_valid_q <= 1'b0;
end else begin
wb_valid_q <= wb_valid_d;
@@ -144,10 +146,15 @@
assign instr_done_wb_o = wb_valid_q & wb_done;
- // Increment instruction retire counters for valid instructions which are not lsu errors
- assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q &
- ~(lsu_resp_valid_i & lsu_resp_err_i);
- assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q;
+ // Increment instruction retire counters for valid instructions which are not lsu errors.
+ // Speculative versions of the signals do not factor in exceptions and whether the instruction
+ // is done yet. These are used to get correct values for instructions reading the relevant
+ // performance counters in the ID stage.
+ assign perf_instr_ret_wb_spec_o = wb_count_q;
+ assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q;
+ assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q &
+ ~(lsu_resp_valid_i & lsu_resp_err_i);
+ assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q;
// Forward data that will be written to the RF back to ID to resolve data hazards. The flopped
// rf_wdata_wb_q is used rather than rf_wdata_wb_o as the latter includes read data from memory
@@ -159,10 +166,14 @@
assign rf_wdata_wb_mux[0] = rf_wdata_id_i;
assign rf_wdata_wb_mux_we[0] = rf_we_id_i;
- // Increment instruction retire counters for valid instructions which are not lsu errors
- assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i &
- ~(lsu_resp_valid_i & lsu_resp_err_i);
- assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i;
+ // Increment instruction retire counters for valid instructions which are not lsu errors.
+ // The speculative signals are always 0 when no writeback stage is present as the raw counter
+ // values will be correct.
+ assign perf_instr_ret_wb_spec_o = 1'b0;
+ assign perf_instr_ret_compressed_wb_spec_o = 1'b0;
+ assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i &
+ ~(lsu_resp_valid_i & lsu_resp_err_i);
+ assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i;
// ready needs to be constant 1 without writeback stage (otherwise ID/EX stage will stall)
assign ready_wb_o = 1'b1;
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
index 07359c4..80f9443 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
@@ -14,7 +14,7 @@
write_sdc_out $lr_synth_sdc_file_in $lr_synth_sdc_file_out
}
-yosys "read_verilog -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
+yosys "read_verilog -defer -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
if { $lr_synth_ibex_branch_target_alu } {
yosys "chparam -set BranchTargetALU 1 $lr_synth_top_module"
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
index 66c7185..88dadea 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
@@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
- rev: 59dcd8c813484eb6dcca67e7e36089fe772b9cc8
+ rev: 605301400555c235564f9336cc5fc220af7e951c
}
}
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md
new file mode 100644
index 0000000..09c9dc8
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/README.md
@@ -0,0 +1,99 @@
+## Overview
+
+RISCV-DV-PyFlow is a purely Python based open-source instruction generator for RISC-V processor
+verification. It uses [PyVSC](https://github.com/fvutils/pyvsc) as the main library for
+randomization and coverage collection. It currently supports the following features:
+
+- Supported instruction set: RV32IMAFDC
+- Supported privileged modes: For now only machine mode is supported.
+- Illegal instruction and HINT instruction generation
+- Random forward/backward branch instructions
+- Supports mixing directed instructions with random instruction stream
+- Support for direct & vectored interrupt table.
+- Multi-hart support
+- Functional coverage framework (reports GUI as well as text, currently
+ supports RV32IMFDC extensions)
+- Supported ISS : Spike, OVPsim
+
+## Supported tests
+
+- riscv_arithmetic_basic_test
+- riscv_amo_test
+- riscv_floating_point_arithmetic_test
+- riscv_floating_point_rand_test
+- riscv_floating_point_mmu_stress_test
+- riscv_b_ext_test
+- riscv_rand_instr_test
+- riscv_jump_stress_test
+- riscv_rand_jump_test
+- riscv_mmu_stress_test
+- riscv_illegal_instr_test
+- riscv_unaligned_load_store_test
+- riscv_single_hart_test
+- riscv_non_compressed_instr_test
+- riscv_loop_test
+
+
+## Getting Started
+
+### Prerequisites
+
+To be able to run the generator, you need to have RISCV-GCC compiler toolchain and ISS
+(Instruction Set Simulator) installed (Spike is preferred).
+
+
+### Install RISCV-DV-PyFlow
+
+Getting the source
+```bash
+git clone https://github.com/google/riscv-dv.git
+```
+
+```bash
+pip3 install -r requirements.txt # install dependencies (only once)
+python3 run.py --help
+```
+
+## Running the Generator
+
+Command to run a single test:
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow
+```
+--simulator=pyflow will invoke the Python generator.
+
+Run a single test 10 times
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --iterations=10 --simulator=pyflow
+```
+Run the generator only, do not compile and simluation with ISS
+```bash
+python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow --steps gen
+```
+## Coverage Model
+The coverage model of PyFlow is developed using PyVSC library.
+
+Command to generate the coverage report.
+#### Process spike simulation log and collect functional coverage
+```bash
+python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization
+```
+--enable_visualization helps enabling coverage report visualization for pyflow.
+#### Get the command reference
+```bash
+cov --help
+```
+#### Run the coverage flow with predefined targets
+```bash
+python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization --target rv32imc
+```
+The coverage reports can be viewed using two ways:
+1) Text format: By opening the CoverageReport.txt file.
+2) GUI format: By opening the cov_db.xml using pyucis-viewer.
+The GUI format could be enabled using "--enable_visualization" command option.
+```bash
+pyucis-viewer cov_db.xml
+```
+## Note
+Currently, time to generate a single program with larger than 10k instructions is around
+12 minutes. We are working on improving the overall performance.
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
index 9ed8f85..8b89abd 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py
@@ -223,6 +223,6 @@
def get_c_opcode(self):
pass
- # TOD0
+ # TODO
def get_func3(self):
pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
index a5e75c4..a8cff5a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py
@@ -19,11 +19,11 @@
import logging
from importlib import import_module
from enum import Enum, IntEnum, auto
-from bitstring import BitArray
from pygen_src.riscv_instr_pkg import *
from pygen_src.riscv_instr_gen_config import cfg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+
class operand_sign_e(IntEnum):
POSITIVE = 0
NEGATIVE = auto()
@@ -35,6 +35,11 @@
DIV_OVERFLOW = auto()
+class div_result_ex_overflow_e(IntEnum):
+ DIV_NORMAL = 0
+ DIV_BY_ZERO = auto()
+
+
class compare_result_e(IntEnum):
EQUAL = 0
LARGER = auto()
@@ -142,7 +147,7 @@
if self.imm_type.name == "UIMM":
self.imm_len = 5
else:
- self.imm_len = 11
+ self.imm_len = 12
def set_mode(self):
# mode setting for Instruction Format
@@ -320,10 +325,11 @@
the result of the check_hazard_condition won't be accurate. Need to
explicitly extract the destination register from the operands '''
if pre_instr.has_rd:
- if ((self.has_rs1 and self.rs1 == pre_instr.rd) or
- (self.has_rs2 and self.rs1 == pre_instr.rd)):
+ if ((self.has_rs1 and (self.rs1 == pre_instr.rd)) or
+ (self.has_rs2 and (self.rs1 == pre_instr.rd))):
+ logging.info("pre_instr {}".format(pre_instr.instr.name))
self.gpr_hazard = hazard_e["RAW_HAZARD"]
- elif self.has_rd and self.rd == pre_instr.rd:
+ elif self.has_rd and (self.rd == pre_instr.rd):
self.gpr_hazard = hazard_e["WAW_HAZARD"]
elif (self.has_rd and
((pre_instr.has_rs1 and (pre_instr.rs1 == self.rd)) or
@@ -333,16 +339,16 @@
self.gpr_hazard = hazard_e["NO_HAZARD"]
if self.category == riscv_instr_category_t.LOAD:
if (pre_instr.category == riscv_instr_category_t.STORE and
- pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+ (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["RAW_HAZARD"]
else:
self.lsu_hazard = hazard_e["NO_HAZARD"]
if self.category == riscv_instr_category_t.STORE:
if (pre_instr.category == riscv_instr_category_t.STORE and
- pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+ (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["WAW_HAZARD"]
elif (pre_instr.category == riscv_instr_category_t.LOAD and
- pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
+ (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["WAR_HAZARD"]
else:
self.lsu_hazard = hazard_e["NO_HAZARD"]
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
index 4d4dcba..3169c5b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py
@@ -116,7 +116,7 @@
self.has_fs1 = 0
self.has_fd = 0
else:
- logging.info("Unsupported format %0s", self.format.name)
+ logging.info("Unsupported format {}".format(self.format.name))
def pre_randomize(self):
super().pre_randomize()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
index 74d922c..b592511 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import logging
@@ -110,12 +108,32 @@
with vsc.if_then(self.XLEN != 32):
self.imm[11:6] == 0
+ @vsc.constraint
+ def csr_c(self):
+ # TODO
+ pass
+
@classmethod
def register(cls, instr_name, instr_group):
logging.info("Registering {}".format(instr_name.name))
cls.instr_registry[instr_name] = instr_group
return 1
+ def __deepcopy__(self, memo):
+ cls = self.__class__ # Extract the class of the object.
+ # Create a new instance of the object based on extracted class.
+ result = cls.__new__(cls)
+ memo[id(self)] = result
+ for k, v in self.__dict__.items():
+ if k in ["_ro_int", "tname", "__field_info"]:
+ continue # Skip the fields which are not required.
+ else:
+ # Copy over attributes by copying directly.
+ setattr(result, k, copy.deepcopy(v, memo))
+ return result
+
+ # Create the list of instructions based on the supported ISA extensions and configuration
+ # of the generator
@classmethod
def create_instr_list(cls, cfg):
cls.instr_names.clear()
@@ -129,6 +147,7 @@
if not instr_inst.is_supported(cfg):
continue
+ # C_JAL is RV32C only instruction
if ((rcs.XLEN != 32) and (instr_name == riscv_instr_name_t.C_JAL)):
continue
if ((riscv_reg_t.SP in cfg.reserved_regs) and
@@ -310,7 +329,7 @@
if self.imm_type.name == "UIMM":
self.imm_len = 5
else:
- self.imm_len = 11
+ self.imm_len = 12
self.imm_mask = (self.imm_mask << self.imm_len) & self.shift_t
def extend_imm(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
index f3f1b5e..46f8a21 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
@@ -14,13 +14,13 @@
import vsc
import random
from importlib import import_module
+from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.isa.riscv_instr import riscv_instr
+from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
from pygen_src.riscv_directed_instr_lib import riscv_mem_access_stream
from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t,
riscv_instr_name_t, riscv_instr_category_t,
riscv_instr_group_t)
-from pygen_src.riscv_instr_gen_config import cfg
-from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
-from pygen_src.isa.riscv_instr import riscv_instr
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
@@ -62,7 +62,6 @@
@vsc.constraint
def aligned_amo_c(self):
-
with vsc.foreach(self.offset, idx = True) as i:
with vsc.if_then(self.XLEN == 32):
self.offset[i] % 4 == 0
@@ -73,7 +72,7 @@
self.data_page = cfg.amo_region
max_data_page_id = len(self.data_page)
self.data_page_id = random.randrange(0, max_data_page_id - 1)
- self.max_offset = self.data_page[self.data_page_id]['size_in_bytes']
+ self.max_offset = self.data_page[self.data_page_id].size_in_bytes
# Use "la" instruction to initialize the offset regiseter
def init_offset_reg(self):
@@ -81,7 +80,7 @@
la_instr = riscv_pseudo_instr()
la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA
la_instr.rd = self.rs1_reg[i]
- la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id]['name'],
+ la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id].name,
self.offset[i])
self.instr_list.insert(0, la_instr)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
index cf751b3..4d8c180 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import logging
@@ -31,35 +29,43 @@
from pygen_src.riscv_utils import factory
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
-'''
- RISC-V assembly program generator
- This is the main class to generate a complete RISC-V program, including the init routine,
- instruction section, data section, stack section, page table, interrupt and exception
- handling etc. Check gen_program() function to see how the program is generated.
-'''
+# ----------------------------------------------------------------------------------
+# RISC-V assembly program generator
+
+# This is the main class to generate a complete RISC-V program, including the init routine,
+# instruction section, data section, stack section, page table, interrupt and exception
+# handling etc. Check gen_program() function to see how the program is generated.
+# ----------------------------------------------------------------------------------
+@vsc.randobj
class riscv_asm_program_gen:
def __init__(self):
self.instr_stream = []
+ # Directed instruction ratio, occurance per 1000 instructions
self.directed_instr_stream_ratio = {}
self.hart = 0
self.page_table_list = []
self.main_program = []
self.sub_program = []
self.data_page_gen = None
+ self.spf_val = vsc.rand_bit_t(32)
+ self.dpf_val = vsc.rand_bit_t(64)
+ # ----------------------------------------------------------------------------------
# Main function to generate the whole program
+ # ----------------------------------------------------------------------------------
# This is the main function to generate all sections of the program.
def gen_program(self):
- # Generate program header
self.instr_stream.clear()
+ # Generate program header
self.gen_program_header()
for hart in range(cfg.num_of_harts):
# Commenting out for now
+ # TODO support for sub_program
# sub_program_name = []
self.instr_stream.append(f"h{int(hart)}_start:")
if not cfg.bare_program_mode:
@@ -70,7 +76,6 @@
self.pre_enter_privileged_mode(hart)
# Init section
self.gen_init_section(hart)
- # To DO
'''
If PMP is supported, we want to generate the associated trap handlers and the test_done
section at the start of the program so we can allow access through the pmpcfg0 CSR
@@ -87,7 +92,8 @@
self.gen_store_fault_handler(hart)
if hart == 0:
self.gen_test_done()
-
+ # Generate sub program
+ # TODO gen_sub_program()
# Generate main program
gt_lbl_str = pkg_ins.get_label("main", hart)
label_name = gt_lbl_str
@@ -103,8 +109,10 @@
min_insert_cnt=1,
instr_stream=self.main_program[hart].directed_instr)
self.main_program[hart].gen_instr(is_main_program=1, no_branch=cfg.no_branch_jump)
-
+ # Setup jump instruction among main program and sub programs
+ # TODO gen_callstack()
self.main_program[hart].post_process_instr()
+ logging.info("Post-processing main program...done")
self.main_program[hart].generate_instr_stream()
logging.info("Generating main program instruction stream...done")
self.instr_stream.extend(self.main_program[hart].instr_string_list)
@@ -113,14 +121,14 @@
to test_done section at the end of main_program, as the test_done
will have moved to the beginning of the program
"""
- self.instr_stream.append("{}j test_done".format(pkg_ins.indent))
- '''
- Test done section
- If PMP isn't supported, generate this in the normal location
- '''
+ self.instr_stream.extend(("{}la x{}, test_done".format(pkg_ins.indent, cfg.scratch_reg),
+ "{}jalr x0, x{}, 0".format(pkg_ins.indent, cfg.scratch_reg)))
+ # Test done section
+ # If PMP isn't supported, generate this in the normal location
if(hart == 0 and not(rcs.support_pmp)):
self.gen_test_done()
-
+ # Shuffle the sub programs and insert to the instruction stream
+ # TODO inser_sub_program()
logging.info("Main/sub program generation...done")
# program end
self.gen_program_end(hart)
@@ -138,6 +146,7 @@
# AMO memory region
if(hart == 0 and riscv_instr_group_t.RV32A in rcs.supported_isa):
self.gen_data_page(hart, amo = 1)
+ # Stack section
self.gen_stack_section(hart)
if not cfg.bare_program_mode:
# Generate kernel program/data/stack section
@@ -145,6 +154,10 @@
# Page table
self.gen_page_table_section(hart)
+ # ----------------------------------------------------------------------------------
+ # Generate kernel program/data/stack sections
+ # ----------------------------------------------------------------------------------
+
def gen_kernel_sections(self, hart):
if rcs.SATP_MODE != satp_mode_t.BARE:
self.instr_stream.append(".align 12")
@@ -152,56 +165,84 @@
self.instr_stream.append(".align 2")
self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart))
self.instr_stream.append(".text")
+ # Kernel programs
+ # TODO
+ # All trap/interrupt handling is in the kernel region
+ # Trap/interrupt delegation to user mode is not supported now
+ # Trap handler
self.gen_all_trap_handler(hart)
+ # Interrupt handling subroutine
for mode in rcs.supported_privileged_mode:
self.gen_interrupt_handler_section(mode, hart)
self.instr_stream.append(pkg_ins.get_label("kernel_instr_end: nop", hart))
+ # User stack and data pages may not be accessible when executing trap handling programs in
+ # machine/supervisor mode. Generate separate kernel data/stack sections to solve it.
+ if not cfg.virtual_addr_translation_on:
+ if rcs.SATP_MODE != satp_mode_t.BARE:
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align 2")
+ # Kernel data pages
+ self.instr_stream.append(pkg_ins.get_label("kernel_data_start:", hart))
+ if not cfg.no_data_page:
+ # Data section
+ self.gen_data_page(hart, 1)
+ # Kernel stack section
self.gen_kernel_stack_section(hart)
def gen_kernel_program(self, hart, seq):
+ # TODO
pass
+ # ----------------------------------------------------------------------------------
+ # Generate any subprograms and set up the callstack
+ # ----------------------------------------------------------------------------------
+
def gen_sub_program(self, hart, sub_program,
sub_program_name, num_sub_program,
is_debug = 0, prefix = "sub"):
+ # TODO
pass
def gen_callstack(self, main_program, sub_program,
sub_program_name, num_sub_program):
+ # TODO
pass
def insert_sub_program(self, sub_program, instr_list):
+ # TODO
pass
+ # ----------------------------------------------------------------------------------
+ # Major sections - init, stack, data, test_done etc.
+ # ----------------------------------------------------------------------------------
def gen_program_header(self):
- string = []
- self.instr_stream.append(".include \"user_define.h\"")
- self.instr_stream.append(".globl _start")
- self.instr_stream.append(".section .text")
+ header_string = []
+ self.instr_stream.extend((".include \"user_define.h\"", ".globl _start", ".section .text"))
if cfg.disable_compressed_instr:
self.instr_stream.append(".option norvc;")
- string.append(".include \"user_init.s\"")
- string.append("csrr x5, mhartid")
-
+ header_string.extend((".include \"user_init.s\"",
+ "csrr x5, {}".format(hex(privileged_reg_t.MHARTID))))
for hart in range(cfg.num_of_harts):
- string.append("li x6, {}\n{}beq x5, x6, {}f".format(hart, pkg_ins.indent, hart))
-
- self.gen_section("_start", string)
-
+ header_string.extend(("li x6, {}".format(hart),
+ "beq x5, x6, {}f".format(hart)))
+ self.gen_section("_start", header_string)
for hart in range(cfg.num_of_harts):
- self.instr_stream.append("{}: j h{}_start".format(hart, hart))
+ self.instr_stream.extend(("{}: la x{}, h{}_start".format(hart, cfg.scratch_reg, hart),
+ "jalr x0, x{}, 0".format(cfg.scratch_reg)))
def gen_program_end(self, hart):
if hart == 0:
+ # Use write_tohost to terminate spike simulation
self.gen_section("write_tohost", ["sw gp, tohost, t5"])
self.gen_section("_exit", ["j write_tohost"])
def gen_data_page_begin(self, hart):
self.instr_stream.append(".section .data")
if hart == 0:
- self.instr_stream.append(".align 6; .global tohost; tohost: .dword 0;")
- self.instr_stream.append(".align 6; .global fromhost; fromhost: .dword 0;")
+ self.instr_stream.extend((".align 6; .global tohost; tohost: .dword 0;",
+ ".align 6; .global fromhost; fromhost: .dword 0;"))
def gen_data_page(self, hart, is_kernel = 0, amo = 0):
self.data_page_gen = riscv_data_page_gen()
@@ -221,15 +262,15 @@
else:
self.instr_stream.append(".align 2")
- self.instr_stream.append(pkg_ins.get_label("user_stack_start:", hart))
- self.instr_stream.append(".rept {}".format(cfg.stack_len - 1))
- self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
- self.instr_stream.append(".endr")
- self.instr_stream.append(pkg_ins.get_label("user_stack_end:", hart))
- self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ self.instr_stream.extend((pkg_ins.get_label("user_stack_start:", hart),
+ ".rept {}".format(cfg.stack_len - 1),
+ ".{}byte 0x0".format(rcs.XLEN // 8), ".endr",
+ pkg_ins.get_label("user_stack_end:", hart),
+ ".{}byte 0x0".format(rcs.XLEN // 8)))
if cfg.use_push_data_section:
- self.instr_stream.push_back(".popsection;")
+ self.instr_stream.append(".popsection;")
+ # The kernal stack is used to save user program context before executing exception handling
def gen_kernel_stack_section(self, hart):
hart_prefix_string = pkg_ins.hart_prefix(hart)
if cfg.use_push_data_section:
@@ -242,33 +283,31 @@
self.instr_stream.append(".align 12")
else:
self.instr_stream.append(".align 2")
-
- self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart))
- self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1))
- self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
- self.instr_stream.append(".endr")
- self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart))
- self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ self.instr_stream.extend((pkg_ins.get_label("kernel_stack_start:", hart),
+ ".rept {}".format(cfg.stack_len - 1),
+ ".{}byte 0x0".format(rcs.XLEN // 8), ".endr",
+ pkg_ins.get_label("kernel_stack_end:", hart),
+ ".{}byte 0x0".format(rcs.XLEN // 8)))
if cfg.use_push_data_section:
- self.instr_stream.push_back(".popsection;")
+ self.instr_stream.append(".popsection;")
def gen_init_section(self, hart):
- string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
- self.instr_stream.append(string)
+ init_string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN)
+ self.instr_stream.append(init_string)
if cfg.enable_floating_point:
self.init_floating_point_gpr()
self.init_gpr()
# Init stack pointer to point to the end of the user stack
- string = "{}la x{}, {}user_stack_end".format(
+ init_string = "{}la x{}, {}user_stack_end".format(
pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart))
- self.instr_stream.append(string)
+ self.instr_stream.append(init_string)
if cfg.enable_vector_extension:
- self.init_vector_engine()
+ self.randomize_vec_gpr_and_csr()
self.core_is_initialized()
self.gen_dummy_csr_write()
if rcs.support_pmp:
- string = pkg_ins.indent + "j main"
- self.instr_stream.append(string)
+ init_string = pkg_ins.indent + "j main"
+ self.instr_stream.append(init_string)
# Setup MISA based on supported extensions
def setup_misa(self):
@@ -316,21 +355,37 @@
else:
logging.critical("{} is not yet supported".format(group.name))
sys.exit(1)
- if privileged_mode_t.SUPERVISOR_MODE.name in rcs.supported_privileged_mode:
+ if privileged_mode_t.SUPERVISOR_MODE in rcs.supported_privileged_mode:
misa[misa_ext_t.MISA_EXT_S] = 1
- self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0],
- hex(misa.get_val())))
- self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, hex(privileged_reg_t.MISA),
- cfg.gpr[0]))
+ self.instr_stream.extend(("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0],
+ hex(misa.get_val())),
+ "{}csrw {}, x{}".format(pkg_ins.indent,
+ hex(privileged_reg_t.MISA), cfg.gpr[0])))
+ # Write to the signature_addr with values to indicate to the core testbench
+ # that is safe to start sending interrupt and debug stimulus
def core_is_initialized(self):
- pass
+ instr = []
+ if cfg.require_signature_addr:
+ if cfg.signature_addr != 0xdeadbeef:
+ self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+ core_status_t.INITIALIZED)
+ self.format_section(instr)
+ self.instr_stream.append(instr)
+ else:
+ logging.critical("The signature_addr is not properly configured!")
+ sys.exit(1)
+ # Generate some dummy writes to xSTATUS/xIE at the beginning of the test to check
+ # repeated writes to these CSRs.
def gen_dummy_csr_write(self):
+ # TODO
pass
+ # Initialize general purpose registers with random value
def init_gpr(self):
reg_val = vsc.rand_bit_t(pkg_ins.DATA_WIDTH)
+ # Init general purpose registers with random values
for i in range(rcs.NUM_GPR):
if i in [cfg.sp.value, cfg.tp.value]:
continue
@@ -343,19 +398,25 @@
except Exception:
logging.critical("Cannot Randomize reg_val")
sys.exit(1)
- init_string = "{}li x{}, {}".format(pkg_ins.indent, i, hex(reg_val.get_val()))
- self.instr_stream.append(init_string)
+ self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, i,
+ hex(reg_val.get_val())))
+ # Initialize vector general purpose registers
+ def init_vec_gpr(self):
+ # TODO
+ pass
+
+ # Initialize floating point general purpose registers
def init_floating_point_gpr(self):
for i in range(rcs.NUM_FLOAT_GPR):
vsc.randselect([
(1, lambda: self.init_floating_point_gpr_with_spf(i)),
(riscv_instr_group_t.RV64D in rcs.supported_isa,
lambda: self.init_floating_point_gpr_with_dpf(i))])
- # Initialize rounding mode of FCSR
- fsrmi_instr = "{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm)
- self.instr_stream.append(fsrmi_instr)
+ # Initialize rounding mode of FCSR and append to the instr_stream
+ self.instr_stream.append("{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm))
+ # get instructions initialize floating_point_gpr with single precision floating value
def init_floating_point_gpr_with_spf(self, int_floating_gpr):
imm = self.get_rand_spf_value()
li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0], hex(imm))
@@ -363,6 +424,7 @@
cfg.gpr[0])
self.instr_stream.extend((li_instr, fmv_instr))
+ # get instructions initialize floating_point_gpr with double precision floating value
def init_floating_point_gpr_with_dpf(self, int_floating_gpr):
imm = vsc.bit_t(64)
imm = self.get_rand_dpf_value()
@@ -378,114 +440,205 @@
fmv_instr = "{}fmv.d.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr, int_gpr2)
self.instr_stream.extend((li_instr0, slli_instr, li_instr1, or_instr, fmv_instr))
- # Get a random single precision floating value
+ def get_randselect(self, addr_range1, addr_range2, flag):
+ if flag:
+ # Get a random double precision floating value
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.dpf_val):
+ self.dpf_val in vsc.rangelist(addr_range1, addr_range2)
+ else:
+ # Get a random single precision floating value
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.spf_val):
+ self.spf_val in vsc.rangelist(addr_range1, addr_range2)
+
+ def get_rng(self, val0, val1, spf_dpf, flag):
+ if flag == 0 and spf_dpf == 32:
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] > 0
+ elif flag == 0 and spf_dpf == 64:
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] > 0
+ elif flag == 1 and spf_dpf == 32:
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] == 0
+ else:
+ with vsc.raw_mode():
+ with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] == 0
+
def get_rand_spf_value(self):
- # TODO randcase
- value = random.randrange(0, 2**32 - 1)
- return value
+ vsc.randselect([
+ # Infinity
+ (1, lambda: self.get_randselect(0x7f80_0000, 0xff80_0000, 0)),
+ # Largest
+ (1, lambda: self.get_randselect(0x7f7f_ffff, 0xff7f_ffff, 0)),
+ # Zero
+ (1, lambda: self.get_randselect(0x0000_0000, 0x8000_0000, 0)),
+ # NaN
+ (1, lambda: self.get_randselect(0x7f80_0001, 0x7fc0_0000, 0)),
+ # Normal
+ (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 0)),
+ # Subnormal
+ (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 1))])
+ return self.spf_val
- # Get a random double precision floating value
def get_rand_dpf_value(self):
- value = vsc.bit_t(64)
- # TODO randcase
- return value
+ vsc.randselect([
+ # Infinity
+ (1, lambda: self.get_randselect(0x7ff0_0000_0000_0000, 0xfff0_0000_0000_0000, 1)),
+ # largest
+ (1, lambda: self.get_randselect(0x7fef_ffff_ffff_ffff, 0xffef_ffff_ffff_ffff, 1)),
+ # Zero
+ (1, lambda: self.get_randselect(0x0000_0000_0000_0000, 0x8000_0000_0000_0000, 1)),
+ # NaN
+ (1, lambda: self.get_randselect(0x7ff0_0000_0000_0001, 0x7ff8_0000_0000_0000, 1)),
+ # Normal
+ (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64 , 0)),
+ # Subnormal
+ (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64, 1))])
+ return self.dpf_val
- def init_vector_engine(self):
- pass
+ # Generate "test_done" section, test is finished by an ECALL instruction
+ # The ECALL trap handler will handle the clean up procedure before finishing the test.
def gen_test_done(self):
- string = pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN)
- self.instr_stream.append(string)
- self.instr_stream.append(pkg_ins.indent + "li gp, 1")
-
+ self.instr_stream.extend((pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN),
+ pkg_ins.indent + "li gp, 1"))
if cfg.bare_program_mode:
self.instr_stream.append(pkg_ins.indent + "j write_tohost")
else:
self.instr_stream.append(pkg_ins.indent + "ecall")
- def gen_register_dump(self):
- string = ""
+ # Dump all GPR to the starting point of the program
+ # TB can check the GPR value for this memory location to compare with expected value generated
+ # by the ISA simulator. If the processor doesn't have a good tracer unit, it might not be
+ # possible to compare the GPR value after each instruction execution.
+ def gen_register_dump(self, instr):
# load base address
- string = "{}la x{}, _start".format(pkg_ins.indent, cfg.gpr[0])
- self.instr_stream.append(string)
-
+ instr.append("la x{}, _start".format(cfg.gpr[0]))
# Generate sw/sd instructions
for i in range(32):
if rcs.XLEN == 64:
- string = "{}sd x{}, {}(x{})".format(
- pkg_ins.indent, i, i * (rcs.XLEN / 8), cfg.gpr[0])
+ dump_str = "sd x{}, {}(x{})".format(i, i * (rcs.XLEN // 8), cfg.gpr[0])
else:
- string = "{}sw x{}, {}(x{})".format(
- pkg_ins.indent, i, int(i * (rcs.XLEN / 8)), cfg.gpr[0])
- self.instr_stream.append(string)
+ dump_str = "sw x{}, {}(x{})".format(i, i * (rcs.XLEN // 8), cfg.gpr[0])
+ instr.append(dump_str)
+
+ # ----------------------------------------------------------------------------------
+ # Privileged mode entering routine
+ # ----------------------------------------------------------------------------------
def pre_enter_privileged_mode(self, hart):
instr = []
- string = []
-
- string.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart)))
- self.gen_section(pkg_ins.get_label("kernel_sp", hart), string)
-
+ privil_str = []
+ # Setup kernel stack pointer
+ privil_str.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart)))
+ self.gen_section(pkg_ins.get_label("kernel_sp", hart), privil_str)
+ # Setup interrupt and exception delegation
if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE):
self.gen_delegation(hart)
+ # Setup trap vector register
self.trap_vector_init(hart)
+ # Setup PMP CSRs
self.setup_pmp(hart)
-
+ # Generate PMPADDR write test sequence
+ self.gen_pmp_csr_write(hart)
+ # Initialize PTE (link page table based on their real physical address)
if cfg.virtual_addr_translation_on:
- self.page_table_list.process_page_table(instr)
+ # TODO
+ # self.page_table_list.process_page_table(instr)
self.gen_section(pkg_ins.get_label("process_pt", hart), instr)
+ # Setup mepc register, jump to init entry
self.setup_epc(hart)
+ # Initialization of any implementation-specific custom CSRs
+ self.setup_custom_csrs(hart)
+ # Setup initial privilege mode
self.gen_privileged_mode_switch_routine(hart)
def gen_privileged_mode_switch_routine(self, hart):
privil_seq = riscv_privileged_common_seq()
- for i in range(len(rcs.supported_privileged_mode)):
+ for privil_mode in rcs.supported_privileged_mode:
instr = []
# csr_handshake = []
- if rcs.supported_privileged_mode[i] != cfg.init_privileged_mode:
+ if privil_mode != cfg.init_privileged_mode:
continue
logging.info("Generating privileged mode routing for {}"
- .format(rcs.supported_privileged_mode[i]))
+ .format(privil_mode.name))
# Enter Privileged mode
privil_seq.hart = hart
privil_seq.randomize()
- privil_seq.enter_privileged_mode(rcs.supported_privileged_mode[i], instr)
- # TODO
+ privil_seq.enter_privileged_mode(privil_mode, instr)
if cfg.require_signature_addr:
+ # TODO
pass
self.instr_stream.extend(instr)
+ # Setup EPC before entering target privileged mode
def setup_epc(self, hart):
instr = []
instr.append("la x{}, {}init".format(cfg.gpr[0], pkg_ins.hart_prefix(hart)))
+
if cfg.virtual_addr_translation_on:
# For supervisor and user mode, use virtual address instead of physical address.
# Virtual address starts from address 0x0, here only the lower 12 bits are kept
# as virtual address offset.
- instr.append("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12) +
- "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12))
- mode_name = cfg.init_privileged_mode.name
+ instr.extend(("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12),
+ "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12)))
instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0]))
- if not rcs.support_pmp:
- instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower()))
self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
+ # Setup PMP CSR configuration
def setup_pmp(self, hart):
+ # TODO
+ pass
+ # Generates a directed stream of instructions to write random values to all supported
+ # pmpaddr CSRs to test write accessibility.
+ # The original CSR values are restored afterwards.
+
+ def gen_pmp_csr_write(self, hart):
+ # TODO
pass
+ # Handles creation of a subroutine to initialize any custom CSRs
+ def setup_custom_csrs(self, hart):
+ # TODO
+ pass
+
+ # This function should be overridden in the riscv_asm_program_gen extended class
+ # corresponding to the RTL implementation if it has any custom CSRs defined.
+
+ # All that needs to be done in the overridden function is to manually create
+ # the instruction strings to set up any custom CSRs and then to push those strings
+ # into the instr queue.
+ def init_custom_csr(self, instr):
+ # TODO
+ pass
+
+ # ---------------------------------------------------------------------------------------
+ # Privileged CSR setup for interrupt and exception handling and delegation
+ # ---------------------------------------------------------------------------------------
+
+ # Interrupt and exception delegation setting.
+ # The lower level exception and interrupt can be delegated to higher level handler.
def gen_delegation(self, hart):
- self.gen_delegation_instr(hart, "MEDELEG", "MIDELEG",
+ self.gen_delegation_instr(hart,
+ privileged_reg_t.MEDELEG,
+ privileged_reg_t.MIDELEG,
cfg.m_mode_exception_delegation,
cfg.m_mode_interrupt_delegation)
if rcs.support_umode_trap:
- self.gen_delegation_instr(hart, "SEDELEG", "SIDELEG",
+ self.gen_delegation_instr(hart,
+ privileged_reg_t.SEDELEG,
+ privileged_reg_t.SIDELEG,
cfg.s_mode_exception_delegation,
cfg.s_mode_interrupt_delegation)
def gen_delegation_instr(self, hart, edeleg, ideleg,
edeleg_enable, ideleg_enable):
+ # TODO
pass
+ # Setup trap vector - MTVEC, STVEC, UTVEC
def trap_vector_init(self, hart):
instr = []
for mode in rcs.supported_privileged_mode:
@@ -498,43 +651,73 @@
else:
logging.critical("Unsupported privileged_mode {}".format(mode.name))
sys.exit(1)
-
+ # Skip utvec init if trap delegation to u_mode is not supported
if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)):
continue
-
if mode < cfg.init_privileged_mode:
continue
-
tvec_name = trap_vec_reg.name
tvec_name = tvec_name.lower()
instr.append("la x{}, {}{}_handler".format(
cfg.gpr[0], pkg_ins.hart_prefix(hart), tvec_name))
if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE):
+ # For supervisor and user mode, use virtual address instead of physical address.
+ # Virtual address starts from address 0x0, here only the lower 20 bits are kept
+ # as virtual address offset.
instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20) +
"srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20))
- instr.append("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode))
- instr.append("csrw {}, x{} # {}".format(
- hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name))
-
+ instr.extend(("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode),
+ "csrw {}, x{} # {}".format(hex(trap_vec_reg), cfg.gpr[0],
+ trap_vec_reg.name)))
self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
+ # ---------------------------------------------------------------------------------------
+ # Exception handling routine
+ # ---------------------------------------------------------------------------------------
+
+ # Trap handling routine
def gen_all_trap_handler(self, hart):
+ instr = []
+ # If PMP isn't supported, generate the relevant trap handler sections as per usual
if not rcs.support_pmp:
self.gen_trap_handlers(hart)
+ # Ecall handler
self.gen_ecall_handler(hart)
+ # Instruction fault handler
self.gen_instr_fault_handler(hart)
+ # Load fault handler
self.gen_load_fault_handler(hart)
+ # Store fault handler
self.gen_store_fault_handler(hart)
+ # Ebreak handler
+ self.gen_ebreak_handler(hart)
+ # Illegal instruction handler
self.gen_illegal_instr_handler(hart)
+ # Generate page table fault handling routine
+ # Page table fault is always handled in machine mode, as virtual address translation may be
+ # broken when page fault happens.
+ self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
+ core_status_t.HANDLING_EXCEPTION)
+ if not self.page_table_list:
+ # TODO
+ # self.page_table_list.gen_page_fault_handling_routine(instr)
+ pass
+ else:
+ instr.append("nop")
+ self.gen_section(pkg_ins.get_label("pt_fault_handler", hart), instr)
def gen_trap_handlers(self, hart):
+ # TODO
self.gen_trap_handler_section(hart, "m", privileged_reg_t.MCAUSE,
privileged_reg_t.MTVEC, privileged_reg_t.MTVAL,
privileged_reg_t.MEPC, privileged_reg_t.MSCRATCH,
privileged_reg_t.MSTATUS, privileged_reg_t.MIE,
privileged_reg_t.MIP)
+ # Generate the interrupt and trap handler for different privileged mode.
+ # The trap handler checks the xCAUSE to determine the type of the exception and jumps to
+ # corresponding exeception handling routine.
def gen_trap_handler_section(self, hart, mode, cause, tvec,
tval, epc, scratch, status, ie, ip):
# is_interrupt = 1
@@ -546,7 +729,6 @@
# Push user mode GPR to kernel stack before executing exception handling,
# this is to avoid exception handling routine modify user program state
# unexpectedly
- # TODO
pkg_ins.push_gpr_to_kernel_stack(
status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
# Checking xStatus can be optional if ISS (like spike) has different implementation of
@@ -554,6 +736,9 @@
if cfg.check_xstatus:
instr.append("csrr x{}, {} # {}".format(
cfg.gpr[0], hex(status), status.name))
+ # Use scratch CSR to save a GPR value
+ # Check if the exception is caused by an interrupt, if yes, jump to interrupt
+ # handler Interrupt is indicated by xCause[XLEN-1]
instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(cause),
cause.name) +
"{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0],
@@ -564,26 +749,29 @@
mode))
# The trap handler will occupy one 4KB page, it will be allocated one entry in
# the page table with a specific privileged mode.
-
if rcs.SATP_MODE != satp_mode_t.BARE:
self.instr_stream.append(".align 12")
else:
self.instr_stream.append(".align {}".format(cfg.tvec_alignment))
-
tvec_name = tvec.name
self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr)
- # TODO Exception handlers
+
+ # Exception handler
instr = []
if cfg.mtvec_mode == mtvec_mode_t.VECTORED:
- pkg_ins.push_gpr_to_kernel_stack(status, scratch,
- cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
+ pkg_ins.push_gpr_to_kernel_stack(
+ status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
core_status_t.HANDLING_EXCEPTION)
- # The trap is caused by an exception, read back xCAUSE, xEPC to see if these
- # CSR values are set properly. The checking is done by comparing against the log
- # generated by ISA simulator (spike).
- instr.extend(("csrr x{}, 0x{} # {}".format(cfg.gpr[0], epc, epc.name),
- "csrr x{}, 0x{} # {}".format(cfg.gpr[0], cause, cause.name),
+ # TODO
+ instr.extend(("csrr x{}, {} # {}".format(cfg.gpr[0], hex(epc), epc.name),
+ "csrr x{}, {} # {}".format(cfg.gpr[0], hex(cause), cause.name),
+ # Check if it's an ECALL exception. Jump to ECALL exception handler
+ # TODO ECALL_SMODE, ECALL_UMODE
+ "li x{}, {} # ECALL_MMODE".format(cfg.gpr[1],
+ hex(exception_cause_t.ECALL_MMODE)),
+ "beq x{}, x{}, {}ecall_handler".format(
+ cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)),
# Illegal instruction exception
"li x{}, {} # ILLEGAL_INSTRUCTION".format(
cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)),
@@ -596,6 +784,7 @@
"jalr x1, x{}, 0".format(cfg.scratch_reg)))
self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
+ # Generate for interrupt vector table
def gen_interrupt_vector_table(self, hart, mode, status, cause, ie,
ip, scratch, instr):
'''In vector mode, the BASE address is shared between interrupt 0 and exception handling.
@@ -634,21 +823,37 @@
"jalr x0, x{}, 0".format(cfg.scratch_reg)))
self.gen_section(pkg_ins.get_label(
"{}mode_intr_vector_{}".format(mode, i), hart), intr_handler)
+ # ECALL trap handler
+ # It does some clean up like dump GPRs before communicating with host to terminate the test.
+ # User can extend this function if some custom clean up routine is needed.
def gen_ecall_handler(self, hart):
- string = ""
- string = pkg_ins.format_string(pkg_ins.get_label(
- "ecall_handler:", hart), pkg_ins.LABEL_STR_LEN)
- self.instr_stream.append(string)
- self.dump_perf_stats()
- self.gen_register_dump()
- string = pkg_ins.format_string(" ", pkg_ins.LABEL_STR_LEN)
- string = string + "j write_tohost"
- self.instr_stream.append(string)
+ instr = []
+ self.dump_perf_stats(instr)
+ self.gen_register_dump(instr)
+ instr.extend(("la x{}, write_tohost".format(cfg.scratch_reg),
+ "jalr x0, x{}, 0".format(cfg.scratch_reg)))
+ self.gen_section(pkg_ins.get_label("ecall_handler", hart), instr)
+ # Ebreak trap handler
+ # When breakpoint exception happens, epc will be written with ebreak instruction
+ # itself. Add epc by 4 and resume execution.
+ # Note the breakpoint could be triggered by a C.EBREAK instruction, the generated program
+ # guarantees that epc + 4 is a valid instruction boundary
+ # TODO: Support random operations in debug mode
+ # TODO: Support ebreak exception delegation
+ # TODO: handshake the correct Xcause CSR based on delegation privil. mode
def gen_ebreak_handler(self, hart):
+ # TODO
pass
+ # Illegal instruction handler
+ # Note: Save the illegal instruction to MTVAL is optional in the spec, and mepc could be
+ # a virtual address that cannot be used in machine mode handler. As a result, there's no way to
+ # know the illegal instruction is compressed or not. This hanlder just simply adds the PC by
+ # 4 and resumes execution. The way that the illegal instruction is injected guarantees that
+ # PC + 4 is a valid instruction boundary.
+ # TODO: handshake the corret Xcause CSR based on delegation setup
def gen_illegal_instr_handler(self, hart):
instr = []
self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS,
@@ -662,24 +867,47 @@
instr.append("mret")
self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart), instr)
+ # TODO: handshake correct csr based on delegation
def gen_instr_fault_handler(self, hart):
+ # TODO
pass
+ # TODO: handshake correct csr based on delegation
def gen_load_fault_handler(self, hart):
+ # TODO
pass
+ # TODO: handshake correct csr based on delegation
def gen_store_fault_handler(self, hart):
+ # TODO
pass
+ # ---------------------------------------------------------------------------------------
+ # Page table setup
+ # ---------------------------------------------------------------------------------------
+
+ # Create page table if virtual address translation is supported.
+ # The page is created based on the address translation mode - SV32, SV39, SV48
+ # Right now only the lowest level 4KB page table is configured as leaf page table entry (PTE),
+ # all the other super pages are link PTE.
def create_page_table(self, hart):
+ # TODO
pass
+ # Generate the page table section of the program
+ # The page table is generated as a group of continuous 4KB data sections.
def gen_page_table_section(self, hart):
+ # TODO
pass
+ # Only extend this function if the core utilizes a PLIC for handling interrupts
+ # In this case, the core will write to a specific location as the response to the interrupt, and
+ # external PLIC unit can detect this response and process the interrupt clean up accordingly.
def gen_plic_section(self, interrupt_handler_instr):
+ # TODO
pass
+ # Interrupt handler routine
def gen_interrupt_handler_section(self, mode, hart):
interrupt_handler_instr = []
# ls_unit = "w" if rcs.XLEN == 32 else "d"
@@ -708,11 +936,12 @@
else:
logging.critical("Unsupported mode: {}".format(mode.name))
sys.exit(1)
-
+ # If nested interrupts are enabled, set xSTATUS.xIE in the interrupt handler
+ # to re-enable interrupt handling capabilities
if cfg.enable_nested_interrupt:
- interrupt_handler_instr.append("csrr x{}, {}".format(cfg.gpr[0], hex(scratch)))
- interrupt_handler_instr.append("bgtz x{}, 1f".format(cfg.gpr[0]))
- interrupt_handler_instr.append("csrwi {}, 0x1".format(hex(scratch)))
+ interrupt_handler_instr.extend(("csrr x{}, {}".format(cfg.gpr[0], hex(scratch)),
+ "bgtz x{}, 1f".format(cfg.gpr[0]),
+ "csrwi {}, 0x1".format(hex(scratch))))
if status == privileged_reg_t.MSTATUS:
interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(8)))
@@ -725,7 +954,8 @@
sys.exit(1)
interrupt_handler_instr.append("1: csrwi {},0".format(hex(scratch)))
-
+ # Read back interrupt related privileged CSR
+ # The value of these CSR are checked by comparing with spike simulation result.
to_extend_interrupt_hanlder_instr = ["csrr x{}, {} # {};".format(cfg.gpr[0],
hex(status),
status.name),
@@ -739,21 +969,30 @@
ip.name)]
interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
self.gen_plic_section(interrupt_handler_instr)
+ # Restore user mode GPR value from kernel stack before return
pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv,
cfg.sp, cfg.tp, interrupt_handler_instr)
interrupt_handler_instr.append("{}ret;".format(mode_prefix))
if rcs.SATP_MODE != satp_mode_t.BARE:
+ # The interrupt handler will use one 4KB page
self.instr_stream.append(".align 12")
else:
self.instr_stream.append(".align 2")
- self.gen_section(pkg_ins.get_label("%0smode_intr_handler" %
- (mode_prefix), hart), interrupt_handler_instr)
+ self.gen_section(pkg_ins.get_label("{}mode_intr_handler".format(mode_prefix), hart),
+ interrupt_handler_instr)
+ # ---------------------------------------------------------------------------------------
+ # Helper functions
+ # ---------------------------------------------------------------------------------------
+
+ # Format a code section, without generating it
def format_section(self, instr):
+ # TODO
pass
+ # Generate a code section
def gen_section(self, label, instr):
if label != "":
string = pkg_ins.format_string("{}:".format(label), pkg_ins.LABEL_STR_LEN)
@@ -763,9 +1002,12 @@
self.instr_stream.append(string)
self.instr_stream.append("")
- def dump_perf_stats(self):
+ # Dump performance CSRs if applicable
+ def dump_perf_stats(self, instr):
+ # TODO
pass
+ # Write the generated program to a file
def gen_test_file(self, test_name):
file = open(test_name, "w+")
for items in self.instr_stream:
@@ -774,6 +1016,8 @@
file.close()
logging.info("{} is generated".format(test_name))
+ # Helper function to generate the proper sequence of handshake instructions
+ # to signal the testbench (see riscv_signature_pkg.sv)
def gen_signature_handshake(self, instr, signature_type,
core_status=core_status_t.INITIALIZED,
test_result=test_result_t.TEST_FAIL,
@@ -828,6 +1072,10 @@
logging.critical("signature_type is not defined")
sys.exit(1)
+ # ---------------------------------------------------------------------------------------
+ # Inject directed instruction stream
+ # ---------------------------------------------------------------------------------------
+
def add_directed_instr_stream(self, name, ratio):
self.directed_instr_stream_ratio[name] = ratio
logging.info("Adding directed instruction stream:%0s ratio:%0d/1000", name, ratio)
@@ -852,6 +1100,7 @@
stream_freq = cfg.args_dict[stream_freq_opts]
self.add_directed_instr_stream(stream_name, stream_freq)
+ # Generate directed instruction stream based on the ratio setting
def generate_directed_instr_stream(self, hart = 0, label = "", original_instr_cnt = 0,
min_insert_cnt = 0, kernel_mode = 0, instr_stream = []):
instr_insert_cnt = 0
@@ -885,5 +1134,18 @@
idx += 1
random.shuffle(instr_stream)
+ # ----------------------------------------------------------------------------------
+ # Generate the debug ROM, and any related programs
+ # ----------------------------------------------------------------------------------
+
def gen_debug_rom(self, hart):
+ # TODO
+ pass
+
+ # ----------------------------------------------------------------------------------
+ # Vector extension generation
+ # ----------------------------------------------------------------------------------
+
+ def randomize_vec_gpr_and_csr(self):
+ # TODO
pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
index 03a4499..ac8e91f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py
@@ -14,16 +14,23 @@
import vsc
import random
from collections import defaultdict
-from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t
from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t
+# -----------------------------------------------------------------------------------------
+# RISC-V assmebly program data section generator
+# There can be user mode and supervisor(kernel) mode data pages
+# -----------------------------------------------------------------------------------------
+
@vsc.randobj
class riscv_data_page_gen:
def __init__(self):
self.data_page_str = []
self.mem_region_setting = defaultdict(list)
+ # The data section can be initialized with different data pattern:
+ # - Random value, incremental value, all zeros
@staticmethod
def gen_data(idx, pattern, num_of_bytes, data):
temp_data = 0
@@ -36,10 +43,9 @@
data[i] = (idx + i) % 256
return data
+ # Generate data pages for all memory regions
def gen_data_page(self, hart_id, pattern, is_kernel=0, amo=0):
- tmp_str = ""
temp_data = []
- page_size = 0
self.data_page_str.clear()
if is_kernel:
self.mem_region_setting = cfg.s_mem_region
@@ -48,8 +54,6 @@
else:
self.mem_region_setting = cfg.mem_region
for i in range(len(self.mem_region_setting)):
- logging.info("mem_region_setting {}".format(self.mem_region_setting[i]))
- for i in range(len(self.mem_region_setting)):
logging.info("Generate data section: {} size:0x{} xwr:0x{}".format(
self.mem_region_setting[i].name,
self.mem_region_setting[i].size_in_bytes,
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
index cbdbb26..3b545f3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
index 0d6784b..91e4823 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -20,14 +19,13 @@
from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
from pygen_src.isa.riscv_instr import riscv_instr
from pygen_src.riscv_instr_gen_config import cfg
-from pygen_src.riscv_instr_pkg import (riscv_reg_t,
- riscv_pseudo_instr_name_t,
- riscv_instr_name_t, pkg_ins,
- mem_region_t)
+from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t,
+ riscv_instr_name_t, mem_region_t, pkg_ins)
from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+# Base class for directed instruction stream
class riscv_directed_instr_stream(riscv_rand_instr_stream):
label = ""
@@ -47,6 +45,7 @@
self.instr_list[0].has_label = 1
+# Base class for memory access stream
@vsc.randobj
class riscv_mem_access_stream(riscv_directed_instr_stream):
def __init__(self):
@@ -65,6 +64,7 @@
self.data_page.extend(cfg.mem_region)
self.max_data_page_id = len(self.data_page)
+ # Use "la" instruction to initialize the base regiseter
def add_rs1_init_la_instr(self, gpr, idx, base = 0):
la_instr = riscv_pseudo_instr()
la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA
@@ -79,6 +79,7 @@
cfg.mem_region[idx].name, base)
self.instr_list.insert(0, la_instr)
+ # Insert some other instructions to mix with mem_access instruction
def add_mixed_instr(self, instr_cnt):
self.setup_allowed_instr(1, 1)
for i in range(instr_cnt):
@@ -87,6 +88,7 @@
self.insert_instr(instr)
+# Stress back to back jump instruction
@vsc.randobj
class riscv_jal_instr(riscv_rand_instr_stream):
def __init__(self):
@@ -96,6 +98,7 @@
self.jump_start = riscv_instr()
self.jump_end = riscv_instr()
self.num_of_jump_instr = vsc.rand_int_t()
+ self.jal = []
@vsc.constraint
def instr_c(self):
@@ -115,6 +118,8 @@
jal.append(riscv_instr_name_t.C_J)
if rcs.XLEN == 32:
jal.append(riscv_instr_name_t.C_JAL)
+
+ # First instruction
self.jump_start = riscv_instr.get_instr(riscv_instr_name_t.JAL)
with self.jump_start.randomize_with() as it:
self.jump_start.rd == RA
@@ -157,6 +162,7 @@
NegativeMax = auto()
+# Strees the numeric corner cases of integer arithmetic operations
@vsc.randobj
class riscv_int_numeric_corner_stream(riscv_directed_instr_stream):
def __init__(self):
@@ -185,6 +191,7 @@
self.avail_regs[i] != riscv_reg_t.ZERO
def pre_randomize(self):
+ # TODO
pass
def post_randomize(self):
@@ -212,7 +219,6 @@
# Push Stack Instructions
class riscv_push_stack_instr(riscv_rand_instr_stream):
-
def __init__(self):
super().__init__()
self.stack_len = 0
@@ -225,12 +231,13 @@
self.push_start_label = ''
def init(self):
+ # Save RA, T0
self.reserved_rd = [cfg.ra]
self.saved_regs = [cfg.ra]
self.num_of_reg_to_save = len(self.saved_regs)
if self.num_of_reg_to_save * (rcs.XLEN / 8) > self.stack_len:
- logging.error('stack len [%0d] is not enough to store %d regs',
- self.stack_len, self.num_of_reg_to_save)
+ logging.error('stack len [{}] is not enough to store {} regs'
+ .format(self.stack_len, self.num_of_reg_to_save))
sys.exit(1)
self.num_of_redundant_instr = random.randrange(3, 10)
self.initialize_instr_list(self.num_of_redundant_instr)
@@ -288,7 +295,6 @@
# Pop stack instruction stream
class riscv_pop_stack_instr(riscv_rand_instr_stream):
-
def __init__(self):
super().__init__()
self.stack_len = 0
@@ -301,8 +307,8 @@
self.reserved_rd = [cfg.ra]
self.num_of_reg_to_save = len(self.saved_regs)
if self.num_of_reg_to_save * 4 > self.stack_len:
- logging.error('stack len [%0d] is not enough to store %d regs',
- self.stack_len, self.num_of_reg_to_save)
+ logging.error('stack len [{}] is not enough to store {} regs'
+ .format(self.stack_len, self.num_of_reg_to_save))
sys.exit(1)
self.num_of_redundant_instr = random.randrange(3, 10)
self.initialize_instr_list(self.num_of_redundant_instr)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py
index 3f534a4..4be43bc 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py
@@ -162,8 +162,8 @@
@vsc.constraint
def b_extension_c(self):
if riscv_instr_group_t.RV32B in rcs.supported_isa:
- with vsc.if_then(self.exception in [illegal_instr_type_e.kIllegalFunc3,
- illegal_instr_type_e.kIllegalFunc7]):
+ with vsc.if_then(self.exception.inside(vsc.rangelist(illegal_instr_type_e.kIllegalFunc3,
+ illegal_instr_type_e.kIllegalFunc7))):
self.opcode.inside(vsc.rangelist([51, 19, 59]))
@vsc.constraint
@@ -338,7 +338,7 @@
def initialize(self):
if (riscv_instr_group_t.RV32F in rcs.supported_isa) or \
(riscv_instr_group_t.RV32D in rcs.supported_isa):
- self.legal_opcode.extend(7, 39, 67, 71, 75, 79, 83)
+ self.legal_opcode.extend((7, 39, 67, 71, 75, 79, 83))
if riscv_instr_group_t.RV64I in rcs.supported_isa:
self.legal_opcode.append(27)
if riscv_instr_group_t.RV32A in rcs.supported_isa:
@@ -347,8 +347,8 @@
(riscv_instr_group_t.RV64M in rcs.supported_isa):
self.legal_opcode.append(59)
if riscv_instr_group_t.RV64I in rcs.supported_isa:
- self.legal_c00_opcode.extend(3, 7)
- self.legal_c10_opcode.extend(3, 7)
+ self.legal_c00_opcode.extend((3, 7))
+ self.legal_c10_opcode.extend((3, 7))
# TODO csr
def get_bin_str(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
index b020e3d..4912fac 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py
@@ -13,6 +13,7 @@
limitations under the License.
"""
+import traceback
from pygen_src.isa.riscv_cov_instr import *
@@ -1381,6 +1382,195 @@
self.cp_align = vsc.cross([self.cp_imm_align, self.cp_rs1_align])
self.cp_ras = vsc.cross([self.cp_rs1_link, self.cp_rd_link])
+ '''MUL instructions'''
+ @vsc.covergroup
+ class mul_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ @vsc.covergroup
+ class mulh_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ @vsc.covergroup
+ class mulhsu_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ @vsc.covergroup
+ class mulhu_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ @vsc.covergroup
+ class div_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,
+ cp_t=vsc.enum_t(div_result_e))
+
+ @vsc.covergroup
+ class divu_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,
+ cp_t=vsc.enum_t(div_result_ex_overflow_e))
+
+ @vsc.covergroup
+ class rem_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,
+ cp_t=vsc.enum_t(div_result_e))
+
+ @vsc.covergroup
+ class remu_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_t))
+ self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign,
+ self.cp_rd_sign])
+ self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result,
+ cp_t=vsc.enum_t(div_result_ex_overflow_e))
+
'''CSR instructions'''
@vsc.covergroup
@@ -1402,7 +1592,7 @@
super().__init__()
self.instr = None
- self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[7:2],
+ self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[6:2],
bins={
"a": vsc.bin_array([], [0, 31])
}
@@ -1430,11 +1620,430 @@
}
)
+ @vsc.covergroup
+ class hint_cg(object):
+ def __init__(self):
+ super().__init__()
+ self.instr = None
+ self.cp_hint0 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(addi=vsc.wildcard_bin_array([],
+ "0b0000_1xxx_x000_0001",
+ "0b0000_x1xx_x000_0001",
+ "0b0000_xx1x_x000_0001",
+ "0b0000_xxx1_x000_0001",
+ "0b0000_xxxx_1000_0001")))
+ self.cp_hint1 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(li=vsc.wildcard_bin(
+ "0b010x_0000_0xxx_xx01")))
+ self.cp_hint2 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(lui=vsc.wildcard_bin(
+ "0b011x_0000_0xxx_xx01")))
+ self.cp_hint3 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(srli64=vsc.wildcard_bin(
+ "0b1000_00xx_x000_0001")))
+ self.cp_hint4 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(srai64=vsc.wildcard_bin(
+ "0b1000_01xx_x000_0001")))
+ self.cp_hint5 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(slli=vsc.wildcard_bin(
+ "0b000x_0000_0xxx_xx10")))
+ self.cp_hint6 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(slli64=vsc.wildcard_bin(
+ "0b0000_xxxx_x000_0010")))
+ self.cp_hint7 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(mv=vsc.wildcard_bin_array([],
+ "0b1000_0000_01xx_xx10",
+ "0b1000_0000_0x1x_xx10",
+ "0b1000_0000_0xx1_xx10",
+ "0b1000_0000_0xxx_1x10",
+ "0b1000_0000_0xxx_x110")))
+ self.cp_hint8 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins=dict(add=vsc.wildcard_bin_array([],
+ "0b1001_0000_01xx_xx10",
+ "0b1001_0000_0x1x_xx10",
+ "0b1001_0000_0xx1_xx10",
+ "0b1001_0000_0xxx_1x10",
+ "0b1001_0000_0xxx_x110"
+ )))
+
+ @vsc.covergroup
+ class illegal_compressed_instr_cg(object):
+ def __init__(self):
+ super().__init__()
+ self.instr = None
+ self.cp_point0 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_illegal=vsc.wildcard_bin(
+ "0b0000_0000_0000_0000")))
+ self.cp_point1 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_addi4spn=vsc.wildcard_bin_array([],
+ "0b0000_0000_000x_x100",
+ "0b0000_0000_000x_1x00",
+ "0b0000_0000_0001_xx00")))
+ self.cp_point2 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_addiw=vsc.wildcard_bin(
+ "0b001x_0000_0xxx_xx01")))
+ self.cp_point3 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_addi16sp=vsc.wildcard_bin(
+ "0b0110_0001_0000_0001")))
+ self.cp_point4 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_lui=vsc.wildcard_bin_array([],
+ "0b0110_xxxx_1000_0001",
+ "0b0110_xx1x_x000_0001",
+ "0b0110_x1xx_x000_0001",
+ "0b0110_1xxx_x000_0001")))
+ self.cp_point5 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_reserv_0=vsc.wildcard_bin(
+ "0b1001_11xx_x10x_xx01")))
+ self.cp_point6 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_reserv_1=vsc.wildcard_bin(
+ "0b1001_11xx_x11x_xx01")))
+ self.cp_point7 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_jr=vsc.wildcard_bin(
+ "0b1000_0000_0000_0010")))
+ self.cp_point8 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_lwsp=vsc.wildcard_bin(
+ "0b010x_0000_0xxx_xx10")))
+ self.cp_point9 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_lqsp=vsc.wildcard_bin(
+ "0b001x_0000_0xxx_xx10")))
+ self.cp_point10 = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins = dict(c_ldsp=vsc.wildcard_bin(
+ "0b011x_0000_0xxx_xx10")))
+
+ '''Compressed instructions'''
+
+ @vsc.covergroup
+ class compressed_opcode_cg(object):
+ # TODO issue with iff parameter
+ def __init__(self):
+ super().__init__()
+ self.instr = None
+ '''self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[15:0],
+ bins={
+ "a": vsc.bin_array([], [0, 31])
+ }
+ )'''
+
+ @vsc.covergroup
+ class c_lw_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+ self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+
+ @vsc.covergroup
+ class c_lwsp_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+
+ @vsc.covergroup
+ class c_sw_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+ self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,
+ cp_t=vsc.enum_t(store_lsu_hazard_e))
+
+ @vsc.covergroup
+ class c_swsp_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+
+ @vsc.covergroup
+ class c_addi4spn_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(store_lsu_hazard_e))
+
+ @vsc.covergroup
+ class c_addi_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(store_lsu_hazard_e))
+
+ @vsc.covergroup
+ class c_addi16sp_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(store_lsu_hazard_e))
+
+ @vsc.covergroup
+ class c_li_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(store_lsu_hazard_e))
+
+ @vsc.covergroup
+ class c_lui_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_sp_t))
+
+ @vsc.covergroup
+ class c_sub_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_add_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_mv_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_andi_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+
+ @vsc.covergroup
+ class c_xor_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_or_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_and_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(hazard_e))
+
+ @vsc.covergroup
+ class c_beqz_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+
+ @vsc.covergroup
+ class c_bnez_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+
+ @vsc.covergroup
+ class c_srli_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+
+ @vsc.covergroup
+ class c_srai_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(compressed_gpr))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+
+ @vsc.covergroup
+ class c_slli_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
+ cp_t=vsc.enum_t(branch_hazard_e))
+
+ @vsc.covergroup
+ class c_j_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+
+ @vsc.covergroup
+ class c_jal_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
+ cp_t=vsc.enum_t(operand_sign_e))
+
+ @vsc.covergroup
+ class c_jr_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],
+ bins={
+ "Zero" : vsc.bin(0),
+ "One" : vsc.bin(1),
+ "Two" : vsc.bin(2),
+ "Three": vsc.bin(3)
+ })
+
+ @vsc.covergroup
+ class c_jalr_cg(object):
+ def __init__(self):
+ super().__init__()
+
+ self.instr = None
+ self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
+ cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
+ self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],
+ bins={
+ "Zero" : vsc.bin(0),
+ "One" : vsc.bin(1),
+ "Two" : vsc.bin(2),
+ "Three": vsc.bin(3)
+ })
+ self.cp_rd_align = vsc.coverpoint(lambda: self.instr.rd_value[1],
+ bins={
+ "Aligned" : vsc.bin(1),
+ "Not-aligned": vsc.bin(0)
+ })
+
def cg_instantiation(self):
self.opcode_cg_i = self.opcode_cg()
self.csrrw_cg_i = self.csrrw_cg()
self.rv32i_misc_cg_i = self.rv32i_misc_cg()
self.mepc_alignment_cg_i = self.mepc_alignment_cg()
+ # self.compressed_opcode_cg_i = self.compressed_opcode_cg()
self.beq_cg_i = self.beq_cg()
self.jal_cg_i = self.jal_cg()
self.lui_cg_i = self.lui_cg()
@@ -1458,13 +2067,56 @@
self.srai_cg_i = self.srai_cg()
self.slt_cg_i = self.slt_cg()
self.slli_cg_i = self.slli_cg()
+ self.mul_cg_i = self.mul_cg()
+ self.mulh_cg_i = self.mulh_cg()
+ self.mulhsu_cg_i = self.mulhsu_cg()
+ self.mulhu_cg_i = self.mulhu_cg()
+ self.div_cg_i = self.div_cg()
+ self.divu_cg_i = self.divu_cg()
+ self.rem_cg_i = self.rem_cg()
+ self.remu_cg_i = self.remu_cg()
+ self.c_lw_cg_i = self.c_lw_cg()
+ self.c_lwsp_cg_i = self.c_lwsp_cg()
+ self.c_sw_cg_i = self.c_sw_cg()
+ self.c_swsp_cg_i = self.c_swsp_cg()
+ self.c_addi4spn_cg_i = self.c_addi4spn_cg()
+ self.c_addi_cg_i = self.c_addi_cg()
+ self.c_addi16sp_cg_i = self.c_addi16sp_cg()
+ self.c_li_cg_i = self.c_li_cg()
+ self.c_lui_cg_i = self.c_lui_cg()
+ self.c_sub_cg_i = self.c_sub_cg()
+ self.c_add_cg_i = self.c_add_cg()
+ self.c_mv_cg_i = self.c_mv_cg()
+ self.c_andi_cg_i = self.c_andi_cg()
+ self.c_xor_cg_i = self.c_xor_cg()
+ self.c_or_cg_i = self.c_or_cg()
+ self.c_and_cg_i = self.c_and_cg()
+ self.c_beqz_cg_i = self.c_beqz_cg()
+ self.c_bnez_cg_i = self.c_bnez_cg()
+ self.c_srli_cg_i = self.c_srli_cg()
+ self.c_srai_cg_i = self.c_srai_cg()
+ self.c_slli_cg_i = self.c_slli_cg()
+ self.c_j_cg_i = self.c_j_cg()
+ self.c_jal_cg_i = self.c_jal_cg()
+ self.c_jr_cg_i = self.c_jr_cg()
+ self.c_jalr_cg_i = self.c_jalr_cg()
+ self.hint_cg_i = self.hint_cg()
+ self.illegal_compressed_instr_cg_i = self.illegal_compressed_instr_cg()
def sample(self, instr):
self.instr_cnt += 1
if self.instr_cnt > 1:
instr.check_hazard_condition(self.pre_instr)
- # TODO: sampling for hint, compressed, and illegal_compressed insts
- if instr.binary[2:0] == 3:
+ # TODO: sampling for compressed_instr_cg
+ if ((instr.binary[1:0] != 3) and (riscv_instr_group_t.RV32C in rcs.supported_isa)):
+ # self.compressed_opcode_cg_i.instr = instr
+ # self.compressed_opcode_cg_i.sample()
+ self.hint_cg_i.instr = instr
+ self.hint_cg_i.sample()
+ self.illegal_compressed_instr_cg_i.instr = instr
+ self.illegal_compressed_instr_cg_i.sample()
+
+ if instr.binary[1:0] == 3:
self.opcode_cg_i.instr = instr
self.opcode_cg_i.sample()
try:
@@ -1474,6 +2126,9 @@
except Exception:
logging.info("Covergroup for instr {} is not supported yet".format(
instr.instr.name))
+ # Trace the error if there is an Exception
+ logging.info("Traceback error log: {}".format(traceback.format_exc()))
+
if instr.group.name == "RV32I":
self.rv32i_misc_cg_i.instr = instr
self.rv32i_misc_cg_i.sample()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
index 0de86af..f99fd4b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import sys
@@ -22,19 +20,48 @@
riscv_reg_t, privileged_mode_t,
riscv_instr_group_t, data_pattern_t,
riscv_instr_category_t, satp_mode_t,
- mem_region_t)
+ mem_region_t, vreg_init_method_t)
+# ----------------------------------------------------------------------------
+# RISC-V assembly program generator configuration class
+# ----------------------------------------------------------------------------
+
@vsc.randobj
class riscv_instr_gen_config:
+
def __init__(self):
- self.main_program_instr_cnt = vsc.rand_int32_t() # count of main_prog
- self.sub_program_instr_cnt = [] # count of sub_prog
- self.debug_program_instr_cnt = 0 # count of debug_rom
- self.debug_sub_program_instr_cnt = [] # count of debug sub_progrms
- self.max_directed_instr_stream_seq = 20
+ # ---------------------------------------------------------------------------
+ # Random instruction generation settings
+ # ---------------------------------------------------------------------------
+
+ # Instruction count of the main program
+ self.main_program_instr_cnt = vsc.rand_int32_t()
+
+ # Instruction count of each sub-program
+ self.sub_program_instr_cnt = []
+
+ # Instruction count of the debug rom
+ self.debug_program_instr_cnt = 0
+
+ # Instruction count of debug sub-programs
+ self.debug_sub_program_instr_cnt = []
+
+ # Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
self.data_page_pattern = vsc.rand_enum_t(data_pattern_t)
+ # Initialization of the vregs
+ # SAME_VALUES_ALL_ELEMS - Using vmv.v.x to fill all the elements of the vreg with
+ # the same value as the one in the GPR selected
+ # RANDOM_VALUES_VMV - Using vmv.v.x + vslide1up.vx to randomize the contents
+ # of each vector element
+ # RANDOM_VALUES_LOAD - Using vle.v, same approach as RANDOM_VALUES_VMV but more
+ # efficient for big VLEN
+ self.vreg_init_method = vreg_init_method_t.RANDOM_VALUES_VMV
+
+ # Maximum directed instruction stream sequence count
+ self.max_directed_instr_stream_seq = 20
+
self.init_delegation()
self.argv = self.parse_args()
self.args_dict = vars(self.argv)
@@ -42,12 +69,16 @@
global rcs
rcs = import_module("pygen_src.target." + self.argv.target + ".riscv_core_setting")
+ # Dict for delegation configuration for each exception and interrupt
+ # When the bit is 1, the corresponding delegation is enabled.
+ # TODO
self.m_mode_exception_delegation = {}
self.s_mode_exception_delegation = {}
self.m_mode_interrupt_delegation = {}
self.s_mode_interrupt_delegation = {}
# init_privileged_mode default to MACHINE_MODE
+ # TODO: remove defult machine_mode once all modes get supported
self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
self.mstatus = vsc.rand_bit_t(rcs.XLEN - 1)
@@ -57,6 +88,8 @@
self.ustatus = vsc.rand_bit_t(rcs.XLEN - 1)
self.uie = vsc.rand_bit_t(rcs.XLEN - 1)
+ # Key fields in xSTATUS
+ # Memory protection bits
self.mstatus_mprv = vsc.rand_bit_t(1)
self.mstatus_mxr = vsc.rand_bit_t(1)
self.mstatus_sum = vsc.rand_bit_t(1)
@@ -65,25 +98,55 @@
self.mstatus_vs = vsc.rand_bit_t(2)
self.mtvec_mode = vsc.rand_enum_t(mtvec_mode_t)
- self.tvec_alignment = vsc.rand_uint8_t(self.argv.tvec_alignment)
+ # TVEC alignment
+ # This value is the log_2 of the byte-alignment of TVEC.BASE field
+ # As per RISC-V privileged spec, default will be set to 2 (4-byte aligned)
+ self.tvec_alignment = vsc.rand_uint32_t(self.argv.tvec_alignment)
+ # Floating point rounding mode
self.fcsr_rm = vsc.rand_enum_t(f_rounding_mode_t)
+
+ # Enable sfence.vma instruction
self.enable_sfence = vsc.rand_bit_t(1)
+
+ # Reserved register
+ # Reserved for various hardcoded routines
self.gpr = vsc.rand_list_t(vsc.enum_t(riscv_reg_t), sz=4)
+ # Used by any DCSR operations inside of the debug rom.
+ # Also used by the PMP generation.
self.scratch_reg = vsc.rand_enum_t(riscv_reg_t)
+
+ # Reg used exclusively by the PMP exception handling routine.
+ # Can overlap with the other GPRs used in the random generation,
+ # as PMP exception handler is hardcoded and does not include any
+ # random instructions.
self.pmp_reg = vsc.rand_enum_t(riscv_reg_t)
+
+ # Use a random register for stack pointer/thread pointer
self.sp = vsc.rand_enum_t(riscv_reg_t)
self.tp = vsc.rand_enum_t(riscv_reg_t)
self.ra = vsc.rand_enum_t(riscv_reg_t)
+
+ # Options for privileged mode CSR checking
+ # Below checking can be made optional as the ISS implementation
+ # could be different with the processor.
self.check_misa_init_val = 0
self.check_xstatus = 1
- self.virtual_addr_translation_on = 0
+
+ # Virtual address translation is on for this test
+ self.virtual_addr_translation_on = vsc.rand_bit_t(1)
# Commenting out for now
- # vector_cfg = riscv_vector_cfg # TODO
+ # vector_cfg = riscv_vector_cfg # TODO
# pmp_cfg = riscv_pmp_cfg # TODO
+ # Stack section word length
+ self.stack_len = 5000
+
+ # -----------------------------------------------------------------------------
+ # User space memory region and stack setting
+ # -----------------------------------------------------------------------------
self.mem_region = vsc.list_t(mem_region_t())
self.amo_region = vsc.list_t(mem_region_t())
self.s_mem_region = vsc.list_t(mem_region_t())
@@ -92,37 +155,52 @@
self.amo_region.extend([mem_region_t(name = "amo_0", size_in_bytes = 64, xwr = 8)])
self.s_mem_region.extend([mem_region_t(name = "s_region_0", size_in_bytes = 4096, xwr = 8),
mem_region_t(name = "s_region_1", size_in_bytes = 4096, xwr = 8)])
-
- self.stack_len = 5000
+ # Kernel Stack section word length
self.kernel_stack_len = 4000
+
+ # Number of instructions for each kernel program
self.kernel_program_instr_cnt = 400
- # list of main implemented CSRs
+
+ # List of all the main implemented CSRs that the boot privilege mode cannot access
+ # e.g. these CSRs are in higher privilege modes - access should raise an exception
self.invalid_priv_mode_csrs = []
+
+ # -----------------------------------------------------------------------------
+ # Command line options or control knobs
+ # -----------------------------------------------------------------------------
+ # Main options for RISC-V assembly program generation
+ # Number of sub-programs per test
self.num_of_sub_program = self.argv.num_of_sub_program
self.instr_cnt = self.argv.instr_cnt
self.num_of_tests = self.argv.num_of_tests
+ # For tests doesn't involve load/store, the data section generation could be skipped
self.no_data_page = self.argv.no_data_page
- self.no_branch_jump = self.argv.no_branch_jump
- self.no_load_store = self.argv.no_load_store
- self.no_csr_instr = self.argv.no_csr_instr
- self.no_ebreak = self.argv.no_ebreak
- self.no_dret = self.argv.no_dret
- self.no_fence = self.argv.no_fence
- self.no_wfi = self.argv.no_wfi
+ # Options to turn off some specific types of instructions
+ self.no_branch_jump = self.argv.no_branch_jump # No branch/jump instruction
+ self.no_load_store = self.argv.no_load_store # No load/store instruction
+ self.no_csr_instr = self.argv.no_csr_instr # No csr instruction
+ self.no_ebreak = self.argv.no_ebreak # No ebreak instruction
+ self.no_dret = self.argv.no_dret # No dret instruction
+ self.no_fence = self.argv.no_fence # No fence instruction
+ self.no_wfi = self.argv.no_wfi # No WFI instruction
self.enable_unaligned_load_store = self.argv.enable_unaligned_load_store
self.illegal_instr_ratio = self.argv.illegal_instr_ratio
self.hint_instr_ratio = self.argv.hint_instr_ratio
+ # Number of harts to be simulated, must be <= NUM_HARTS
if self.argv.num_of_harts is None:
self.num_of_harts = rcs.NUM_HARTS
else:
self.num_of_harts = self.argv.num_of_harts
+ # Use SP as stack pointer
+ self.fix_sp = vsc.bit_t(1)
self.fix_sp = self.argv.fix_sp
+ # Use push/pop section for data pages
self.use_push_data_section = self.argv.use_push_data_section
+ # Directed boot privileged mode, u, m, s
self.boot_mode_opts = self.argv.boot_mode
# self.isa = self.argv.isa
-
if self.boot_mode_opts:
- logging.info("Got boot mode option - %0s", self.boot_mode_opts)
+ logging.info("Got boot mode option - {}".format(self.boot_mode_opts))
if self.boot_mode_opts == "m":
self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
elif self.boot_mode_opts == "s":
@@ -130,50 +208,89 @@
elif self.boot_mode_opts == "u":
self.init_privileged_mode = privileged_mode_t.USER_MODE
else:
- logging.error("Illegal boot mode option - %0s", self.boot_mode_opts)
-
+ logging.error("Illegal boot mode option - {}".format(self.boot_mode_opts))
self.enable_page_table_exception = self.argv.enable_page_table_exception
self.no_directed_instr = self.argv.no_directed_instr
self.asm_test_suffix = self.argv.asm_test_suffix
+ # Enable interrupt bit in MSTATUS (MIE, SIE, UIE)
self.enable_interrupt = self.argv.enable_interrupt
self.enable_nested_interrupt = self.argv.enable_nested_interrupt
+ # We need a separate control knob for enabling timer interrupts, as Spike
+ # throws an exception if xIE.xTIE is enabled
self.enable_timer_irq = self.argv.enable_timer_irq
+ # Generate a bare program without any init/exit/error handling/page table routines
+ # The generated program can be integrated with a larger program.
+ # Note that the bare mode program is not expected to run in standalone mode
self.bare_program_mode = self.argv.bare_program_mode
+ # Enable accessing illegal CSR instruction
+ # - Accessing non-existence CSR
+ # - Accessing CSR with wrong privileged mode
self.enable_illegal_csr_instruction = self.argv.enable_illegal_csr_instruction
+ # Enable accessing CSRs at an invalid privilege level
self.enable_access_invalid_csr_level = self.argv.enable_access_invalid_csr_level
+ # Enable misaligned instruction (caused by JALR instruction)
self.enable_misaligned_instr = self.argv.enable_misaligned_instr
+ # Enable some dummy writes to main system CSRs (xSTATUS/xIE) at beginning of test
+ # to check repeated writes
self.enable_dummy_csr_write = self.argv.enable_dummy_csr_write
self.randomize_csr = self.argv.randomize_csr
+ # sfence support
self.allow_sfence_exception = self.argv.allow_sfence_exception
+ # Interrupt/Exception Delegation
self.no_delegation = self.argv.no_delegation
self.force_m_delegation = self.argv.force_m_delegation
self.force_s_delegation = self.argv.force_s_delegation
- self.support_supervisor_mode = 0
+ self.support_supervisor_mode = 0 # TODO
self.disable_compressed_instr = self.argv.disable_compressed_instr
self.require_signature_addr = self.argv.require_signature_addr
-
if self.require_signature_addr:
self.signature_addr = int(self.argv.signature_addr, 16)
else:
self.signature_addr = 0xdeadbeef
-
+ # Enable a full or empty debug_rom section.
+ # Full debug_rom will contain random instruction streams.
+ # Empty debug_rom will contain just dret instruction and will return immediately.
+ # Will be empty by default.
self.gen_debug_section = self.argv.gen_debug_section
+ # Enable generation of a directed sequence of instructions containing
+ # ebreak inside the debug_rom.
+ # Disabled by default.
self.enable_ebreak_in_debug_rom = self.argv.enable_ebreak_in_debug_rom
+ # Enable setting dcsr.ebreak(m/s/u)
self.set_dcsr_ebreak = self.argv.set_dcsr_ebreak
+ # Number of sub programs in the debug rom
self.num_debug_sub_program = self.argv.num_debug_sub_program
+ # Enable debug single stepping
self.enable_debug_single_step = self.argv.enable_debug_single_step
- self.single_step_iterations = 0
+ # Number of single stepping iterations
+ self.single_step_iterations = vsc.rand_uint32_t()
+ # Enable mstatus.tw bit - causes u-mode WFI to raise illegal instruction exceptions
self.set_mstatus_tw = self.argv.set_mstatus_tw
+ # Enable users to set mstatus.mprv to enable privilege checks on memory accesses.
self.set_mstatus_mprv = vsc.bit_t(1)
self.set_mstatus_mprv = self.argv.set_mstatus_mprv
- self.min_stack_len_per_program = 10 * (rcs.XLEN / 8)
- self.max_stack_len_per_program = 16 * (rcs.XLEN / 8)
+ # Stack space allocated to each program, need to be enough to store necessary context
+ # Example: RA, SP, T0
+ self.min_stack_len_per_program = 10 * (rcs.XLEN // 8)
+ self.max_stack_len_per_program = 16 * (rcs.XLEN // 8)
+ # Maximum branch distance, avoid skipping large portion of the code
self.max_branch_step = 20
+ # Reserved registers
self.reserved_regs = vsc.list_t(vsc.enum_t(riscv_reg_t))
+ # Floating point support
+ self.enable_floating_point = vsc.bit_t(1)
self.enable_floating_point = self.argv.enable_floating_point
+ # Vector extension support
self.enable_vector_extension = self.argv.enable_vector_extension
+ # Only generate vector instructions
+ self. vector_instr_only = vsc.bit_t(1)
+ # Bit manipulation extension support
self.enable_b_extension = self.argv.enable_b_extension
self.enable_bitmanip_groups = self.argv.enable_bitmanip_groups
+
+ # -----------------------------------------------------------------------------
+ # Command line options for instruction distribution control
+ # -----------------------------------------------------------------------------
self.dist_control_mode = 0
self.category_dist = {}
self.march_isa = self.argv.march_isa
@@ -198,35 +315,26 @@
@vsc.constraint
def default_c(self):
+ # TODO Add constraint related to sub_program
self.main_program_instr_cnt in vsc.rangelist(vsc.rng(10, self.instr_cnt))
@vsc.constraint
- def sp_tp_c(self):
- if self.fix_sp:
- self.sp == riscv_reg_t.SP
- self.sp != self.tp
- self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP,
- riscv_reg_t.RA, riscv_reg_t.ZERO))
- self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
- riscv_reg_t.RA, riscv_reg_t.ZERO))
+ def debug_mode_c(self):
+ # TODO
+ pass
+ # Keep the number of single step iterations relatively small
@vsc.constraint
- def gpr_c(self):
- with vsc.foreach(self.gpr, idx = True) as i:
- self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
- riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
- vsc.unique(self.gpr)
+ def debug_single_step_c(self):
+ # TODO
+ pass
+ # Boot privileged mode distribution
@vsc.constraint
- def ra_c(self):
- self.ra != riscv_reg_t.SP
- self.ra != riscv_reg_t.TP
- self.ra != riscv_reg_t.ZERO
-
- @vsc.constraint
- def reserve_scratch_reg_c(self):
- self.scratch_reg.not_inside(vsc.rangelist(riscv_reg_t.ZERO, self.sp,
- self.tp, self.ra, riscv_reg_t.GP))
+ def boot_privileged_mode_dist_c(self):
+ # Boot to higher privileged mode more often
+ # TODO
+ pass
@vsc.constraint
def mtvec_c(self):
@@ -234,16 +342,11 @@
with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT):
vsc.soft(self.tvec_alignment == 2)
with vsc.else_then():
+ # Setting MODE = Vectored may impose an additional alignmentconstraint on BASE,
+ # requiring up to 4×XLEN-byte alignment
vsc.soft(self.tvec_alignment == self.tvec_ceil)
@vsc.constraint
- def floating_point_c(self):
- with vsc.if_then(self.enable_floating_point):
- self.mstatus_fs == 1
- with vsc.else_then():
- self.mstatus_fs == 0
-
- @vsc.constraint
def mstatus_c(self):
with vsc.if_then(self.set_mstatus_mprv == 1):
self.mstatus_mprv == 1
@@ -254,6 +357,124 @@
self.mstatus_sum == 0
self.mstatus_tvm == 0
+ # Exception delegation setting
+ @vsc.constraint
+ def exception_delegation_c(self):
+ # Do not delegate instruction page fault to supervisor/user mode because this may introduce
+ # dead loop. All the subsequent instruction fetches may fail and program cannot recover.
+ # TODO
+ pass
+
+ # Spike only supports a subset of exception and interrupt delegation
+ # You can modify this constraint if your ISS support different set of delegations
+ @vsc.constraint
+ def delegation_c(self):
+ # TODO
+ pass
+
+ @vsc.constraint
+ def ra_c(self):
+ self.ra != riscv_reg_t.SP
+ self.ra != riscv_reg_t.TP
+ self.ra != riscv_reg_t.ZERO
+
+ @vsc.constraint
+ def sp_tp_c(self):
+ with vsc.if_then(self.fix_sp == 1):
+ self.sp == riscv_reg_t.SP
+ self.sp != self.tp
+ self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP,
+ riscv_reg_t.RA, riscv_reg_t.ZERO))
+ self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
+ riscv_reg_t.RA, riscv_reg_t.ZERO))
+
+ # This reg is used in various places throughout the generator,
+ # so need more conservative constraints on it.
+ @vsc.constraint
+ def reserve_scratch_reg_c(self):
+ self.scratch_reg.not_inside(vsc.rangelist(riscv_reg_t.ZERO, self.sp,
+ self.tp, self.ra, riscv_reg_t.GP))
+
+ # This reg is only used inside PMP exception routine,
+ # so we can be a bit looser with constraints.
+ @vsc.constraint
+ def reserved_pmp_reg_c(self):
+ # TODO
+ pass
+
+ @vsc.constraint
+ def gpr_c(self):
+ with vsc.foreach(self.gpr, idx = True) as i:
+ self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+ riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+ vsc.unique(self.gpr)
+
+ @vsc.constraint
+ def addr_translation_rnd_order_c(self):
+ # TODO
+ pass
+
+ @vsc.constraint
+ def addr_translation_c(self):
+ with vsc.if_then((self.init_privil_mode != privileged_mode_t.MACHINE_MODE) &
+ (self.SATP_MODE != satp_mode_t.BARE)):
+ self.virtual_addr_translation_on == 1
+ with vsc.else_then():
+ self.virtual_addr_translation_on == 0
+
+ @vsc.constraint
+ def floating_point_c(self):
+ with vsc.if_then(self.enable_floating_point == 1):
+ self.mstatus_fs == 1
+ with vsc.else_then():
+ self.mstatus_fs == 0
+
+ @vsc.constraint
+ def mstatus_vs_c(self):
+ # TODO
+ pass
+
+ def setup_instr_distribution(self):
+ if self.dist_control_mode:
+ category_iter = iter([x for x in riscv_instr_category_t.__members__])
+ category = riscv_instr_category_t(0)
+ while True:
+ opts = "dist_{}".format(category.name)
+ opts = opts.lower()
+ if self.args_dict[opts]:
+ self.category_dist[category] = self.args_dict[opts]
+ else:
+ self.category_dist[category] = 10 # Default ratio
+ logging.info("Set dist[{}] = {}".format(category, self.category_dist[category]))
+ category = next(category_iter)
+ if category != riscv_instr_category_t(0):
+ break
+
+ # Initialize the exception/interrupt delegation associate array, set all delegation default to 0
+ def init_delegation(self):
+ # TODO
+ pass
+
+ def pre_randomize(self):
+ for mode in rcs.supported_privileged_mode:
+ if mode == privileged_mode_t.SUPERVISOR_MODE:
+ self.support_supervisor_mode = 1
+
+ def get_non_reserved_gpr(self):
+ pass
+
+ def post_randomize(self):
+ # Setup the list all reserved registers
+ self.reserved_regs.extend((self.tp, self.sp, self.scratch_reg))
+ # Need to save all loop registers, and RA/T0
+ self.min_stack_len_per_program = 2 * (rcs.XLEN // 8)
+ logging.info("min_stack_len_per_program value = {}"
+ .format(self.min_stack_len_per_program))
+ self.check_setting() # check if the setting is legal
+ # WFI is not supported in umode
+ if self.init_privileged_mode == privileged_mode_t.USER_MODE:
+ self.no_wfi = 1
+
def check_setting(self):
support_64b = 0
support_128b = 0
@@ -296,47 +517,8 @@
.format(rcs.SATP_MODE.name))
sys.exit("Supported SATP mode is not provided")
- def setup_instr_distribution(self):
- if self.dist_control_mode:
- category_iter = iter([x for x in riscv_instr_category_t.__members__])
- category = riscv_instr_category_t(0)
- while True:
- opts = "dist_{}".format(category.name)
- opts = opts.lower()
- if self.args_dict[opts]:
- self.category_dist[category] = self.args_dict[opts]
- else:
- self.category_dist[category] = 10
- logging.info("Set dist[{}] = {}".format(category, self.category_dist[category]))
- category = next(category_iter)
- if category != riscv_instr_category_t(0):
- break
-
- # TODO
- def init_delegation(self):
- pass
-
- def pre_randomize(self):
- for mode in rcs.supported_privileged_mode:
- if mode == privileged_mode_t.SUPERVISOR_MODE:
- self.support_supervisor_mode = 1
-
- def get_non_reserved_gpr(self):
- pass
-
- def post_randomize(self):
- self.reserved_regs.append(self.tp)
- self.reserved_regs.append(self.sp)
- self.reserved_regs.append(self.scratch_reg)
- self.min_stack_len_per_program = 2 * (rcs.XLEN / 8)
- logging.info("min_stack_len_per_program value = {}"
- .format(self.min_stack_len_per_program))
- self.check_setting() # check if the setting is legal
-
- if self.init_privileged_mode == privileged_mode_t.USER_MODE:
- logging.info("mode = USER_MODE")
- self.no_wfi = 1
-
+ # Populate invalid_priv_mode_csrs with the main implemented CSRs for each supported privilege
+ # mode
def get_invalid_priv_lvl_csr(self):
invalid_lvl = []
# Debug CSRs are inaccessible from all but Debug Mode
@@ -416,7 +598,7 @@
help = 'illegal_instr_ratio', type = int, default = 0)
parse.add_argument('--hint_instr_ratio', help = 'hint_instr_ratio', type = int, default = 0)
parse.add_argument('--num_of_harts', help = 'num_of_harts',
- type = int, default = 1)
+ type = int)
parse.add_argument('--enable_unaligned_load_store',
help = 'enable_unaligned_load_store', choices = [0, 1],
type = int, default = 0)
@@ -486,7 +668,6 @@
if ($value$plusargs("tvec_alignment=%0d", tvec_alignment)) begin
tvec_alignment.rand_mode(0);
end
-
vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg");
pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg");
pmp_cfg.rand_mode(pmp_cfg.pmp_randomize);
@@ -495,7 +676,6 @@
get_invalid_priv_lvl_csr();
'''
args = parse.parse_args()
-
return args
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
index 41f4ba3..5808a4f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import logging
@@ -26,6 +24,14 @@
self.size_in_bytes = vsc.uint32_t(i=size_in_bytes)
self.xwr = vsc.uint8_t(i=xwr)
+# Initialization of the vregs
+
+
+class vreg_init_method_t(IntEnum):
+ SAME_VALUES_ALL_ELEMS = 0
+ RANDOM_VALUES_VMV = auto()
+ RANDOM_VALUES_LOAD = auto()
+
class satp_mode_t(IntEnum):
BARE = 0b0000
@@ -50,12 +56,13 @@
class imm_t(IntEnum):
- IMM = 0
- UIMM = auto()
- NZUIMM = auto()
- NZIMM = auto()
+ IMM = 0 # Signed immediate
+ UIMM = auto() # Unsigned immediate
+ NZUIMM = auto() # Non-zero unsigned immediate
+ NZIMM = auto() # Non-zero signed immediate
+# Privileged mode
class privileged_mode_t(IntEnum):
USER_MODE = 0b00
SUPERVISOR_MODE = 0b01
@@ -90,6 +97,7 @@
class riscv_instr_name_t(IntEnum):
+ # RV32I instructions
LUI = 0
AUIPC = auto()
JAL = auto()
@@ -138,6 +146,7 @@
CSRRWI = auto()
CSRRSI = auto()
CSRRCI = auto()
+ # RV32B instructions
ANDN = auto()
ORN = auto()
XNOR = auto()
@@ -195,6 +204,7 @@
BFP = auto()
SHFLI = auto()
UNSHFLI = auto()
+ # RV64B instructions
ADDIWU = auto()
SLLIU_W = auto()
ADDWU = auto()
@@ -238,6 +248,7 @@
PACKW = auto()
PACKUW = auto()
BFPW = auto()
+ # RV32M instructions
MUL = auto()
MULH = auto()
MULHSU = auto()
@@ -246,11 +257,13 @@
DIVU = auto()
REM = auto()
REMU = auto()
+ # RV64M instructions
MULW = auto()
DIVW = auto()
DIVUW = auto()
REMW = auto()
REMUW = auto()
+ # RV32F instructions
FLW = auto()
FSW = auto()
FMADD_S = auto()
@@ -277,10 +290,12 @@
FCVT_S_W = auto()
FCVT_S_WU = auto()
FMV_W_X = auto()
+ # RV64F instructions
FCVT_L_S = auto()
FCVT_LU_S = auto()
FCVT_S_L = auto()
FCVT_S_LU = auto()
+ # RV32D instructions
FLD = auto()
FSD = auto()
FMADD_D = auto()
@@ -307,12 +322,14 @@
FCVT_WU_D = auto()
FCVT_D_W = auto()
FCVT_D_WU = auto()
+ # RV64D instructions
FCVT_L_D = auto()
FCVT_LU_D = auto()
FMV_X_D = auto()
FCVT_D_L = auto()
FCVT_D_LU = auto()
FMV_D_X = auto()
+ # RV64I instructions
LWU = auto()
LD = auto()
SD = auto()
@@ -325,6 +342,7 @@
SLLW = auto()
SRLW = auto()
SRAW = auto()
+ # RV32C instructions
C_LW = auto()
C_SW = auto()
C_LWSP = auto()
@@ -352,6 +370,7 @@
C_JAL = auto()
C_JR = auto()
C_JALR = auto()
+ # RV64C instructions
C_ADDIW = auto()
C_SUBW = auto()
C_ADDW = auto()
@@ -359,6 +378,7 @@
C_SD = auto()
C_LDSP = auto()
C_SDSP = auto()
+ # RV128C instructions
C_SRLI64 = auto()
C_SRAI64 = auto()
C_SLLI64 = auto()
@@ -366,14 +386,17 @@
C_SQ = auto()
C_LQSP = auto()
C_SQSP = auto()
+ # RV32FC instructions
C_FLW = auto()
C_FSW = auto()
C_FLWSP = auto()
C_FSWSP = auto()
+ # RV32DC instructions
C_FLD = auto()
C_FSD = auto()
C_FLDSP = auto()
C_FSDSP = auto()
+ # RV32A instructions
LR_W = auto()
SC_W = auto()
AMOSWAP_W = auto()
@@ -385,6 +408,7 @@
AMOMAX_W = auto()
AMOMINU_W = auto()
AMOMAXU_W = auto()
+ # RV64A instructions
LR_D = auto()
SC_D = auto()
AMOSWAP_D = auto()
@@ -396,6 +420,7 @@
AMOMAX_D = auto()
AMOMINU_D = auto()
AMOMAXU_D = auto()
+ # Vector instructions
VSETVL = auto()
VSETVLI = auto()
VADD = auto()
@@ -448,6 +473,10 @@
VWMACC = auto()
VWMACCSU = auto()
VWMACCUS = auto()
+ # VQMACCU = auto()
+ # VQMACC = auto()
+ # VQMACCSU = auto()
+ # VQMACCUS = auto()
VMERGE = auto()
VMV = auto()
VSADDU = auto()
@@ -462,6 +491,7 @@
VSSRA = auto()
VNCLIPU = auto()
VNCLIP = auto()
+ # 14. Vector Floating-Point instructions
VFADD = auto()
VFSUB = auto()
VFRSUB = auto()
@@ -511,6 +541,7 @@
VFNCVT_F_X_W = auto()
VFNCVT_F_F_W = auto()
VFNCVT_ROD_F_F_W = auto()
+ # 15. Vector reduction instructions
VREDSUM_VS = auto()
VREDMAXU_VS = auto()
VREDMAX_VS = auto()
@@ -526,6 +557,7 @@
VFREDMAX_VS = auto()
VFWREDOSUM_VS = auto()
VFWREDSUM_VS = auto()
+ # Vector mask instructions
VMAND_MM = auto()
VMNAND_MM = auto()
VMANDNOT_MM = auto()
@@ -541,6 +573,7 @@
VMSOF_M = auto()
VIOTA_M = auto()
VID_V = auto()
+ # Vector permutation instructions
VMV_X_S = auto()
VMV_S_X = auto()
VFMV_F_S = auto()
@@ -555,12 +588,45 @@
VMV2R_V = auto()
VMV4R_V = auto()
VMV8R_V = auto()
+ # Vector load/store instructions
+ VLE_V = auto()
+ VSE_V = auto()
+ VLSE_V = auto()
+ VSSE_V = auto()
+ VLXEI_V = auto()
+ VSXEI_V = auto()
+ VSUXEI_V = auto()
+ VLEFF_V = auto()
+ # Segmented load/store instruction
+ VLSEGE_V = auto()
+ VSSEGE_V = auto()
+ VLSEGEFF_V = auto()
+ VLSSEGE_V = auto()
+ VSSSEGE_V = auto()
+ VLXSEGEI_V = auto()
+ VSXSEGEI_V = auto()
+ VSUXSEGEI_V = auto()
+ # Vector AMO instruction
+ # EEW vector AMOs
+ VAMOSWAPE_V = auto()
+ VAMOADDE_V = auto()
+ VAMOXORE_V = auto()
+ VAMOANDE_V = auto()
+ VAMOORE_V = auto()
+ VAMOMINE_V = auto()
+ VAMOMAXE_V = auto()
+ VAMOMINUE_V = auto()
+ VAMOMAXUE_V = auto()
+ # Supervisor instruction
DRET = auto()
MRET = auto()
URET = auto()
SRET = auto()
WFI = auto()
SFENCE_VMA = auto()
+ # Custom instructions
+ # TODO add a way to import custom instructions here from isa/custom/riscv_custom_instr_enum.py
+ # You can add other instructions here
INVALID_INSTR = auto()
@@ -677,6 +743,7 @@
R_FORMAT = auto()
S_FORMAT = auto()
R4_FORMAT = auto()
+ # Compressed instruction format
CI_FORMAT = auto()
CB_FORMAT = auto()
CJ_FORMAT = auto()
@@ -686,13 +753,15 @@
CS_FORMAT = auto()
CSS_FORMAT = auto()
CIW_FORMAT = auto()
+ # Vector instruction format
VSET_FORMAT = auto()
VA_FORMAT = auto()
- VS2_FORMAT = auto()
+ VS2_FORMAT = auto() # op vd,vs2
VL_FORMAT = auto()
VS_FORMAT = auto()
+# Vector arithmetic instruction variant
class va_variant_t(IntEnum):
VV = 0
VI = auto()
@@ -725,269 +794,277 @@
CHANGELEVEL = auto()
TRAP = auto()
INTERRUPT = auto()
- AMO = auto()
-
-
-# typedef bit[11:0] riscv_csr_t;
+ # TODO import vector_category
+ AMO = auto() # (last one)
class privileged_reg_t(IntEnum):
- USTATUS = 0x000
- UIE = 0x004
- UTVEC = 0x005
- USCRATCH = 0x040
- UEPC = 0x041
- UCAUSE = 0x042
- UTVAL = 0x043
- UIP = 0x044
- FFLAGS = 0x001
- FRM = 0x002
- FCSR = 0x003
- CYCLE = 0xC00
- TIME = 0xC01
- INSTRET = 0xC02
- HPMCOUNTER3 = 0xC03
- HPMCOUNTER4 = 0xC04
- HPMCOUNTER5 = 0xC05
- HPMCOUNTER6 = 0xC06
- HPMCOUNTER7 = 0xC07
- HPMCOUNTER8 = 0xC08
- HPMCOUNTER9 = 0xC09
- HPMCOUNTER10 = 0xC0A
- HPMCOUNTER11 = 0xC0B
- HPMCOUNTER12 = 0xC0C
- HPMCOUNTER13 = 0xC0D
- HPMCOUNTER14 = 0xC0E
- HPMCOUNTER15 = 0xC0F
- HPMCOUNTER16 = 0xC10
- HPMCOUNTER17 = 0xC11
- HPMCOUNTER18 = 0xC12
- HPMCOUNTER19 = 0xC13
- HPMCOUNTER20 = 0xC14
- HPMCOUNTER21 = 0xC15
- HPMCOUNTER22 = 0xC16
- HPMCOUNTER23 = 0xC17
- HPMCOUNTER24 = 0xC18
- HPMCOUNTER25 = 0xC19
- HPMCOUNTER26 = 0xC1A
- HPMCOUNTER27 = 0xC1B
- HPMCOUNTER28 = 0xC1C
- HPMCOUNTER29 = 0xC1D
- HPMCOUNTER30 = 0xC1E
- HPMCOUNTER31 = 0xC1F
- CYCLEH = 0xC80
- TIMEH = 0xC81
- INSTRETH = 0xC82
- HPMCOUNTER3H = 0xC83
- HPMCOUNTER4H = 0xC84
- HPMCOUNTER5H = 0xC85
- HPMCOUNTER6H = 0xC86
- HPMCOUNTER7H = 0xC87
- HPMCOUNTER8H = 0xC88
- HPMCOUNTER9H = 0xC89
- HPMCOUNTER10H = 0xC8A
- HPMCOUNTER11H = 0xC8B
- HPMCOUNTER12H = 0xC8C
- HPMCOUNTER13H = 0xC8D
- HPMCOUNTER14H = 0xC8E
- HPMCOUNTER15H = 0xC8F
- HPMCOUNTER16H = 0xC90
- HPMCOUNTER17H = 0xC91
- HPMCOUNTER18H = 0xC92
- HPMCOUNTER19H = 0xC93
- HPMCOUNTER20H = 0xC94
- HPMCOUNTER21H = 0xC95
- HPMCOUNTER22H = 0xC96
- HPMCOUNTER23H = 0xC97
- HPMCOUNTER24H = 0xC98
- HPMCOUNTER25H = 0xC99
- HPMCOUNTER26H = 0xC9A
- HPMCOUNTER27H = 0xC9B
- HPMCOUNTER28H = 0xC9C
- HPMCOUNTER29H = 0xC9D
- HPMCOUNTER30H = 0xC9E
- HPMCOUNTER31H = 0xC9F
- SSTATUS = 0x100
- SEDELEG = 0x102
- SIDELEG = 0x103
- SIE = 0x104
- STVEC = 0x105
- SCOUNTEREN = 0x106
- SSCRATCH = 0x140
- SEPC = 0x141
- SCAUSE = 0x142
- STVAL = 0x143
- SIP = 0x144
- SATP = 0x180
- MVENDORID = 0xF11
- MARCHID = 0xF12
- MIMPID = 0xF13
- MHARTID = 0xF14
- MSTATUS = 0x300
- MISA = 0x301
- MEDELEG = 0x302
- MIDELEG = 0x303
- MIE = 0x304
- MTVEC = 0x305
- MCOUNTEREN = 0x306
- MSCRATCH = 0x340
- MEPC = 0x341
- MCAUSE = 0x342
- MTVAL = 0x343
- MIP = 0x344
- PMPCFG0 = 0x3A0
- PMPCFG1 = 0x3A1
- PMPCFG2 = 0x3A2
- PMPCFG3 = 0x3A3
- PMPADDR0 = 0x3B0
- PMPADDR1 = 0x3B1
- PMPADDR2 = 0x3B2
- PMPADDR3 = 0x3B3
- PMPADDR4 = 0x3B4
- PMPADDR5 = 0x3B5
- PMPADDR6 = 0x3B6
- PMPADDR7 = 0x3B7
- PMPADDR8 = 0x3B8
- PMPADDR9 = 0x3B9
- PMPADDR10 = 0x3BA
- PMPADDR11 = 0x3BB
- PMPADDR12 = 0x3BC
- PMPADDR13 = 0x3BD
- PMPADDR14 = 0x3BE
- PMPADDR15 = 0x3BF
- MCYCLE = 0xB00
- MINSTRET = 0xB02
- MHPMCOUNTER3 = 0xB03
- MHPMCOUNTER4 = 0xB04
- MHPMCOUNTER5 = 0xB05
- MHPMCOUNTER6 = 0xB06
- MHPMCOUNTER7 = 0xB07
- MHPMCOUNTER8 = 0xB08
- MHPMCOUNTER9 = 0xB09
- MHPMCOUNTER10 = 0xB0A
- MHPMCOUNTER11 = 0xB0B
- MHPMCOUNTER12 = 0xB0C
- MHPMCOUNTER13 = 0xB0D
- MHPMCOUNTER14 = 0xB0E
- MHPMCOUNTER15 = 0xB0F
- MHPMCOUNTER16 = 0xB10
- MHPMCOUNTER17 = 0xB11
- MHPMCOUNTER18 = 0xB12
- MHPMCOUNTER19 = 0xB13
- MHPMCOUNTER20 = 0xB14
- MHPMCOUNTER21 = 0xB15
- MHPMCOUNTER22 = 0xB16
- MHPMCOUNTER23 = 0xB17
- MHPMCOUNTER24 = 0xB18
- MHPMCOUNTER25 = 0xB19
- MHPMCOUNTER26 = 0xB1A
- MHPMCOUNTER27 = 0xB1B
- MHPMCOUNTER28 = 0xB1C
- MHPMCOUNTER29 = 0xB1D
- MHPMCOUNTER30 = 0xB1E
- MHPMCOUNTER31 = 0xB1F
- MCYCLEH = 0xB80
- MINSTRETH = 0xB82
- MHPMCOUNTER3H = 0xB83
- MHPMCOUNTER4H = 0xB84
- MHPMCOUNTER5H = 0xB85
- MHPMCOUNTER6H = 0xB86
- MHPMCOUNTER7H = 0xB87
- MHPMCOUNTER8H = 0xB88
- MHPMCOUNTER9H = 0xB89
- MHPMCOUNTER10H = 0xB8A
- MHPMCOUNTER11H = 0xB8B
- MHPMCOUNTER12H = 0xB8C
- MHPMCOUNTER13H = 0xB8D
- MHPMCOUNTER14H = 0xB8E
- MHPMCOUNTER15H = 0xB8F
- MHPMCOUNTER17H = 0xB90
- MHPMCOUNTER18H = 0xB91
- MHPMCOUNTER19H = 0xB92
- MHPMCOUNTER20H = 0xB93
- MHPMCOUNTER21H = 0xB94
- MHPMCOUNTER22H = 0xB95
- MHPMCOUNTER23H = 0xB96
- MHPMCOUNTER24H = 0xB97
- MHPMCOUNTER25H = 0xB98
- MHPMCOUNTER26H = 0xB99
- MHPMCOUNTER27H = 0xB9A
- MHPMCOUNTER28H = 0xB9B
- MHPMCOUNTER29H = 0xB9C
- MHPMCOUNTER30H = 0xB9D
- MHPMCOUNTER31H = 0xB9E
- MCOUNTINHIBIT = 0x320F
- MHPMEVENT3 = 0x323
- MHPMEVENT4 = 0x324
- MHPMEVENT5 = 0x325
- MHPMEVENT6 = 0x326
- MHPMEVENT7 = 0x327
- MHPMEVENT8 = 0x328
- MHPMEVENT9 = 0x329
- MHPMEVENT10 = 0x32A
- MHPMEVENT11 = 0x32B
- MHPMEVENT12 = 0x32C
- MHPMEVENT13 = 0x32D
- MHPMEVENT14 = 0x32E
- MHPMEVENT15 = 0x32F
- MHPMEVENT16 = 0x330
- MHPMEVENT17 = 0x331
- MHPMEVENT18 = 0x332
- MHPMEVENT19 = 0x333
- MHPMEVENT20 = 0x334
- MHPMEVENT21 = 0x335
- MHPMEVENT22 = 0x336
- MHPMEVENT23 = 0x337
- MHPMEVENT24 = 0x338
- MHPMEVENT25 = 0x339
- MHPMEVENT26 = 0x33A
- MHPMEVENT27 = 0x33B
- MHPMEVENT28 = 0x33C
- MHPMEVENT29 = 0x33D
- MHPMEVENT30 = 0x33E
- MHPMEVENT31 = 0x33F
- TSELECT = 0x7A0
- TDATA1 = 0x7A1
- TDATA2 = 0x7A2
- TDATA3 = 0x7A3
- DCSR = 0x7B0
- DPC = 0x7B1
- DSCRATCH0 = 0x7B2
- DSCRATCH1 = 0x7B3
- VSTART = 0x008
- VXSTAT = 0x009
- VXRM = 0x00A
- VL = 0xC20
- VTYPE = 0xC21
- VLENB = 0xC22
+ # User mode register
+ USTATUS = 0x000 # User status
+ UIE = 0x004 # User interrupt-enable register
+ UTVEC = 0x005 # User trap-handler base address
+ USCRATCH = 0x040 # Scratch register for user trap handlers
+ UEPC = 0x041 # User exception program counter
+ UCAUSE = 0x042 # User trap cause
+ UTVAL = 0x043 # User bad address or instruction
+ UIP = 0x044 # User interrupt pending
+ FFLAGS = 0x001 # Floating-Point Accrued Exceptions
+ FRM = 0x002 # Floating-Point Dynamic Rounding Mode
+ FCSR = 0x003 # Floating-Point Control/Status Register (FRM + FFLAGS)
+ CYCLE = 0xC00 # Cycle counter for RDCYCLE instruction
+ TIME = 0xC01 # Timer for RDTIME instruction
+ INSTRET = 0xC02 # Instructions-retired counter for RDINSTRET instruction
+ HPMCOUNTER3 = 0xC03 # Performance-monitoring counter
+ HPMCOUNTER4 = 0xC04 # Performance-monitoring counter
+ HPMCOUNTER5 = 0xC05 # Performance-monitoring counter
+ HPMCOUNTER6 = 0xC06 # Performance-monitoring counter
+ HPMCOUNTER7 = 0xC07 # Performance-monitoring counter
+ HPMCOUNTER8 = 0xC08 # Performance-monitoring counter
+ HPMCOUNTER9 = 0xC09 # Performance-monitoring counter
+ HPMCOUNTER10 = 0xC0A # Performance-monitoring counter
+ HPMCOUNTER11 = 0xC0B # Performance-monitoring counter
+ HPMCOUNTER12 = 0xC0C # Performance-monitoring counter
+ HPMCOUNTER13 = 0xC0D # Performance-monitoring counter
+ HPMCOUNTER14 = 0xC0E # Performance-monitoring counter
+ HPMCOUNTER15 = 0xC0F # Performance-monitoring counter
+ HPMCOUNTER16 = 0xC10 # Performance-monitoring counter
+ HPMCOUNTER17 = 0xC11 # Performance-monitoring counter
+ HPMCOUNTER18 = 0xC12 # Performance-monitoring counter
+ HPMCOUNTER19 = 0xC13 # Performance-monitoring counter
+ HPMCOUNTER20 = 0xC14 # Performance-monitoring counter
+ HPMCOUNTER21 = 0xC15 # Performance-monitoring counter
+ HPMCOUNTER22 = 0xC16 # Performance-monitoring counter
+ HPMCOUNTER23 = 0xC17 # Performance-monitoring counter
+ HPMCOUNTER24 = 0xC18 # Performance-monitoring counter
+ HPMCOUNTER25 = 0xC19 # Performance-monitoring counter
+ HPMCOUNTER26 = 0xC1A # Performance-monitoring counter
+ HPMCOUNTER27 = 0xC1B # Performance-monitoring counter
+ HPMCOUNTER28 = 0xC1C # Performance-monitoring counter
+ HPMCOUNTER29 = 0xC1D # Performance-monitoring counter
+ HPMCOUNTER30 = 0xC1E # Performance-monitoring counter
+ HPMCOUNTER31 = 0xC1F # Performance-monitoring counter
+ CYCLEH = 0xC80 # Upper 32 bits of CYCLE, RV32I only
+ TIMEH = 0xC81 # Upper 32 bits of TIME, RV32I only
+ INSTRETH = 0xC82 # Upper 32 bits of INSTRET, RV32I only
+ HPMCOUNTER3H = 0xC83 # Upper 32 bits of HPMCOUNTER3, RV32I only
+ HPMCOUNTER4H = 0xC84 # Upper 32 bits of HPMCOUNTER4, RV32I only
+ HPMCOUNTER5H = 0xC85 # Upper 32 bits of HPMCOUNTER5, RV32I only
+ HPMCOUNTER6H = 0xC86 # Upper 32 bits of HPMCOUNTER6, RV32I only
+ HPMCOUNTER7H = 0xC87 # Upper 32 bits of HPMCOUNTER7, RV32I only
+ HPMCOUNTER8H = 0xC88 # Upper 32 bits of HPMCOUNTER8, RV32I only
+ HPMCOUNTER9H = 0xC89 # Upper 32 bits of HPMCOUNTER9, RV32I only
+ HPMCOUNTER10H = 0xC8A # Upper 32 bits of HPMCOUNTER10, RV32I only
+ HPMCOUNTER11H = 0xC8B # Upper 32 bits of HPMCOUNTER11, RV32I only
+ HPMCOUNTER12H = 0xC8C # Upper 32 bits of HPMCOUNTER12, RV32I only
+ HPMCOUNTER13H = 0xC8D # Upper 32 bits of HPMCOUNTER13, RV32I only
+ HPMCOUNTER14H = 0xC8E # Upper 32 bits of HPMCOUNTER14, RV32I only
+ HPMCOUNTER15H = 0xC8F # Upper 32 bits of HPMCOUNTER15, RV32I only
+ HPMCOUNTER16H = 0xC90 # Upper 32 bits of HPMCOUNTER16, RV32I only
+ HPMCOUNTER17H = 0xC91 # Upper 32 bits of HPMCOUNTER17, RV32I only
+ HPMCOUNTER18H = 0xC92 # Upper 32 bits of HPMCOUNTER18, RV32I only
+ HPMCOUNTER19H = 0xC93 # Upper 32 bits of HPMCOUNTER19, RV32I only
+ HPMCOUNTER20H = 0xC94 # Upper 32 bits of HPMCOUNTER20, RV32I only
+ HPMCOUNTER21H = 0xC95 # Upper 32 bits of HPMCOUNTER21, RV32I only
+ HPMCOUNTER22H = 0xC96 # Upper 32 bits of HPMCOUNTER22, RV32I only
+ HPMCOUNTER23H = 0xC97 # Upper 32 bits of HPMCOUNTER23, RV32I only
+ HPMCOUNTER24H = 0xC98 # Upper 32 bits of HPMCOUNTER24, RV32I only
+ HPMCOUNTER25H = 0xC99 # Upper 32 bits of HPMCOUNTER25, RV32I only
+ HPMCOUNTER26H = 0xC9A # Upper 32 bits of HPMCOUNTER26, RV32I only
+ HPMCOUNTER27H = 0xC9B # Upper 32 bits of HPMCOUNTER27, RV32I only
+ HPMCOUNTER28H = 0xC9C # Upper 32 bits of HPMCOUNTER28, RV32I only
+ HPMCOUNTER29H = 0xC9D # Upper 32 bits of HPMCOUNTER29, RV32I only
+ HPMCOUNTER30H = 0xC9E # Upper 32 bits of HPMCOUNTER30, RV32I only
+ HPMCOUNTER31H = 0xC9F # Upper 32 bits of HPMCOUNTER31, RV32I only
+ # Supervisor mode register
+ SSTATUS = 0x100 # Supervisor status
+ SEDELEG = 0x102 # Supervisor exception delegation register
+ SIDELEG = 0x103 # Supervisor interrupt delegation register
+ SIE = 0x104 # Supervisor interrupt-enable register
+ STVEC = 0x105 # Supervisor trap-handler base address
+ SCOUNTEREN = 0x106 # Supervisor counter enable
+ SSCRATCH = 0x140 # Scratch register for supervisor trap handlers
+ SEPC = 0x141 # Supervisor exception program counter
+ SCAUSE = 0x142 # Supervisor trap cause
+ STVAL = 0x143 # Supervisor bad address or instruction
+ SIP = 0x144 # Supervisor interrupt pending
+ SATP = 0x180 # Supervisor address translation and protection
+ # Machine mode register
+ MVENDORID = 0xF11 # Vendor ID
+ MARCHID = 0xF12 # Architecture ID
+ MIMPID = 0xF13 # Implementation ID
+ MHARTID = 0xF14 # Hardware thread ID
+ MSTATUS = 0x300 # Machine status
+ MISA = 0x301 # ISA and extensions
+ MEDELEG = 0x302 # Machine exception delegation register
+ MIDELEG = 0x303 # Machine interrupt delegation register
+ MIE = 0x304 # Machine interrupt-enable register
+ MTVEC = 0x305 # Machine trap-handler base address
+ MCOUNTEREN = 0x306 # Machine counter enable
+ MSCRATCH = 0x340 # Scratch register for machine trap handlers
+ MEPC = 0x341 # Machine exception program counter
+ MCAUSE = 0x342 # Machine trap cause
+ MTVAL = 0x343 # Machine bad address or instruction
+ MIP = 0x344 # Machine interrupt pending
+ PMPCFG0 = 0x3A0 # Physical memory protection configuration
+ PMPCFG1 = 0x3A1 # Physical memory protection configuration, RV32 only
+ PMPCFG2 = 0x3A2 # Physical memory protection configuration
+ PMPCFG3 = 0x3A3 # Physical memory protection configuration, RV32 only
+ PMPADDR0 = 0x3B0 # Physical memory protection address register
+ PMPADDR1 = 0x3B1 # Physical memory protection address register
+ PMPADDR2 = 0x3B2 # Physical memory protection address register
+ PMPADDR3 = 0x3B3 # Physical memory protection address register
+ PMPADDR4 = 0x3B4 # Physical memory protection address register
+ PMPADDR5 = 0x3B5 # Physical memory protection address register
+ PMPADDR6 = 0x3B6 # Physical memory protection address register
+ PMPADDR7 = 0x3B7 # Physical memory protection address register
+ PMPADDR8 = 0x3B8 # Physical memory protection address register
+ PMPADDR9 = 0x3B9 # Physical memory protection address register
+ PMPADDR10 = 0x3BA # Physical memory protection address register
+ PMPADDR11 = 0x3BB # Physical memory protection address register
+ PMPADDR12 = 0x3BC # Physical memory protection address register
+ PMPADDR13 = 0x3BD # Physical memory protection address register
+ PMPADDR14 = 0x3BE # Physical memory protection address register
+ PMPADDR15 = 0x3BF # Physical memory protection address register
+ MCYCLE = 0xB00 # Machine cycle counter
+ MINSTRET = 0xB02 # Machine instructions-retired counter
+ MHPMCOUNTER3 = 0xB03 # Machine performance-monitoring counter
+ MHPMCOUNTER4 = 0xB04 # Machine performance-monitoring counter
+ MHPMCOUNTER5 = 0xB05 # Machine performance-monitoring counter
+ MHPMCOUNTER6 = 0xB06 # Machine performance-monitoring counter
+ MHPMCOUNTER7 = 0xB07 # Machine performance-monitoring counter
+ MHPMCOUNTER8 = 0xB08 # Machine performance-monitoring counter
+ MHPMCOUNTER9 = 0xB09 # Machine performance-monitoring counter
+ MHPMCOUNTER10 = 0xB0A # Machine performance-monitoring counter
+ MHPMCOUNTER11 = 0xB0B # Machine performance-monitoring counter
+ MHPMCOUNTER12 = 0xB0C # Machine performance-monitoring counter
+ MHPMCOUNTER13 = 0xB0D # Machine performance-monitoring counter
+ MHPMCOUNTER14 = 0xB0E # Machine performance-monitoring counter
+ MHPMCOUNTER15 = 0xB0F # Machine performance-monitoring counter
+ MHPMCOUNTER16 = 0xB10 # Machine performance-monitoring counter
+ MHPMCOUNTER17 = 0xB11 # Machine performance-monitoring counter
+ MHPMCOUNTER18 = 0xB12 # Machine performance-monitoring counter
+ MHPMCOUNTER19 = 0xB13 # Machine performance-monitoring counter
+ MHPMCOUNTER20 = 0xB14 # Machine performance-monitoring counter
+ MHPMCOUNTER21 = 0xB15 # Machine performance-monitoring counter
+ MHPMCOUNTER22 = 0xB16 # Machine performance-monitoring counter
+ MHPMCOUNTER23 = 0xB17 # Machine performance-monitoring counter
+ MHPMCOUNTER24 = 0xB18 # Machine performance-monitoring counter
+ MHPMCOUNTER25 = 0xB19 # Machine performance-monitoring counter
+ MHPMCOUNTER26 = 0xB1A # Machine performance-monitoring counter
+ MHPMCOUNTER27 = 0xB1B # Machine performance-monitoring counter
+ MHPMCOUNTER28 = 0xB1C # Machine performance-monitoring counter
+ MHPMCOUNTER29 = 0xB1D # Machine performance-monitoring counter
+ MHPMCOUNTER30 = 0xB1E # Machine performance-monitoring counter
+ MHPMCOUNTER31 = 0xB1F # Machine performance-monitoring counter
+ MCYCLEH = 0xB80 # Upper 32 bits of MCYCLE, RV32I only
+ MINSTRETH = 0xB82 # Upper 32 bits of MINSTRET, RV32I only
+ MHPMCOUNTER3H = 0xB83 # Upper 32 bits of HPMCOUNTER3, RV32I only
+ MHPMCOUNTER4H = 0xB84 # Upper 32 bits of HPMCOUNTER4, RV32I only
+ MHPMCOUNTER5H = 0xB85 # Upper 32 bits of HPMCOUNTER5, RV32I only
+ MHPMCOUNTER6H = 0xB86 # Upper 32 bits of HPMCOUNTER6, RV32I only
+ MHPMCOUNTER7H = 0xB87 # Upper 32 bits of HPMCOUNTER7, RV32I only
+ MHPMCOUNTER8H = 0xB88 # Upper 32 bits of HPMCOUNTER8, RV32I only
+ MHPMCOUNTER9H = 0xB89 # Upper 32 bits of HPMCOUNTER9, RV32I only
+ MHPMCOUNTER10H = 0xB8A # Upper 32 bits of HPMCOUNTER10, RV32I only
+ MHPMCOUNTER11H = 0xB8B # Upper 32 bits of HPMCOUNTER11, RV32I only
+ MHPMCOUNTER12H = 0xB8C # Upper 32 bits of HPMCOUNTER12, RV32I only
+ MHPMCOUNTER13H = 0xB8D # Upper 32 bits of HPMCOUNTER13, RV32I only
+ MHPMCOUNTER14H = 0xB8E # Upper 32 bits of HPMCOUNTER14, RV32I only
+ MHPMCOUNTER15H = 0xB8F # Upper 32 bits of HPMCOUNTER15, RV32I only
+ MHPMCOUNTER16H = 0xB8F # Upper 32 bits of HPMCOUNTER16, RV32I only
+ MHPMCOUNTER17H = 0xB90 # Upper 32 bits of HPMCOUNTER17, RV32I only
+ MHPMCOUNTER18H = 0xB91 # Upper 32 bits of HPMCOUNTER18, RV32I only
+ MHPMCOUNTER19H = 0xB92 # Upper 32 bits of HPMCOUNTER19, RV32I only
+ MHPMCOUNTER20H = 0xB93 # Upper 32 bits of HPMCOUNTER20, RV32I only
+ MHPMCOUNTER21H = 0xB94 # Upper 32 bits of HPMCOUNTER21, RV32I only
+ MHPMCOUNTER22H = 0xB95 # Upper 32 bits of HPMCOUNTER22, RV32I only
+ MHPMCOUNTER23H = 0xB96 # Upper 32 bits of HPMCOUNTER23, RV32I only
+ MHPMCOUNTER24H = 0xB97 # Upper 32 bits of HPMCOUNTER24, RV32I only
+ MHPMCOUNTER25H = 0xB98 # Upper 32 bits of HPMCOUNTER25, RV32I only
+ MHPMCOUNTER26H = 0xB99 # Upper 32 bits of HPMCOUNTER26, RV32I only
+ MHPMCOUNTER27H = 0xB9A # Upper 32 bits of HPMCOUNTER27, RV32I only
+ MHPMCOUNTER28H = 0xB9B # Upper 32 bits of HPMCOUNTER28, RV32I only
+ MHPMCOUNTER29H = 0xB9C # Upper 32 bits of HPMCOUNTER29, RV32I only
+ MHPMCOUNTER30H = 0xB9D # Upper 32 bits of HPMCOUNTER30, RV32I only
+ MHPMCOUNTER31H = 0xB9E # Upper 32 bits of HPMCOUNTER31, RV32I only
+ MCOUNTINHIBIT = 0x320F # Machine counter-inhibit register
+ MHPMEVENT3 = 0x323 # Machine performance-monitoring event selector
+ MHPMEVENT4 = 0x324 # Machine performance-monitoring event selector
+ MHPMEVENT5 = 0x325 # Machine performance-monitoring event selector
+ MHPMEVENT6 = 0x326 # Machine performance-monitoring event selector
+ MHPMEVENT7 = 0x327 # Machine performance-monitoring event selector
+ MHPMEVENT8 = 0x328 # Machine performance-monitoring event selector
+ MHPMEVENT9 = 0x329 # Machine performance-monitoring event selector
+ MHPMEVENT10 = 0x32A # Machine performance-monitoring event selector
+ MHPMEVENT11 = 0x32B # Machine performance-monitoring event selector
+ MHPMEVENT12 = 0x32C # Machine performance-monitoring event selector
+ MHPMEVENT13 = 0x32D # Machine performance-monitoring event selector
+ MHPMEVENT14 = 0x32E # Machine performance-monitoring event selector
+ MHPMEVENT15 = 0x32F # Machine performance-monitoring event selector
+ MHPMEVENT16 = 0x330 # Machine performance-monitoring event selector
+ MHPMEVENT17 = 0x331 # Machine performance-monitoring event selector
+ MHPMEVENT18 = 0x332 # Machine performance-monitoring event selector
+ MHPMEVENT19 = 0x333 # Machine performance-monitoring event selector
+ MHPMEVENT20 = 0x334 # Machine performance-monitoring event selector
+ MHPMEVENT21 = 0x335 # Machine performance-monitoring event selector
+ MHPMEVENT22 = 0x336 # Machine performance-monitoring event selector
+ MHPMEVENT23 = 0x337 # Machine performance-monitoring event selector
+ MHPMEVENT24 = 0x338 # Machine performance-monitoring event selector
+ MHPMEVENT25 = 0x339 # Machine performance-monitoring event selector
+ MHPMEVENT26 = 0x33A # Machine performance-monitoring event selector
+ MHPMEVENT27 = 0x33B # Machine performance-monitoring event selector
+ MHPMEVENT28 = 0x33C # Machine performance-monitoring event selector
+ MHPMEVENT29 = 0x33D # Machine performance-monitoring event selector
+ MHPMEVENT30 = 0x33E # Machine performance-monitoring event selector
+ MHPMEVENT31 = 0x33F # Machine performance-monitoring event selector
+ TSELECT = 0x7A0 # Debug/Trace trigger register select
+ TDATA1 = 0x7A1 # First Debug/Trace trigger data register
+ TDATA2 = 0x7A2 # Second Debug/Trace trigger data register
+ TDATA3 = 0x7A3 # Third Debug/Trace trigger data register
+ TINFO = 0x7A4 # Debug trigger info register
+ TCONTROL = 0x7A5 # Debug trigger control register
+ MCONTEXT = 0x7A8 # Machine mode trigger context register
+ SCONTEXT = 0x7AA # Supervisor mode trigger context register
+ DCSR = 0x7B0 # Debug control and status register
+ DPC = 0x7B1 # Debug PC
+ DSCRATCH0 = 0x7B2 # Debug scratch register
+ DSCRATCH1 = 0x7B3 # Debug scratch register (last one)
+ VSTART = 0x008 # Vector start position
+ VXSTAT = 0x009 # Fixed point saturate flag
+ VXRM = 0x00A # Fixed point rounding mode
+ VL = 0xC20 # Vector length
+ VTYPE = 0xC21 # Vector data type register
+ VLENB = 0xC22 # VLEN/8 (vector register length in bytes)
class privileged_reg_fld_t(IntEnum):
- RSVD = 0
- MXL = auto()
- EXTENSION = auto()
- MODE = auto()
- ASID = auto()
- PPN = auto()
+ RSVD = 0 # Reserved field
+ MXL = auto() # mis.mxl
+ EXTENSION = auto() # mis.extension
+ MODE = auto() # satp.mode
+ ASID = auto() # satp.asid
+ PPN = auto() # satp.ppn
class privileged_level_t(IntEnum):
- M_LEVEL = 0b11
- S_LEVEL = 0b01
- U_LEVEL = 0b00
+ M_LEVEL = 0b11 # Machine mode
+ S_LEVEL = 0b01 # Supervisor mode
+ U_LEVEL = 0b00 # User mode
class reg_field_access_t(IntEnum):
- WPRI = 0
- WLRL = auto()
- WARL = auto()
+ WPRI = 0 # Reserved Writes Preserve Values, Reads Ignore Value
+ WLRL = auto() # Write/Read Only Legal Values
+ WARL = auto() # Write Any Values, Reads Legal Values
+# Pseudo instructions
class riscv_pseudo_instr_name_t(IntEnum):
LI = 0
LA = auto()
+# Data pattern of the memory model
class data_pattern_t(IntEnum):
RAND_DATA = 0
ALL_ZERO = auto()
@@ -995,12 +1072,12 @@
class pte_permission_t(IntEnum):
- NEXT_LEVEL_PAGE = 0b000
- READ_ONLY_PAGE = 0b001
- READ_WRITE_PAGE = 0b011
- EXECUTE_ONLY_PAGE = 0b100
- READ_EXECUTE_PAGE = 0b101
- R_W_EXECUTE_PAGE = 0b111
+ NEXT_LEVEL_PAGE = 0b000 # Pointer to next level of page table.
+ READ_ONLY_PAGE = 0b001 # Read-only page.
+ READ_WRITE_PAGE = 0b011 # Read-write page.
+ EXECUTE_ONLY_PAGE = 0b100 # Execute-only page.
+ READ_EXECUTE_PAGE = 0b101 # Read-execute page.
+ R_W_EXECUTE_PAGE = 0b111 # Read-write-execute page
class interrupt_cause_t(IntEnum):
@@ -1098,42 +1175,7 @@
RA = 0
T1 = auto()
-
-# Ignore ZERO as src1 of load instructions
-class riscv_reg_ex_zero_t(IntEnum):
- RA = 0
- SP = auto()
- GP = auto()
- TP = auto()
- T0 = auto()
- T1 = auto()
- T2 = auto()
- S0 = auto()
- S1 = auto()
- A0 = auto()
- A1 = auto()
- A2 = auto()
- A3 = auto()
- A4 = auto()
- A5 = auto()
- A6 = auto()
- A7 = auto()
- S2 = auto()
- S3 = auto()
- S4 = auto()
- S5 = auto()
- S6 = auto()
- S7 = auto()
- S8 = auto()
- S9 = auto()
- S10 = auto()
- S11 = auto()
- T3 = auto()
- T4 = auto()
- T5 = auto()
- T6 = auto()
-
-
+# PMP address matching mode
class pmp_addr_mode_t(Enum):
OFF = 0b00
TOR = 0b01
@@ -1166,7 +1208,7 @@
ZBR = auto()
ZBM = auto()
ZBT = auto()
- ZB_TMP = auto()
+ ZB_TMP = auto() # for uncategorized instructions
class all_gpr(Enum):
@@ -1204,8 +1246,8 @@
T6 = auto()
-class compressed_gpr(Enum):
- S0 = 0
+class compressed_gpr(IntEnum):
+ S0 = 8
S1 = auto()
A0 = auto()
A1 = auto()
@@ -1215,7 +1257,7 @@
A5 = auto()
-class all_categories(Enum):
+class all_categories(IntEnum):
LOAD = 0
STORE = auto()
SHIFT = auto()
@@ -1233,6 +1275,75 @@
INTERRUPT = auto()
AMO = auto()
+# Ignore ZERO and SP
+class riscv_reg_ex_zero_sp_t(IntEnum):
+ RA = 1
+ GP = 3
+ TP = auto()
+ T0 = auto()
+ T1 = auto()
+ T2 = auto()
+ S0 = auto()
+ S1 = auto()
+ A0 = auto()
+ A1 = auto()
+ A2 = auto()
+ A3 = auto()
+ A4 = auto()
+ A5 = auto()
+ A6 = auto()
+ A7 = auto()
+ S2 = auto()
+ S3 = auto()
+ S4 = auto()
+ S5 = auto()
+ S6 = auto()
+ S7 = auto()
+ S8 = auto()
+ S9 = auto()
+ S10 = auto()
+ S11 = auto()
+ T3 = auto()
+ T4 = auto()
+ T5 = auto()
+ T6 = auto()
+
+# Ignore ZERO only
+class riscv_reg_ex_zero_t(IntEnum):
+ RA = 1
+ SP = auto()
+ GP = auto()
+ TP = auto()
+ T0 = auto()
+ T1 = auto()
+ T2 = auto()
+ S0 = auto()
+ S1 = auto()
+ A0 = auto()
+ A1 = auto()
+ A2 = auto()
+ A3 = auto()
+ A4 = auto()
+ A5 = auto()
+ A6 = auto()
+ A7 = auto()
+ S2 = auto()
+ S3 = auto()
+ S4 = auto()
+ S5 = auto()
+ S6 = auto()
+ S7 = auto()
+ S8 = auto()
+ S9 = auto()
+ S10 = auto()
+ S11 = auto()
+ T3 = auto()
+ T4 = auto()
+ T5 = auto()
+ T6 = auto()
+
+# Currently PyVSC doesn't supports ignore bins
+# TODO riscv_reg_ex_zero_sp_t and riscv_reg_ex_zero_t is added as a WA and it can be removed later.
def get_val(in_string, hexa=0):
if len(in_string) > 2:
@@ -1422,6 +1533,113 @@
riscv_instr_name_t.CSRRCI: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.CSR,
riscv_instr_group_t.RV32I, imm_t.UIMM],
+ #RV32M
+ riscv_instr_name_t.MUL: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.MULH: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.MULHU: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.MULHSU: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.DIV: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.DIVU: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.REM: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ riscv_instr_name_t.REMU: [riscv_instr_format_t.R_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32M],
+ # RV32C
+ riscv_instr_name_t.C_LW: [riscv_instr_format_t.CL_FORMAT,
+ riscv_instr_category_t.LOAD,
+ riscv_instr_group_t.RV32C, imm_t.UIMM],
+ riscv_instr_name_t.C_SW: [riscv_instr_format_t.CS_FORMAT,
+ riscv_instr_category_t.STORE,
+ riscv_instr_group_t.RV32C, imm_t.UIMM],
+ riscv_instr_name_t.C_LWSP: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.LOAD,
+ riscv_instr_group_t.RV32C, imm_t.UIMM],
+ riscv_instr_name_t.C_SWSP: [riscv_instr_format_t.CSS_FORMAT,
+ riscv_instr_category_t.STORE,
+ riscv_instr_group_t.RV32C, imm_t.UIMM],
+ riscv_instr_name_t.C_ADDI4SPN: [riscv_instr_format_t.CIW_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+ riscv_instr_name_t.C_ADDI: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C, imm_t.NZIMM],
+ riscv_instr_name_t.C_ADDI16SP: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C, imm_t.NZIMM],
+ riscv_instr_name_t.C_LI: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_LUI: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C, imm_t.NZIMM],
+ riscv_instr_name_t.C_SUB: [riscv_instr_format_t.CA_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_ADD: [riscv_instr_format_t.CR_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_NOP: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_MV: [riscv_instr_format_t.CR_FORMAT,
+ riscv_instr_category_t.ARITHMETIC,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_ANDI: [riscv_instr_format_t.CB_FORMAT,
+ riscv_instr_category_t.LOGICAL,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_XOR: [riscv_instr_format_t.CA_FORMAT,
+ riscv_instr_category_t.LOGICAL,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_OR: [riscv_instr_format_t.CA_FORMAT,
+ riscv_instr_category_t.LOGICAL,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_AND: [riscv_instr_format_t.CA_FORMAT,
+ riscv_instr_category_t.LOGICAL,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_BEQZ: [riscv_instr_format_t.CB_FORMAT,
+ riscv_instr_category_t.BRANCH,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_BNEZ: [riscv_instr_format_t.CB_FORMAT,
+ riscv_instr_category_t.BRANCH,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_SRLI: [riscv_instr_format_t.CB_FORMAT,
+ riscv_instr_category_t.SHIFT,
+ riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+ riscv_instr_name_t.C_SRAI: [riscv_instr_format_t.CB_FORMAT,
+ riscv_instr_category_t.SHIFT,
+ riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+ riscv_instr_name_t.C_SLLI: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.SHIFT,
+ riscv_instr_group_t.RV32C, imm_t.NZUIMM],
+ riscv_instr_name_t.C_J: [riscv_instr_format_t.CJ_FORMAT,
+ riscv_instr_category_t.JUMP,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_JAL: [riscv_instr_format_t.CJ_FORMAT,
+ riscv_instr_category_t.JUMP,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_JR: [riscv_instr_format_t.CR_FORMAT,
+ riscv_instr_category_t.JUMP,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_JALR: [riscv_instr_format_t.CR_FORMAT,
+ riscv_instr_category_t.JUMP,
+ riscv_instr_group_t.RV32C],
+ riscv_instr_name_t.C_EBREAK: [riscv_instr_format_t.CI_FORMAT,
+ riscv_instr_category_t.SYSTEM,
+ riscv_instr_group_t.RV32C],
}
# if instruction is not present in the dictionary,second argument well
# be assigned as default value of passed argument
@@ -1442,9 +1660,11 @@
from pygen_src.riscv_instr_gen_config import cfg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+ # xSTATUS bit mask
MPRV_BIT_MASK = BitArray(uint=0x1 << 0x17, length=rcs.XLEN)
SUM_BIT_MASK = BitArray(uint=0x1 << 0x18, length=rcs.XLEN)
MPP_BIT_MASK = BitArray(uint=0x3 << 0x11, length=rcs.XLEN)
+
MAX_USED_VADDR_BITS = 30
IMM25_WIDTH = 25
IMM12_WIDTH = 12
@@ -1456,6 +1676,8 @@
MAX_SUB_PROGRAM_CNT = 20
MAX_CALL_PER_FUNC = 5
indent = LABEL_STR_LEN * " "
+ SINGLE_PRECISION_FRACTION_BITS = 23
+ DOUBLE_PRECISION_FRACTION_BITS = 52
def hart_prefix(self, hart=0):
if rcs.NUM_HARTS <= 1:
@@ -1466,13 +1688,16 @@
def get_label(self, label, hart=0):
return (self.hart_prefix(hart) + label)
+ # Format the string to a fixed length
def format_string(self, string, length=10):
formatted_str = length * " "
- if (int(length) < len(string)):
+ if int(length) < len(string):
return string
formatted_str = string + formatted_str[0: (int(length) - len(string))]
return formatted_str
+ # Print the data in the following format
+ # 0xabcd, 0x1234, 0x3334 ...
def format_data(self, data, byte_per_group=4):
string = "0x"
for i in range(len(data)):
@@ -1482,70 +1707,55 @@
string = string + "{:02x}".format(data[i])
return string
+ # Push general purpose register to stack, this is needed before trap handling
def push_gpr_to_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
- store_instr = ''
- if rcs.XLEN == 32:
- store_instr = "sw"
- else:
- store_instr = "sd"
+ store_instr = "sw" if rcs.XLEN == 32 else "sd"
if scratch in rcs.implemented_csr:
# Use kernal stack for handling exceptions. Save the user mode stack
# pointer to the scratch register
- instr.append(pkg_ins.format_string(
- "csrrw x{}, {}, x{}".format(sp, hex(scratch.value), sp)))
- # Move TP to SP
- instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(sp, tp)))
+ instr.extend(("csrrw x{}, {}, x{}".format(sp, hex(scratch), sp),
+ # Move TP to SP
+ "add x{}, x{}, zero".format(sp, tp)))
# If MPRV is set and MPP is S/U mode, it means the address translation and
# memory protection for load/store instruction is the same as the mode indicated
# by MPP. In this case, we need to use the virtual address to access the kernel stack.
- if(status.name == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE):
+ if(status == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE):
# We temporarily use tp to check mstatus to avoid changing other GPR. The value
# of sp has been saved to xScratch and can be restored later.
if mprv:
- instr.append(pkg_ins.format_string(
- "csrr x{}, 0x{} // MSTATUS".format(tp, status.value)))
- instr.append(pkg_ins.format_string(
- "srli x{}, x{}, 11".format(tp, tp))) # Move MPP to bit 0
- instr.append(pkg_ins.format_string(
- "andi x{}, x{}, 0x3".format(tp, tp))) # keep the MPP bits
- # Check if MPP equals to M-mode('b11)
- instr.append(pkg_ins.format_string("xori x{}, x{}, 0x3".format(tp, tp)))
- # Use physical address for kernel SP
- instr.append(pkg_ins.format_string("bnez x{}, 1f".format(tp)))
- # Use virtual address for stack pointer
- instr.append(pkg_ins.format_string(
- "slli x{}, x{}, {}".format(sp, sp,
- rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS)))
- instr.append(pkg_ins.format_string(
- "srli x{}, x{}, {}".format(sp, sp,
- rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS)))
+ instr.extend(("csrr x{}, {} // MSTATUS".format(tp, hex(status)),
+ "srli x{}, x{}, 11".format(tp, tp), # Move MPP to bit 0
+ "andi x{}, x{}, 0x3".format(tp, tp), # keep the MPP bits
+ # Check if MPP equals to M-mode('b11)
+ "xori x{}, x{}, 0x3".format(tp, tp),
+ # Use physical address for kernel SP
+ "bnez x{}, 1f".format(tp),
+ # Use virtual address for stack pointer
+ "slli x{}, x{}, {}".format(sp, sp,
+ rcs.XLEN - self.MAX_USED_VADDR_BITS),
+ "srli x{}, x{}, {}".format(sp, sp,
+ rcs.XLEN - self.MAX_USED_VADDR_BITS)))
# Reserve space from kernel stack to save all 32 GPR except for x0
- instr.append(pkg_ins.format_string(
- "1: addi x{}, x{}, -{}".format(sp, sp, int(31 * (rcs.XLEN / 8)))))
+ instr.append("1: addi x{}, x{}, -{}".format(sp, sp, 31 * (rcs.XLEN // 8)))
# Push all GPRs to kernel stack
for i in range(1, 32):
- instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format(
- store_instr, i, int(i * (rcs.XLEN / 8)), sp)))
+ instr.append("{} x{}, {}(x{})".format(
+ store_instr, i, i * (rcs.XLEN // 8), sp))
+ # Pop general purpose register from stack, this is needed before returning to user program
def pop_gpr_from_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
- load_instr = ''
- if rcs.XLEN == 32:
- load_instr = "lw"
- else:
- load_instr = "ld"
+ load_instr = "lw" if rcs.XLEN == 32 else "ld"
# Pop user mode GPRs from kernel stack
for i in range(1, 32):
- instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format(
- load_instr, i, int(i * (rcs.XLEN / 8)), sp)))
+ instr.append("{} x{}, {}(x{})".format(
+ load_instr, i, i * (rcs.XLEN // 8), sp))
# Restore kernel stack pointer
- instr.append(pkg_ins.format_string(
- "addi x{}, x{}, {}".format(sp, sp, int(31 * (rcs.XLEN / 8)))))
+ instr.append("addi x{}, x{}, {}".format(sp, sp, 31 * (rcs.XLEN // 8)))
if scratch in rcs.implemented_csr:
# Move SP to TP
- instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(tp, sp)))
- # Restore user mode stack pointer
- instr.append(pkg_ins.format_string(
- "csrrw x{}, 0x{}, x{}".format(sp, scratch.value, sp)))
+ instr.extend(("add x{}, x{}, zero".format(tp, sp),
+ # Restore user mode stack pointer
+ "csrrw x{}, {}, x{}".format(sp, hex(scratch), sp)))
pkg_ins = riscv_instr_pkg()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
index 5c1a1f0..6227302 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,53 +8,83 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import re
-import logging
-import random
import sys
+import random
+import logging
import vsc
from importlib import import_module
from collections import defaultdict
+from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
from pygen_src.riscv_illegal_instr import riscv_illegal_instr, illegal_instr_type_e
-from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.riscv_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr
from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_name_t, riscv_reg_t,
riscv_instr_category_t)
-from pygen_src.riscv_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+# -----------------------------------------------------------------------------------------
+# RISC-V instruction sequence
+
+# This class is used to generate a single instruction sequence for a RISC-V assembly program.
+# It's used by riscv_asm_program_gen to generate the main program and all sub-programs. The
+# flow is explained below:
+# For main program:
+# - Generate instruction sequence body.
+# - Post-process the load/store/branch instructions.
+# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen).
+# For sub program:
+# - Generate the stack push instructions which are executed when entering this program.
+# - Generate instruction sequence body.
+# - Generate the stack pop instructions which are executed before exiting this program.
+# - Post-process the load/store/branch instructions.
+# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen).
+# - Generate a return instruction at the end of the program.
+# -----------------------------------------------------------------------------------------
+
class riscv_instr_sequence:
def __init__(self):
- self.instr_cnt = 0
+ self.instr_cnt = 0 # Instruction count of this sequence
self.instr_stream = riscv_rand_instr_stream()
- self.is_main_program = 0
- self.is_debug_program = 0
- self.label_name = ""
+ self.is_main_program = 0 # Main instruction streams
+ self.is_debug_program = 0 # Indicates whether sequence is debug program
+ self.label_name = "" # Label of the sequence (program name)
self.instr_string_list = [] # Save the instruction list
self.program_stack_len = vsc.int32_t(0) # Stack space allocated for this program
self.directed_instr = [] # List of all directed instruction stream
self.illegal_instr_pct = 0 # Percentage of illegal instructions
self.hint_instr_pct = 0 # Percentage of hint instructions
- self.branch_idx = [None] * 30
self.instr_stack_enter = riscv_push_stack_instr()
self.instr_stack_exit = riscv_pop_stack_instr()
self.illegal_instr = riscv_illegal_instr()
- def gen_instr(self, is_main_program, no_branch = 1):
+ # Main function to generate the instruction stream
+ # The main random instruction stream is generated by instr_stream.gen_instr(), which generates
+ # each instruction one by one with a separate randomization call. It's not done by a single
+ # randomization call for the entire instruction stream because this solution won't scale if
+ # we have hundreds of thousands of instructions to generate. The constraint solver slows down
+ # considerably as the instruction stream becomes longer. The downside is we cannot specify
+ # constraints between instructions. The way to solve it is to have a dedicated directed
+ # instruction stream for such scenarios, like hazard sequence.
+ def gen_instr(self, is_main_program, no_branch = 0):
self.is_main_program = is_main_program
self.instr_stream.initialize_instr_list(self.instr_cnt)
- logging.info("Start generating %d instruction" % len(self.instr_stream.instr_list))
+ logging.info("Start generating {} instruction".format(len(self.instr_stream.instr_list)))
+ # Do not generate load/store instruction here
+ # The load/store instruction will be inserted as directed instruction stream
self.instr_stream.gen_instr(no_branch = no_branch, no_load_store = 1,
is_debug_program = self.is_debug_program)
-
if not is_main_program:
self.gen_stack_enter_instr()
self.gen_stack_exit_instr()
+ logging.info("Finishing instruction generation")
+ # Generate the stack push operations for this program
+ # It pushes the necessary context to the stack like RA, T0,loop registers etc. The stack
+ # pointer(SP) is reduced by the amount the stack space allocated to this program.
def gen_stack_enter_instr(self):
allow_branch = 0 if (self.illegal_instr_pct > 0 or self.hint_instr_pct > 0) else 1
allow_branch &= not cfg.no_branch_jump
@@ -63,6 +92,7 @@
with vsc.randomize_with(self.program_stack_len):
self.program_stack_len in vsc.rangelist(vsc.rng(cfg.min_stack_len_per_program,
cfg.max_stack_len_per_program))
+ # Keep stack len word aligned to avoid unaligned load/store
self.program_stack_len % (rcs.XLEN // 8) == 0
except Exception:
logging.critical("Cannot randomize program_stack_len")
@@ -79,50 +109,44 @@
self.instr_stack_exit.gen_pop_stack_instr(self.program_stack_len,
self.instr_stack_enter.saved_regs)
- '''
- ----------------------------------------------------------------------------------------------
- Instruction post-process
+ # ----------------------------------------------------------------------------------------------
+ # Instruction post-process
- Post-process is required for branch instructions:
+ # Post-process is required for branch instructions:
- Need to assign a valid branch target. This is done by picking a random instruction label in
- this sequence and assigning to the branch instruction. All the non-atomic instructions
- will have a unique numeric label as the local branch target identifier.
- The atomic instruction streams don't have labels except for the first instruction. This is
- to avoid branching into an atomic instruction stream which breaks its atomicy. The
- definition of an atomic instruction stream here is a sequence of instructions which must be
- executed in-order.
- In this sequence, only forward branch is handled. The backward branch target is implemented
- in a dedicated loop instruction sequence. Randomly choosing a backward branch target could
- lead to dead loops in the absence of proper loop exiting conditions.
- ----------------------------------------------------------------------------------------------
- '''
-
+ # Need to assign a valid branch target. This is done by picking a random instruction label in
+ # this sequence and assigning to the branch instruction. All the non-atomic instructions
+ # will have a unique numeric label as the local branch target identifier.
+ # The atomic instruction streams don't have labels except for the first instruction. This is
+ # to avoid branching into an atomic instruction stream which breaks its atomicy. The
+ # definition of an atomic instruction stream here is a sequence of instructions which must be
+ # executed in-order.
+ # In this sequence, only forward branch is handled. The backward branch target is implemented
+ # in a dedicated loop instruction sequence. Randomly choosing a backward branch target could
+ # lead to dead loops in the absence of proper loop exiting conditions.
+ # ----------------------------------------------------------------------------------------------
def post_process_instr(self):
label_idx = 0
branch_cnt = 0
+ branch_idx = [None] * 30
j = 0
branch_target = defaultdict(lambda: None)
-
+ # Insert directed instructions, it's randomly mixed with the random instruction stream.
for instr in self.directed_instr:
self.instr_stream.insert_instr_stream(instr.instr_list)
- '''
- Assign an index for all instructions, these indexes wont change
- even a new instruction is injected in the post process.
- '''
+ # Assign an index for all instructions, these indexes wont change
+ # even a new instruction is injected in the post process.
for i in range(len(self.instr_stream.instr_list)):
self.instr_stream.instr_list[i].idx = label_idx
if(self.instr_stream.instr_list[i].has_label and
not(self.instr_stream.instr_list[i].atomic)):
if((self.illegal_instr_pct > 0) and
(self.instr_stream.instr_list[i].insert_illegal_instr == 0)):
- '''
- The illegal instruction generator always increase PC by 4 when resume execution,
- need to make sure PC + 4 is at the correct instruction boundary.
- '''
- if(self.instr_stream.instr_list[i].is_compressed):
+ # The illegal instruction generator always increase PC by 4 when resume
+ # execution, need to make sure PC + 4 is at the correct instruction boundary.
+ if self.instr_stream.instr_list[i].is_compressed:
if(i < (len(self.instr_stream.instr_list) - 1)):
- if(self.instr_stream.instr_list[i + 1].is_compressed):
+ if self.instr_stream.instr_list[i + 1].is_compressed:
self.instr_stream.instr_list[i].is_illegal_instr = random.randrange(
0, min(100, self.illegal_instr_pct))
else:
@@ -130,54 +154,54 @@
0, min(100, self.illegal_instr_pct))
if(self.hint_instr_pct > 0 and
(self.instr_stream.instr_list[i].is_illegal_instr == 0)):
- if(self.instr_stream.instr_list[i].is_compressed):
+ if self.instr_stream.instr_list[i].is_compressed:
self.instr_stream.instr_list[i].is_hint_instr = random.randrange(
0, min(100, self.hint_instr_pct))
self.instr_stream.instr_list[i].label = "{}".format(label_idx)
self.instr_stream.instr_list[i].is_local_numeric_label = 1
label_idx += 1
-
# Generate branch target
- for i in range(len(self.branch_idx)):
- self.branch_idx[i] = random.randint(1, cfg.max_branch_step)
+ for i in range(len(branch_idx)):
+ branch_idx[i] = random.randint(1, cfg.max_branch_step)
- while(j < len(self.instr_stream.instr_list)):
+ while j < len(self.instr_stream.instr_list):
if((self.instr_stream.instr_list[j].category == riscv_instr_category_t.BRANCH) and
(not self.instr_stream.instr_list[j].branch_assigned) and
(not self.instr_stream.instr_list[j].is_illegal_instr)):
- '''
- Post process the branch instructions to give a valid local label
- Here we only allow forward branch to avoid unexpected infinite loop
- The loop structure will be inserted with a separate routine using
- reserved loop registers
- '''
+ # Post process the branch instructions to give a valid local label
+ # Here we only allow forward branch to avoid unexpected infinite loop
+ # The loop structure will be inserted with a separate routine using
+ # reserved loop registers
branch_target_label = 0
- # branch_byte_offset = 0
branch_target_label = self.instr_stream.instr_list[j].idx + \
- self.branch_idx[branch_cnt]
+ branch_idx[branch_cnt]
if(branch_target_label >= label_idx):
branch_target_label = label_idx - 1
branch_cnt += 1
- if(branch_cnt == len(self.branch_idx)):
+ if(branch_cnt == len(branch_idx)):
branch_cnt = 0
- random.shuffle(self.branch_idx)
+ random.shuffle(branch_idx)
logging.info("Processing branch instruction[%0d]:%0s # %0d -> %0d", j,
self.instr_stream.instr_list[j].convert2asm(),
self.instr_stream.instr_list[j].idx, branch_target_label)
self.instr_stream.instr_list[j].imm_str = "{}f".format(branch_target_label)
self.instr_stream.instr_list[j].branch_assigned = 1
branch_target[branch_target_label] = 1
-
# Remove the local label which is not used as branch target
if(self.instr_stream.instr_list[j].has_label and
self.instr_stream.instr_list[j].is_local_numeric_label):
idx = int(self.instr_stream.instr_list[j].label)
- if(not branch_target[idx]):
+ if not branch_target[idx]:
self.instr_stream.instr_list[j].has_label = 0
j += 1
logging.info("Finished post-processing instructions")
+ # Inject a jump instruction stream
+ # This function is called by riscv_asm_program_gen with the target program label
+ # The jump routine is implmented with an atomic instruction stream(riscv_jump_instr). Similar
+ # to load/store instructions, JALR/JAL instructions also need a proper base address and offset
+ # as the jump target.
def insert_jump_instr(self):
# TODO riscv_jump_instr class implementation
"""
@@ -194,6 +218,9 @@
"""
pass
+ # Convert the instruction stream to the string format.
+ # Label is attached to the instruction if available, otherwise attach proper space to make
+ # the code indent consistent.
def generate_instr_stream(self, no_label = 0):
prefix = ''
string = ''
@@ -208,15 +235,15 @@
self.label_name), length = pkg_ins.LABEL_STR_LEN)
self.instr_stream.instr_list[i].has_label = 1
else:
- if(self.instr_stream.instr_list[i].has_label):
+ if self.instr_stream.instr_list[i].has_label:
prefix = pkg_ins.format_string(string = '{}:'.format(
self.instr_stream.instr_list[i].label), length = pkg_ins.LABEL_STR_LEN)
else:
prefix = pkg_ins.format_string(string = " ", length = pkg_ins.LABEL_STR_LEN)
string = prefix + self.instr_stream.instr_list[i].convert2asm()
self.instr_string_list.append(string)
- if(rcs.support_pmp and not re.search("main", self.label_name)):
- self.instr_string_list.insert(0, ".align 2")
+ if(rcs.support_pmp and not re.search("main", self.label_name)):
+ self.instr_string_list.insert(0, ".align 2")
self.insert_illegal_hint_instr()
prefix = pkg_ins.format_string(str(i), pkg_ins.LABEL_STR_LEN)
if not self.is_main_program:
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
index 5b957d1..ac2fbdb 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,6 +9,7 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
+
import random
import logging
import sys
@@ -20,15 +20,12 @@
from pygen_src.riscv_instr_gen_config import cfg
+# Base class for RISC-V instruction stream
+# A instruction stream here is a queue of RISC-V basic instructions.
+# This class also provides some functions to manipulate the instruction stream, like insert a new
+# instruction, mix two instruction streams etc.
@vsc.randobj
class riscv_instr_stream:
- '''
- Base class for RISC-V instruction stream
- A instruction stream here is a queue of RISC-V basic instructions.
- This class also provides some functions to manipulate the instruction stream, like insert a new
- instruction, mix two instruction streams etc.
- '''
-
def __init__(self):
self.instr_list = []
self.instr_cnt = 0
@@ -40,6 +37,7 @@
self.reserved_rd = vsc.list_t(vsc.enum_t(riscv_reg_t))
self.hart = 0
+ # Initialize the instruction stream, create each instruction instance
def initialize_instr_list(self, instr_cnt):
self.instr_list.clear()
self.instr_cnt = instr_cnt
@@ -50,12 +48,11 @@
instr = riscv_instr()
self.instr_list.append(instr)
+ # Insert an instruction to the existing instruction stream at the given index
+ # When index is -1, the instruction is injected at a random location
def insert_instr(self, instr, idx = -1):
- """
- Insert an instruction to the existing instruction stream at the given index
- When index is -1, the instruction is injected at a random location
- """
current_instr_cnt = len(self.instr_list)
+ # TODO
if idx == -1:
idx = random.randint(0, current_instr_cnt - 1)
while self.instr_list[idx].atomic:
@@ -64,16 +61,14 @@
self.instr_list.append(instr)
return
elif idx > current_instr_cnt or idx < 0:
- logging.error("Cannot insert instr:%0s at idx %0d", instr.convert2asm(), idx)
+ logging.error("Cannot insert instr:{} at idx {}".format(instr.convert2asm(), idx))
sys.exit(1)
self.instr_list.insert(idx, instr)
+ # Insert an instruction to the existing instruction stream at the given index
+ # When index is -1, the instruction is injected at a random location
+ # When replace is 1, the original instruction at the inserted position will be replaced
def insert_instr_stream(self, new_instr, idx = -1, replace = 0):
- """
- Insert an instruction to the existing instruction stream at the given index
- When index is -1, the instruction is injected at a random location
- When replace is 1, the original instruction at the inserted position will be replaced
- """
current_instr_cnt = len(self.instr_list)
if current_instr_cnt == 0:
@@ -97,7 +92,7 @@
logging.critical("Cannot inject the instruction")
sys.exit(1)
elif idx > current_instr_cnt or idx < 0:
- logging.error("Cannot insert instr stream at idx %0d", idx)
+ logging.error("Cannot insert instr stream at idx {}".format(idx))
sys.exit(1)
# When replace is 1, the original instruction at this index will be removed.
# The label of the original instruction will be copied to the head
@@ -117,17 +112,15 @@
self.instr_list = self.instr_list[0:idx] + new_instr + \
self.instr_list[idx:current_instr_cnt]
+ # Mix the input instruction stream with the original instruction, the instruction order is
+ # preserved. When 'contained' is set, the original instruction stream will be inside the
+ # new instruction stream with the first and last instruction from the input instruction stream.
+ # new_instr is a list of riscv_instr
def mix_instr_stream(self, new_instr, contained = 0):
- """
- Mix the input instruction stream with the original instruction, the instruction order is
- preserved. When 'contained' is set, the original instruction stream will be inside the
- new instruction stream with the first and last instruction from the input instruction
- stream.
- new_instr is a list of riscv_instr
- """
current_instr_cnt = len(self.instr_list)
new_instr_cnt = len(new_instr)
insert_instr_position = [0] * new_instr_cnt
+ # TODO
if len(insert_instr_position) > 0:
insert_instr_position.sort()
for i in range(new_instr_cnt):
@@ -148,16 +141,13 @@
return s
+# Generate a random instruction stream based on the configuration
+# There are two ways to use this class to generate instruction stream
+# 1. For short instruction stream, you can call randomize() directly.
+# 2. For long instruction stream (>1K), randomize() all instructions together might take a
+# long time for the constraint solver. In this case, you can call gen_instr to generate
+# instructions one by one. The time only grows linearly with the instruction count
class riscv_rand_instr_stream(riscv_instr_stream):
- """
- Generate a random instruction stream based on the configuration
- There are two ways to use this class to generate instruction stream
- 1. For short instruction stream, you can call randomize() directly.
- 2. For long instruction stream (>1K), randomize() all instructions together might take a
- long time for the constraint solver. In this case, you can call gen_instr to generate
- instructions one by one. The time only grows linearly with the instruction count
- """
-
def __init__(self):
# calling super constructor
super().__init__()
@@ -196,7 +186,7 @@
riscv_reg_t.A5)))
with vsc.foreach(self.avail_regs, idx = True) as i:
self.avail_regs[i].not_inside(vsc.rangelist(cfg.reserved_regs,
- self.reserved_rd))
+ self.reserved_rd))
except Exception:
logging.critical("Cannot randomize avail_regs")
sys.exit(1)'''
@@ -209,12 +199,14 @@
if no_load_store:
self.category_dist[riscv_instr_category_t.LOAD.name] = 0
self.category_dist[riscv_instr_category_t.STORE.name] = 0
- logging.info("setup_instruction_dist: %0d", len(self.category_dist))
+ logging.info("setup_instruction_dist: {}".format(len(self.category_dist)))
def gen_instr(self, no_branch = 0, no_load_store = 1, is_debug_program = 0):
self.setup_allowed_instr(no_branch, no_load_store)
for i in range(len(self.instr_list)):
self.instr_list[i] = self.randomize_instr(self.instr_list[i], is_debug_program)
+ # Do not allow branch instruction as the last instruction because there's no
+ # forward branch target
while self.instr_list[-1].category == riscv_instr_category_t.BRANCH:
self.instr_list.pop()
if len(self.instr_list) == 0:
@@ -268,3 +260,11 @@
instr.rs1 != cfg.reserved_regs[i]
# TODO: Add constraint for CSR, floating point register
return instr
+
+ def get_init_gpr_instr(self, gpr, val):
+ # TODO
+ pass
+
+ def add_init_vector_gpr_instr(self, gpr, val):
+ # TODO
+ pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py
index 7df1cb7..bf0160e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py
@@ -32,6 +32,7 @@
SPARSE = auto()
+# Base class for all load/store instruction stream
@vsc.randobj
class riscv_load_store_base_instr_stream(riscv_mem_access_stream):
def __init__(self):
@@ -213,6 +214,7 @@
self.load_store_instr.append(instr)
+# A single load/store instruction
@vsc.randobj
class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
@@ -224,6 +226,7 @@
self.num_mixed_instr < 5
+# Back to back load/store instructions
@vsc.randobj
class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
@@ -237,6 +240,19 @@
self.num_mixed_instr == 0
+# Back to back load/store instructions
+@vsc.randobj
+class riscv_load_store_shared_mem_stream(riscv_load_store_stress_instr_stream):
+ def __init__(self):
+ super().__init__()
+
+ def pre_randomize(self):
+ self.load_store_shared_memory = 1
+ super().pre_randomize()
+
+
+# Random load/store sequence
+# A random mix of load/store instructions and other instructions
@vsc.randobj
class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
@@ -248,6 +264,7 @@
self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(10, 30)))
+# Use a small set of GPR to create various WAW, RAW, WAR hazard scenario
@vsc.randobj
class riscv_load_store_hazard_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
index 4631a2a..49e7c0c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -30,7 +29,7 @@
super().init_reg(reg_name)
# ---------------Machine mode register ----------------
# Machine status Register
- if(reg_name == privileged_reg_t.MSTATUS):
+ if reg_name == privileged_reg_t.MSTATUS:
self.privil_level = privileged_level_t.M_LEVEL
self.add_field("UIE", 1, reg_field_access_t.WARL)
self.add_field("SIE", 1, reg_field_access_t.WARL)
@@ -51,7 +50,7 @@
self.add_field("TVM", 1, reg_field_access_t.WARL)
self.add_field("TW", 1, reg_field_access_t.WARL)
self.add_field("TSR", 1, reg_field_access_t.WARL)
- if(rcs.XLEN == 32):
+ if rcs.XLEN == 32:
self.add_field("WPRI3", 8, reg_field_access_t.WPRI)
else:
self.add_field("WPRI3", 9, reg_field_access_t.WPRI)
@@ -60,7 +59,7 @@
self.add_field("WPRI4", rcs.XLEN - 37, reg_field_access_t.WPRI)
self.add_field("SD", 1, reg_field_access_t.WARL)
# Machine interrupt-enable register
- elif(reg_name == privileged_reg_t.MIE):
+ elif reg_name == privileged_reg_t.MIE:
self.privil_level = privileged_level_t.M_LEVEL
self.add_field("USIE", 1, reg_field_access_t.WARL)
self.add_field("SSIE", 1, reg_field_access_t.WARL)
@@ -75,5 +74,6 @@
self.add_field("WPEI2", 1, reg_field_access_t.WPRI)
self.add_field("MEIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI3", rcs.XLEN - 12, reg_field_access_t.WPRI)
+ # TODO add condition for rest of the modes
else:
logging.error("reg %0s is not supported yet", reg_name.name)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
index ce612a1..1fdf1bf 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import logging
@@ -22,6 +20,7 @@
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+# This class provides some common routines for privileged mode operations
@vsc.randobj
class riscv_privileged_common_seq():
def __init___(self):
@@ -79,8 +78,8 @@
def gen_csr_instr(self, regs, instrs):
for i in range(len(regs)):
- instrs.append("li x{}, {}".format(cfg.gpr[0].value, hex(regs[i].get_val())))
- instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name.value),
+ instrs.append("li x{}, {}".format(cfg.gpr[0], hex(regs[i].get_val())))
+ instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name),
cfg.gpr[0], regs[i].reg_name.name))
def setup_satp(self, instrs):
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
index c573634..a47b205 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -9,7 +8,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
"""
import vsc
@@ -36,11 +34,12 @@
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I)
'''
+ # Convert the instruction to assembly code
def convert2asm(self, prefix = ""):
asm_str = pkg_ins.format_string(self.get_instr_name(), pkg_ins.MAX_INSTR_STR_LEN)
+ # instr rd,imm
asm_str = "{}{}, {}".format(asm_str, self.rd.name, self.get_imm())
-
- if(self.comment != ""):
+ if self.comment != "":
asm_str = "{} #{}".format(asm_str, self.comment)
return asm_str.lower()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
index 395b2d0..9550119 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -21,7 +20,10 @@
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
+# -----------------------------------------------
# Light weight RISC-V register class library
+# -----------------------------------------------
+
# Base class for RISC-V register field
@vsc.randobj
class riscv_reg_field:
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py
index 1f67bcb..65a395e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py
@@ -12,9 +12,8 @@
from enum import IntEnum, auto
+
# Will be the lowest 8 bits of the data word
-
-
class signature_type_t(IntEnum):
'''
Information sent to the core relating its current status.
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
index 127b085..543f1a9 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py
@@ -26,6 +26,10 @@
riscv_single_load_store_instr_stream)
+# ----------------------------------------------------------
+# pyflow commmon utility helpers functions
+# ----------------------------------------------------------
+
def factory(obj_of):
objs = {
"riscv_directed_instr_stream": riscv_directed_instr_stream,
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py
index d984036..d5d9349 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,74 +9,109 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
- exception_cause_t, satp_mode_t,
- riscv_instr_group_t, privileged_mode_t,
- mtvec_mode_t)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+ riscv_instr_group_t, mtvec_mode_t,
+ privileged_mode_t)
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
-
-
+# XLEN
XLEN = 32
-implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID,
- privileged_reg_t.MIMPID, privileged_reg_t.MHARTID,
- privileged_reg_t.MSTATUS, privileged_reg_t.MISA, privileged_reg_t.MIE,
- privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
- privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
- privileged_reg_t.MTVAL, privileged_reg_t.MIP]
-
+# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32A]
-supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-
+# Interrupt mode support
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
max_interrupt_vector_num = 16
-support_debug_mode = 0
-
-NUM_HARTS = 2
-
+# Physical memory protection support
support_pmp = 0
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
+# Support delegate trap to user mode
support_umode_trap = 0
+# Support sfence.vma instruction
support_sfence = 0
+# Support unaligned load/store
support_unaligned_load_store = 1
+# GPR Setting
NUM_FLOAT_GPR = 32
-
NUM_GPR = 32
-
NUM_VEC_GPR = 32
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
+# Maximum size of a single vector element
ELEN = 32
+# Minimum size of a sub-element, which must be at most 8-bits.
SELEN = 8
-#VELEN =
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
-MAX_MUL = 8
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
- interrupt_cause_t.M_TIMER_INTR,
- interrupt_cause_t.M_EXTERNAL_INTR]
-implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT,
- exception_cause_t.ILLEGAL_INSTRUCTION,
- exception_cause_t.BREAKPOINT,
- exception_cause_t.LOAD_ADDRESS_MISALIGNED,
- exception_cause_t.LOAD_ACCESS_FAULT,
- exception_cause_t.ECALL_MMODE]
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 2
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
+ privileged_reg_t.MARCHID, # Architecture ID
+ privileged_reg_t.MIMPID, # Implementation ID
+ privileged_reg_t.MHARTID, # Hardware thread ID
+ privileged_reg_t.MSTATUS, # Machine status
+ privileged_reg_t.MISA, # ISA and extensions
+ privileged_reg_t.MIE, # Machine interrupt-enable register
+ privileged_reg_t.MTVEC, # Machine trap-handler base address
+ privileged_reg_t.MCOUNTEREN, # Machine counter enable
+ privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
+ privileged_reg_t.MEPC, # Machine exception program counter
+ privileged_reg_t.MCAUSE, # Machine trap cause
+ privileged_reg_t.MTVAL, # Machine bad address or instruction
+ privileged_reg_t.MIP # Machine interrupt pending
+ ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
index fbcc451..ef9ee53 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,37 +9,108 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
+
+import math
from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
- riscv_instr_group_t, privileged_mode_t)
+ riscv_instr_group_t, mtvec_mode_t,
+ privileged_mode_t)
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
XLEN = 32
-implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, privileged_reg_t.MIMPID,
- privileged_reg_t.MHARTID, privileged_reg_t.MSTATUS,
- privileged_reg_t.MISA, privileged_reg_t.MIE,
- privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
- privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
- privileged_reg_t.MTVAL, privileged_reg_t.MIP]
-
+# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
-supported_isa = [riscv_instr_group_t.RV32I]
-
+# Supported Privileged mode
supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-NUM_HARTS = 1
-support_pmp = 0
-
-support_debug_mode = 0
-
+# Unsupported instructions
unsupported_instr = []
+# ISA supported by the processor
+supported_isa = [riscv_instr_group_t.RV32I]
+
+# Interrupt mode support
+supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
+max_interrupt_vector_num = 16
+
+# Physical memory protection support
+support_pmp = 0
+
+# Debug mode support
+support_debug_mode = 0
+
+# Support delegate trap to user mode
support_umode_trap = 0
+# Support sfence.vma instruction
+support_sfence = 0
+
+# Support unaligned load/store
+support_unaligned_load_store = 1
+
# GPR Setting
NUM_FLOAT_GPR = 32
NUM_GPR = 32
NUM_VEC_GPR = 32
-max_interrupt_vector_num = 16
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
+VECTOR_EXTENSION_ENABLE = 0
+
+VLEN = 512
+
+# Maximum size of a single vector element
+ELEN = 32
+
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
+
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
+
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
+
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
+ privileged_reg_t.MARCHID, # Architecture ID
+ privileged_reg_t.MIMPID, # Implementation ID
+ privileged_reg_t.MHARTID, # Hardware thread ID
+ privileged_reg_t.MSTATUS, # Machine status
+ privileged_reg_t.MISA, # ISA and extensions
+ privileged_reg_t.MIE, # Machine interrupt-enable register
+ privileged_reg_t.MTVEC, # Machine trap-handler base address
+ privileged_reg_t.MCOUNTEREN, # Machine counter enable
+ privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
+ privileged_reg_t.MEPC, # Machine exception program counter
+ privileged_reg_t.MCAUSE, # Machine trap cause
+ privileged_reg_t.MTVAL, # Machine bad address or instruction
+ privileged_reg_t.MIP # Machine interrupt pending
+ ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
index ae18332..5de8125 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,71 +9,111 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
- exception_cause_t, satp_mode_t,
- riscv_instr_group_t, privileged_mode_t,
- mtvec_mode_t)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+ riscv_instr_group_t, mtvec_mode_t,
+ privileged_mode_t)
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
XLEN = 32
-implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID,
- privileged_reg_t.MIMPID, privileged_reg_t.MHARTID,
- privileged_reg_t.MSTATUS, privileged_reg_t.MISA, privileged_reg_t.MIE,
- privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
- privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
- privileged_reg_t.MTVAL, privileged_reg_t.MIP]
-
+# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32F,
riscv_instr_group_t.RV32FC, riscv_instr_group_t.RV32D,
riscv_instr_group_t.RV32DC, riscv_instr_group_t.RV32A]
-supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-
+# Interrupt mode support
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
max_interrupt_vector_num = 16
-support_debug_mode = 0
-
-NUM_HARTS = 1
-
+# Physical memory protection support
support_pmp = 0
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
+# Support delegate trap to user mode
support_umode_trap = 0
+# Support sfence.vma instruction
support_sfence = 0
+# Support unaligned load/store
support_unaligned_load_store = 1
+# GPR Setting
NUM_FLOAT_GPR = 32
-
NUM_GPR = 32
-
NUM_VEC_GPR = 32
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
+# Maximum size of a single vector element
ELEN = 32
-SELEN = 0
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
-MAX_MUL = 8
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
- interrupt_cause_t.M_TIMER_INTR,
- interrupt_cause_t.M_EXTERNAL_INTR]
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
-implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT,
- exception_cause_t.ILLEGAL_INSTRUCTION,
- exception_cause_t.BREAKPOINT,
- exception_cause_t.LOAD_ADDRESS_MISALIGNED,
- exception_cause_t.LOAD_ACCESS_FAULT,
- exception_cause_t.ECALL_MMODE]
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
+ privileged_reg_t.MARCHID, # Architecture ID
+ privileged_reg_t.MIMPID, # Implementation ID
+ privileged_reg_t.MHARTID, # Hardware thread ID
+ privileged_reg_t.MSTATUS, # Machine status
+ privileged_reg_t.MISA, # ISA and extensions
+ privileged_reg_t.MIE, # Machine interrupt-enable register
+ privileged_reg_t.MTVEC, # Machine trap-handler base address
+ privileged_reg_t.MCOUNTEREN, # Machine counter enable
+ privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
+ privileged_reg_t.MEPC, # Machine exception program counter
+ privileged_reg_t.MCAUSE, # Machine trap cause
+ privileged_reg_t.MTVAL, # Machine bad address or instruction
+ privileged_reg_t.MIP # Machine interrupt pending
+ ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
index 7f46476..d91f2ed 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,44 +9,52 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
- exception_cause_t, satp_mode_t,
- riscv_instr_group_t, privileged_mode_t,
- mtvec_mode_t)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+ riscv_instr_group_t, mtvec_mode_t,
+ privileged_mode_t)
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
XLEN = 32
-implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, privileged_reg_t.MIMPID,
- privileged_reg_t.MHARTID, privileged_reg_t.MSTATUS,
- privileged_reg_t.MISA, privileged_reg_t.MIE,
- privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
- privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
- privileged_reg_t.MTVAL, privileged_reg_t.MIP]
-
+# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
-supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
- riscv_instr_group_t.RV32C]
-
+# Supported Privileged mode
supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
-
-max_interrupt_vector_num = 16
-
-support_debug_mode = 0
-
-NUM_HARTS = 1
-
-support_pmp = 0
-
+# Unsupported instructions
unsupported_instr = []
+# ISA supported by the processor
+supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, riscv_instr_group_t.RV32C]
+
+# Interrupt mode support
+supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
+max_interrupt_vector_num = 16
+
+# Physical memory protection support
+support_pmp = 0
+
+# Debug mode support
+support_debug_mode = 0
+
+# Support delegate trap to user mode
support_umode_trap = 0
+# Support sfence.vma instruction
support_sfence = 0
+# Support unaligned load/store
support_unaligned_load_store = 1
# GPR Setting
@@ -55,22 +62,55 @@
NUM_GPR = 32
NUM_VEC_GPR = 32
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
+# Maximum size of a single vector element
ELEN = 32
-SELEN = 0
+# Minimum size of a sub-element, which must be at most 8-bits.
+SELEN = 8
-MAX_MUL = 8
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
- interrupt_cause_t.M_TIMER_INTR,
- interrupt_cause_t.M_EXTERNAL_INTR]
+# Maxium LMUL supported by the core
+MAX_LMUL = 8
-implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT,
- exception_cause_t.ILLEGAL_INSTRUCTION,
- exception_cause_t.BREAKPOINT, exception_cause_t.LOAD_ADDRESS_MISALIGNED,
- exception_cause_t.LOAD_ACCESS_FAULT,
- exception_cause_t.ECALL_MMODE]
+
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
+ privileged_reg_t.MARCHID, # Architecture ID
+ privileged_reg_t.MIMPID, # Implementation ID
+ privileged_reg_t.MHARTID, # Hardware thread ID
+ privileged_reg_t.MSTATUS, # Machine status
+ privileged_reg_t.MISA, # ISA and extensions
+ privileged_reg_t.MIE, # Machine interrupt-enable register
+ privileged_reg_t.MTVEC, # Machine trap-handler base address
+ privileged_reg_t.MCOUNTEREN, # Machine counter enable
+ privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
+ privileged_reg_t.MEPC, # Machine exception program counter
+ privileged_reg_t.MCAUSE, # Machine trap cause
+ privileged_reg_t.MTVAL, # Machine bad address or instruction
+ privileged_reg_t.MIP # Machine interrupt pending
+ ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
index 8a11e93..0299170 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
@@ -1,7 +1,6 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -10,45 +9,53 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
- exception_cause_t, satp_mode_t,
- riscv_instr_group_t, privileged_mode_t,
- mtvec_mode_t)
+
+import math
+from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
+ riscv_instr_group_t, mtvec_mode_t,
+ privileged_mode_t)
+# -----------------------------------------------------------------------------
+# Processor feature configuration
+# -----------------------------------------------------------------------------
+
+# XLEN
XLEN = 32
-implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID,
- privileged_reg_t.MIMPID, privileged_reg_t.MHARTID,
- privileged_reg_t.MSTATUS, privileged_reg_t.MISA,
- privileged_reg_t.MIE, privileged_reg_t.MTVEC,
- privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH,
- privileged_reg_t.MEPC, privileged_reg_t.MCAUSE,
- privileged_reg_t.MTVAL, privileged_reg_t.MIP]
-
+# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
+# Supported Privileged mode
+supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
+
+# Unsupported instructions
+unsupported_instr = []
+
+# ISA supported by the processor
supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32B]
-supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
-
+# Interrupt mode support
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
+# The number of interrupt vectors to be generated, only used if VECTORED
+# interrupt mode is supported
max_interrupt_vector_num = 16
-support_debug_mode = 0
-
-NUM_HARTS = 1
-
+# Physical memory protection support
support_pmp = 0
-unsupported_instr = []
+# Debug mode support
+support_debug_mode = 0
+# Support delegate trap to user mode
support_umode_trap = 0
+# Support sfence.vma instruction
support_sfence = 0
+# Support unaligned load/store
support_unaligned_load_store = 1
# GPR Setting
@@ -56,23 +63,55 @@
NUM_GPR = 32
NUM_VEC_GPR = 32
+# -----------------------------------------------------------------------------
+# Vector extension configuration
+# -----------------------------------------------------------------------------
+
+# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
+# Maximum size of a single vector element
ELEN = 32
+# Minimum size of a sub-element, which must be at most 8-bits.
SELEN = 8
+# Maximum size of a single vector element (encoded in vsew format)
+VELEN = int(math.log(ELEN) // math.log(2)) - 3
+
+# Maxium LMUL supported by the core
MAX_LMUL = 8
-implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR,
- interrupt_cause_t.M_TIMER_INTR,
- interrupt_cause_t.M_EXTERNAL_INTR]
-implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT,
- exception_cause_t.ILLEGAL_INSTRUCTION,
- exception_cause_t.BREAKPOINT,
- exception_cause_t.LOAD_ADDRESS_MISALIGNED,
- exception_cause_t.LOAD_ACCESS_FAULT,
- exception_cause_t.ECALL_MMODE]
+# -----------------------------------------------------------------------------
+# Multi-harts configuration
+# -----------------------------------------------------------------------------
+
+# Number of harts
+NUM_HARTS = 1
+
+# -----------------------------------------------------------------------------
+# Previleged CSR implementation
+# -----------------------------------------------------------------------------
+
+# Implemented previlieged CSR list
+implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
+ privileged_reg_t.MARCHID, # Architecture ID
+ privileged_reg_t.MIMPID, # Implementation ID
+ privileged_reg_t.MHARTID, # Hardware thread ID
+ privileged_reg_t.MSTATUS, # Machine status
+ privileged_reg_t.MISA, # ISA and extensions
+ privileged_reg_t.MIE, # Machine interrupt-enable register
+ privileged_reg_t.MTVEC, # Machine trap-handler base address
+ privileged_reg_t.MCOUNTEREN, # Machine counter enable
+ privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
+ privileged_reg_t.MEPC, # Machine exception program counter
+ privileged_reg_t.MCAUSE, # Machine trap cause
+ privileged_reg_t.MTVAL, # Machine bad address or instruction
+ privileged_reg_t.MIP # Machine interrupt pending
+ ]
+
+# Implementation-specific custom CSRs
+custom_csr = []
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
index 75e29d5..66287da 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
@@ -24,6 +24,7 @@
from pygen_src.riscv_utils import gen_config_table
+# Base test
class riscv_instr_base_test:
def __init__(self):
self.start_idx = cfg.argv.start_idx
@@ -41,17 +42,23 @@
if cfg.asm_test_suffix != "":
self.asm_file_name = "{}.{}".format(self.asm_file_name,
cfg.asm_test_suffix)
+ self.asm.get_directed_instr_stream()
test_name = "{}_{}.S".format(self.asm_file_name,
num + self.start_idx)
- self.asm.get_directed_instr_stream()
+ self.apply_directed_instr()
+ logging.info("All directed instruction is applied")
self.asm.gen_program()
self.asm.gen_test_file(test_name)
+ logging.info("TEST GENERATION DONE")
def randomize_cfg(self):
cfg.randomize()
logging.info("riscv_instr_gen_config is randomized")
gen_config_table()
+ def apply_directed_instr(self):
+ pass
+
start_time = time.time()
riscv_base_test_ins = riscv_instr_base_test()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
index 6d406f9..a1cabab 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
@@ -106,6 +106,11 @@
def get_coverage_report(self):
model = vsc.get_coverage_report_model()
cov_dir = cfg.argv.log_file_name.split("/")[0]
+ file = open('{}/CoverageGroups.txt'.format(cov_dir), 'w')
+ file.write("CoverGroups, CoverPoints and Bins Summary\n")
+ str_report = vsc.get_coverage_report(details=True)
+ file.write("{}\n".format(str_report))
+ file.close()
file = open('{}/CoverageReport.txt'.format(cov_dir), 'w')
file.write("Groups Coverage Summary\n")
file.write("Total groups in report: {}\n".format(
@@ -125,18 +130,6 @@
pass
def sample(self):
- binary = vsc.int_t(rcs.XLEN)
- binary.set_val(get_val(self.trace["binary"], hexa=1))
- # TODO: Currently handled using string formatting as part select
- # isn't yet supported for global vsc variables
- # width is rcs.XLEN+2 because of 0b in the beginning of binary_bin
- binary_bin = format(binary.get_val(), '#0{}b'.format(rcs.XLEN + 2))
- if binary_bin[-2:] != "11": # TODO: and RV32C in supported_isa
- # TODO: sample compressed instruction
- pass
- if binary_bin[-2:] == "11":
- # TODO: sampling
- pass
processed_instr_name = self.process_instr_name(self.trace["instr"])
if processed_instr_name in riscv_instr_name_t.__members__:
instr_name = riscv_instr_name_t[processed_instr_name]
@@ -145,9 +138,10 @@
# cov_instr is created, time to manually assign attributes
# TODO: This will get fixed later when we get an inst from template
instruction.assign_attributes()
- if instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I",
+ if (instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I",
"RV64M", "RV64C", "RV32F", "RV64F",
- "RV32D", "RV64D", "RV32B", "RV64B"]:
+ "RV32D", "RV64D", "RV32B", "RV64B"]) \
+ and (instruction.group in rcs.supported_isa):
self.assign_trace_info_to_instr(instruction)
instruction.pre_sample()
self.instr_cg.sample(instruction)
@@ -178,7 +172,7 @@
def process_instr_name(self, instruction):
instruction = instruction.upper()
- instruction.replace(".", "_")
+ instruction = instruction.replace(".", "_")
instruction = self.update_instr_name(instruction)
return instruction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
index 352c520..2c61df2 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
@@ -31,13 +31,14 @@
gen_config_table()
def apply_directed_instr(self):
+ # Mix below directed instruction streams with the random instructions
self.asm.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 4)
- self.asm.add_directed_instr_stream("riscv_loop_instr", 3)
+ # self.asm.add_directed_instr_stream("riscv_loop_instr", 3)
self.asm.add_directed_instr_stream("riscv_jal_instr", 4)
- self.asm.add_directed_instr_stream("riscv_hazard_instr_stream", 4)
+ # self.asm.add_directed_instr_stream("riscv_hazard_instr_stream", 4)
self.asm.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 4)
- self.asm.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4)
- self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4)
+ # self.asm.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4)
+ # self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4)
start_time = time.time()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
index 0458b01..c476504 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/run.py
@@ -380,11 +380,21 @@
# Run the instruction generator
if not argv.co:
seed_gen = SeedGen(argv.start_seed, argv.seed, argv.seed_yaml)
+ if argv.simulator == 'pyflow':
+ """Default timeout of Pyflow is 20 minutes, if the user
+ doesn't specified their own gen_timeout value from CMD
+ """
+ if argv.gen_timeout == 360:
+ gen_timeout = 1200
+ else:
+ gen_timeout = argv.gen_timeout
+ else:
+ gen_timeout = argv.gen_timeout
do_simulate(sim_cmd, argv.simulator, test_list, cwd, argv.sim_opts,
seed_gen,
argv.csr_yaml, argv.isa, argv.end_signature_addr,
argv.lsf_cmd,
- argv.gen_timeout, argv.log_suffix, argv.batch_size,
+ gen_timeout, argv.log_suffix, argv.batch_size,
output_dir,
argv.verbose, check_return_code, argv.debug, argv.target)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
index 045ef20..e3ca844 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/scripts/lib.py
@@ -157,7 +157,7 @@
stderr=subprocess.STDOUT)
children.append(ps)
for i in range(len(children)):
- logging.info("Command progress: {}/{}".format(i, len(children)))
+ logging.info("Command progress: {}/{}".format(i + 1, len(children)))
logging.debug("Waiting for command: {}".format(cmd_list[i]))
try:
output = children[i].communicate(timeout=timeout_s)[0]
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
old mode 100755
new mode 100644
index 22c7b7f..335c5e4
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
@@ -31,7 +31,7 @@
has_rs3 = 1'b0;
case (format) inside
R_FORMAT: begin
- if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP,
+ if (instr_name inside {BMATFLIP,
CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D,
CRC32C_D}) begin
has_rs2 = 1'b0;
@@ -61,21 +61,12 @@
if (format inside {I_FORMAT}) begin
if (category inside {SHIFT, LOGICAL}) begin
- if (group == RV64B && !(instr_name inside {SLLIU_W})) begin
- imm_len = $clog2(XLEN) - 1;
- end else begin
- imm_len = $clog2(XLEN);
- end
+ imm_len = $clog2(XLEN);
end
-
// ARITHMETIC RV32B
if (instr_name inside {SHFLI, UNSHFLI}) begin
imm_len = $clog2(XLEN) - 1;
end
- // ARITHMETIC RV64B
- if (instr_name inside {ADDIWU}) begin
- imm_len = 12;
- end
end
imm_mask = imm_mask << imm_len;
@@ -117,63 +108,38 @@
function bit [6:0] get_opcode();
case (instr_name) inside
- ANDN, ORN, XNOR, GORC, SLO, SRO, ROL, ROR, SBCLR, SBSET, SBINV, SBEXT,
- GREV: get_opcode = 7'b0110011;
- SLOI, SROI, RORI, SBCLRI, SBSETI, SBINVI, SBEXTI, GORCI, GREVI, CMIX, CMOV,
- FSL: get_opcode = 7'b0010011;
- FSR, FSRI, CLZ, CTZ, PCNT, BMATFLIP, SEXT_B, SEXT_H, CRC32_B, CRC32_H, CRC32_W, CRC32C_B,
- CRC32C_H: get_opcode = 7'b0010011;
+ GORC, SLO, SRO, GREV, XPERM_N, XPERM_B, XPERM_H, XPERM_W: get_opcode = 7'b0110011;
+ GORCI, SLOI, SROI, GREVI, CMIX, CMOV, FSL: get_opcode = 7'b0010011;
+ FSR, FSRI, BMATFLIP, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H: get_opcode = 7'b0010011;
CRC32C_W, CRC32_D, CRC32C_D: get_opcode = 7'b0010011;
- CLMUL, CLMULR, CLMULH, MIN, MAX, MINU, MAXU, SHFL, UNSHFL, BDEP, BEXT, PACK, PACKU, BMATOR,
- BMATXOR, PACKH, BFP: get_opcode = 7'b0110011;
+ SHFL, UNSHFL, BCOMPRESS, BDECOMPRESS, PACK, PACKU, BMATOR, BMATXOR, PACKH, BFP: get_opcode
+ = 7'b0110011;
SHFLI, UNSHFLI: get_opcode = 7'b0010011;
- ADDIWU, SLLIU_W: get_opcode = 7'b0011011;
- ADDWU, SUBWU, ADDU_W, SUBU_W, SLOW, SROW, ROLW, RORW, SBCLRW, SBSETW, SBINVW, SBEXTW, GORCW,
- GREVW: get_opcode = 7'b0111011;
- SLOIW, SROIW, RORIW, SBCLRIW, SBSETIW, SBINVIW, GORCIW, GREVIW: get_opcode = 7'b0011011;
+ SLOW, SROW, GORCW, GREVW: get_opcode = 7'b0111011;
+ SLOIW, SROIW, GORCIW, GREVIW: get_opcode = 7'b0011011;
FSLW, FSRW: get_opcode = 7'b0111011;
- FSRIW, CLZW, CTZW, PCNTW: get_opcode = 7'b0011011;
- CLMULW, CLMULRW, CLMULHW, SHFLW, UNSHFLW, BDEPW, BEXTW, PACKW, PACKUW,
- BFPW: get_opcode = 7'b0111011;
+ FSRIW: get_opcode = 7'b0011011;
+ SHFLW, UNSHFLW, BCOMPRESSW, BDECOMPRESSW, PACKW, PACKUW, BFPW: get_opcode = 7'b0111011;
default: get_opcode = super.get_opcode();
endcase
endfunction
virtual function bit [2:0] get_func3();
case (instr_name) inside
- ANDN: get_func3 = 3'b111;
- ORN: get_func3 = 3'b110;
- XNOR: get_func3 = 3'b100;
GORC: get_func3 = 3'b101;
+ GORCI: get_func3 = 3'b101;
SLO: get_func3 = 3'b001;
SRO: get_func3 = 3'b101;
- ROL: get_func3 = 3'b001;
- ROR: get_func3 = 3'b101;
- SBCLR: get_func3 = 3'b001;
- SBSET: get_func3 = 3'b001;
- SBINV: get_func3 = 3'b001;
- SBEXT: get_func3 = 3'b101;
- GREV: get_func3 = 3'b101;
SLOI: get_func3 = 3'b001;
SROI: get_func3 = 3'b101;
- RORI: get_func3 = 3'b101;
- SBCLRI: get_func3 = 3'b001;
- SBSETI: get_func3 = 3'b001;
- SBINVI: get_func3 = 3'b001;
- SBEXTI: get_func3 = 3'b101;
- GORCI: get_func3 = 3'b101;
+ GREV: get_func3 = 3'b101;
GREVI: get_func3 = 3'b101;
CMIX: get_func3 = 3'b001;
CMOV: get_func3 = 3'b101;
FSL: get_func3 = 3'b001;
FSR: get_func3 = 3'b101;
FSRI: get_func3 = 3'b101;
- CLZ: get_func3 = 3'b001;
- CTZ: get_func3 = 3'b001;
- PCNT: get_func3 = 3'b001;
BMATFLIP: get_func3 = 3'b001;
- SEXT_B: get_func3 = 3'b001;
- SEXT_H: get_func3 = 3'b001;
CRC32_B: get_func3 = 3'b001;
CRC32_H: get_func3 = 3'b001;
CRC32_W: get_func3 = 3'b001;
@@ -182,17 +148,10 @@
CRC32C_W: get_func3 = 3'b001;
CRC32_D: get_func3 = 3'b001;
CRC32C_D: get_func3 = 3'b001;
- CLMUL: get_func3 = 3'b001;
- CLMULR: get_func3 = 3'b010;
- CLMULH: get_func3 = 3'b011;
- MIN: get_func3 = 3'b100;
- MAX: get_func3 = 3'b101;
- MINU: get_func3 = 3'b110;
- MAXU: get_func3 = 3'b111;
SHFL: get_func3 = 3'b001;
UNSHFL: get_func3 = 3'b101;
- BDEP: get_func3 = 3'b110;
- BEXT: get_func3 = 3'b110;
+ BCOMPRESS: get_func3 = 3'b110;
+ BDECOMPRESS: get_func3 = 3'b110;
PACK: get_func3 = 3'b100;
PACKU: get_func3 = 3'b100;
BMATOR: get_func3 = 3'b011;
@@ -201,46 +160,30 @@
BFP: get_func3 = 3'b111;
SHFLI: get_func3 = 3'b001;
UNSHFLI: get_func3 = 3'b101;
- ADDIWU: get_func3 = 3'b100;
- SLLIU_W: get_func3 = 3'b001;
- ADDWU: get_func3 = 3'b000;
- SUBWU: get_func3 = 3'b000;
- ADDU_W: get_func3 = 3'b000;
- SUBU_W: get_func3 = 3'b000;
SLOW: get_func3 = 3'b001;
SROW: get_func3 = 3'b101;
ROLW: get_func3 = 3'b001;
- RORW: get_func3 = 3'b101;
- SBCLRW: get_func3 = 3'b001;
- SBSETW: get_func3 = 3'b001;
- SBINVW: get_func3 = 3'b001;
- SBEXTW: get_func3 = 3'b101;
GORCW: get_func3 = 3'b101;
GREVW: get_func3 = 3'b101;
SLOIW: get_func3 = 3'b001;
SROIW: get_func3 = 3'b101;
RORIW: get_func3 = 3'b101;
- SBCLRIW: get_func3 = 3'b001;
- SBSETIW: get_func3 = 3'b001;
- SBINVIW: get_func3 = 3'b001;
GORCIW: get_func3 = 3'b101;
GREVIW: get_func3 = 3'b101;
FSLW: get_func3 = 3'b001;
FSRW: get_func3 = 3'b101;
FSRIW: get_func3 = 3'b101;
- CLZW: get_func3 = 3'b001;
- CTZW: get_func3 = 3'b001;
- PCNTW: get_func3 = 3'b001;
- CLMULW: get_func3 = 3'b001;
- CLMULRW: get_func3 = 3'b010;
- CLMULHW: get_func3 = 3'b011;
SHFLW: get_func3 = 3'b001;
UNSHFLW: get_func3 = 3'b101;
- BDEPW: get_func3 = 3'b110;
- BEXTW: get_func3 = 3'b110;
+ BCOMPRESSW: get_func3 = 3'b110;
+ BDECOMPRESSW: get_func3 = 3'b110;
PACKW: get_func3 = 3'b100;
PACKUW: get_func3 = 3'b100;
BFPW: get_func3 = 3'b111;
+ XPERM_N: get_func3 = 3'b010;
+ XPERM_B: get_func3 = 3'b100;
+ XPERM_H: get_func3 = 3'b110;
+ XPERM_W: get_func3 = 3'b000;
default: get_func3 = super.get_func3();
endcase
;
@@ -256,17 +199,8 @@
SRO: get_func7 = 7'b0010000;
ROL: get_func7 = 7'b0110000;
ROR: get_func7 = 7'b0110000;
- SBCLR: get_func7 = 7'b0100100;
- SBSET: get_func7 = 7'b0010100;
- SBINV: get_func7 = 7'b0110100;
- SBEXT: get_func7 = 7'b0100100;
GREV: get_func7 = 7'b0110100;
- CLZ: get_func7 = 7'b0110000;
- CTZ: get_func7 = 7'b0110000;
- PCNT: get_func7 = 7'b0110000;
BMATFLIP: get_func7 = 7'b0110000;
- SEXT_B: get_func7 = 7'b0110000;
- SEXT_H: get_func7 = 7'b0110000;
CRC32_B: get_func7 = 7'b0110000;
CRC32_H: get_func7 = 7'b0110000;
CRC32_W: get_func7 = 7'b0110000;
@@ -275,58 +209,35 @@
CRC32C_W: get_func7 = 7'b0110000;
CRC32_D: get_func7 = 7'b0110000;
CRC32C_D: get_func7 = 7'b0110000;
- CLMUL: get_func7 = 7'b0000101;
- CLMULR: get_func7 = 7'b0000101;
- CLMULH: get_func7 = 7'b0000101;
- MIN: get_func7 = 7'b0000101;
- MAX: get_func7 = 7'b0000101;
- MINU: get_func7 = 7'b0000101;
- MAXU: get_func7 = 7'b0000101;
SHFL: get_func7 = 7'b0000100;
UNSHFL: get_func7 = 7'b0000100;
- BDEP: get_func7 = 7'b0100100;
- BEXT: get_func7 = 7'b0000100;
+ BCOMPRESS: get_func7 = 7'b0000100;
+ BDECOMPRESS: get_func7 = 7'b0100100;
PACK: get_func7 = 7'b0000100;
PACKU: get_func7 = 7'b0100100;
BMATOR: get_func7 = 7'b0000100;
BMATXOR: get_func7 = 7'b0100100;
PACKH: get_func7 = 7'b0000100;
BFP: get_func7 = 7'b0100100;
- ADDWU: get_func7 = 7'b0000101;
- SUBWU: get_func7 = 7'b0100101;
- ADDU_W: get_func7 = 7'b0000100;
- SUBU_W: get_func7 = 7'b0100100;
SLOW: get_func7 = 7'b0010000;
SROW: get_func7 = 7'b0010000;
- ROLW: get_func7 = 7'b0110000;
- RORW: get_func7 = 7'b0110000;
- SBCLRW: get_func7 = 7'b0100100;
- SBSETW: get_func7 = 7'b0010100;
- SBINVW: get_func7 = 7'b0110100;
- SBEXTW: get_func7 = 7'b0100100;
GORCW: get_func7 = 7'b0010100;
+ GORCIW: get_func7 = 7'b0010100;
GREVW: get_func7 = 7'b0110100;
+ GREVIW: get_func7 = 7'b0110100;
SLOIW: get_func7 = 7'b0010000;
SROIW: get_func7 = 7'b0010000;
- RORIW: get_func7 = 7'b0110000;
- SBCLRIW: get_func7 = 7'b0100100;
- SBSETIW: get_func7 = 7'b0010100;
- SBINVIW: get_func7 = 7'b0110100;
- GORCIW: get_func7 = 7'b0010100;
- GREVIW: get_func7 = 7'b0110100;
- CLZW: get_func7 = 7'b0110000;
- CTZW: get_func7 = 7'b0110000;
- PCNTW: get_func7 = 7'b0110000;
- CLMULW: get_func7 = 7'b0000101;
- CLMULRW: get_func7 = 7'b0000101;
- CLMULHW: get_func7 = 7'b0000101;
SHFLW: get_func7 = 7'b0000100;
UNSHFLW: get_func7 = 7'b0000100;
- BDEPW: get_func7 = 7'b0100100;
- BEXTW: get_func7 = 7'b0000100;
+ BCOMPRESSW: get_func7 = 7'b0000100;
+ BDECOMPRESSW: get_func7 = 7'b0100100;
PACKW: get_func7 = 7'b0000100;
PACKUW: get_func7 = 7'b0100100;
BFPW: get_func7 = 7'b0100100;
+ XPERM_N: get_func7 = 7'b0010100;
+ XPERM_B: get_func7 = 7'b0010100;
+ XPERM_H: get_func7 = 7'b0010100;
+ XPERM_W: get_func7 = 7'b0010100;
default: get_func7 = super.get_func7();
endcase
@@ -337,17 +248,9 @@
SLOI: get_func5 = 5'b00100;
SROI: get_func5 = 5'b00100;
RORI: get_func5 = 5'b01100;
- SBCLRI: get_func5 = 5'b01001;
- SBSETI: get_func5 = 5'b01001;
- SBINVI: get_func5 = 5'b01101;
- SBEXTI: get_func5 = 5'b01001;
GORCI: get_func5 = 5'b00101;
GREVI: get_func5 = 5'b01101;
- CLZW: get_func5 = 5'b00000;
- CTZW: get_func5 = 5'b00001;
- PCNTW: get_func5 = 5'b00010;
-
CRC32_B: get_func5 = 5'b10000;
CRC32_H: get_func5 = 5'b10001;
CRC32_W: get_func5 = 5'b10010;
@@ -357,12 +260,7 @@
CRC32_D: get_func5 = 5'b10011;
CRC32C_D: get_func5 = 5'b11011;
- CLZ: get_func5 = 5'b00000;
- CTZ: get_func5 = 5'b00001;
- PCNT: get_func5 = 5'b00010;
BMATFLIP: get_func5 = 5'b00011;
- SEXT_B: get_func5 = 5'b00100;
- SEXT_H: get_func5 = 5'b00101;
default: `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
endcase
endfunction
@@ -385,23 +283,15 @@
string binary = "";
case (format)
R_FORMAT: begin
- if ((category inside {LOGICAL}) && (group == RV32B)) begin
- if (instr_name inside {SEXT_B, SEXT_H}) begin
- binary =
- $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
- end
- end
-
if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
- if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CLZ, CTZ,
- PCNT}) begin
+ if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W}) begin
binary =
$sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
end
end
if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
- if (instr_name inside {CLZW, CTZW, PCNTW, CRC32_D, CRC32C_D, BMATFLIP}) begin
+ if (instr_name inside {CRC32_D, CRC32C_D, BMATFLIP}) begin
binary =
$sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
end
@@ -413,8 +303,6 @@
binary = $sformatf("%8h", {get_func5(), imm[6:0], rs1, get_func3(), rd, get_opcode()});
end else if ((category inside {SHIFT, LOGICAL}) && (group == RV64B)) begin
binary = $sformatf("%8h", {get_func7(), imm[4:0], rs1, get_func3(), rd, get_opcode()});
- if (instr_name == SLLIU_W)
- binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()});
end
if (instr_name inside {FSRI}) begin
@@ -450,37 +338,19 @@
virtual function bit is_supported(riscv_instr_gen_config cfg);
return cfg.enable_b_extension && (
- (ZBB inside {cfg.enable_bitmanip_groups} && instr_name inside {
- CLZ, CTZ, CLZW, CTZW, PCNT, PCNTW,
- SLO, SLOI, SLOW, SLOIW,
- SRO, SROI, SROW, SROIW,
- MIN, MINU, MAX, MAXU,
- ADDWU, ADDIWU, SUBWU,
- ADDU_W, SUBU_W,
- SLLIU_W,
- ANDN, ORN,
- XNOR, PACK, PACKW, PACKU, PACKUW, PACKH,
- ROL, ROLW, ROR, RORW, RORI, RORIW
- }) ||
- (ZBS inside {cfg.enable_bitmanip_groups} && instr_name inside {
- SBSET, SBSETW, SBSETI, SBSETIW,
- SBCLR, SBCLRW, SBCLRI, SBCLRIW,
- SBINV, SBINVW, SBINVI, SBINVIW,
- SBEXT, SBEXTW, SBEXTI
- }) ||
(ZBP inside {cfg.enable_bitmanip_groups} && instr_name inside {
GREV, GREVW, GREVI, GREVIW,
GORC, GORCW, GORCI, GORCIW,
- SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI
+ SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI,
+ XPERM_N, XPERM_B, XPERM_H, XPERM_W,
+ SLO, SLOW, SLOI, SLOIW,
+ SRO, SROW, SROI, SROIW
}) ||
(ZBE inside {cfg.enable_bitmanip_groups} && instr_name inside {
- BEXT, BEXTW,
- BDEP, BDEPW
+ BCOMPRESS, BCOMPRESSW,
+ BDECOMPRESS, BDECOMPRESSW
}) ||
(ZBF inside {cfg.enable_bitmanip_groups} && instr_name inside {BFP, BFPW}) ||
- (ZBC inside {cfg.enable_bitmanip_groups} && instr_name inside {
- CLMUL, CLMULW, CLMULH, CLMULHW, CLMULR, CLMULRW
- }) ||
(ZBR inside {cfg.enable_bitmanip_groups} && instr_name inside {
CRC32_B, CRC32_H, CRC32_W, CRC32_D,
CRC32C_B, CRC32C_H, CRC32C_W, CRC32C_D
@@ -490,10 +360,7 @@
}) ||
(ZBT inside {cfg.enable_bitmanip_groups} && instr_name inside {
CMOV, CMIX,
- FSL, FSLW, FSR, FSRW, FSRI, FSRIW}) ||
- // TODO, spec 0.92 doesn't categorize these 2 instr, put them in ZB_TMP #572
- (ZB_TMP inside {cfg.enable_bitmanip_groups} && instr_name inside {
- SEXT_B, SEXT_H})
+ FSL, FSLW, FSR, FSRW, FSRI, FSRIW})
);
endfunction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
index 385af7b..04fdcb7 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv
@@ -318,11 +318,11 @@
C_ADD:
binary = $sformatf("%4h", {get_func3(), 1'b1, rd, rs2, get_c_opcode()});
C_FSDSP, C_SDSP:
- binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:3], imm[8:6], rs2, get_c_opcode()});
+ binary = $sformatf("%4h", {get_func3(), imm[5:3], imm[8:6], rs2, get_c_opcode()});
C_SQSP:
- binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:4], imm[9:6], rs2, get_c_opcode()});
+ binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[9:6], rs2, get_c_opcode()});
C_SWSP, C_FSWSP:
- binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:2], imm[7:6], rs2, get_c_opcode()});
+ binary = $sformatf("%4h", {get_func3(), imm[5:2], imm[7:6], rs2, get_c_opcode()});
default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
endcase
return {prefix, binary};
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
index 6639090..088f389 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv
@@ -248,7 +248,7 @@
if (group inside {RV32F, RV64F}) begin
fs1_sign = get_fp_operand_sign(fs1_value, 31);
fs2_sign = get_fp_operand_sign(fs2_value, 31);
- fs3_sign = get_fp_operand_sign(fs2_value, 31);
+ fs3_sign = get_fp_operand_sign(fs3_value, 31);
fd_sign = get_fp_operand_sign(fd_value, 31);
end else if (instr_name == FCVT_S_D) begin
fs1_sign = get_fp_operand_sign(fs1_value, 63);
@@ -259,7 +259,7 @@
end else begin
fs1_sign = get_fp_operand_sign(fs1_value, 63);
fs2_sign = get_fp_operand_sign(fs2_value, 63);
- fs3_sign = get_fp_operand_sign(fs2_value, 63);
+ fs3_sign = get_fp_operand_sign(fs3_value, 63);
fd_sign = get_fp_operand_sign(fd_value, 63);
end
endfunction : pre_sample
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
index c444adc..2b2f322 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
@@ -344,7 +344,7 @@
if(imm_type == UIMM) begin
imm_len = 5;
end else begin
- imm_len = 11;
+ imm_len = 12;
end
end
imm_mask = imm_mask << imm_len;
@@ -580,7 +580,7 @@
if(instr_name inside {FENCE, FENCE_I})
binary = $sformatf("%8h", {17'b0, get_func3(), 5'b0, get_opcode()});
else if(category == CSR)
- binary = $sformatf("%8h", {csr[10:0], imm[4:0], get_func3(), rd, get_opcode()});
+ binary = $sformatf("%8h", {csr[11:0], imm[4:0], get_func3(), rd, get_opcode()});
else if(instr_name == ECALL)
binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()});
else if(instr_name inside {URET, SRET, MRET})
@@ -604,7 +604,7 @@
end
R_FORMAT: begin
if(category == CSR)
- binary = $sformatf("%8h", {csr[10:0], rs1, get_func3(), rd, get_opcode()});
+ binary = $sformatf("%8h", {csr[11:0], rs1, get_func3(), rd, get_opcode()});
else if(instr_name == SFENCE_VMA)
binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()});
else
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
new file mode 100644
index 0000000..0600ac4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zba_instr extends riscv_instr;
+ `uvm_object_utils(riscv_zba_instr)
+
+ function new(string name = "");
+ super.new(name);
+ endfunction : new
+
+ function void pre_randomize();
+ super.pre_randomize();
+ endfunction
+
+ virtual function void set_imm_len();
+ if (!(instr_name inside {SLLI_UW})) begin
+ imm_len = $clog2(XLEN) - 1;
+ end else begin
+ imm_len = $clog2(XLEN);
+ end
+ imm_mask = imm_mask << imm_len;
+ endfunction : set_imm_len
+
+ function bit[6:0] get_opcode();
+ case (instr_name) inside
+ SH1ADD, SH2ADD, SH3ADD : get_opcode = 7'b0110011;
+ SH1ADD_UW, SH2ADD_UW, SH3ADD_UW : get_opcode = 7'b0111011;
+ SLLI_UW : get_opcode = 7'b0011011;
+ default : get_opcode = super.get_opcode();
+ endcase
+ endfunction : get_opcode
+
+ virtual function bit [2:0] get_func3();
+ case (instr_name) inside
+ ADD_UW : get_func3 = 3'b000;
+ SH1ADD : get_func3 = 3'b010;
+ SH2ADD : get_func3 = 3'b100;
+ SH3ADD : get_func3 = 3'b110;
+ SH1ADD_UW : get_func3 = 3'b010;
+ SH2ADD_UW : get_func3 = 3'b100;
+ SH3ADD_UW : get_func3 = 3'b110;
+ SLLI_UW : get_func3 = 3'b001;
+ default : get_func3 = super.get_func3();
+ endcase
+ endfunction : get_func3
+
+ function bit [6:0] get_func7();
+ case (instr_name) inside
+ ADD_UW : get_func7 = 7'b0000100;
+ SH1ADD : get_func7 = 7'b0010000;
+ SH2ADD : get_func7 = 7'b0010000;
+ SH3ADD : get_func7 = 7'b0010000;
+ SH1ADD_UW : get_func7 = 7'b0010000;
+ SH2ADD_UW : get_func7 = 7'b0010000;
+ SH3ADD_UW : get_func7 = 7'b0010000;
+ SLLI_UW : get_func7 = 7'b0010000;
+ default : get_func7 = super.get_func7();
+ endcase
+ endfunction : get_func7
+
+ virtual function string convert2bin(string prefix = "");
+ string binary = "";
+ if (instr_name inside {SLLI_UW}) begin
+ binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()});
+ end
+ else begin
+ binary = super.convert2bin(prefix);
+ end
+ endfunction : convert2bin
+
+ virtual function bit is_supported(riscv_instr_gen_config cfg);
+ return (cfg.enable_zba_extension &&
+ (RV32ZBA inside { supported_isa } || RV64ZBA inside { supported_isa }) &&
+ instr_name inside {
+ ADD_UW,
+ SH1ADD, SH1ADD_UW,
+ SH2ADD, SH2ADD_UW,
+ SH3ADD, SH3ADD_UW,
+ SLLI_UW
+ });
+ endfunction : is_supported
+
+endclass : riscv_zba_instr
+
+
+
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
new file mode 100644
index 0000000..475671a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbb_instr extends riscv_instr;
+ `uvm_object_utils(riscv_zbb_instr)
+
+ function new(string name = "");
+ super.new(name);
+ endfunction : new
+
+ virtual function void set_rand_mode();
+ super.set_rand_mode();
+ case (format) inside
+ R_FORMAT: begin
+ if (instr_name inside { ZEXT_H }) begin
+ has_rs2 = 1'b0;
+ end
+ end
+
+ I_FORMAT: begin
+ if (instr_name inside { CLZ, CLZW, CTZ, CTZW, CPOP, CPOPW, ORC_B, SEXT_B, SEXT_H, REV8 })
+ begin
+ has_imm = 1'b0;
+ end
+ end
+
+ endcase
+ endfunction : set_rand_mode
+
+ function void pre_randomize();
+ super.pre_randomize();
+ endfunction
+
+ function bit is_rv64();
+ is_rv64 = (group == RV64B);
+ endfunction : is_rv64
+
+ virtual function void set_imm_len();
+ if (format inside {I_FORMAT}) begin
+ if (instr_name inside {RORI}) begin
+ imm_len = $clog2(XLEN);
+ end else begin
+ imm_len = 5;
+ end
+ end
+ imm_mask = imm_mask << imm_len;
+ endfunction : set_imm_len
+
+ virtual function string convert2asm(string prefix = "");
+ string asm_str_final;
+ string asm_str;
+
+ asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN);
+
+ case (format)
+ I_FORMAT : begin // instr rd rs1
+ if (!has_imm) begin
+ asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
+ end
+ end
+
+ R_FORMAT : begin // instr rd rs1
+ if (!has_rs2) begin
+ asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
+ end
+ end
+
+ default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
+ endcase
+
+ if (asm_str_final == "") begin
+ return super.convert2asm(prefix);
+ end
+
+ if (comment != "") begin
+ asm_str_final = { asm_str_final, " #", comment };
+ end
+
+ return asm_str_final.tolower();
+
+ endfunction : convert2asm
+
+ function bit[6:0] get_opcode();
+ case (instr_name) inside
+ ANDN, MAX, MAXU, MIN, MINU,
+ ORN, ROL, ROR, XNOR : get_opcode = 7'b011_0011;
+ ZEXT_H : get_opcode = 7'b011_0011 | (is_rv64() << 3);
+ ROLW, RORW : get_opcode = 7'b011_1011;
+ CLZ, CPOP, CTZ, ORC_B,
+ CLZW, CPOPW, CTZW, RORIW : get_opcode = 7'b001_1011;
+ REV8, RORI, SEXT_B, SEXT_H : get_opcode = 7'b001_0011;
+ default : get_opcode = super.get_opcode();
+ endcase
+ endfunction : get_opcode
+
+ virtual function bit [2:0] get_func3();
+ case (instr_name) inside
+ ANDN : get_func3 = 3'b111;
+ CLZ : get_func3 = 3'b001;
+ CLZW : get_func3 = 3'b001;
+ CPOP : get_func3 = 3'b001;
+ CPOPW : get_func3 = 3'b001;
+ CTZ : get_func3 = 3'b001;
+ CTZW : get_func3 = 3'b001;
+ MAX : get_func3 = 3'b110;
+ MAXU : get_func3 = 3'b111;
+ MIN : get_func3 = 3'b100;
+ MINU : get_func3 = 3'b101;
+ ORC_B : get_func3 = 3'b101;
+ ORN : get_func3 = 3'b110;
+ REV8 : get_func3 = 3'b101;
+ ROL : get_func3 = 3'b001;
+ ROLW : get_func3 = 3'b001;
+ ROR : get_func3 = 3'b101;
+ RORW : get_func3 = 3'b101;
+ RORI : get_func3 = 3'b101;
+ RORIW : get_func3 = 3'b101;
+ SEXT_B : get_func3 = 3'b001;
+ SEXT_H : get_func3 = 3'b001;
+ XNOR : get_func3 = 3'b100;
+ ZEXT_H : get_func3 = 3'b100;
+ default : get_func3 = super.get_func3();
+ endcase
+ endfunction : get_func3
+
+ virtual function bit [4:0] get_func5();
+ case (instr_name) inside
+ CLZ : get_func5 = 5'b0_0000;
+ CLZW : get_func5 = 5'b0_0000;
+ CPOP : get_func5 = 5'b0_0010;
+ CPOPW : get_func5 = 5'b0_0010;
+ CTZ : get_func5 = 5'b0_0001;
+ CTZW : get_func5 = 5'b0_0001;
+ ORC_B : get_func5 = 5'b0_0111;
+ REV8 : get_func5 = 5'b1_1000;
+ SEXT_B : get_func5 = 5'b0_0100;
+ SEXT_H : get_func5 = 5'b0_0101;
+ endcase
+ endfunction : get_func5
+
+ virtual function bit [6:0] get_func7();
+ case (instr_name) inside
+ ANDN : get_func7 = 7'b010_0000;
+ CLZ : get_func7 = 7'b011_0000;
+ CLZW : get_func7 = 7'b011_0000;
+ CPOP : get_func7 = 7'b011_0000;
+ CPOPW : get_func7 = 7'b011_0000;
+ CTZ : get_func7 = 7'b011_0000;
+ CTZW : get_func7 = 7'b011_0000;
+ MAX : get_func7 = 7'b000_0101;
+ MAXU : get_func7 = 7'b000_0101;
+ MIN : get_func7 = 7'b000_0101;
+ MINU : get_func7 = 7'b000_0101;
+ ORC_B : get_func7 = 7'b001_0100;
+ ORN : get_func7 = 7'b010_0000;
+ REV8 : get_func7 = 7'b011_0100 | is_rv64(); // 0110101 64 bit
+ ROL : get_func7 = 7'b011_0000;
+ ROLW : get_func7 = 7'b011_0000;
+ ROR : get_func7 = 7'b011_0000;
+ RORW : get_func7 = 7'b011_0000;
+ RORI : get_func7 = 7'b011_0000;
+ RORIW : get_func7 = 7'b011_0000;
+ SEXT_B : get_func7 = 7'b011_0000;
+ SEXT_H : get_func7 = 7'b011_0000;
+ XNOR : get_func7 = 7'b010_0000;
+ ZEXT_H : get_func7 = 7'b000_0100;
+ default : get_func7 = super.get_func7();
+ endcase
+ endfunction : get_func7
+
+ virtual function string convert2bin(string prefix = "");
+ string binary = "";
+
+ case (format)
+ R_FORMAT: begin
+ if (instr_name inside { ZEXT_H }) begin
+ binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
+ end
+ end
+
+ I_FORMAT: begin
+ case (instr_name) inside
+ CLZ, CLZW, CPOP, CPOPW, CTZ, CTZW, ORC_B, REV8, SEXT_B, SEXT_H: begin
+ binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd,
+ get_opcode()});
+ end
+ RORIW: begin
+ binary = $sformatf("%8h", {get_func7(), imm[5:0], rs1, get_func3(), rd, get_opcode()});
+ end
+ RORI: begin
+ // set bit 0 of funct7 only if rv64 and shamt[MSB] is set
+ binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1,
+ get_func3(), rd, get_opcode()});
+ end
+ endcase
+ end
+
+ default: begin
+ if (binary == "") begin
+ binary = super.convert2bin(prefix);
+ end
+ end
+
+ endcase // case (format)
+ endfunction : convert2bin
+
+ virtual function bit is_supported(riscv_instr_gen_config cfg);
+ return (cfg.enable_zbb_extension &&
+ (RV32ZBB inside { supported_isa } || RV64ZBB inside { supported_isa }) &&
+ instr_name inside {
+ ANDN,
+ CLZ, CLZW,
+ CPOP, CPOPW,
+ CTZ, CTZW,
+ MAX, MAXU,
+ MIN, MINU,
+ ORC_B, ORN,
+ REV8,
+ ROL, ROLW,
+ ROR, RORW,
+ RORI, RORIW,
+ SEXT_B, SEXT_H,
+ XNOR,
+ ZEXT_H
+ });
+ endfunction : is_supported
+
+endclass : riscv_zbb_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
new file mode 100644
index 0000000..8bc825e
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbc_instr extends riscv_instr;
+ `uvm_object_utils(riscv_zbc_instr)
+
+ function new(string name = "");
+ super.new(name);
+ endfunction : new
+
+ function void pre_randomize();
+ super.pre_randomize();
+ endfunction : pre_randomize
+
+ function bit[6:0] get_opcode();
+ case (instr_name) inside
+ CLMUL,
+ CLMULH,
+ CLMULR : get_opcode = 7'b011_0011;
+ default : get_opcode = super.get_opcode();
+ endcase
+ endfunction : get_opcode
+
+ function bit [2:0] get_func3();
+ case (instr_name) inside
+ CLMUL : get_func3 = 3'b001;
+ CLMULH : get_func3 = 3'b011;
+ CLMULR : get_func3 = 3'b010;
+ default : get_func3 = super.get_func3();
+ endcase
+ endfunction : get_func3
+
+ function bit [6:0] get_func7();
+ case (instr_name) inside
+ CLMUL : get_func7 = 7'b000_0101;
+ CLMULH : get_func7 = 7'b000_0101;
+ CLMULR : get_func7 = 7'b000_0101;
+ default : get_func7 = super.get_func7();
+ endcase
+ endfunction : get_func7
+
+ virtual function string convert2bin(string prefix = "");
+ string binary = "";
+ if (instr_name inside {CLMUL, CLMULH, CLMULR}) begin
+ binary = $sformatf("%8h", {get_func7(), rs2, rs1, get_func3(), rd, get_opcode()});
+ end
+ else begin
+ binary = super.convert2bin(prefix);
+ end
+ endfunction : convert2bin
+
+ virtual function bit is_supported(riscv_instr_gen_config cfg);
+ return (cfg.enable_zbc_extension &&
+ (RV32ZBC inside { supported_isa } || RV64ZBC inside { supported_isa }) &&
+ instr_name inside {
+ CLMUL, CLMULH, CLMULR
+ });
+ endfunction : is_supported
+
+endclass : riscv_zbc_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
new file mode 100644
index 0000000..95004ed
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class riscv_zbs_instr extends riscv_instr;
+ `uvm_object_utils(riscv_zbs_instr)
+
+ function new(string name = "");
+ super.new(name);
+ endfunction : new
+
+ function void pre_randomize();
+ super.pre_randomize();
+ endfunction : pre_randomize
+
+ function bit is_rv64();
+ is_rv64 = (group == RV64B);
+ endfunction : is_rv64
+
+ virtual function void set_imm_len();
+ if (format inside {I_FORMAT}) begin
+ if (instr_name inside { BCLRI, BEXTI, BINVI, BSETI }) begin
+ imm_len = $clog2(XLEN);
+ end
+ end
+ imm_mask = imm_mask << imm_len;
+ endfunction : set_imm_len
+
+ function bit [6:0] get_opcode();
+ case (instr_name) inside
+ BCLR, BEXT, BINV, BSET,
+ BCLRI, BEXTI, BINVI, BSETI : begin
+ get_opcode = 7'b0010011;
+ end
+ default : get_opcode = super.get_opcode();
+ endcase
+ endfunction : get_opcode
+
+ function bit [2:0] get_func3();
+ case (instr_name) inside
+ BCLR : get_func3 = 3'b001;
+ BCLRI : get_func3 = 3'b001;
+ BEXT : get_func3 = 3'b101;
+ BEXTI : get_func3 = 3'b101;
+ BINV : get_func3 = 3'b001;
+ BINVI : get_func3 = 3'b001;
+ BSET : get_func3 = 3'b001;
+ BSETI : get_func3 = 3'b001;
+ default : get_func3 = super.get_func3();
+ endcase
+ endfunction : get_func3
+
+ function bit [6:0] get_func7();
+ case (instr_name) inside
+ BCLR : get_func7 = 7'b0100100;
+ BCLRI : get_func7 = 7'b0100100;
+ BEXT : get_func7 = 7'b0100100;
+ BEXTI : get_func7 = 7'b0100100;
+ BINV : get_func7 = 7'b0110100;
+ BINVI : get_func7 = 7'b0110100;
+ BSET : get_func7 = 7'b0010100;
+ BSETI : get_func7 = 7'b0010100;
+ default : get_func7 = super.get_func7();
+ endcase
+ endfunction : get_func7
+
+ virtual function string convert2bin(string prefix = "");
+ string binary = "";
+
+ case (format) inside
+ I_FORMAT : begin
+ case (instr_name) inside
+ BCLRI, BEXTI, BINVI, BSETI : begin
+ binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1,
+ get_func3(), rd, get_opcode()});
+ end
+ endcase
+ end
+ default : begin
+ if (binary == "") begin
+ return super.convert2bin(prefix);
+ end
+ end
+ endcase
+ endfunction : convert2bin
+
+ virtual function bit is_supported(riscv_instr_gen_config cfg);
+ return (cfg.enable_zbs_extension &&
+ (RV32ZBS inside { supported_isa } || RV64ZBS inside { supported_isa }) &&
+ instr_name inside {
+ BCLR, BEXT, BINV, BSET,
+ BCLRI, BEXTI, BINVI, BSETI
+ });
+ endfunction : is_supported
+
+endclass : riscv_zbs_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
index 984a1d4..4c568cc 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32b_instr.sv
@@ -15,62 +15,40 @@
* limitations under the License.
*/
+// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+
// LOGICAL instructions
-`DEFINE_B_INSTR(SEXT_B, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(SEXT_H, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(ANDN, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(ORN , R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(XNOR, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(GORC, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(GORCI, I_FORMAT, LOGICAL, RV32B, UIMM)
-`DEFINE_B_INSTR(CMIX, R4_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(CMOV, R4_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACK, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACKU, R_FORMAT, LOGICAL, RV32B)
-`DEFINE_B_INSTR(PACKH, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(GORC, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(GORCI, I_FORMAT, LOGICAL, RV32B, UIMM)
+`DEFINE_B_INSTR(CMIX, R4_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(CMOV, R4_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACK, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACKU, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(PACKH, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_N, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_B, R_FORMAT, LOGICAL, RV32B)
+`DEFINE_B_INSTR(XPERM_H, R_FORMAT, LOGICAL, RV32B)
// SHIFT intructions
-`DEFINE_B_INSTR(SLO, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SRO, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(ROL, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(ROR, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBCLR, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBSET, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBINV, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(SBEXT, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(GREV, R_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(GREVI, I_FORMAT, SHIFT, RV32B , UIMM)
-`DEFINE_B_INSTR(SLOI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SROI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(RORI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBCLRI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBSETI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBINVI , I_FORMAT, SHIFT, RV32B ,UIMM)
-`DEFINE_B_INSTR(SBEXTI , I_FORMAT, SHIFT, RV32B ,UIMM)
+`DEFINE_B_INSTR(SLO, R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(SRO, R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(SLOI, I_FORMAT, SHIFT, RV32B, UIMM)
+`DEFINE_B_INSTR(SROI, I_FORMAT, SHIFT, RV32B, UIMM)
+`DEFINE_B_INSTR(GREV, R_FORMAT, SHIFT, RV32B)
+`DEFINE_B_INSTR(GREVI, I_FORMAT, SHIFT, RV32B, UIMM)
`DEFINE_B_INSTR(FSL, R4_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(FSR, R4_FORMAT, SHIFT, RV32B)
-`DEFINE_B_INSTR(FSRI, I_FORMAT, SHIFT, RV32B ,UIMM)
+`DEFINE_B_INSTR(FSRI, I_FORMAT, SHIFT, RV32B, UIMM)
// ARITHMETIC intructions
-`DEFINE_B_INSTR(CLZ, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CTZ, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(PCNT, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_B, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_H, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32_W, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_B, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_H, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CRC32C_W, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMUL, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MIN, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MAX, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MINU, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(MAXU, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(SHFL, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(UNSHFL, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BDEP, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BEXT, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(BFP, R_FORMAT, ARITHMETIC, RV32B)
-`DEFINE_B_INSTR(SHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)
-`DEFINE_B_INSTR(UNSHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)
-
+`DEFINE_B_INSTR(CRC32_B, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32_H, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32_W, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_B, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_H, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(CRC32C_W, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(SHFL, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(UNSHFL, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(SHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)
+`DEFINE_B_INSTR(UNSHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)
+`DEFINE_B_INSTR(BCOMPRESS, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(BDECOMPRESS, R_FORMAT, ARITHMETIC, RV32B)
+`DEFINE_B_INSTR(BFP, R_FORMAT, ARITHMETIC, RV32B)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
new file mode 100644
index 0000000..91edfd1
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBA_INSTR(SH1ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
+`DEFINE_ZBA_INSTR(SH2ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
+`DEFINE_ZBA_INSTR(SH3ADD, R_FORMAT, ARITHMETIC, RV32ZBA);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
new file mode 100644
index 0000000..afa88d8
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBB_INSTR(ANDN, R_FORMAT, LOGICAL, RV32ZBB);
+`DEFINE_ZBB_INSTR(CLZ, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(CPOP, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(CTZ, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MAX, R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MAXU, R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MIN, R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(MINU, R_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(ORC_B, I_FORMAT, LOGICAL, RV32ZBB);
+`DEFINE_ZBB_INSTR(ORN, R_FORMAT, LOGICAL, RV32ZBB);
+`DEFINE_ZBB_INSTR(REV8, I_FORMAT, SHIFT, RV32ZBB);
+`DEFINE_ZBB_INSTR(ROL, R_FORMAT, SHIFT, RV32ZBB);
+`DEFINE_ZBB_INSTR(ROR, R_FORMAT, SHIFT, RV32ZBB);
+`DEFINE_ZBB_INSTR(RORI, I_FORMAT, SHIFT, RV32ZBB, UIMM);
+`DEFINE_ZBB_INSTR(SEXT_B, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(SEXT_H, I_FORMAT, ARITHMETIC, RV32ZBB);
+`DEFINE_ZBB_INSTR(XNOR, R_FORMAT, LOGICAL, RV32ZBB);
+`DEFINE_ZBB_INSTR(ZEXT_H, R_FORMAT, ARITHMETIC, RV32ZBB);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
new file mode 100644
index 0000000..032e18a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBC_INSTR(CLMUL, R_FORMAT, ARITHMETIC, RV32ZBC)
+`DEFINE_ZBC_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32ZBC)
+`DEFINE_ZBC_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32ZBC)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
new file mode 100644
index 0000000..9cbc0b2
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBS_INSTR(BCLR, R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BCLRI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BEXT, R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BEXTI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BINV, R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BINVI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
+`DEFINE_ZBS_INSTR(BSET, R_FORMAT, SHIFT, RV32ZBS)
+`DEFINE_ZBS_INSTR(BSETI, I_FORMAT, SHIFT, RV32ZBS, UIMM)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
index 9c681c4..7cafd68 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64b_instr.sv
@@ -15,54 +15,32 @@
* limitations under the License.
*/
-// ARITHMETIC intructions
-`DEFINE_B_INSTR(BMATOR, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BMATXOR, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BMATFLIP, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CRC32_D, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CRC32C_D, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDIWU, I_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDWU, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SUBWU, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(ADDU_W, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SUBU_W, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLZW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CTZW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(PCNTW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULRW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(CLMULHW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(SHFLW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(UNSHFLW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BDEPW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BEXTW, R_FORMAT, ARITHMETIC, RV64B)
-`DEFINE_B_INSTR(BFPW, R_FORMAT, ARITHMETIC, RV64B)
+// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+// ARITHMETIC intructions
+`DEFINE_B_INSTR(BMATOR, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BMATXOR, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BMATFLIP, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(CRC32_D, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(CRC32C_D, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(SHFLW, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(UNSHFLW, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BCOMPRESSW, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BDECOMPRESSW, R_FORMAT, ARITHMETIC, RV64B)
+`DEFINE_B_INSTR(BFPW, R_FORMAT, ARITHMETIC, RV64B)
// SHIFT intructions
-`DEFINE_B_INSTR(SLLIU_W, I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SLOW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SROW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(ROLW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(RORW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBCLRW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBSETW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBINVW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SBEXTW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(GREVW, R_FORMAT, SHIFT, RV64B)
-`DEFINE_B_INSTR(SLOIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SROIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(RORIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBCLRIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBSETIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(SBINVIW , I_FORMAT, SHIFT, RV64B, UIMM)
-`DEFINE_B_INSTR(GREVIW, I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(SLOIW, I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(SROIW, I_FORMAT, SHIFT, RV64B, UIMM)
+`DEFINE_B_INSTR(GREVW, R_FORMAT, SHIFT, RV64B)
+`DEFINE_B_INSTR(GREVIW, I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(FSLW, R4_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(FSRW, R4_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(FSRIW, I_FORMAT, SHIFT, RV64B, UIMM)
-
// LOGICAL instructions
-`DEFINE_B_INSTR(GORCW, R_FORMAT, LOGICAL, RV64B)
-`DEFINE_B_INSTR(GORCIW, I_FORMAT, LOGICAL, RV64B, UIMM)
-`DEFINE_B_INSTR(PACKW, R_FORMAT, LOGICAL, RV64B)
-`DEFINE_B_INSTR(PACKUW, R_FORMAT, LOGICAL, RV64B)
-
+`DEFINE_B_INSTR(GORCW, R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(GORCIW, I_FORMAT, LOGICAL, RV64B, UIMM)
+`DEFINE_B_INSTR(PACKW, R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(PACKUW, R_FORMAT, LOGICAL, RV64B)
+`DEFINE_B_INSTR(XPERM_W, R_FORMAT, LOGICAL, RV64B)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
new file mode 100644
index 0000000..e354430
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBA_INSTR(ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH1ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH2ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SH3ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA);
+`DEFINE_ZBA_INSTR(SLLI_UW, I_FORMAT, SHIFT, RV64ZBA, UIMM);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
new file mode 100644
index 0000000..e1c278c
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 Google LLC
+ * Copyright 2021 Silicon Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+`DEFINE_ZBB_INSTR(CLZW, I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(CPOPW, I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(CTZW, I_FORMAT, ARITHMETIC, RV64ZBB);
+`DEFINE_ZBB_INSTR(ROLW, R_FORMAT, SHIFT, RV64ZBB);
+`DEFINE_ZBB_INSTR(RORW, R_FORMAT, SHIFT, RV64ZBB);
+`DEFINE_ZBB_INSTR(RORIW, I_FORMAT, SHIFT, RV64ZBB, UIMM);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
index 96cca5f..9822d67 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
@@ -452,6 +452,8 @@
RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1;
RVV : misa[MISA_EXT_V] = 1'b1;
RV32X, RV64X : misa[MISA_EXT_X] = 1'b1;
+ RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS,
+ RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS : ; // No Misa bit for Zb* extensions
default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported",
supported_isa[i].name()))
endcase
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
index fc30b41..aee215c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
@@ -105,3 +105,22 @@
class riscv_``instr_n``_instr extends riscv_b_instr; \
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+//Zba-extension instruction
+`define DEFINE_ZBA_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+ class riscv_``instr_n``_instr extends riscv_zba_instr; \
+ `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbb-extension instruction
+`define DEFINE_ZBB_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+ class riscv_``instr_n``_instr extends riscv_zbb_instr; \
+ `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbc-extension instruction
+`define DEFINE_ZBC_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+ class riscv_``instr_n``_instr extends riscv_zbc_instr; \
+ `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
+
+//Zbs-extension instruction
+`define DEFINE_ZBS_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
+ class riscv_``instr_n``_instr extends riscv_zbs_instr; \
+ `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
index 91ced68..60ff4b5 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
@@ -181,6 +181,38 @@
}
}
+ constraint zba_extension_c {
+ if (RV32ZBA inside {supported_isa}) {
+ if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+ !(opcode inside {7'b0110011, 7'b0111011, 7'b0011011});
+ }
+ }
+ }
+
+ constraint zbb_extension_c {
+ if (RV32ZBB inside {supported_isa}) {
+ if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+ !(opcode inside {7'b0110011, 7'b0010011, 7'b0111011, 7'b0011011});
+ }
+ }
+ }
+
+ constraint zbc_extension_c {
+ if (RV32ZBB inside {supported_isa}) {
+ if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+ !(opcode inside {7'b0110011});
+ }
+ }
+ }
+
+ constraint zbs_extension_c {
+ if (RV32ZBS inside {supported_isa}) {
+ if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
+ !(opcode inside {7'b0110011, 7'b0010011});
+ }
+ }
+ }
+
constraint illegal_compressed_op_c {
if (exception == kIllegalCompressedOpcode) {
c_op != 2'b01;
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
index 33896ad..badc423 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv
@@ -34,6 +34,10 @@
`define SAMPLE_F(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_floating_point_instr)
`define SAMPLE_B(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_b_instr)
+`define SAMPLE_ZBA(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zba_instr)
+`define SAMPLE_ZBB(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbb_instr)
+`define SAMPLE_ZBC(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbc_instr)
+`define SAMPLE_ZBS(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbs_instr)
`define INSTR_CG_BEGIN(INSTR_NAME, INSTR_CLASS = riscv_instr) \
covergroup ``INSTR_NAME``_cg with function sample(INSTR_CLASS instr);
@@ -377,6 +381,58 @@
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+`define ZBA_I_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBA_R_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rs2 : coverpoint instr.rs2; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBB_I_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBB_R_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rs2 : coverpoint instr.rs2; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBC_I_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBC_R_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rs2 : coverpoint instr.rs2; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
+`define ZBS_I_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
+
+`define ZBS_R_INSTR_CG_BEGIN(INSTR_NAME) \
+ `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \
+ cp_rs1 : coverpoint instr.rs1; \
+ cp_rs2 : coverpoint instr.rs2; \
+ cp_rd : coverpoint instr.rd; \
+ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
+
`define B_I_INSTR_CG_BEGIN(INSTR_NAME) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \
cp_rs1 : coverpoint instr.rs1; \
@@ -857,43 +913,177 @@
`FCLASS_INSTR_CG_BEGIN(fclass_d, D)
`CG_END
- // B extension
+ // B extension instructions ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+ `ZBA_R_INSTR_CG_BEGIN(sh1add)
+ `CG_END
+ `ZBA_R_INSTR_CG_BEGIN(sh2add)
+ `CG_END
+ `ZBA_R_INSTR_CG_BEGIN(sh3add)
+ `CG_END
+ `ZBA_R_INSTR_CG_BEGIN(sh1add_uw)
+ `CG_END
+ `ZBA_R_INSTR_CG_BEGIN(sh2add_uw)
+ `CG_END
+ `ZBA_R_INSTR_CG_BEGIN(sh3add_uw)
+ `CG_END
+
// Count Leading/Trailing Zeros (clz, ctz)
- `B_R_INSTR_NO_RS2_CG_BEGIN(clz)
+ `ZBB_I_INSTR_CG_BEGIN(clz)
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
`CG_END
- `B_R_INSTR_NO_RS2_CG_BEGIN(ctz)
+ `ZBB_I_INSTR_CG_BEGIN(ctz)
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
`CG_END
- `B_R_INSTR_NO_RS2_CG_BEGIN(clzw)
- `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN/2-1)
+ `ZBB_I_INSTR_CG_BEGIN(clzw)
+ `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
`CG_END
- `B_R_INSTR_NO_RS2_CG_BEGIN(ctzw)
- `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN/2-1)
+ `ZBB_I_INSTR_CG_BEGIN(ctzw)
+ `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
`CG_END
- // Count Bits Set (pcnt)
- `B_R_INSTR_NO_RS2_CG_BEGIN(pcnt)
+ `ZBB_I_INSTR_CG_BEGIN(cpop)
`CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
`CG_END
- `B_R_INSTR_NO_RS2_CG_BEGIN(pcntw)
- `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN/2-1)
+ `ZBB_I_INSTR_CG_BEGIN(cpopw)
+ `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
`CG_END
// Logic-with-negate (andn, orn, xnor)
- `B_R_INSTR_CG_BEGIN(andn)
+ `ZBB_R_INSTR_CG_BEGIN(andn)
`CG_END
- `B_R_INSTR_CG_BEGIN(orn)
+ `ZBB_R_INSTR_CG_BEGIN(orn)
`CG_END
- `B_R_INSTR_CG_BEGIN(xnor)
+ `ZBB_R_INSTR_CG_BEGIN(xnor)
`CG_END
+ // Or-combine
+ `ZBB_R_INSTR_CG_BEGIN(orc_b)
+ `CP_VALUE_RANGE(or_combine_mode, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ // Min/max instructions (min, max, minu, maxu)
+ `ZBB_R_INSTR_CG_BEGIN(min)
+ cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
+ cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
+ bins equal = {1};
+ }
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(max)
+ cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
+ cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
+ bins equal = {1};
+ }
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(minu)
+ cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
+ cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
+ bins equal = {1};
+ }
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(maxu)
+ cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
+ cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
+ bins equal = {1};
+ }
+ `CG_END
+
+ // Sign-extend instructions (sext.b, sext.h)
+ `ZBB_I_INSTR_CG_BEGIN(sext_b)
+ `CG_END
+
+ `ZBB_I_INSTR_CG_BEGIN(sext_h)
+ `CG_END
+
+ `ZBB_I_INSTR_CG_BEGIN(zext_h)
+ `CG_END
+
+ // Rotate (Left/Right) (rol, ror, rori)
+ `ZBB_R_INSTR_CG_BEGIN(ror)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(rol)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBB_I_INSTR_CG_BEGIN(rori)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(rorw)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(rolw)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
+ `CG_END
+
+ `ZBB_I_INSTR_CG_BEGIN(roriw)
+ `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1)
+ `CG_END
+
+ `ZBB_R_INSTR_CG_BEGIN(rev8)
+ `CG_END
+
+ // Multiplication
+ `ZBC_R_INSTR_CG_BEGIN(clmul)
+ `CG_END
+
+ `ZBC_R_INSTR_CG_BEGIN(clmulh)
+ `CG_END
+
+ `ZBC_R_INSTR_CG_BEGIN(clmulr)
+ `CG_END
+
+ `ZBA_I_INSTR_CG_BEGIN(slli_uw)
+ `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ `ZBA_R_INSTR_CG_BEGIN(add_uw)
+ `CG_END
+
+ `ZBS_R_INSTR_CG_BEGIN(bclr)
+ `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_I_INSTR_CG_BEGIN(bclri)
+ `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_R_INSTR_CG_BEGIN(bext)
+ `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_I_INSTR_CG_BEGIN(bexti)
+ `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_R_INSTR_CG_BEGIN(binv)
+ `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_I_INSTR_CG_BEGIN(binvi)
+ `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_R_INSTR_CG_BEGIN(bset)
+ `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
+ `CG_END
+
+ `ZBS_I_INSTR_CG_BEGIN(bseti)
+ `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
+ `CG_END
+
+ // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
// Pack two words in one register (pack, packu, packh)
`B_R_INSTR_CG_BEGIN(pack)
`CG_END
@@ -910,75 +1100,6 @@
`B_R_INSTR_CG_BEGIN(packuw)
`CG_END
- // Min/max instructions (min, max, minu, maxu)
- `B_R_INSTR_CG_BEGIN(min)
- cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
- cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
- bins equal = {1};
- }
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(max)
- cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
- cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
- bins equal = {1};
- }
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(minu)
- cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
- cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
- bins equal = {1};
- }
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(maxu)
- cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
- cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
- bins equal = {1};
- }
- `CG_END
-
- // Sign-extend instructions (sext.b, sext.h)
- `B_R_INSTR_NO_RS2_CG_BEGIN(sext_b)
- `CG_END
-
- `B_R_INSTR_NO_RS2_CG_BEGIN(sext_h)
- `CG_END
-
- // Single-bit instructions (sbset, sbclr, sbinv, sbext)
- `B_R_INSTR_CG_BEGIN(sbset)
- `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(sbclr)
- `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(sbinv)
- `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(sbext)
- `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(sbseti)
- `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(sbclri)
- `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(sbinvi)
- `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(sbexti)
- `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
- `CG_END
-
// Shift Ones (Left/Right) (slo, sloi, sro, sroi)
`B_R_INSTR_CG_BEGIN(slo)
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1)
@@ -1012,31 +1133,6 @@
`CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN/2-1)
`CG_END
- // Rotate (Left/Right) (rol, ror, rori)
- `B_R_INSTR_CG_BEGIN(ror)
- `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(rol)
- `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(rori)
- `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(rorw)
- `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(rolw)
- `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(roriw)
- `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1)
- `CG_END
-
// Generalized Reverse (grev, grevi, rev)
`B_R_INSTR_CG_BEGIN(grev)
`CP_VALUE_RANGE(reverse_mode, instr.rs2_value, 0, XLEN-1)
@@ -1135,34 +1231,16 @@
`CP_VALUE_RANGE(offset, instr.rs2_value[20:16], 0, XLEN/2-1)
`CG_END
- `B_R_INSTR_CG_BEGIN(bext)
+ `B_R_INSTR_CG_BEGIN(bcompress)
`CG_END
- `B_R_INSTR_CG_BEGIN(bextw)
+ `B_R_INSTR_CG_BEGIN(bcompressw)
`CG_END
- `B_R_INSTR_CG_BEGIN(bdep)
+ `B_R_INSTR_CG_BEGIN(bdecompress)
`CG_END
- `B_R_INSTR_CG_BEGIN(bdepw)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmul)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmulh)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmulr)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmulw)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmulhw)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(clmulrw)
+ `B_R_INSTR_CG_BEGIN(bdecompressw)
`CG_END
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32_b)
@@ -1230,25 +1308,6 @@
`CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN/2-1)
`CG_END
- `B_R_INSTR_CG_BEGIN(addwu)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(subwu)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(addiwu)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(addu_w)
- `CG_END
-
- `B_R_INSTR_CG_BEGIN(subu_w)
- `CG_END
-
- `B_I_INSTR_CG_BEGIN(slliu_w)
- `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
- `CG_END
-
// CSR instructions
`CSR_INSTR_CG_BEGIN(csrrw)
cp_rs1 : coverpoint instr.rs1;
@@ -1971,103 +2030,120 @@
fcvt_d_lu_cg = new();
`CG_SELECTOR_END
+ `CG_SELECTOR_BEGIN(RV32ZBA)
+ sh1add_cg = new();
+ sh2add_cg = new();
+ sh3add_cg = new();
+ `CG_SELECTOR_END
+ `CG_SELECTOR_BEGIN(RV32ZBB)
+ andn_cg = new();
+ clz_cg = new();
+ cpop_cg = new();
+ ctz_cg = new();
+ max_cg = new();
+ maxu_cg = new();
+ min_cg = new();
+ minu_cg = new();
+ orc_b_cg = new();
+ orn_cg = new();
+ rev8_cg = new();
+ rol_cg = new();
+ ror_cg = new();
+ rori_cg = new();
+ sext_b_cg = new();
+ sext_h_cg = new();
+ xnor_cg = new();
+ zext_h_cg = new();
+ `CG_SELECTOR_END
+ `CG_SELECTOR_BEGIN(RV32ZBC)
+ clmul_cg = new();
+ clmulh_cg = new();
+ clmulr_cg = new();
+ `CG_SELECTOR_END
+ `CG_SELECTOR_BEGIN(RV32ZBS)
+ bclr_cg = new();
+ bclri_cg = new();
+ bext_cg = new();
+ bexti_cg = new();
+ binv_cg = new();
+ binvi_cg = new();
+ bset_cg = new();
+ bseti_cg = new();
+ `CG_SELECTOR_END
+
`CG_SELECTOR_BEGIN(RV32B)
- clz_cg = new();
- ctz_cg = new();
- pcnt_cg = new();
- andn_cg = new();
- orn_cg = new();
- xnor_cg = new();
- pack_cg = new();
- packh_cg = new();
- min_cg = new();
- max_cg = new();
- minu_cg = new();
- maxu_cg = new();
- sext_b_cg = new();
- sext_h_cg = new();
- sbset_cg = new();
- sbclr_cg = new();
- sbinv_cg = new();
- sbext_cg = new();
- sbseti_cg = new();
- sbclri_cg = new();
- sbinvi_cg = new();
- sbexti_cg = new();
- slo_cg = new();
- sro_cg = new();
- sloi_cg = new();
- sroi_cg = new();
- ror_cg = new();
- rol_cg = new();
- rori_cg = new();
- grev_cg = new();
- grevi_cg = new();
- shfli_cg = new();
- unshfli_cg = new();
- shfl_cg = new();
- unshfl_cg = new();
- gorc_cg = new();
- gorci_cg = new();
- bfp_cg = new();
- bext_cg = new();
- bdep_cg = new();
- clmul_cg = new();
- clmulh_cg = new();
- clmulr_cg = new();
- crc32_b_cg = new();
- crc32_h_cg = new();
- crc32_w_cg = new();
- crc32c_b_cg = new();
- crc32c_h_cg = new();
- crc32c_w_cg = new();
- cmix_cg = new();
- cmov_cg = new();
- fsl_cg = new();
- fsr_cg = new();
- fsri_cg = new();
+ pack_cg = new();
+ packh_cg = new();
+ slo_cg = new();
+ sro_cg = new();
+ sloi_cg = new();
+ sroi_cg = new();
+ grev_cg = new();
+ grevi_cg = new();
+ shfli_cg = new();
+ unshfli_cg = new();
+ shfl_cg = new();
+ unshfl_cg = new();
+ gorc_cg = new();
+ gorci_cg = new();
+ bfp_cg = new();
+ bcompress_cg = new();
+ bdecompress_cg = new();
+ crc32_b_cg = new();
+ crc32_h_cg = new();
+ crc32_w_cg = new();
+ crc32c_b_cg = new();
+ crc32c_h_cg = new();
+ crc32c_w_cg = new();
+ cmix_cg = new();
+ cmov_cg = new();
+ fsl_cg = new();
+ fsr_cg = new();
+ fsri_cg = new();
+ `CG_SELECTOR_END
+
+ `CG_SELECTOR_BEGIN(RV64ZBA)
+ add_uw_cg = new();
+ sh1add_uw_cg = new();
+ sh2add_uw_cg = new();
+ sh3add_uw_cg = new();
+ slli_uw_cg = new();
+ `CG_SELECTOR_END
+ `CG_SELECTOR_BEGIN(RV64ZBB)
+ clzw_cg = new();
+ cpopw_cg = new();
+ ctzw_cg = new();
+ rolw_cg = new();
+ rorw_cg = new();
+ roriw_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV64B)
- clzw_cg = new();
- ctzw_cg = new();
- pcntw_cg = new();
- packw_cg = new();
- packuw_cg = new();
- slow_cg = new();
- srow_cg = new();
- sloiw_cg = new();
- sroiw_cg = new();
- rorw_cg = new();
- rolw_cg = new();
- roriw_cg = new();
- grevw_cg = new();
- greviw_cg = new();
- shflw_cg = new();
- unshflw_cg = new();
- gorcw_cg = new();
- gorciw_cg = new();
- bfpw_cg = new();
- bextw_cg = new();
- bdepw_cg = new();
- clmulw_cg = new();
- clmulhw_cg = new();
- clmulrw_cg = new();
- crc32_d_cg = new();
- crc32c_d_cg = new();
- bmator_cg = new();
- bmatxor_cg = new();
- bmatflip_cg = new();
- fslw_cg = new();
- fsrw_cg = new();
- fsriw_cg = new();
- addwu_cg = new();
- subwu_cg = new();
- addiwu_cg = new();
- addu_w_cg = new();
- subu_w_cg = new();
- slliu_w_cg = new();
+ packw_cg = new();
+ packuw_cg = new();
+ slow_cg = new();
+ srow_cg = new();
+ sloiw_cg = new();
+ sroiw_cg = new();
+ grevw_cg = new();
+ greviw_cg = new();
+ shflw_cg = new();
+ unshflw_cg = new();
+ gorcw_cg = new();
+ gorciw_cg = new();
+ bfpw_cg = new();
+ bcompressw_cg = new();
+ bdecompressw_cg = new();
+ crc32_d_cg = new();
+ crc32c_d_cg = new();
+ bmator_cg = new();
+ bmatxor_cg = new();
+ bmatflip_cg = new();
+ fslw_cg = new();
+ fsrw_cg = new();
+ fsriw_cg = new();
`CG_SELECTOR_END
+
// Ignore the exception which cannot be covered when running with ISS
if (iss_mode) begin
int i;
@@ -2284,36 +2360,49 @@
FLE_D : `SAMPLE_F(fle_d_cg, instr)
FCLASS_S : `SAMPLE_F(fclass_s_cg, instr)
FCLASS_D : `SAMPLE_F(fclass_d_cg, instr)
+ // RV32ZBA
+ SH1ADD : `SAMPLE_ZBA(sh1add_cg, instr)
+ SH2ADD : `SAMPLE_ZBA(sh2add_cg, instr)
+ SH3ADD : `SAMPLE_ZBA(sh3add_cg, instr)
+ // RV32ZBB
+ ANDN : `SAMPLE_ZBB(andn_cg, instr)
+ CLZ : `SAMPLE_ZBB(clz_cg, instr)
+ CPOP : `SAMPLE_ZBB(cpop_cg, instr)
+ CTZ : `SAMPLE_ZBB(ctz_cg, instr)
+ MAX : `SAMPLE_ZBB(max_cg, instr)
+ MAXU : `SAMPLE_ZBB(maxu_cg, instr)
+ MIN : `SAMPLE_ZBB(min_cg, instr)
+ MINU : `SAMPLE_ZBB(minu_cg, instr)
+ ORC_B : `SAMPLE_ZBB(orc_b_cg, instr)
+ ORN : `SAMPLE_ZBB(orn_cg, instr)
+ REV8 : `SAMPLE_ZBB(rev8_cg, instr)
+ ROL : `SAMPLE_ZBB(rol_cg, instr)
+ ROR : `SAMPLE_ZBB(ror_cg, instr)
+ RORI : `SAMPLE_ZBB(rori_cg, instr)
+ SEXT_B : `SAMPLE_ZBB(sext_b_cg, instr)
+ SEXT_H : `SAMPLE_ZBB(sext_h_cg, instr)
+ XNOR : `SAMPLE_ZBB(xnor_cg, instr)
+ ZEXT_H : `SAMPLE_ZBB(zext_h_cg, instr)
+ // RV32ZBC
+ CLMUL : `SAMPLE_ZBC(clmul_cg, instr)
+ CLMULH : `SAMPLE_ZBC(clmulh_cg, instr)
+ CLMULR : `SAMPLE_ZBC(clmulr_cg, instr)
+ // RV32ZBS
+ BCLR : `SAMPLE_ZBS(bclr_cg, instr)
+ BCLRI : `SAMPLE_ZBS(bclri_cg, instr)
+ BEXT : `SAMPLE_ZBS(bext_cg, instr)
+ BEXTI : `SAMPLE_ZBS(bexti_cg, instr)
+ BINV : `SAMPLE_ZBS(binv_cg, instr)
+ BINVI : `SAMPLE_ZBS(binvi_cg, instr)
+ BSET : `SAMPLE_ZBS(bset_cg, instr)
+ BSETI : `SAMPLE_ZBS(bseti_cg, instr)
// RV32B
- CLZ : `SAMPLE_B(clz_cg, instr)
- CTZ : `SAMPLE_B(ctz_cg, instr)
- PCNT : `SAMPLE_B(pcnt_cg, instr)
- ANDN : `SAMPLE_B(andn_cg, instr)
- ORN : `SAMPLE_B(orn_cg, instr)
- XNOR : `SAMPLE_B(xnor_cg, instr)
PACK : `SAMPLE_B(pack_cg, instr)
PACKH : `SAMPLE_B(packh_cg, instr)
- MIN : `SAMPLE_B(min_cg, instr)
- MAX : `SAMPLE_B(max_cg, instr)
- MINU : `SAMPLE_B(minu_cg, instr)
- MAXU : `SAMPLE_B(maxu_cg, instr)
- SEXT_B : `SAMPLE_B(sext_b_cg, instr)
- SEXT_H : `SAMPLE_B(sext_h_cg, instr)
- SBSET : `SAMPLE_B(sbset_cg, instr)
- SBCLR : `SAMPLE_B(sbclr_cg, instr)
- SBINV : `SAMPLE_B(sbinv_cg, instr)
- SBEXT : `SAMPLE_B(sbext_cg, instr)
- SBSETI : `SAMPLE_B(sbseti_cg, instr)
- SBCLRI : `SAMPLE_B(sbclri_cg, instr)
- SBINVI : `SAMPLE_B(sbinvi_cg, instr)
- SBEXTI : `SAMPLE_B(sbexti_cg, instr)
SLO : `SAMPLE_B(slo_cg, instr)
SRO : `SAMPLE_B(sro_cg, instr)
SLOI : `SAMPLE_B(sloi_cg, instr)
SROI : `SAMPLE_B(sroi_cg, instr)
- ROR : `SAMPLE_B(ror_cg, instr)
- ROL : `SAMPLE_B(rol_cg, instr)
- RORI : `SAMPLE_B(rori_cg, instr)
GREV : `SAMPLE_B(grev_cg, instr)
GREVI : `SAMPLE_B(grevi_cg, instr)
SHFLI : `SAMPLE_B(shfli_cg, instr)
@@ -2323,11 +2412,8 @@
GORC : `SAMPLE_B(gorc_cg, instr)
GORCI : `SAMPLE_B(gorci_cg, instr)
BFP : `SAMPLE_B(bfp_cg, instr)
- BEXT : `SAMPLE_B(bext_cg, instr)
- BDEP : `SAMPLE_B(bdep_cg, instr)
- CLMUL : `SAMPLE_B(clmul_cg, instr)
- CLMULH : `SAMPLE_B(clmulh_cg, instr)
- CLMULR : `SAMPLE_B(clmulr_cg, instr)
+ BCOMPRESS : `SAMPLE_B(bcompress_cg, instr)
+ BDECOMPRESS: `SAMPLE_B(bdecompress_cg, instr)
CRC32_B : `SAMPLE_B(crc32_b_cg, instr)
CRC32_H : `SAMPLE_B(crc32_h_cg, instr)
CRC32_W : `SAMPLE_B(crc32_w_cg, instr)
@@ -2339,45 +2425,43 @@
FSL : `SAMPLE_B(fsl_cg, instr)
FSR : `SAMPLE_B(fsr_cg, instr)
FSRI : `SAMPLE_B(fsri_cg, instr)
+ // RV64ZBA
+ ADD_UW : `SAMPLE_ZBA(add_uw_cg, instr)
+ SH1ADD_UW : `SAMPLE_ZBA(sh1add_uw_cg, instr)
+ SH2ADD_UW : `SAMPLE_ZBA(sh2add_uw_cg, instr)
+ SH3ADD_UW : `SAMPLE_ZBA(sh3add_uw_cg, instr)
+ SLLI_UW : `SAMPLE_ZBA(slli_uw_cg, instr)
+ // RV64ZBB
+ CLZW : `SAMPLE_ZBB(clzw_cg, instr)
+ CPOPW : `SAMPLE_ZBB(cpopw_cg, instr)
+ CTZW : `SAMPLE_ZBB(ctzw_cg, instr)
+ ROLW : `SAMPLE_ZBB(rolw_cg, instr)
+ RORW : `SAMPLE_ZBB(rorw_cg, instr)
+ RORIW : `SAMPLE_ZBB(roriw_cg, instr)
// RV64B
- CLZW : `SAMPLE_B(clzw_cg, instr)
- CTZW : `SAMPLE_B(ctzw_cg, instr)
- PCNTW : `SAMPLE_B(pcntw_cg, instr)
- PACKW : `SAMPLE_B(packw_cg, instr)
- PACKUW : `SAMPLE_B(packuw_cg, instr)
- SLOW : `SAMPLE_B(slow_cg, instr)
- SROW : `SAMPLE_B(srow_cg, instr)
- SLOIW : `SAMPLE_B(sloiw_cg, instr)
- SROIW : `SAMPLE_B(sroiw_cg, instr)
- RORW : `SAMPLE_B(rorw_cg, instr)
- ROLW : `SAMPLE_B(rolw_cg, instr)
- RORIW : `SAMPLE_B(roriw_cg, instr)
- GREVW : `SAMPLE_B(grevw_cg, instr)
- GREVIW : `SAMPLE_B(greviw_cg, instr)
- SHFLW : `SAMPLE_B(shflw_cg, instr)
- UNSHFLW : `SAMPLE_B(unshflw_cg, instr)
- GORCW : `SAMPLE_B(gorcw_cg, instr)
- GORCIW : `SAMPLE_B(gorciw_cg, instr)
- BFPW : `SAMPLE_B(bfpw_cg, instr)
- BEXTW : `SAMPLE_B(bextw_cg, instr)
- BDEPW : `SAMPLE_B(bdepw_cg, instr)
- CLMULW : `SAMPLE_B(clmulw_cg, instr)
- CLMULHW : `SAMPLE_B(clmulhw_cg, instr)
- CLMULRW : `SAMPLE_B(clmulrw_cg, instr)
- CRC32_D : `SAMPLE_B(crc32_d_cg, instr)
- CRC32C_D : `SAMPLE_B(crc32c_d_cg, instr)
- BMATOR : `SAMPLE_B(bmator_cg, instr)
- BMATXOR : `SAMPLE_B(bmatxor_cg, instr)
- BMATFLIP : `SAMPLE_B(bmatflip_cg, instr)
- FSLW : `SAMPLE_B(fslw_cg, instr)
- FSRW : `SAMPLE_B(fsrw_cg, instr)
- FSRIW : `SAMPLE_B(fsriw_cg, instr)
- ADDWU : `SAMPLE_B(addwu_cg, instr)
- SUBWU : `SAMPLE_B(subwu_cg, instr)
- ADDIWU : `SAMPLE_B(addiwu_cg, instr)
- ADDU_W : `SAMPLE_B(addu_w_cg, instr)
- SUBU_W : `SAMPLE_B(subu_w_cg, instr)
- SLLIU_W : `SAMPLE_B(slliu_w_cg, instr)
+ PACKW : `SAMPLE_B(packw_cg, instr)
+ PACKUW : `SAMPLE_B(packuw_cg, instr)
+ SLOW : `SAMPLE_B(slow_cg, instr)
+ SROW : `SAMPLE_B(srow_cg, instr)
+ SLOIW : `SAMPLE_B(sloiw_cg, instr)
+ SROIW : `SAMPLE_B(sroiw_cg, instr)
+ GREVW : `SAMPLE_B(grevw_cg, instr)
+ GREVIW : `SAMPLE_B(greviw_cg, instr)
+ SHFLW : `SAMPLE_B(shflw_cg, instr)
+ UNSHFLW : `SAMPLE_B(unshflw_cg, instr)
+ GORCW : `SAMPLE_B(gorcw_cg, instr)
+ GORCIW : `SAMPLE_B(gorciw_cg, instr)
+ BFPW : `SAMPLE_B(bfpw_cg, instr)
+ BCOMPRESSW : `SAMPLE_B(bcompressw_cg, instr)
+ BDECOMPRESSW : `SAMPLE_B(bdecompressw_cg, instr)
+ CRC32_D : `SAMPLE_B(crc32_d_cg, instr)
+ CRC32C_D : `SAMPLE_B(crc32c_d_cg, instr)
+ BMATOR : `SAMPLE_B(bmator_cg, instr)
+ BMATXOR : `SAMPLE_B(bmatxor_cg, instr)
+ BMATFLIP : `SAMPLE_B(bmatflip_cg, instr)
+ FSLW : `SAMPLE_B(fslw_cg, instr)
+ FSRW : `SAMPLE_B(fsrw_cg, instr)
+ FSRIW : `SAMPLE_B(fsriw_cg, instr)
`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
default: begin
if (instr.group == RV32I) begin
@@ -2459,7 +2543,9 @@
instr = riscv_instr::create_instr(instr_name);
if ((instr.group inside {supported_isa}) &&
(instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C,
- RVV, RV64B, RV32B})) begin
+ RVV, RV64B, RV32B,
+ RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS,
+ RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS})) begin
if (((instr_name inside {URET}) && !support_umode_trap) ||
((instr_name inside {SRET, SFENCE_VMA}) &&
!(SUPERVISOR_MODE inside {supported_privileged_mode})) ||
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
index 4aeb819..9a2fdd1 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
@@ -252,6 +252,12 @@
bit vector_instr_only;
// Bit manipulation extension support
bit enable_b_extension;
+
+ bit enable_zba_extension;
+ bit enable_zbb_extension;
+ bit enable_zbc_extension;
+ bit enable_zbs_extension;
+
b_ext_group_t enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT,
ZB_TMP};
@@ -516,6 +522,10 @@
`uvm_field_int(vector_instr_only, UVM_DEFAULT)
`uvm_field_int(enable_b_extension, UVM_DEFAULT)
`uvm_field_array_enum(b_ext_group_t, enable_bitmanip_groups, UVM_DEFAULT)
+ `uvm_field_int(enable_zba_extension, UVM_DEFAULT)
+ `uvm_field_int(enable_zbb_extension, UVM_DEFAULT)
+ `uvm_field_int(enable_zbc_extension, UVM_DEFAULT)
+ `uvm_field_int(enable_zbs_extension, UVM_DEFAULT)
`uvm_field_int(use_push_data_section, UVM_DEFAULT)
`uvm_object_utils_end
@@ -575,6 +585,10 @@
get_bool_arg_value("+enable_floating_point=", enable_floating_point);
get_bool_arg_value("+enable_vector_extension=", enable_vector_extension);
get_bool_arg_value("+enable_b_extension=", enable_b_extension);
+ get_bool_arg_value("+enable_zba_extension=", enable_zba_extension);
+ get_bool_arg_value("+enable_zbb_extension=", enable_zbb_extension);
+ get_bool_arg_value("+enable_zbc_extension=", enable_zbc_extension);
+ get_bool_arg_value("+enable_zbs_extension=", enable_zbs_extension);
cmdline_enum_processor #(b_ext_group_t)::get_array_values("+enable_bitmanip_groups=",
enable_bitmanip_groups);
if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
@@ -600,6 +614,27 @@
if (!(RV32C inside {supported_isa})) begin
disable_compressed_instr = 1;
end
+
+ if (!((RV32ZBA inside {supported_isa}) ||
+ (RV64ZBA inside {supported_isa}))) begin
+ enable_zba_extension = 0;
+ end
+
+ if (!((RV32ZBB inside {supported_isa}) ||
+ (RV64ZBB inside {supported_isa}))) begin
+ enable_zbb_extension = 0;
+ end
+
+ if (!((RV32ZBC inside {supported_isa}) ||
+ (RV64ZBC inside {supported_isa}))) begin
+ enable_zbc_extension = 0;
+ end
+
+ if (!((RV32ZBS inside {supported_isa}) ||
+ (RV64ZBS inside {supported_isa}))) begin
+ enable_zbs_extension = 0;
+ end
+
vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg");
pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg");
pmp_cfg.rand_mode(pmp_cfg.pmp_randomize);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
index 5376def..0524f66 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
@@ -99,7 +99,15 @@
RV128C,
RVV,
RV32B,
+ RV32ZBA,
+ RV32ZBB,
+ RV32ZBC,
+ RV32ZBS,
RV64B,
+ RV64ZBA,
+ RV64ZBB,
+ RV64ZBC,
+ RV64ZBS,
RV32X,
RV64X
} riscv_instr_group_t;
@@ -154,108 +162,115 @@
CSRRWI,
CSRRSI,
CSRRCI,
- // RV32B instructions
+ // RV32ZBA instructions
+ SH1ADD,
+ SH2ADD,
+ SH3ADD,
+ // RV32ZBB instructions
ANDN,
+ CLZ,
+ CPOP,
+ CTZ,
+ MAX,
+ MAXU,
+ MIN,
+ MINU,
+ ORC_B,
ORN,
- XNOR,
- GORC,
- SLO,
- SRO,
+ REV8,
ROL,
ROR,
- SBCLR,
- SBSET,
- SBINV,
- SBEXT,
- GREV,
- SLOI,
- SROI,
RORI,
- SBCLRI,
- SBSETI,
- SBINVI,
- SBEXTI,
+ SEXT_B,
+ SEXT_H,
+ XNOR,
+ ZEXT_H,
+ // RV32ZBC instructions
+ CLMUL,
+ CLMULH,
+ CLMULR,
+ // RV32ZBS instructions
+ BCLR,
+ BCLRI,
+ BEXT,
+ BEXTI,
+ BINV,
+ BINVI,
+ BSET,
+ BSETI,
+ // RV32B instructions
+ // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+ GORC,
GORCI,
- GREVI,
CMIX,
CMOV,
+ PACK,
+ PACKU,
+ PACKH,
+ XPERM_N,
+ XPERM_B,
+ XPERM_H,
+ SLO,
+ SRO,
+ SLOI,
+ SROI,
+ GREV,
+ GREVI,
FSL,
FSR,
FSRI,
- CLZ,
- CTZ,
- PCNT,
- SEXT_B,
- SEXT_H,
CRC32_B,
CRC32_H,
CRC32_W,
CRC32C_B,
CRC32C_H,
CRC32C_W,
- CLMUL,
- CLMULR,
- CLMULH,
- MIN,
- MAX,
- MINU,
- MAXU,
SHFL,
UNSHFL,
- BDEP,
- BEXT,
- PACK,
- PACKU,
- BMATOR,
- BMATXOR,
- PACKH,
- BFP,
SHFLI,
UNSHFLI,
+ BCOMPRESS,
+ BDECOMPRESS,
+ BFP,
+ // RV64ZBA instructions
+ ADD_UW,
+ SH1ADD_UW,
+ SH2ADD_UW,
+ SH3ADD_UW,
+ SLLI_UW,
+ // RV64ZBB instructions
+ CLZW,
+ CPOPW,
+ CTZW,
+ ROLW,
+ RORW,
+ RORIW,
//RV64B instructions
- ADDIWU,
- SLLIU_W,
- ADDWU,
- SUBWU,
+ // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
+ BMATOR,
+ BMATXOR,
BMATFLIP,
CRC32_D,
CRC32C_D,
- ADDU_W,
- SUBU_W,
+ SHFLW,
+ UNSHFLW,
+ BCOMPRESSW,
+ BDECOMPRESSW,
+ BFPW,
SLOW,
SROW,
- ROLW,
- RORW,
- SBCLRW,
- SBSETW,
- SBINVW,
- SBEXTW,
- GORCW,
- GREVW,
SLOIW,
SROIW,
- RORIW,
- SBCLRIW,
- SBSETIW,
- SBINVIW,
- GORCIW,
+ GREVW,
GREVIW,
FSLW,
FSRW,
FSRIW,
- CLZW,
- CTZW,
- PCNTW,
- CLMULW,
- CLMULRW,
- CLMULHW,
- SHFLW,
- UNSHFLW,
- BDEPW,
- BEXTW,
+ GORCW,
+ GORCIW,
PACKW,
PACKUW,
- BFPW,
+ XPERM_W,
// RV32M instructions
MUL,
MULH,
@@ -1151,6 +1166,7 @@
} vxrm_t;
typedef enum int {
+ ZBA,
ZBB,
ZBS,
ZBP,
@@ -1178,7 +1194,7 @@
parameter int DATA_WIDTH = 32;
// Parameters for output assembly program formatting
- parameter int MAX_INSTR_STR_LEN = 11;
+ parameter int MAX_INSTR_STR_LEN = 13;
parameter int LABEL_STR_LEN = 18;
// Parameter for program generation
@@ -1372,10 +1388,18 @@
`include "riscv_vector_cfg.sv"
`include "riscv_pmp_cfg.sv"
typedef class riscv_instr;
+ typedef class riscv_zba_instr;
+ typedef class riscv_zbb_instr;
+ typedef class riscv_zbc_instr;
+ typedef class riscv_zbs_instr;
typedef class riscv_b_instr;
`include "riscv_instr_gen_config.sv"
`include "isa/riscv_instr.sv"
`include "isa/riscv_amo_instr.sv"
+ `include "isa/riscv_zba_instr.sv"
+ `include "isa/riscv_zbb_instr.sv"
+ `include "isa/riscv_zbc_instr.sv"
+ `include "isa/riscv_zbs_instr.sv"
`include "isa/riscv_b_instr.sv"
`include "isa/riscv_floating_point_instr.sv"
`include "isa/riscv_vector_instr.sv"
@@ -1388,9 +1412,15 @@
`include "isa/rv32f_instr.sv"
`include "isa/rv32i_instr.sv"
`include "isa/rv32b_instr.sv"
+ `include "isa/rv32zba_instr.sv"
+ `include "isa/rv32zbb_instr.sv"
+ `include "isa/rv32zbc_instr.sv"
+ `include "isa/rv32zbs_instr.sv"
`include "isa/rv32m_instr.sv"
`include "isa/rv64a_instr.sv"
`include "isa/rv64b_instr.sv"
+ `include "isa/rv64zba_instr.sv"
+ `include "isa/rv64zbb_instr.sv"
`include "isa/rv64c_instr.sv"
`include "isa/rv64d_instr.sv"
`include "isa/rv64f_instr.sv"
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
index 91693c0..4784657 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv
@@ -89,7 +89,8 @@
mstatus.set_field("SPP", 0);
// Enable interrupt
mstatus.set_field("MPIE", cfg.enable_interrupt);
- mstatus.set_field("MIE", cfg.enable_interrupt);
+ // MIE is set when returning with mret, avoids trapping before returning
+ mstatus.set_field("MIE", 0);
mstatus.set_field("SPIE", cfg.enable_interrupt);
mstatus.set_field("SIE", cfg.enable_interrupt);
mstatus.set_field("UPIE", cfg.enable_interrupt);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
index 11048dc..e255cb8 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/testlist.yaml
@@ -34,24 +34,24 @@
description: >
Random test with all useful knobs
gen_opts: >
- +instr_cnt=10000
+ +instr_cnt=100000
+num_of_sub_program=5
+illegal_instr_ratio=5
+hint_instr_ratio=5
+stream_name_0=riscv_load_store_rand_instr_stream
- +stream_freq_0=4
+ +stream_freq_0=20
+stream_name_1=riscv_loop_instr
- +stream_freq_1=4
+ +stream_freq_1=20
+stream_name_2=riscv_hazard_instr_stream
- +stream_freq_2=4
+ +stream_freq_2=20
+stream_name_3=riscv_load_store_hazard_instr_stream
- +stream_freq_3=4
+ +stream_freq_3=20
+stream_name_4=riscv_mem_region_stress_test
- +stream_freq_4=4
+ +stream_freq_4=20
+stream_name_5=riscv_jal_instr
- +stream_freq_5=4
+ +stream_freq_5=20
+stream_name_6=riscv_int_numeric_corner_stream
- +stream_freq_6=4
+ +stream_freq_6=20
+dist_control_mode=1
+dist_shift=10
+dist_arithmetic=10