Compare commits

...

400 commits

Author SHA1 Message Date
Mike Thompson
733743da0f
Fix URLs to point to CV32A60X-specific files on RTDs. (#2938)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
This fixes the paths for the CV32A60X-specific documentation (from the cv32a60x branch). Whenever the cv32a60x branch is updated, the documentation will be regenerated by RTD.
2025-04-16 23:00:33 +02:00
André Sintzoff
30811d1e7e
docs: link to CV32A60X design documentation (#2931)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2025-04-15 11:36:38 +02:00
Mike Thompson
8bcb14a2df
CV32A60X ISA (#2922)
* Bring in CV32A60X ISA from the cv32a60x branch
2025-04-15 09:40:35 +02:00
AngelaGonzalezMarino
f7fae486ff
Fix https://github.com/openhwgroup/cva6/issues/2912 (#2916)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Fix the wrong connection of ASID in MMU. Should solve #2912
2025-04-11 17:21:29 +02:00
Enrico Zelioli
b9da1d9e2d
Fix instruction tracer for superscalar mode (#2901)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
This PR adapts the instr_tracer module to support superscalar mode.
2025-04-06 13:30:18 +02:00
Côme
7b3054156e
Add CVA6 performance model (#2880)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2025-03-28 14:50:12 +01:00
Florian Zaruba
4a1bffa87a
CODEOWNERS: remove zarubaf from global owners (#2869)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2025-03-27 00:05:15 +01:00
Côme
1342bc960b
remove useless COMMA macro (#2850)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
This macro is not required and makes the file harder to parse.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-20 19:01:12 +01:00
Valentin Thomazic
75bc12d01b
ci: fix pmp tests (#2851)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Run PMP tests on cv32a65x since PMP has been disabled on cv32a60x by #2848
2025-03-20 17:43:56 +01:00
André Sintzoff
a165a2bb50
cv32a60x_config_pkg.sv: set NrPMPEntries to 0 (#2848)
to build correct RISC-V ISA privilege manual
2025-03-20 12:23:22 +01:00
Guillaume Chauvon
b258d27816
[CVXIF] Initialize exception fields for RVH (#2844)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Following what was done in branch_unit, I set up a default value for hypervisor exception fields in cvxif_fu.
Should fix issue #2831

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-19 17:31:29 +01:00
André Sintzoff
79c7c2c681
docs: add HTML generation for cv32a60x (followup PR2838) (#2845)
update global doc Makefile

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-19 12:00:13 +01:00
Valentin Thomazic
d94db10fb1
Minor dashboard-related adjustement (#2841)
* wait for dashboard generation before commenting PRs with pipeline report link.
* change dashboard link and badge

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-19 11:14:10 +01:00
André Sintzoff
21506e4c66
docs: add CV32A60X configuration in RISC-V ISA manual (#2838)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* docs: spec_builder.py: add missing extensions
* docs: fix unpriv manual (opcode map, Zcmop)
* in opcode map, write not used when corresponding extension is disabled
* use correct condition for Zcmop extension
* docs: remove PMP chapter when no PMP
* docs: add tailored RISC-V ISA manual for CV32A60X configuration

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-19 00:03:00 +01:00
Guillaume Chauvon
b38c259c8c
Initialize compressed related signals in id_stage when RVC is disabled (#2833)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Add else case to initialize signals going into decoder.
Should fix #2819
2025-03-17 17:35:43 +01:00
Katharina
0e2e5128b2
Assign a default value to tinst in decoder (#2830)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
This PR assigns 0 to tinst by default.
Even though tinst is only used when CVA6Cfg.RVH is enabled, I chose to assign it a default value in all configurations, since the signal is defined for all configurations.

Fixes #2803

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-14 22:42:29 +01:00
Jonathan Balkind
2b1f45cad9
Update CODEOWNERS with jbalkind and cfuguet (#2829)
Updating @Jbalkind and adding @cfuguet to CODEOWNERS
2025-03-14 22:39:36 +01:00
Valentin Thomazic
45e845d165
ci: test PMP with CV32A60X (#2825)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Bring the tests added by #2648 in Gitlab CI:
* Rename PMP tests with generic names
* Add a CV32A60X PMP testlist
* Adapt PMP test script to run the testlist
* Add a CI job running said test script
2025-03-12 23:21:10 +01:00
khandelwaltanuj
3a389af151
added correct reset val (#2823)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
For cv64a60ax configuration
2025-03-12 15:19:15 +01:00
OlivierBetschi
c3fe25aeda
PMP Verif Plan and tests (#2648)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Verification Plan provided in VP_TOOL for the PMP. The verification plan should be complete, however only a partial set of the tests is available. This is not included in the CI but a bash script is available to run the test.
2025-03-12 13:17:40 +01:00
MaxCThales
f984dc347f
Granularity .3f only in report for kGates (#2820)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Changing the type of Kgates from int to float in order to add more granularity on the report (usefull when the difference is under 1k Gates)

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-03-11 21:39:51 +01:00
Riccardo Tedeschi
028ce43fce
docs: add bht2lvl image (#2814)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2025-03-07 22:01:28 +01:00
Geza Lore
c511b21911
Workaround for Verilator ordering issue in OpenPiton cache adapter (#2809)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
This code hits verilator/verilator#5829 due to the use of partial assignments to dcache_rtrn_o in this always block, while reading other bits of the same packed struct elsewhere in the block.

The actual effect of this is that with a Verilator simulation, invalidation requests incoming from the coherence network are sometimes ignored breaking AMOs.

Moving the assignments to the bits read in the always block into the same always block avoids this issue.

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-06 17:16:13 +01:00
Riccardo Tedeschi
aae9b2eb66
bp: add BHT with private history (#2793)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This PR adds a new two-level BHT predictor with private history. The new BPType parameters allow choosing between the original BHT and the new one.

Co-authored-by: Gianmarco Ottavi <ottavig91@gmail.com>
2025-03-06 09:45:45 +01:00
Nils Wistoff
d971232cd7
mmu: Use latched value to determine if misaligned exception occurred (#2802)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Adds to #2798. Sorry for noticing this only now. Together with #2798, this reverts a bug that was introduced in #2528.

Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
2025-02-28 23:50:35 +01:00
khandelwaltanuj
ab89beaebb
Adding a new configuration file for cv64a60ax and dv target RV64IMAFDC (#2761)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
A new configuration file and core v target is added to start working on a 64 bit CVA6 core.

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-28 07:55:13 +01:00
Nils Wistoff
14ef741bae
mmu: Latch misaligned exception to fix misattribution (#2798)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
The load and store units sample the MMU exception one cycle after
`dtlb_hit` is asserted. However, misaligned exceptions are currently fed
through the MMU, potentially attributing a misaligned exception to the
*preceding* instruction. Fix this by latching the misaligned exception.

Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-27 23:08:22 +01:00
Matteo Perotti
3e73712c3e
cva6_ptw: fix latch when RVH is disabled (#2795)
Fix a small latch created when RVH is off.
2025-02-27 23:05:25 +01:00
AngelaGonzalezMarino
6e0cf8d730
Altera fpga update (#2790)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Update Altera APU design to support linux in both 32 and 64 bits
* Move JTAG UART inside peripherals to properly connect the interruput request to PLIC
* Reduce the frequency of operation to 100MHz to avoid timing issues in 64bit version
* Update UART read and write operation in bootrom to allow keyboard interrupt
2025-02-25 22:12:55 +01:00
Riccardo Tedeschi
bac134b7b5
cv*_config_pkg.sv: separately parametrize RVF and RVD (#2786)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Use separate parametrization for RVF and RVD support. In the cv32a6_imafc_sv32 configuration RVD is currently enabled, leading to compilation errors.

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-25 07:13:29 +01:00
Valentin Thomazic
dfdc72cb5a
Enable gdb on toolchain builder (#2789)
As discussed in #2775 (comment) , this pr enables gdb back on the toolchain build scripts. It also updates the README to use the current toolchain name for the gdb section.
2025-02-25 07:09:27 +01:00
Nils Wistoff
2d411b2dc8
instr_tracer.sv: Fix double sampling (#2782)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Currently, the instruction trace update logic is triggered on both clock
edges, leading to double entries in the instruction trace and a wrong
cycle count. Fix this by updating the trace only on positive clock edges.

Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
2025-02-20 07:18:59 +01:00
Nils Wistoff
a55db35bd1
Makefile: Fix FPGA bootrom path (#2774)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
`src/bootrom/bootrom_$(XLEN).sv` does not exist relative to the Makefile
and is not built by the recipe. Like all other FPGA source files, prefix
the full path to `bootrom_$(XLEN).sv`.

Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-19 23:21:09 +01:00
JeanRochCoulon
e4c28b0b03
Simplify the Verilog "inside" (from @flaviens) (#2776)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Hi! Some tools like morty struggle with this expression. I suggest this very simple rewrite. No need for fancy constructs here.
Thanks @flaviens for this contribution
2025-02-19 09:45:30 +01:00
Guillaume Chauvon
be7c8746c6
Add parameter type to define which coprocessor is instantiated on CVXIF (#2772)
Add parameter CoproType to select which coprocessor to instantiate when CvxifEn == 1
---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-19 08:52:17 +01:00
Jérôme Quévremont
373401537e
[Skip CI] Update to CONTRIBUTING.md (#2769)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Writing some rules that were previously implicit.

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-13 21:27:35 +01:00
Côme
07bb91f5a2
ci: require correct formatting (#2771)
let CI fail if verible catches mismatches to prevent them from being accidentally merged

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-13 21:25:37 +01:00
Nils Wistoff
abf21ee221
cva6_icache: Fix formatting (#2770)
Run verible verilog format to fix upstream formatting.

Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
2025-02-13 21:24:31 +01:00
dependabot[bot]
7b759a8b71
Bump verif/sim/dv from f0c570d to 7e54b67 (#2763)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Bumps [verif/sim/dv](https://github.com/google/riscv-dv) from `f0c570d` to `7e54b67`.
- [Commits](f0c570d112...7e54b678ab)

---
updated-dependencies:
- dependency-name: verif/sim/dv
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-11 10:48:31 +01:00
Matteo Perotti
1bc415391a
[RVV] CVA6 re-parametrization and MMU interface (#2652)
Follow-up to the discussion on extending Linux support to the Ara vector processor.

* Main changes:
Add:
Add external MMU interface to share the MMU with the external accelerator.
Add avoid_neg() function used to clip negative numbers to zero. Useful for parametric array sizes and vector multipliers.

Modifications:
2 commit ports by default in cv64a6_imafdcv_config_pkg.
Change exception_t from localparam to param in cva6.sv.
Add parameters accelerator_req_t, accelerator_resp_t, acc_mmu_req_t, and acc_mmu_resp_t to cva6.sv.
Replace the fall-through register with a spill register in acc_dispatcher to decouple timing with the accelerator.
Decrease cache sizes in cv64a6_imafdcv_sv39_config_pkg.
Modify Bender.yml package name from ariane to cva6.
Add harmless code to prevent synthesizer tool from crashing when compiling csr_regfile.

* Collateral changes:
Fixes:
Guard some X-IF code lines with correct parameter in cva6.sv.
Parametrize the tracer interface with NrCommitPorts.
Add missing local dependencies to Bender.yml.

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-02-11 07:22:31 +01:00
Guillaume Chauvon
2ef1c1b1fc
Update ID stage to support ZCMP, ZCMT and CVXIF with Superscalar (#2756)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Add support for Superscalar with ZCMP, ZCMT and CVXIF.
ZCMP decoder, ZCMT decoder and CVXIF interface driver are using port 0.
Standard RVC and 32 bits instruction can take port 0 or 1.
2025-02-03 13:40:02 +01:00
Jalali
fd8c890def
Makefile : Add target to generate functional coverage using verdi tool (#2755)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Co-authored-by: André Sintzoff <61976467+ASintzoff@users.noreply.github.com>
2025-01-31 14:13:36 +01:00
Jalali
70972dad54
Update rvfi_tracer and cva6.py (#2684)
* RVFI Tracer : Update tracer to support interrupts

* Randomize sv_seed by default

* Change pc64 to pc

* Fixes

* cva6.py : add the capability to create a log for sv_seed

* Tracer : keep pc64 64 targets failed

* Fix UVM seed for performance tests

---------

Co-authored-by: André Sintzoff <61976467+ASintzoff@users.noreply.github.com>
2025-01-31 13:10:27 +01:00
André Sintzoff
10fced1c99
csr_regfile.sv: move CVA6Cfg.DebugEn to improve code coverage (#2753)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Use CVA6Cfg.DebugEn in an outer test instead of in inner tests
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-31 05:46:24 +01:00
André Sintzoff
0ec65198bc
doc: fix description of signals in instr_scan.sv (#2752)
as use in design document (automatically generated part)

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-31 05:44:24 +01:00
André Sintzoff
a3372c51f0
cva6_rvfi_probes.sv: fix be5ac20e4 (PR 2749) (#2751)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
rs1_i and rs2_i have XLEN width

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-29 15:50:34 +01:00
André Sintzoff
07f19ea319
decoder.sv: add condition CVA6Cfg.SoftwareInterruptEn (#2747)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
to improve conditional coverage
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-29 11:46:34 +01:00
André Sintzoff
59822e7ad1
instr_scan.sv: remove useless condition (#2748)
is_rvc is redundant with riscv::OpcodeC1, riscv::OpcodeC2

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-29 11:45:47 +01:00
JeanRochCoulon
be5ac20e46
Fix RVFI rs1/rs2 len from VLEN to XLEN (#2749)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
RVFI rs1 and rs2 operands were VLEN, it has been fixed to be XLEN.
2025-01-28 18:37:07 +01:00
Jalali
3e8eb88e88
Fix UVM scoreboard check VLEN bits only (#2742)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2025-01-28 00:07:58 +01:00
Farhan Ali Shah
542fe39adc
Adding support for ZCMT Extension for Code-Size Reduction in CVA6 (#2659)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
## Introduction
This PR implements the ZCMT extension in the CVA6 core, targeting the 32-bit embedded-class platforms. ZCMT is a code-size reduction feature that utilizes compressed table jump instructions (cm.jt and cm.jalt) to reduce code size for embedded systems
**Note:** Due to implementation complexity, ZCMT extension is primarily targeted at embedded class CPUs. Additionally, it is not compatible with architecture class profiles.(Ref. [Unprivilege spec 27.20](https://drive.google.com/file/d/1uviu1nH-tScFfgrovvFCrj7Omv8tFtkp/view))

## Key additions

- Added zcmt_decoder module for compressed table jump instructions: cm.jt (jump table) and cm.jalt (jump-and-link table)

- Implemented the Jump Vector Table (JVT) CSR to store the base address of the jump table in csr_reg module

- Implemented a return address stack, enabling cm.jalt to behave equivalently to jal ra (jump-and-link with return address), by pushing the return address onto the stack in zcmt_decoder module

## Implementation in CVA6
The implementation of the ZCMT extension involves the following major modifications:

### compressed decoder 
The compressed decoder scans and identifies the cm.jt and cm.jalt instructions, and generates signals indicating that the instruction is both compressed and a ZCMT instruction.

### zcmt_decoder
A new zcmt_decoder module was introduced to decode the cm.jt and cm.jalt instructions, fetch the base address of the JVT table from JVT CSR, extract the index and construct jump instructions to ensure efficient integration of the ZCMT extension in embedded platforms. Table.1 shows the IO port connection of zcmt_decoder module. High-level block diagram of zcmt implementation in CVA6 is shown in Figure 1.

_Table. 1 IO port connection with zcmt_decoder module_
Signals | IO | Description | Connection | Type
-- | -- | -- | -- | --
clk_i | in | Subsystem Clock | SUBSYSTEM | logic
rst_ni | in | Asynchronous reset active low | SUBSYSTEM | logic
instr_i | in | Instruction in | compressed_decoder | logic [31:0]
pc_i | in | Current PC | PC from FRONTEND | logic [CVA6Cfg.VLEN-1:0]
is_zcmt_instr_i | in | Is instruction a zcmt instruction | compressed_decoder | logic
illegal_instr_i | in | Is instruction a illegal instruction | compressed_decoder | logic
is_compressed_i | in | Is instruction a compressed instruction | compressed_decoder | logic
jvt_i | in | JVT struct from CSR | CSR | jvt_t
req_port_i | in | Handshake between CACHE and FRONTEND (fetch) | Cache | dcache_req_o_t
instr_o | out | Instruction out | cvxif_compressed_if_driver | logic [31:0]
illegal_instr_o | out | Is the instruction is illegal | cvxif_compressed_if_driver | logic
is_compressed_o | out | Is the instruction is compressed | cvxif_compressed_if_driver | logic
fetch_stall_o | out | Stall siganl | cvxif_compressed_if_driver | logic
req_port_o | out | Handshake between CACHE and FRONTEND (fetch) | Cache | dcache_req_i_t

### branch unit condition
A condition is implemented in the branch unit to ensure that ZCMT instructions always cause a misprediction, forcing the program to jump to the calculated address of the newly constructed jump instruction.

### JVT CSR
A new JVT csr is implemented in csr_reg which holds the base address of the JVT table. The base address is fetched from the JVT CSR, and combined with the index value to calculate the effective address.

### No MMU
Embedded platform does not utilize the MMU, so zcmt_decoder is connected with cache through port 0 of the Dcache module for implicit read access from the memory.

![zcmt_block drawio](https://github.com/user-attachments/assets/ac7bba75-4f56-42f4-9f5e-0c18f00d4dae)
_Figure. 1 High level block diagram of ZCMT extension implementation_

## Known Limitations
The implementation targets 32-bit instructions for embedded-class platforms without an MMU. Since the core does not utilize an MMU, it is leveraged to connect the zcmt_decoder to the cache via port 0.

## Testing and Verification

- Developed directed test cases to validate cm.jt and cm.jalt instruction functionality
- Verified correct initialization and updates of JVT CSR

### Test Plan 
A test plan is developed to test the functionality of ZCMT extension along with JVT CSR. Directed Assembly test executed to check the functionality. 

_Table. 2 Test plan_
S.no | Features | Description | Pass/Fail Criteria | Test Type | Test status
-- | -- | -- | -- | ---- | --
1 | cm.jt | Simple assembly test to validate the working of cm.jt instruction in  CV32A60x. | Check against Spike's ref. model | Directed | Pass
2 | cm.jalt | Simple assembly test to validate the working of cm.jalt instruction in both CV32A60x. | Check against Spike's ref. model | Directed | Pass
3 | cm.jalt with return address stack | Simple assembly test to validate the working of cm.jalt instruction with return address stack in both CV32A60x. It works as jump and link ( j ra, imm) | Check against Spike's ref. model | Directed | Pass
4 | JVT CSR | Read and write base address of Jump table to JVT CSR | Check against Spike's ref. model | Directed | Pass


**Note**: Please find the test under CVA6_REPO_DIR/verif/tests/custom/zcmt"
2025-01-27 13:23:26 +01:00
Riccardo Tedeschi
fb4a8d4472
Fix missing parametrization in performance counters (#2740)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2025-01-26 21:51:25 +01:00
André Sintzoff
3ebb510374
dvplan_csr-access.md: remove file in VerifPlans/csr_access (#2739)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
as the file is also located in VerifPlans/source

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-24 13:56:24 +01:00
Pascal Cotret
9d039197d1
update smoke tests file names (#2736)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Related to issue #2715

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-23 17:54:21 +01:00
Riccardo Tedeschi
024b8eada8
config_pkg: fix HPDCache related parameter (#2731)
The AXI AW channel in the HPDcache is shared by three components:

Write Buffer
Flush Controller
Uncached Controller
The ID for each transaction is generated based on its source as follows:

Write Buffer: {1'b0, write_buffer_entry_index}
Flush Controller: {1'b1, flush_controller_index}
Uncached Controller: '1
To distinguish between flush transactions and uncached transactions, the flush transaction ID must include at least one 0.

Currently, the AXI ID is limited to 4 bits, while the flush controller supports 8 entries. As a result, when a transaction is sent from the 8th entry of the flush controller, all bits of the ID are set to 1. This causes the HPDcache to misroute the response to the uncached controller instead of the flush controller.

The parameter CVA6ConfigWtDcacheWbufDepth is used in the WB cache to set the number of flush entries. To avoid modifying the ID width, the number of flush entries must be less than 8. Non-power-of-two values are supported.

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-23 17:53:07 +01:00
André Sintzoff
cbb08e8d19
docs: clarify WLRL CSR fields on CVA6 (fix #1053) (#2733)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
as priv-csrs.adoc was not yet tailored for CVA6, the file is copied
and tailored

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-23 16:48:13 +01:00
Guillaume Chauvon
3ce44b1b4e
Spyglass clean up: multiple change to remove Spyglass warnings (#2727)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Multiple changes to clean up code and remove Spyglass warnings.

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-23 08:32:31 +01:00
Guillaume Chauvon
664c515b22
Fix decoding of CLRI, BINVI, BSETI, BEXTI and RORI where bit 25 is reserved in RV32 (#2728)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Fix decoding of some bitmanip instruction where decoding differs between rv32 and rv64.
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-22 23:45:09 +01:00
Jalali
c19a3c1ace
Spike : mtvec doesn't support vectored mode for cv32a65x (#2729)
This is a spike fix for cv32a65x config.
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-22 23:42:47 +01:00
André Sintzoff
45aa060b5c
docs: regenerate dvplan_csr-access.md (#2625) (#2714)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Previous fix was not correct (PR 2627)
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-22 10:51:14 +01:00
dependabot[bot]
14998fc161
Bump verif/core-v-verif from 19b5a3f to 60e5724 (#2724)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-22 09:11:11 +01:00
André Sintzoff
f80c507aea
docs/requirements.txt: add missing packages for RTD (#2726)
this should fix build of design documents

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-22 09:07:01 +01:00
Mike Thompson
b9886a27a2
Clean up table (#2725) 2025-01-22 08:29:35 +01:00
André Sintzoff
02092dbcf0
riscv-isa-manual: ignore mm-formal.adoc (#2723)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
as this appendix requires Java and as it is not relevant for CV32A65X

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-21 17:42:39 +01:00
Guillaume Chauvon
24c6a891b8
Docs: define values for CVXIF in 60x and 65x configuration (#2721)
Set values for X_NUM_RS in embedded configurations to 2.

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-21 17:06:26 +01:00
André Sintzoff
fb899feec1
fix 023e67e9 (define PATH variable and make in one command) (#2722)
to avoid PATH export, define it in the same command with make

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-21 17:04:24 +01:00
André Sintzoff
b6b259914a
fix 8e5872c03 (add missing smctr.adoc file) (#2720)
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-21 16:25:18 +01:00
André Sintzoff
023e67e9be
.readthedocs.yaml: add node modules to PATH environment variable (#2719)
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-21 16:00:13 +01:00
Guillaume Chauvon
98604b5920
csr_regfile: SEIP is read only 0 (fix #2056) (#2716)
Fix #2056

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-21 14:53:37 +01:00
André Sintzoff
7bdfa5f63e
.readthedocs.yaml: clone submodule recursively (#2718)
as riscv-isa-manual has a submodule, clone it

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2025-01-21 14:34:40 +01:00
André Sintzoff
8e5872c03b
update riscv-isa-manual to riscv-isa-release-4f277ff-2025-01-17 (#2717)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Since last riscv-isa-manual update (CVA6 commit 67a6ae966):
	- minor documentation changes
	- new unsupported Zsmctr extension
	- add missing asciidoctor-lists gem in dependencies/Gemfile

Gemfile update is needed for ReadTheDocs

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
2025-01-21 09:56:51 +01:00
Guillaume Chauvon
3d2ff00b1c
Modify MSUB, NMADD, NMSUB behaviour to differs from other instructions. (#2712)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
MSUB = rs1 - rs2 - rs3
NMADD = ~(rs1 + rs2 + rs3)
NMSUB = ~(rs1 - rs2 - rs3)
2025-01-17 14:12:08 +01:00
OlivierBetschi
e840a61e80
Rewrite assert to avoid multi assertion (#2713)
This should fix github CI failing with verilator due to the assert combination
2025-01-17 12:39:05 +01:00
Côme
7af0f2e4d1
ariane_pkg: remove unused localparam ISSUE_WIDTH (#2710)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This localparam is not needed anymore.
2025-01-16 23:12:33 +01:00
Guillaume Chauvon
41c22069a0
Add parameter to disable software interrupt. Fix issue #2500 (#2711)
Fix issue #2500
Add parameter to disable software interrupt.
MIP.MSIP and MIE.MSIE are now read only when this parameter is disabled.
2025-01-16 23:09:57 +01:00
dependabot[bot]
5518a41c08
Bump verif/core-v-verif from 464bf7a to 19b5a3f (#2703)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2025-01-15 19:57:00 +01:00
Guillaume Chauvon
21b247dca7
CI: copy seeds in artifacts for generated tests (#2708)
Save seeds in artifacts for generated tests. It will help to reproduce the test in case of failure.
2025-01-15 17:48:01 +01:00
Nils Wistoff
86c53c5334
config_pkg: Update configurations with new flush parameter (#2704)
#2691 extended the cva6_user_cfg_t struct by two new parameters to control the cache's flush behaviour. Add these new parameters to all configs to fix compilation errors due to incomplete struct literals.
2025-01-15 17:47:07 +01:00
Nils Wistoff
cb5c623e50
mmu: Fix pmpcfg, pmpaddr width (#2707)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
PR #2692 changed the bus width for `pmpcfg` and `pmpaddr` in most
modules. Do the same in `cva6_mmu` and `cva6_ptw` to fix port width
mismatches.
2025-01-15 11:17:37 +01:00
Nils Wistoff
b28545ef78
id_stage/pmp_entry: Fix formatting (#2705)
Run verible verilog format to fix upstream formatting.
2025-01-15 10:29:18 +01:00
Jérôme Quévremont
a12d511432
[Skip CI] Extending RESOURCES.md document (#2629)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Adding more references from PULP and Zero Day Labs.
Fixing a few typos.
Unified the layout.
2025-01-10 21:59:42 +01:00
Cesar Fuguet
db568f3e1d
Fully support the Write-Back mode of the HPDcache in the CVA6 (#2691)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This PR modifies some components in the CVA6 to fully support the WB mode of the HPDcache.

When on WB mode, there may be coherency issues between the Instruction Cache and the Data Cache. This may happen when the software writes on instruction segments (e.g. to relocate a code in memory).

This PR contains the following modifications:

The CVA6 controller module rises the flush signal to the caches when executing a fence or fence.i instruction.
The HPDcache cache subsystem translates this fence signal to a FLUSH request to the cache (when the HPDcache is in WB mode).
Add new parameters in the CVA6 configuration packages:
DcacheFlushOnInvalidate: It changes the behavior of the CVA6 controller. When this parameter is set, the controller rises the Flush signal on fence instructions.
DcacheInvalidateOnFlush: It changes the behavior of the HPDcache request adapter. When issuing a flush, it also asks the HPDcache to invalidate the cachelines.
Add additional values to the DcacheType enum: HPDCACHE_WT, HPDCACHE_WB, HPDCACHE_WT_WB
In addition, it also fixes some issues with the rvfi_mem_paddr signal from the store_buffer.
2025-01-10 17:57:32 +01:00
Nils Wistoff
71f96d4329
wt_axi_adapter: Remove redundant, parameterization-breaking zero extensions (#2697)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
zero-extended the paddrs to match the axi_addr width and thus fix lint warnings. However, this breaks elaboration if AxiAddrWidth <= PLEN. To fix lint warnings without breaking parametrisation, use explicit casts to pad/truncate as required.
2025-01-10 08:27:10 +01:00
Nils Wistoff
ee58bfab94
wt_dcache_buffer: Avoid out-of-range user signal access (#2698)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
If the data user signal is disabled and the user bus width is reduced,
the slice operator into the user field will cause elaboration errors.
Since the faulty else block is anyways without effect, just remove it.
2025-01-09 14:42:41 +01:00
André Sintzoff
1c6b89df5b
doc: RVZicntr extension can be not supported (#2699)
counters.adoc: condition around Zicntr text
2025-01-09 14:38:49 +01:00
JeanRochCoulon
837b204753
Make PMP disableable (#2692)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2025-01-09 12:14:18 +01:00
Matteo Perotti
5a484fce42
cache_subsystem: 🐛 Fix AXI read len (#2696)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
AxiRdBlenDcache -> AxiRdBlenIcache
2025-01-08 23:06:53 +01:00
Jalali
6268d28939
Code coverage : Add option to support coverage condition with arithmetic operations (#2694)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Fix issue#1902
2025-01-08 18:55:08 +01:00
Nils Wistoff
e55f25d23c
csr_regfile: Fix irq/ex delegation in RVH (#2689)
In RVH, interrupts are currently delegated if hxdeleg is set but mxdeleg
is not, violating the spec ("A trap/irq *that has been delegated to
HS-mode (using mxdeleg)* is further delegated to VS-mode if the
corresponding hxdeleg bit is set"). Fix and simplify the corresponding logic.
2025-01-08 13:40:30 +01:00
AngelaGonzalezMarino
bca4e1544f
update readme with information how to generate bitstream for agilex 7 (#2690)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2025-01-08 12:01:33 +01:00
JeanRochCoulon
31008fc4b9
remove ifndef VERILATOR (#2686) 2025-01-08 09:08:44 +01:00
AngelaGonzalezMarino
eab88770ec
Altera flow support (#2649)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Integration of bitstream generation for Altera APU in general flow.
* Automatic generation of IPs and sources required for Altera FPGA
* Adaptation of bootrom code (UART used in Altera is different and needs a different driver)
* Generation of project for Quartus Pro adding required sources and constraints - Quartus Pro licence required by users
* Configuration file for openocd connection with vJTAG tap
2025-01-07 23:45:49 +01:00
JeanRochCoulon
2155d0e9c4
Fix #2665 #2400 #2657 (#2685)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* Fix #2400: define new PmpNapotEn parameter to disable NAPOT

* Fix #2665 by removing NA4 related RTL lines

* Fix Spyglass

* Fix gate count
2025-01-07 08:45:28 +01:00
dependabot[bot]
86a80f0eaa
Bump verif/core-v-verif from 6c1e999 to 464bf7a (#2683)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2025-01-03 11:14:15 +01:00
Jalali
446defb900
CVXIF VSEQ: RD equal x10 for CUS_ADD_RS3_RTYPE (#2682)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Fix cvxif vseq
2025-01-02 14:51:24 +01:00
Guillaume Chauvon
4b9cbf9223
Various fixes for CVXIF following verification. (#2678)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
* [CVXIF] Various fixes for bugs report with CVXIF's UVM agent

* Update options and simulators to support CVXIF's UVM agent

---------

Co-authored-by: ajalali <ayoub.jalali@external.thalesgroup.com>
Co-authored-by: André Sintzoff <61976467+ASintzoff@users.noreply.github.com>
2024-12-20 13:28:49 +01:00
Jalali
b4a037d33b
Interrupt cov : sample when rvfi.intr is asserted (#2675)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-12-19 16:20:45 +01:00
JeanRochCoulon
73bae85e0c
[HOT FIX] Update expected_synth.yml (#2676)
Fix unexpected gate count increase due to Zbkb crypto extension
2024-12-19 14:00:37 +01:00
Jalali
d4b337851c
RVFI : For synchronous trap, check mcause MSB also (#2674) 2024-12-19 12:10:56 +01:00
Munail Waqar
f7dd49efa5
Adding support for Scalar Crypto Extension (Bitmanip instructions for Cryptography, Zbkb) (#2653)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Introduction
This PR adds support for Zbkb extension in the CVA6 core. It also adds the documentation for this extension. These changes have been tested with self-written single instruction tests and with the riscv-arch-tests. This PR will be followed by other PRs that will add complete support for the Zkn - NIST Algorithm Suite extension.

Implementation
Zbkb Extension:
Added support for the Zbkb instruction set. It essentially expands the Zbb extension with additional instructions useful in cryptography. These instructions are pack, packh, packw, brev8, unzip and zip.

Modifications
1. A new bit ZKN was added. The complete Zkn extension will be added under this bit for ease of use. This configuration will also require the RVB (bitmanip) bit to be set.
2. Updated the ALU and decoder to recognize and handle Zbkb instructions.

Documentation and Reference
The official RISC-V Cryptography Extensions Volume I was followed to ensure alignment with ratification. The relevant documentation for the Zbkb instruction was also added.

Verification
Assembly Tests:
The instructions were tested and verified with the K module of both 32 bit and 64 bit versions of the riscv-arch-tests to ensure proper functionality. These tests check for ISA compliance, edge cases and use assertions to ensure expected behavior. The tests include:
pack-01.S
packh-01.S
packw-01.S
brev8-01.S
unzip-01.S
zip-01.S
2024-12-18 22:35:41 +01:00
Côme
b5caf14c50
ci: use different variables for runner tags (#2673)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This allows a more grained management of CI resources.
2024-12-18 07:40:38 +01:00
Côme
a4cec295a8
csr only uses one commit port (#2671)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Only the first commit port is used by CSR.
2024-12-17 23:37:02 +01:00
Côme
c5bde40636
apply verible (#2670)
There were formatting issues in core/
2024-12-17 23:29:24 +01:00
Fatima Saleem
f4355fa49b
bug fix: canonical check on virtual address for data accesses (#2667)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
As mentioned in the spec, we need to perform a canonical check on the virtual address for instruction fetch, load, and store. If the check fails, it will cause the page-fault exception.

This PR fixes the above two:
- Changes INSTR_ACCESS_FAULT to INSTR_PAGE_FAULT
- Adding virtual address check on data accesses as well
2024-12-16 11:07:24 +01:00
Côme
fd213fc19e
cut dangerous path from flush to issue (#2666)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
serdiv is the only FLU which has a combinational path from flush_i
to the result bus
2024-12-12 19:10:26 +01:00
Jalali
66ae110a51
CVXIF Verif : Connect CVXIF new agent (#2663)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-12-11 18:29:02 +01:00
Zbigniew Chamski
ed89c717f7
[CV32A65X] Update PMPADDRn spec to make bit 0 ROCST 0. Update config files. (#2651)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Update CV32A65X-annotated privileged ISA specification to reflect the fact that with PMP granularity 8 and only supported PMP address matching modes being OFF and TOR, bit 0 of the pmpaddr0..pmpaddr7 registers can be safely made read-only zero. Update riscv-config specifications and its generated files accordingly.
2024-12-09 13:22:38 +01:00
Valentin Thomazic
5ff6b2d32e
check spike version in cva6.py (#2654)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Spike version check seems to have been commented by mistake, this pr fixes it
2024-12-05 15:29:24 +01:00
AngelaGonzalezMarino
f7eb9c1e7b
Altera apu agilex7 (#2647)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This PR is adding the APU design adapted to Altera Agilex7 FPGA.

It does not include integration in the Makefile nor automatic generation of Altera IPs, that will be the last PR of the Altera support.
2024-12-04 15:54:41 +01:00
Cra2yPierr0t
de0ebf0409
add cv64a6_imafdch_sv39 config to cva6.py (#2646)
Make cv64a6_imafdch_sv39 available from cva6.py
2024-12-04 10:27:37 +01:00
OlivierBetschi
23355d29f0
Pmp/extracted pmp master (#2528)
Extraction of the PMP outside of the MMU.
2024-12-04 10:06:36 +01:00
André Sintzoff
b5b316ad12
doc: fix build (cva6_frontend.adoc) (#2644)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
use defined adoc variable
2024-12-03 07:43:05 +01:00
AngelaGonzalezMarino
9877af5eb6
fix size of vectors when AxiNumWords=1 (#2639)
in wt_axi_adapter, axi_rd_blen and axi_wr_blen are defined like this:

logic [$clog2(AxiNumWords)-1:0] axi_rd_blen, axi_wr_blen;

However, if AxiNumWords=1, this gives a synthesis error. This happens if the cache line is set to 64 bits (same as AXI width).

It can be fixed by changing to:
logic [AxiNumWords > 1 ? $clog2(AxiNumWords) : AxiNumWords-1:0] axi_rd_blen, axi_wr_blen;
2024-12-03 07:14:29 +01:00
AngelaGonzalezMarino
ba8ac715d8
use dcache_assoc_width (#2640)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
cva6/core/cache_subsystem/wt_dcache_missunit.sv

Line 202 in b718824
 .OutWidth ($clog2(CVA6Cfg.DCACHE_SET_ASSOC)) 

Better to use the width parameter which already contemplates the case of 0 to avoid issues if associativity is set to 1
cva6/core/include/build_config_pkg.sv

Line 134 in b718824
 cfg.DCACHE_SET_ASSOC_WIDTH = CVA6Cfg.DcacheSetAssoc > 1 ? $clog2(CVA6Cfg.DcacheSetAssoc) : CVA6Cfg.DcacheSetAssoc;
2024-12-02 17:40:38 +01:00
dependabot[bot]
84e3a39dde
Bump verif/core-v-verif from b7f57c1 to 9601c80 (#2642)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Bumps [verif/core-v-verif](https://github.com/openhwgroup/core-v-verif) from `b7f57c1` to `9601c80`.
- [Release notes](https://github.com/openhwgroup/core-v-verif/releases)
- [Commits](b7f57c145c...9601c80f4c)

---
updated-dependencies:
- dependency-name: verif/core-v-verif
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: André Sintzoff <61976467+ASintzoff@users.noreply.github.com>
2024-11-29 18:03:14 +01:00
Valentin Thomazic
aa62eec15c
Provide the correct environment for doc build (#2643)
* Add riscv-isa-sim submodule

* Add cmake, bison, flex, pango, gdk-pixbuf-2.0, libgdk-pixbuf2.0-0, gdk-pixbuf-2.0, libgtk2.0-dev

* Update .readthedocs.yaml
2024-11-29 17:25:10 +01:00
Valentin Thomazic
820a8c6e01
Fix documentation build (#2641)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* Fix rtd yaml
* add rtd badge to readme
2024-11-29 14:37:50 +01:00
AngelaGonzalezMarino
b718824e1e
Altera opt 3 (#2613)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
The third optimization for Altera FPGA is to move the register file to LUTRAM. Same as before, the reason why the optimization previously done for Xilinx is not working, is that in that case asynchronous RAM primitives are used, and Altera does not support asynchronous RAM. Therefore, this optimization consists in using synchronous RAM for the register file.

The main changes to the existing code are:

Changes in ariane_regfile_fpga.sv file: The idea is the same as before, since synchronous RAM takes one clock cycle to read, we need to store the data when it is written, in case it is read right after. For this there is an auxiliary register that stores the last written data. On the read side, we need to identify if the data to be read is available in the RAM or if it is still in the auxiliary register (read after write). To compensate for the synchronous RAM delay the address is advanced one clock cycle. In this case there is a multiplexer in the output to select the block from where data is read, here we need to keep the read address for one clock cycle to select the right block when data is available.

Changes in issue_read_operands.sv file: adjust address to read from register file (when synchronous RAM is used reads take one cycle, so we advance the address). Since this address is an input, we need a new input port that brings the address in advance “issue_instr_i_prev”.

Changes in issue_stage.sv file: To connect the new input port that brings the address in advance “decoded_instr_i_prev”.

Changes in id_stage.sv file: To output the instruction to be issued before registering it (one clock cycle in advance). A new output port is needed for this “issue_entry_o_prev”

Changes in cva6.sv file: To connect the new output of the id_stage to the issue_stage to bring the address in advance to the register file (issue_entry_id_issue_prev)
2024-11-28 14:26:29 +01:00
Valentin Thomazic
dd649f28ad
Show config for smoke-bench job (#2637)
Show the config on the smoke gen dashboard report
2024-11-28 12:03:46 +01:00
Valentin Thomazic
160c322f53
improve dashboard-provided log (#2636)
* Due to the increased count of warnings, provide tail of log instead of head on the dashboard
* Add tandem yaml report file on the jobs reports
* Reduce UVM Verbosity on smoke gen tests
2024-11-28 11:46:47 +01:00
Guillaume Chauvon
7c326f5407
Fix gate simulation: Update hpdcache_sram black box (#2632)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Update hpdcache_sram black box which changed with bump of hpdcache repository
2024-11-27 14:45:15 +01:00
Valentin Thomazic
6ee7a7d0c2
CI fixes (#2634)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* Increase timeout for compliance testlist
* Switch to verilator for riscv-tests-v for faster sim
* fix reports for non tandem jobs
2024-11-27 08:00:41 +01:00
Jalali
5b1c194cb7
UVM_ENV : Clean up CVA6 UVM env (#2633)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This MR do some cleaning on the uvm env :

* fixing typo
* remove unused code
* printing in the right place
2024-11-26 15:30:48 +01:00
AEzzejjari
2157aaa926
Accelerate the performance of the AXI agent (#2631)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Accelerate the performance of the AXI agent by disabling all the randomization and sending responses with zero delay
2024-11-25 18:02:30 +01:00
André Sintzoff
f800707738
docs: update URL in CSR access DV plan (fix #2625) (#2627)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
CSR are no more described in CV32A6_Control_Status_Registers.html
2024-11-22 15:12:57 +01:00
Jalali
7eb33df0ac
Interrupt agent : Modify README also clean interrupt_pkg (#2571)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-11-21 23:59:42 +01:00
AngelaGonzalezMarino
c389382c89
Altera opt 2 (#2602)
The second optimization for Altera FPGA is to move the BHT to LUTRAM. Same as before, the reason why the optimization previously done for Xilinx is not working, is that in that case asynchronous RAM primitives are used, and Altera does not support asynchronous RAM. Therefore, this optimization consists in using synchronous RAM for the BHT.

The main changes to the existing code are:

New RAM module to infer synchronous RAM in altera with 2 independent read ports and one write port (SyncThreePortRam.sv)

Changes in the frontend.sv file: modify input to vpc_i port of BHT, by advancing the address to read, in order to compensate for the delay of synchronous RAM.

Changes in the bht.sv file: This case is more complex because of the logic operations that need to be performed inside the BHT. First, the pc pointed by bht_update_i is read from the memory, modified according to the saturation counter and valid bit, and finally written again in the memory. The prediction output is given based on the vpc_i. With asynchronous memory, the new data written via update_i is available one clock cycle after writing it. So, if vpc_i tries to read the address that was previously written by update_i, everything is fine. However, in the case of synchronous memory there are three clock cycles of latency (one for reading the pc content (read port 1), another one for writing it, and another one for reading in the other port (read port 0)). For this reason, there is the need to adapt the design to these new latency constraints:

First, there is the need for a delay on the address write of the synchronous RAM, to wait for the previous pc read and store the right modified data.

Once this is solved, similarly to the FIFO case, there is the need for an auxiliary buffer that will store the data written in the FIFO, allowing to have it available 2 clock cycles after the update_i was valid. This is because after having the correct data, the RAM takes 2 clock cycles until data can be available in the output (one clock cycle for writing and one for reading).

Finally, there is a multiplexer in the output that permits to deliver the correct prediction providing the data from the update logic (1 cycle of delay), the auxiliary register (2 cycles of delay), or the RAM (3 or more cycles of delay), depending on the delay since the update_i was valid (i.e. written to the memory).
2024-11-21 23:36:18 +01:00
Zbigniew Chamski
8a84f788d6
Increase Spike PMP granularity to 8. Update yaml spec files accordingly. (#2624)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Update riscv-config spec files and Spike Yaml file for CV32A65X.

Bump CVV to change Spike default PMP granularity to 8 and to include corresponding Spike Yaml parameter.
2024-11-21 12:19:24 +01:00
Yan
25f2f3190d
Fix $fatal system task incorrect usage (#2619)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
To fix  #2618
2024-11-20 22:22:50 +01:00
AEzzejjari
7ee22cd93a
Improving frontend documentation (#2617)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Improving frontend documentation
2024-11-20 18:56:26 +01:00
AEzzejjari
6a8d1f422e
Integrating the new version of the AXI agent (#2604)
Integrating the modifications to the AXI agent made by CEA
2024-11-20 18:55:15 +01:00
Valentin Thomazic
e571c1ced1
fix simu gate step 1: cva6.py refactor & collect report (#2621)
* cva6 refactor & cleanup to enable tandem reports generation for elf tests such as testelf for simu-gate:
   1. merge redundant functions to run directed tests in `cva6.py` (`run_c`, `run_elf`, `run_assembly` -> `run_test`)
   2. removed broken and unused functions by the way (`run_c_from_dir`, `run_assembly_from_dir`)
* collect sim reports of simu-gate job to display them in the cva6 dashboard : ⚠️ the simu gate job will still fail but the result on the dashboard will be accurate and will allow debugging
2024-11-20 18:43:22 +01:00
BRH
2f81dba77f
Fixed wrong axi signal (#2614)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-11-20 10:45:21 +01:00
Valentin Thomazic
e7f27c1300
Disable tandem on riscv-tests-v tests (#2609)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
* Disable tandem on riscv-tests-v testlist
* More relevant error message on report tandem script
Related issue: #2605
2024-11-18 23:15:59 +01:00
JeanRochCoulon
a283d3eea2
Define cv32a60x configuration (#2608)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-11-18 15:51:21 +01:00
AngelaGonzalezMarino
33c5d77bd8
Altera opt 1 (#2592)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
The first optimization for Altera FPGA is to move the instruction queue to LUTRAM. The reason why the optimization previously done for Xilinx is not working, is that in that case asynchronous RAM primitives are used, and Altera does not support asynchronous RAM. Therefore, this optimization consists in using synchronous RAM for the instruction queue and FIFOs inside wt axi adapter.

The main changes to the existing code are:

New RAM module to infer synchronous RAM in altera with independent read and write ports (SyncDpRam_ind_r_w.sv)

Changes inside cva6_fifo_v3 to adapt to the use of synchronous RAM instead of asynchronous:

When the FIFO is not empty, next data is always read and available at the output hiding the reading latency introduced by synchronous RAM (similar to fall-through approach). This is a simplification that is possible because in a FIFO we always know what is the next address to be read.

When data is read right after write, we can’t use the previous method because there is a latency to first write the data in the FIFO, and then to read it. For this reason, in the new design there is an auxiliary register used to hide this latency. This is used only if the FIFO is empty, so we detect when the word written is first word, and keep it in this register. If the next cycle comes a read, the data out is taken from the aux register. Afterwards the data is already available in the RAM and can be read continuously as in the first case.

All this is only used inf FpgaAlteraEn parameter is enabled, otherwise the previous implementation with asynchronous RAM applies (when FpgaEn is set), or the register based implementation (when FpgaEn is not set).
2024-11-15 14:34:15 +01:00
Nils Wistoff
f54b9d4152
csr_regfile: Fix S-mode traps when H extension is enabled (#2599)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
If Hypervisor extension is enabled, the logic required to properly trap
to S mode is currently excluded. Fix this by adjusting the if block.
2024-11-14 12:35:40 +01:00
JeanRochCoulon
2d9936d171
Disable superscalar for cv32a65x configuration (Enable single issue) (#2600) 2024-11-14 12:22:30 +01:00
Côme
7eb59c3e16
iro: remove an unreachable statement (#2588)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2024-11-12 20:32:40 +01:00
Côme
43edcd467e
document issue stage (#2598)
* Fill docs/design/design-manual/source/cva6_issue_stage.adoc
* Add variables to docs/design/design-manual/source/design.adoc
* Update port doc comments in core/issue_stage.sv, core/issue_read_operands.sv and core/scoreboard.sv
2024-11-12 20:28:25 +01:00
AngelaGonzalezMarino
6a86ebd2af
add CVA6ConfigFpgaAltera parameter (#2590)
First step to add FpgaAltera optimization parameter
2024-11-12 20:27:15 +01:00
AngelaGonzalezMarino
16f37b95e6
Fix issue when NrPMPEntries=0 (#2589)
Additional fix to #2392
2024-11-12 15:32:08 +01:00
Valentin Thomazic
4f5492d341
Add failure checks in report_tandem script (#2597)
Add failures checks in `.gitlab-ci/scripts/report_tandem.py`:
* catch wrong or missing log directory
* catch wrong yaml reports
2024-11-12 14:56:25 +01:00
JeanRochCoulon
7ae45e1b96
use "testelf" branch for the gate simulation (#2595)
The simu-gate ci job was broken since a while. This PR fixes it.
2024-11-12 14:55:05 +01:00
JeanRochCoulon
5bc34d73a9
Revert "csr_regfile: Fix S-mode traps when H extension is enabled (#2587)" (#2594)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This reverts commit 485c382b23.
2024-11-12 10:41:03 +01:00
Nils Wistoff
485c382b23
csr_regfile: Fix S-mode traps when H extension is enabled (#2587)
If Hypervisor extension is enabled, the logic required to properly trap to S mode is currently excluded. Fix this by adjusting the if block.
2024-11-12 08:33:13 +01:00
dependabot[bot]
67f185cac5
Bump verif/core-v-verif from 72bd7ca to f73efc4 (#2593) 2024-11-12 07:10:27 +01:00
Côme
4619a67fc6
expand glob port maps (#2585)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Expands all glob port maps in the core/ directory of this repository except the core/cache_subsystem/ directory, despite the glob port maps in core/cache_subsystem/miss_handler.sv and core/cache_subsystem/std_nbdcache.sv.

Also reorders port maps to keep the same order as port declarations.
2024-11-07 16:51:46 +01:00
Guillaume Chauvon
65285e5498
Dev/hpdcache fpga (#2586)
Set HPDCACHE as default cache for FPGA boot configuration ie. cv32a6_imac_sv32
2024-11-07 16:50:48 +01:00
Jalali
aea4e3d174
Remove compile-time define from Makefile and update core-v-verif HASH (#2584) 2024-11-07 13:46:46 +01:00
joncapltd
a48fe03f0e
New tutorial for coprocessor modification. (#2518)
This adds a tutorial on how to customise the example coprocessor with your own instructions and test them.
2024-11-07 13:45:10 +01:00
Matteo Perotti
f2d88cddc6
RVV: 🐛 fix exception propagation from Ara (#2583)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
Fix Ara's exception propagation using correct exception_t data type.
2024-11-06 23:48:28 +01:00
Zbigniew Chamski
4604195f52
[benchmarks] Pass DV_OPTS to dhrystone execution. (#2582)
ix the dhrystone execution script so that any ISS options accumulated in shell variable DV_OPTS are duly propagated to cva6.py.
2024-11-06 18:23:14 +01:00
Cesar Fuguet
6bbc1e6d35
update the hpdcache to its latest version (#2579)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-11-05 23:57:20 +01:00
Riccardo Tedeschi
01845dd76b
Initialize mock_uart signals on reset (#2580)
The former kind of signal initialization generates compilation errors using VCS to simulate the design due to multiple drivers driving those signals. Since these signals are handled inside the always_ff block, they can just be reset.
2024-11-05 17:53:48 +01:00
Valentin Thomazic
3d267f9344
refactor gitlab ci & collect full fpga build artifacts (#2576)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* refactor gitlab ci & collect full fpga build artifacts
* remove fpga log.tail from dashboard
2024-11-04 19:37:52 +01:00
JeanRochCoulon
3a9c2aa1ba
[HOT FIX] Update expected gate count result (#2574)
This gate count increase has been added by #2555. The root cause has not been found but the deviation is small, and as it impacts the merge process (the ci is red), I prefer to fix the ci.
2024-11-04 17:41:58 +01:00
Valentin Thomazic
51543db607
fix readme links (#2575)
Fix dashboard and label links in README (see #2554 )
2024-11-04 17:33:19 +01:00
Côme
9676d230fb
Mention that PR must be updated in CONTRIBUTING.md (#2568)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-11-04 12:09:41 +01:00
Côme
0687510f02
document superscalar cv32a65x (frontend + decode) (#2570)
Update the documentation of cv32a65x to make it superscalar.
This first PR only updates the documentation of the frontend and decode stages.
2024-11-04 09:29:48 +01:00
André Sintzoff
7aad781b74
doc: pmp granularity equals to 8-byte (#2572) 2024-11-04 09:27:23 +01:00
Nils Wistoff
aeb0b646bf
cache_ctrl: Generalise AXI offset generation (#2573)
For `XLEN = 64`, some tools (e.g. VCS) still elaborate the offset generation block for `XLEN = 32`, throwing an elaboration error (illegal bit access). Fix this by generating the AXI offset in an equivalent, parameter-agnostic and tool-friendly way.
2024-11-04 09:24:57 +01:00
Matteo Perotti
9e670f64c6
acc_dispatcher: don't issue instruction from buffer if flushing (#2490)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
The controller flushes the pipeline and all the unissued instructions in the presence of instructions with side effects (e.g., fence).
The accelerator dispatcher buffer (now used with the Ara RVV Vector processor) is flushed when this happens and avoids accepting a new instruction in that cycle, but it does not prevent the actual issuing of instructions during a flush cycle.
This fix avoids the issue during a flush cycle.
2024-11-01 17:04:12 +01:00
slgth
ab2283c075
doc: keep documentation in sync with the code (#2558)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
Both the ISA and design documentations use some parameters generated from the RTL (ports, parameters).
As of now, they are committed to the repository and can be out of sync with the code.

This PR removes them from the repository and freshly generates them from the code when building HTML files.

This PR also removes prebuilt HTML files (design & ISA docs) and generates them when building the top-level Read the Docs documentation (make -C docs).
2024-10-25 12:27:09 +02:00
Jean-Roch Coulon
01c636dd55 report_benchmarks.py: update results
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
61c38ea459 Install Verilator only if DV_SIMULATORS == veri-testharness 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
9ceab195fd Clean-up: Remove unused regression suites and tools from CI job scripts 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
6fc8d60c14 Dhrystone_smoke.sh: smoke-smoke is done on dhrystone for the cv32a65x configuration 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
8a457272b7 Split smoke-tests.sh into 3 tests to speed-up CI timing execution of light stage 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
ce24338d5b Run 4 iterations of coremark to improve results 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
fd6037fefe Set BHTEntries=128, cache=WT and scoreboardentries=8, Icache size=16384 to improve Coremark and Dhrystone results 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
37a9cf733b Create dedicated spike.yaml file for cv32a65x configuration. When another configuration is selected, no spike.yaml is provided to Spike, the default internal Spike configuration is used. When hwconfig is targetedi with cv32a65x as reference, cv32a65x spike.yaml is recopied into hwconfig directory. 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
9cfadbeded Create dedicated linker scripts for cv32a65x configuration. When another configuration is targeted, the default linker script is used (config/genxxx/linker/link.ld). When hwconfig is targeted, linker scripts are recopied into hwconfig directory.
Keep only one unique linker script: link.ldi. Remove test.ld file.
2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
1d0076eec3 smoke-hwconfig: run with vcs-uvm and use return0 test to speed-up CI light stage timing execution 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
8e605df1f9 Declare VLEN as new CVA6 parameter 2024-10-23 18:24:38 +02:00
Jean-Roch Coulon
4ca7a3ae38 Fix: Replace riscv_pkg:VLEN by CVA6Cfg.VLEN 2024-10-23 18:24:38 +02:00
JeanRochCoulon
45eaace82b
Revert "Multicommits to shorten smoke-tests duration, to declare VLEN as para…" (#2564)
This reverts commit 0877e8e446.
2024-10-23 18:12:49 +02:00
JeanRochCoulon
0877e8e446
Multicommits to shorten smoke-tests duration, to declare VLEN as parameter, to improve coremark results, to implement spike.yaml/linker dedicated to 65x (#2563)
- FIX: Replace riscv_pkg:VLEN by CVA6Cfg.VLEN
- Declare VLEN as new CVA6 parameter
- smoke-hwconfig: run with vcs-uvm and use return0 tests to speed-up CI light stage timing execution
- Use dedicated linker scripts for 65x configuration.
- Use dedicated spike.yaml for 65x configuration.
- Set BHTEntries=128, cache=WT, scoreboard entries=8 to improve Coremark and Dhrystone results
- Run 4 iterations of coremark to improve results
2024-10-23 17:56:06 +02:00
Anouar
20b64e8939
Performance tb (#2562)
For reminder, the option --issrun_opts="+tb_performance_mode" allows to disable UVM features like assertion and log generation to reduce simulation time.
2024-10-23 13:11:25 +02:00
Moritz Schneider
21dc824040
Fix pmpaddr read logic considering G=2 (#2469)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
fixes #2465
2024-10-23 08:54:25 +02:00
Riccardo Tedeschi
53472eb026
Move timing statement outside of always_comb block (#2552)
Fix following requirement:

The assertion included in the always_comb block apparently violates the requirements in [section 9.2.2.2.2 of the SystemVerilog standard](https://ieeexplore.ieee.org/document/10458102):

Statements in an always_comb shall not include those that block, have blocking timing or event
controls, or fork-join statements.
2024-10-23 07:32:49 +02:00
Nils Wistoff
b4d000bb77
cv64a6_imafdch_sv39_wb_config: Fix undefined parameter (#2513)
The parameter `CVA6ConfigTechnoCut` is undefined and causes elaboration
errors. Align this with the other configurations and set it to constant `0`.
2024-10-23 06:12:17 +02:00
Côme
c1c2f9d922
ci: print results in job logs (#2561)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
This modification allows:
- printing the results in the terminal
- running the script from the terminal (without the environment variables from CI)
The yaml report is only built in CI, but the results are always printed.
2024-10-22 19:03:46 +02:00
André Sintzoff
67a6ae966c
update riscv-isa-manual to riscv-isa-release-2c07aa2-2024-10-18 (#2560)
Since last riscv-isa-manual update (CVA6 commit 3059b1cb2):
        - Privileged Architecture 1.13 ratified
        - minor documentation changes
        - wavedrom file renamed to .edn
2024-10-22 14:44:02 +02:00
Côme
0bf937a772
increase code coverage in commit stage (#2555)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled
`exception_o.valid` is always 0 here because the context requires:

- `commit_ack_o[0]`
- `commit_instr_i[0].fu != CSR`

Proof.

***********************************************************
We have `commit_ack_o[0]` and `commit_instr_i[0].fu != CSR`
We need to prove `!exception_o.valid`.
***********************************************************

`exception_o.valid` is built such that:
    `exception_o.valid => !commit_drop_i[0] && (csr_exception_i.valid || commit_instr_i[0].ex.valid)`
By contraposition:
    `!(!commit_drop_i[0] && (csr_exception_i.valid || commit_instr_i[0].ex.valid)) => !exception_o.valid`
By De Morgan:
    `commit_drop_i[0] || !(csr_exception_i.valid || commit_instr_i[0].ex.valid) => !exception_o.valid`
    `commit_drop_i[0] || (!csr_exception_i.valid && !commit_instr_i[0].ex.valid) => !exception_o.valid`
    `(commit_drop_i[0] || !csr_exception_i.valid) && (commit_drop_i[0] || !commit_instr_i[0].ex.valid) => !exception_o.valid`
Goal split.

***********************************************************
We have `commit_ack_o[0]` and `commit_instr_i[0].fu != CSR`
We need to prove both:
1.`commit_drop_i[0] || !csr_exception_i.valid`
2. `commit_drop_i[0] || !commit_instr_i[0].ex.valid`
***********************************************************

`csr_exception_i.valid` is built such that (see `core/csr_regfile.sv`):
    `csr_exception_i.valid => commit_instr_i[0].fu == CSR`
By contraposition:
    `commit_instr_i[0].fu != CSR => !csr_exception_i.valid`
Because `commit_instr_i[0].fu != CSR`:
    `!csr_exception_i.valid`
By implication:
    `commit_drop_i[0] || !csr_exception_i.valid`
Goal 1 reached.

`commit_ack_o[0]` is built such that:
    `commit_ack_o[0] => commit_instr_i[0].ex.valid && commit_drop_i[0] || !commit_instr_i[0].ex_valid`
Which can be simplified (AB+!A = AB+!A(B+1) = AB+!AB+!A = (A+!A)B+!A = B+!A):
    `commit_ack_o[0] => commit_drop_i[0] || !commit_instr_i[0].ex_valid`
Because `commit_ack_o[0]`:
    `commit_drop_i[0] || !commit_instr_i[0].ex.valid`
Goal 2 reached.
Qed.
2024-10-18 07:02:07 +00:00
Zbigniew Chamski
cff48e4c75
Add tandem verification documentation (#2553)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-10-17 11:38:54 +02:00
André Sintzoff
48480c72d0 tristan doc: move files to sub-directory 2024-10-17 08:56:21 +02:00
André Sintzoff
a0f9deabff tristan: add 2024 work 2024-10-17 08:56:21 +02:00
André Sintzoff
be4a6ee364 tristan_verification_specifications.adoc: 2023 version 2024-10-17 08:56:21 +02:00
Jalali
7394941220
Interrupt verif : Implement clear mechanism in interrupt's agent (#2527)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
* INTERRUPT VERIF : Implement interrupt clear mechanism

* Interrupt Verif : Add irq_timeout to exit when we failed to write into irq_add

Also change uvm_warining to uvm_info

* Fix comment
2024-10-16 11:50:56 -04:00
AngelaGonzalezMarino
1de0da8d96
always update prediction output based on RAM content (#2549)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-10-16 16:05:48 +02:00
AEzzejjari
dff627162b
Add an option to disable AXI assertions from the command line (#2545)
The AXI assertions are enabled by default. To disable them, you need to add -issrun_opts="+uvmt_set_axi_assert_cfg=0" to the command line.
2024-10-16 08:37:40 +02:00
JeanRochCoulon
c8f2c39e48
Use uvm testbench to run gate simulations (#2548)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions
2024-10-16 07:08:59 +02:00
Anouar
9c3aea232f
Performance tb (#2543) 2024-10-11 16:57:45 +02:00
JeanRochCoulon
7ae870e02f
cv32a65x CI: Enlarge cache to increase bench result and switch from -O3 to -Os compiler option (#2541)
* .gitlab-ci.yml: Enlarge cv32a65x cache size

* Dhrystone_smoke.sh: switch from -O3 to -Os option
2024-10-11 09:42:37 +02:00
André Sintzoff
5131fb030c
doc PMP: rephrase PMP configuration description (#2540) 2024-10-11 09:12:22 +02:00
Jérôme Quévremont
0649adc0b5
Adding 10xE (#2533) 2024-10-09 17:50:31 +02:00
Guillaume Chauvon
fea98c65de
[HOTFIX] Fix Handling of CVXIF instruction being interrupted (#2537) 2024-10-09 16:34:45 +02:00
Zbigniew Chamski
2b3a82f2cc Fix CVV#2531: Make mie.MSIE and mip.MSIP RO-zero, prevent SW writes to mip. 2024-10-08 22:53:32 +02:00
Jean-Roch Coulon
b744f9bb09 Create job dedicated to benchmark CVA6 2024-10-08 21:14:33 +02:00
Jean-Roch Coulon
e7f423404f Set clock period at 20ns and fix vcs-uvm simulation time 2024-10-08 21:14:33 +02:00
Jean-Roch Coulon
2ec24264e4 Add vcs-uvm-gate ISS target 2024-10-08 21:14:33 +02:00
Cesar Fuguet
8f06d41850
Update RESOURCES.md (#2530)
Add an item pointing to the HPDcache in the related building blocks section

Co-authored-by: Jérôme Quévremont <jerome.quevremont@thalesgroup.com>
2024-10-04 18:45:34 +02:00
JeanRochCoulon
08c81658ec
Display report at the end of dhrystone and coremark executions (#2529) 2024-10-04 17:52:06 +02:00
Jérôme Quévremont
4a642d35d9
Resources and ecosystem (#2514) 2024-10-04 15:21:17 +02:00
JeanRochCoulon
51653c6377
Revert "[PMP] Extracted PMP (#2476)" (#2524)
This reverts commit 969c1518f2.
2024-10-04 07:39:35 +02:00
CoralieAllioux
969c1518f2
[PMP] Extracted PMP (#2476)
* Remove misaligned_ex computation: get it from outside

* Remove data and instr pmps, get match_execution from outside

* Get data and instr allow from outside

* Simplify fetch_instruction exception when instr not allow by pmp

* Simplify exception when data not allow by pmp, getting it from outside

* Apply verible format

* First public version of extracted pmp

* Integrate PMP fully outside MMU

* fix translation_valid and dtlb_ppn when no mmu

* Add pmp_data_if in needed file lists

* Fix exception tval when translation is enabled

* integrate no_locked assertions for pmp: now in blocking assignments to avoid raise condition in simulation

* Fix mixed assignment for no_locked_if

* Remove assertion no_locked from pmp: need clk and reset

* Apply verible format

---------

Co-authored-by: Olivier Betschi <olivier.betschi@fr.bosch.com>
2024-10-03 08:21:56 +00:00
Zbigniew Chamski
44072bfd83
[pmpcfg detailed spec] Add proposed CSR spec output. (#2522) 2024-10-02 23:32:12 +02:00
Andrea
ff01467041
Fixed btb for FPGA targets (#2521) 2024-10-02 23:31:40 +02:00
JeanRochCoulon
c6ae849f7a
put dhrystone in smoke job group and coremark in regress job group (#2520) 2024-10-01 08:56:42 +02:00
jzthales
6ccd8d8bfa
Refactor forwarding in issue_stage module (#2519) 2024-10-01 06:13:30 +02:00
JeanRochCoulon
56532c6963
Simplify CI (#2517)
Modify CI to always check with Tandem and promote UVM TB use
2024-09-27 10:01:46 +02:00
Nils Wistoff
860f47fed7
ci: Update phiwag/edatools gpg key (#2515) 2024-09-26 22:46:14 +02:00
dependabot[bot]
967fc5d021
Bump verif/core-v-verif from c3d0c72 to 4e17969 (#2512) 2024-09-24 23:24:11 +02:00
AEzzejjari
923d9c2e8f
Drive the AXI interface slave signals with 'Z in the active mode (#2511) 2024-09-24 18:24:52 +02:00
Riccardo Tedeschi
164d7c7fc9
Add AW lock register to handle W FIFO push signal (#2461) 2024-09-24 08:42:16 +02:00
Zbigniew Chamski
bc7eeb7b01
[interrupt verification] Add .uvmif support to global verif linker script (#2507) 2024-09-23 17:51:14 +02:00
Zbigniew Chamski
f974e105bf
Add a basic mechanism for interrupt acknowledge. (#2502) 2024-09-19 18:31:42 +02:00
André Sintzoff
8070febca0
spyglass: remove W528 warnings in decoder.sv (#2503) 2024-09-19 15:45:36 +02:00
Jalali
6a4af755aa
UVM environment: mcountinhibit doesn't raise an exception (#2494)
fix in UVM environment after fixed RTL bug on mcountinhibit
(commit faf4536)
2024-09-06 14:31:12 +02:00
MarioOpenHWGroup
e9382ba3ac
Bump verif/core-v-verif csr-injection (#2491)
* Bump cvv/csr-injection

* Bump core-v-verif

* [ci] try to fix the CI

* [ci] fix lint

* [ci] Fix stages

* [ci] Deprecated set-output
2024-09-04 17:39:34 +02:00
André Sintzoff
6561f2c641
report_benchmark.py: fix Dhrystone cycles after PR #2484 (#2488)
after commit 111df66 the CVA6 configuration used for Dhrystone
benchmark is rv64gc_zba_zbb_zbs_zbc instead of rv64imafdc_zicsr_zifencei

therefore the number of cycles is reduced
2024-09-02 16:39:12 +02:00
dependabot[bot]
ea3a55450b
Bump core/cache_subsystem/hpdcache from 25ffa34 to b4519e7 (#2466) 2024-08-31 08:51:52 +02:00
valentinThomazic
9362816e1c
fix simulation errors not detected on ci w/ tandem (#2486) 2024-08-30 22:23:03 +02:00
AEzzejjari
d577aaf850
Fix vcs-uvm simulation flow (#2485) 2024-08-30 17:57:35 +02:00
JeanRochCoulon
8ef28596d5
Code clean-up of the number of register address bits (#2483) 2024-08-30 17:22:53 +02:00
JeanRochCoulon
111df66d27
fix hwconfig setup in cva6.py (#2484) 2024-08-30 17:09:23 +02:00
valentinThomazic
a66efad475
fix jal riscv-arch-test (#2479) 2024-08-30 07:13:04 +02:00
AEzzejjari
668829de6e
Set the environment configuration only from env_cfg constraints. (#2408) 2024-08-29 18:00:32 +02:00
MarioOpenHWGroup
776e0137b6
[RVFI] Connect RVFI.intr to enable interrupts on TANDEM (#2475)
* [RVFI] Connect rvfi

* Lower verbosity to uvme_axi_covg
* Add unified_traps as a param for yaml
* Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-29 11:33:42 +02:00
MarioOpenHWGroup
6249bd1929
[TANDEM] CSR Params Refactor + CSR API (#2407) 2024-08-28 12:25:41 +02:00
valentinThomazic
004f819c14
Tandem for 65x (#2473) 2024-08-28 11:19:44 +02:00
Côme
0d2097be0c
Fix minstret (#2471) 2024-08-28 10:54:52 +02:00
JeanRochCoulon
faf4536b37
fix #2464: exception is not generated when INHIBIT CSR is accessed (#2468) 2024-08-27 10:38:48 +02:00
valentinThomazic
53b51ac5a7
do not use tandem on test suites in ci (#2463) 2024-08-26 23:56:51 +02:00
Côme
339d3dd851
Increase code coverage on second ALU by removing branch logic (#2362) 2024-08-26 17:32:24 +02:00
Côme
064cec2066
fix missing ZCMP condition in commit stage to increasse Code Coverage (#2459) 2024-08-24 11:48:36 +02:00
Côme
4c36aafaf0
fix CI (#2460)
* fix .gitlab-ci.yml

* Update report_tandem.py
2024-08-23 11:34:17 -04:00
EasyIP2023
37b58243fa
docs: expand wy-nav-content width to edge of screen (#2452) 2024-08-22 18:10:19 +02:00
valentinThomazic
28affa2346
[CI] use spike tandem on smoke-tests (#2438) 2024-08-22 17:04:48 +02:00
Côme
76e5b40961
fix single-step which was x in cv32a65x config and fix mcycle for double commit (#2369) 2024-08-22 12:03:20 +02:00
dependabot[bot]
12f41b52ac
Bump verif/core-v-verif from e06bd57 to 628ba12 (#2456) 2024-08-20 08:37:35 +02:00
André Sintzoff
051ba348f9
spyglass: remove WRN_1024 warnings (#2448) 2024-08-19 15:44:30 +02:00
Zbigniew Chamski
89eb77a249
[Spike tandem] Fix Yaml config files for CV32A65X. Fix Questa tandem. Add workaround for AXI end-of-test asserts. (#2436) 2024-08-19 11:09:32 +02:00
André Sintzoff
834e3e74d5
spyglass: ignore some multiple assignment W415a warnings (#2446) 2024-08-14 14:17:38 +02:00
JeanRochCoulon
d2889fa174
Display number of cycles at test termination (#2443)
Reported by RVFI_tracer module
2024-08-13 17:12:13 +02:00
André Sintzoff
e5618977d1
spyglass: move assignments in if clause as only used there (#2444) 2024-08-13 17:11:10 +02:00
Guillaume Chauvon
4f45b575aa
Add ariane_peripherals and testharness to fpga_filter (#2445) 2024-08-13 16:18:11 +02:00
Jalali
9b576c1200
Configure uvm scoreboard to fix 64 issue (#2440) 2024-08-13 09:16:54 +02:00
André Sintzoff
af4e3744d4
spyglass: remove useless assignments (#2439) 2024-08-12 15:06:39 +02:00
MarioOpenHWGroup
4b51643826
TANDEM Configuration fixes (#2420) 2024-08-09 12:34:40 +02:00
valentinThomazic
7435cb310e
fix Spyglass job falsely reporting fail (#2435) 2024-08-07 12:12:38 +02:00
André Sintzoff
3059b1cb25
update riscv-isa-manual to riscv-isa-release-5ddbdd678-2024-08-01 (#2434)
since last riscv-isa-manual update (CVA6 commit 0bd8b8693)
2024-08-07 11:52:07 +02:00
xiaoweish
0c60bc6e3d
Add debug_test to cva6 (#2339) 2024-08-02 08:50:50 +02:00
JeanRochCoulon
ce4b25c51a
[HOT FIX] fix is_inside_execute (#2429)
fix #2385
2024-08-02 08:42:11 +02:00
JeanRochCoulon
14fd617455
Fix expected_synth.yml (#2428)
Difficult to adjust it all the time !
2024-08-02 06:47:03 +02:00
Jalali
2e0a202440
Add check CSR counter in UVM scoreboard (#2427) 2024-08-02 00:20:47 +02:00
Asmaa Kassimi
12be3adb81
Solve some of W240 and W415a warnings increased by PMP entries (#2415) 2024-08-01 18:43:13 +02:00
Guillaume Chauvon
81671e39fa
Fixes and Update CVXIF non regression tests, regression and TB (#2424) 2024-08-01 16:06:24 +02:00
dependabot[bot]
6269f72b63
Bump verif/core-v-verif from bd42aee to e06bd57 (#2422) 2024-07-30 15:09:37 +02:00
Asmaa Kassimi
d4b62d7372
automate lint check process (#2414) 2024-07-30 09:22:13 +02:00
Zbigniew Chamski
4e9abb284c
[cv32a65x] Remove unsupported Zifencei from riscv-config ISA string. (#2419) 2024-07-30 09:20:33 +02:00
dependabot[bot]
bed9a17880
Bump verif/core-v-verif from 1e7f049 to bd42aee (#2418) 2024-07-30 07:08:21 +02:00
Zbigniew Chamski
8dcdf8fb56
[riscv-config] Add memory map entry to platform schema and to CV32A65X platform spec. (#2411) 2024-07-26 23:50:51 +02:00
slgth
6a649d6515
docs: more fixes (#2412) 2024-07-26 23:49:41 +02:00
slgth
2249202769
docs: multiple fixes (#2409) 2024-07-26 15:27:42 +02:00
AbdessamiiOukalrazqou
a4583a6e4d
[gen_from_riscv_config] improve readme file to support debug spec (#2406) 2024-07-26 15:25:54 +02:00
valentinThomazic
934823d89c
Add custom config in gitlab ci (#2405) 2024-07-26 15:04:40 +02:00
Guillaume Chauvon
211af02e5e
Separate RAW and WAW process to fix CVXIF with Superscalar (#2395) 2024-07-26 14:58:18 +02:00
Zbigniew Chamski
96b0508525
[riscv-config] Update PMP definitions in cv32q65x spec (#2401) 2024-07-25 22:06:51 +02:00
AbdessamiiOukalrazqou
b438a8ba8e
[gen_from_riscv_config] Improve the tool to support debug spec (#2398) 2024-07-25 20:07:45 +02:00
slgth
e9648eaf8c
Design documentation: AsciiDoc conversion (#2399) 2024-07-25 17:18:27 +02:00
Moritz Schneider
fd489a16fb
Fix off by one error in PMP length (#2394) 2024-07-25 12:08:53 +02:00
Asmaa Kassimi
631513eda8
Add RVU condition to increase coverage (#2396) 2024-07-25 12:03:38 +02:00
Somya Dashora
1e48237a7a
Update csr_regfile.sv to fix #2373 (#2374) 2024-07-25 09:54:13 +02:00
slgth
3deb95af21
cv64a6_mmu: add RISC-V ISA documentation to main page (#2393) 2024-07-25 08:37:27 +02:00
CoralieAllioux
335c91cc08
[Xcelium flow] Xrun compile fixes (#2389) 2024-07-25 07:37:43 +02:00
Asmaa Kassimi
4c48a60804
increase condition coverage in lsu, issue and commit stages (#2391) 2024-07-25 07:37:21 +02:00
Zbigniew Chamski
846e1a1269
[CI DEBUG] Track cause of failures in Spike version check. (#2360) 2024-07-24 23:56:04 +02:00
Côme
4ff16f9da3
set WtDcacheWbufDepth to 8 (#2390) 2024-07-24 23:54:26 +02:00
Asmaa Kassimi
14be0af7f0
solve simple lint errors (#2388) 2024-07-24 12:09:25 +02:00
dependabot[bot]
7181278223
Bump verif/core-v-verif from 20c2d30 to f42effb (#2381) 2024-07-23 23:21:25 +02:00
Jalali
118f353f54
Exclude page fault exceptions if mmu isn't supported (#2387) 2024-07-23 19:40:49 +02:00
JeanRochCoulon
04ebfbd713
Disable PMA execute and nonidempotent features (#2385) 2024-07-23 15:57:22 +00:00
valentinThomazic
d4809a7e2b
change required dhrystone cycles count value (#2386) 2024-07-23 17:55:43 +02:00
Côme
2acf5ba407
fix ex_stage synthesis (#2384) 2024-07-23 14:09:01 +02:00
AEzzejjari
4b2b6e2983
Enable HPDcache in the UVM config (#2379) 2024-07-22 22:53:15 +02:00
AbdessamiiOukalrazqou
aa4ced4a8a
[gen_from_riscv_config] improve readme file and requirements file to support spike (#2380) 2024-07-22 18:04:53 +02:00
valentinThomazic
77c6cc328d
fix CI regression testlists (#2378) 2024-07-22 17:29:25 +02:00
Côme
4a223bee46
decorrelate instr and addr depths in IQ (#2375) 2024-07-22 14:22:56 +02:00
JeanRochCoulon
8d413b7c54
doc PMA: cv32a65x is always idempotent and without caches (#2377) 2024-07-22 11:15:06 +00:00
dependabot[bot]
95049c4a3d
Bump verif/core-v-verif from 66cd091 to 20c2d30 (#2367) 2024-07-22 10:23:52 +02:00
AbdessamiiOukalrazqou
5f8605838e
[gen_from_riscv_config] fix access issues for PMP registers, improve Factorization algorithm , improve csr_updater.yaml, add spike support (#2372) 2024-07-21 22:39:50 +02:00
André Sintzoff
8c70976759
docs: use correct commit for riscv-isa-manual submodule (#2368)
fix after 8fa590b5c
2024-07-15 12:42:07 +00:00
Jalali
6c0e3f82c5
Verif: Add load hazard instructions (#2354) 2024-07-15 12:39:52 +00:00
Asmaa Kassimi
8aa0f634f6
condition load and store modules (#2349) 2024-07-13 09:32:51 +02:00
Jérôme Quévremont
c4b4216981
Update cva6_requirements_specification.rst (#2364)
Specify CV-X-IF version supported: 1.0.0.
Mention of B extension (with includes the Zb* extensions, already in the specification).
Make FENCE.T as a "should" instead of "shall" as we do not have plans to integrate it yet.
2024-07-12 18:14:26 +02:00
Côme
0cbd894a7a
update port and config docs (#2363) 2024-07-12 17:00:36 +02:00
jzthales
71653038d7
Doc lsu (#2359) 2024-07-12 16:49:02 +02:00
Jalali
da1c7477ed
Increase simulation time on CSR tests (#2361) 2024-07-12 16:21:04 +02:00
valentinThomazic
e53c669df1
Enable tandem on smoke-gen tests in ci (#2357) 2024-07-12 16:05:02 +02:00
Zbigniew Chamski
3e62b0b910
[Spike Yaml] HOTFIX: Add libyaml-cpp to preload list of RTL simulators. (#2358) 2024-07-12 11:52:01 +02:00
Guillaume Chauvon
8fa590b5c3
CVXIF 1.0.0 (#2340) 2024-07-12 10:53:18 +02:00
Côme
5fcc39dbee
remove round interval (#2353) 2024-07-11 17:35:03 +02:00
Mathieu Gouttenoire
18bfc238f9
Change sh to bash in toolchain-builder README (#2355) 2024-07-11 15:44:56 +02:00
Zbigniew Chamski
48ef515ba0
[Spike Yaml] Integrate Spike Yaml support. (#2304) 2024-07-11 08:37:37 +02:00
Côme
2dcb7417b4
make cv32a65x superscalar (#2348) 2024-07-10 23:33:49 +02:00
Asmaa Kassimi
214444cc93
csr_regfile lint error fix (#2346) 2024-07-10 13:13:26 +02:00
Jalali
dc9dc150e7
Increase supported PMP entries in UVM testbench (#2344) 2024-07-10 11:54:29 +02:00
JeanRochCoulon
58d490b461
Update PMP entry number from 16 to 64 (#2343) 2024-07-10 09:54:16 +00:00
Asmaa Kassimi
d9a7fdb836
condition branch_unit and alu (#2342) 2024-07-10 11:02:18 +02:00
LQUA
f44655809f
Add CV64A6_MMU core in user manual (#2324) 2024-07-09 16:49:31 +02:00
valentinThomazic
c50012ac76
Remove duplicate and out of date infos on verif readme (#2338) 2024-07-09 16:48:37 +02:00
Moritz Schneider
b6a3aa1b03
Fix non-standard usage of SystemVerilog (#2336)
Strings cannot be initially assigned to an integer without a cast.
2024-07-09 10:39:52 +02:00
dependabot[bot]
7c351b3c8e
Bump verif/core-v-verif from 1173e7e to 2d9f96e (#2337) 2024-07-09 07:24:09 +02:00
Isaar Ahmad
0c58e39987
Update README.md : Updated gcc-toolchain-builder path (#2332) 2024-07-06 18:54:53 +02:00
Côme
37d93a3758
superscalar: do not issue CSR with another instruction (#2329) 2024-07-05 23:49:44 +02:00
André Sintzoff
51114ee0a1
machine.adoc: add missing table (#2331)
For CVA6, add table:
Encoding of A field in PMP configuration registers
2024-07-05 23:49:20 +02:00
Moritz Schneider
6044454a07
Fix index calculation for PMPCFG CSR write logic (#2330) 2024-07-05 22:56:27 +02:00
Asmaa Kassimi
67dba2cad3
condition csr_regfile.sv (#2310) 2024-07-05 14:14:01 +02:00
Côme
4df49a6b0f
superscalar: make SuperscalarEn a CVA6Cfg attribute (#2322) 2024-07-05 14:09:48 +02:00
valentinThomazic
051a2f94ff
Retry FPGA boot in CI when failed (#2325) 2024-07-05 12:06:42 +02:00
André Sintzoff
0bd8b8693a
update riscv-isa-manual to riscv-isa-release-ebf2e3a0b-2024-07-03 (#2323)
since last riscv-isa-manual update (CVA6 commit 105d3601b):
- minor documentation changes
- use of docs-resources submodule inside riscv-isa-manual
- requires asciidoctor-lists
2024-07-05 12:06:16 +02:00
Jalali
2616d5e649
add UVM interrupt agent (#2309) 2024-07-05 11:54:34 +02:00
Guillaume Chauvon
9900d5fd19
Fix benchmark.sh with correct GCC options and order (#2313) 2024-07-05 11:52:27 +02:00
Moritz Schneider
246961b3c3
Increase max num PMPs to 64 (#2279) 2024-07-04 14:09:37 +02:00
Mathieu Gouttenoire
d98ac1490a
New toolchain builder script for GCC and LLVM (#2320)
* Move build-toolchain.sh

* New toolchain builder script for GCC and LLVM
2024-07-04 09:46:41 +02:00
LQUA
66caecdfe6
Add RISCV documentation for cv64a6_mmu (#2315) 2024-07-03 17:24:07 +02:00
Jalali
702fedf23f
Fix issue #2479 #2468 (#2318) 2024-07-03 17:14:15 +02:00
Asmaa Kassimi
ace1643e91
Add lambda function to sort lint summary according to severity (#2316) 2024-07-03 16:46:30 +02:00
Jalali
f18bac51b3
Bump CVV to fix issue 2484 (#2302) 2024-07-02 17:41:23 +02:00
Jalali
9ebe42f033
Add illegal instruction to cover corner case in decoder (#2307) 2024-07-02 17:40:45 +02:00
Asmaa Kassimi
3874c41320
fix lint errors in csr_regfile.sv (#2306) 2024-07-02 15:36:04 +02:00
dependabot[bot]
0721ebb609
Bump verif/core-v-verif from 0e97e74 to 4531071 (#2305) 2024-07-02 08:23:22 +02:00
Côme
636e6aff47
superscalar add second ALU (#2303) 2024-06-30 18:24:11 +02:00
Zbigniew Chamski
aa5d7f8217
Bump CVV to use improved scoreboard reporting in tandem simulations. (#2301) 2024-06-28 15:28:07 +02:00
Côme
ce1e889716
update expected area (#2299) 2024-06-28 15:02:58 +02:00
Guillaume Chauvon
ced13a56b1
Fix typo on Bitmanip comment (#2300) 2024-06-28 15:01:50 +02:00
Jalali
33ab2efa83
Makefile : passing the tandem_enable value into UVM testbench (#2287) 2024-06-26 23:02:46 +02:00
xiaoweish
88f13c5874
Update uvml_mem use for core-v-verif's PR: 2480/2481/2482 (#2295) 2024-06-26 23:00:57 +02:00
xiaoweish
398778a1ba
Add vcs -full64 option back (#2294) 2024-06-26 22:58:55 +02:00
MarioOpenHWGroup
3f62e343fb
CI: Hash all the core-v-verif folder (#2296) 2024-06-26 20:51:58 +02:00
JeanRochCoulon
21383ce16d
Fix mstatus.mpp in relation to the possible legal values (#2285) 2024-06-21 17:27:48 +02:00
AbdessamiiOukalrazqou
ee0847e30a
[gen_from_riscv_config] add custom-gen.yaml support / fix hyperlinks in csr design doc / improve readme/fix csr_updater.yaml (#2286) 2024-06-21 17:19:42 +02:00
Moritz Schneider
fe1a19fca7
Fix WARL behavior of MPP (#2283)
Related to #2274
2024-06-21 14:38:57 +02:00
André Sintzoff
21733e55d7
decoder.sv: add checks for some B instructions (fix #2276) (#2282) 2024-06-21 10:54:10 +02:00
Côme
96ae8ed223
superscalar: allow speculative instructions (#2278) 2024-06-20 15:55:56 +02:00
Michael Platzer
318be6dcde
Use correct fault type for VLSU overflow (#2273) 2024-06-19 21:31:00 +02:00
André Sintzoff
89568b0c10
doc: clarify mtval register description when not enabled (#2271) 2024-06-19 13:00:33 +02:00
Zbigniew Chamski
17ea49439f
[riscv-config] Update riscv-config tool, CV32A65X specs and the rendering of CSRs. (#2270) 2024-06-19 12:08:15 +02:00
Gregor Haas
c92245b20b
Implement simple uart-based updater for the bootrom (#2267) 2024-06-19 11:24:01 +02:00
Cesar Fuguet
9df64701bd
Update submodule core/cache_subsystem/hpdcache (#2265) 2024-06-18 11:54:35 +02:00
MarioOpenHWGroup
c78ede91f9
Bump CVV 2465 and adapt cva6pkg (#2263) 2024-06-17 16:49:10 +02:00
xiaoweish
c93587b1f9
Update UART submodule to version 0.2.1 and Use SV UART in vcs-testharness (#2196) 2024-06-17 09:24:18 +02:00
AngelaGonzalezMarino
db088159eb
Mmu design document (#2117) 2024-06-17 09:23:44 +02:00
slgth
802066bfd3
docs: move riscv-isa-manual outside of cv32a65x documentation (#2264) 2024-06-16 23:20:41 +02:00
JeanRochCoulon
7e8e2c931f
Fix CSR chapter insertion and rename Design Doc names (remove "for cv32a65x") (#2262) 2024-06-14 15:39:22 +02:00
CoralieAllioux
205872acc6
Fix initialization of memory array in simulation (#2259) 2024-06-14 14:34:08 +02:00
CoralieAllioux
3ed5e78c91
[Xcelium flow] xrun testharness rules (#2223) 2024-06-14 14:31:56 +02:00
Jalali
212c14e4b4
CSR verification : modify coverage based on new specification (#2261) 2024-06-14 14:01:23 +02:00
JeanRochCoulon
d83b3f6ffd
Execute SpyGlass lint job only when RTL is modified (#2255) 2024-06-14 09:19:06 +00:00
Mathieu Gouttenoire
3d00079c19
Prepare for LLVM (#2251) 2024-06-14 11:12:03 +02:00
AbdessamiiOukalrazqou
3fccfba900
[gen_from_riscv_config]modify csr updater.py /fix-2191 , modify csr_updater.yaml (#2258) 2024-06-14 10:51:37 +02:00
slgth
e3943f5913
cv64a6_mmu: set NrPMPEntries to 16 (fixes #2244) (#2248) 2024-06-14 10:05:35 +02:00
JeanRochCoulon
cb6211bbb8
Remove cv32a6_embedded configuration (#2246) 2024-06-14 08:30:17 +02:00
JeanRochCoulon
e26267b220
[HOT FIX] fix synthesis job (#2256)
Fix read_section_sv type
2024-06-14 08:26:06 +02:00
Asmaa Kassimi
77264cd572
add spyglass waiver file to waive ErrorAnalyzeBBox error (#2254) 2024-06-13 16:54:54 +02:00
André Sintzoff
105d3601b6
update riscv-isa-manual to riscv-isa-release-c8c8075-2024-06-12 (#2253) 2024-06-13 16:45:04 +02:00
AngelaGonzalezMarino
8164828913
Fix instruction realign when C extension is not used (#2241) 2024-06-13 11:17:25 +02:00
slgth
b1850a8cb7
docs: fix spec_builder.py (#2249) 2024-06-12 20:07:22 +02:00
André Sintzoff
361b17e7b0 cv32a65x doc: fix RISC-V unpriv pdf generation
issue introduced in 718c4e23

Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2024-06-12 11:32:36 +02:00
André Sintzoff
d5b7cc77ff cv32a65x doc: split unpriv and priv HTML pages
Signed-off-by: André Sintzoff <andre.sintzoff@thalesgroup.com>
2024-06-12 11:18:31 +02:00
Coralie Allioux
6c0cf186fc Fix ALL_SIMV_UVM_FLAGS auto-merge 2024-06-12 11:16:18 +02:00
Coralie Allioux
2c48fccb52 Remove unused variables 2024-06-12 11:16:18 +02:00
Coralie Allioux
fa2a676007 Fix incdir for uvme and uvmt + fix dpi lib 2024-06-12 11:16:18 +02:00
isabelle schmid
36098bf827 Correct uvme and uvmt path 2024-06-12 11:16:18 +02:00
isabelle schmid
fa9a36860c Add xrun-testharness support 2024-06-12 11:16:18 +02:00
Coralie Allioux
27aab922b9 Fix tohost_addr: RISCV bin must be more generic 2024-06-12 11:16:18 +02:00
isabelle schmid
4e2baff507 Fix tohost_addr and xrun flags 2024-06-12 11:16:18 +02:00
isabelle schmid
dec70a18c5 Make it compliant with new DPI build 2024-06-12 11:16:18 +02:00
isabelle schmid
db6e0c9696 Add xcelium flow 2024-06-12 11:16:18 +02:00
isabelle schmid
c36837142f Add xrun-testharness 2024-06-12 11:01:15 +02:00
isabelle schmid
27836559ae Add xrun-uvm options 2024-06-12 11:01:15 +02:00
CoralieAllioux
28e94e5ce3
[Xcelium flow] Clean DPI void function import (#2222) 2024-06-12 09:45:33 +02:00
CoralieAllioux
367fe5850a
[Xcelium flow] corev dv yaml (#2210) 2024-06-12 09:44:44 +02:00
Akiho Kawada
bc7149adc7
refactor hpdcache_cache_subsystem module code to ease reutilization (#2173) 2024-06-11 23:12:30 +02:00
slgth
f57a6c0106
Move CV32A65X documentation into its own chapter (#2236) 2024-06-11 18:01:25 +02:00
JeanRochCoulon
4391fc4b14
Use cv32a6_imac_sv32 to generate FPGA bitstream (#2229) 2024-06-11 16:25:07 +02:00
André Sintzoff
546a8c26da
csr_regfile.sv: if no U-mode, mstatus.tw is read-only 0 (fix #2228) (#2233) 2024-06-11 15:08:28 +02:00
JeanRochCoulon
91871d97f3
Update functionality.rst (#2235) 2024-06-11 12:31:52 +02:00
JeanRochCoulon
2266f75f2d
MTVAL is read-only zero when TvalEn = 0 (#2231) 2024-06-11 11:22:41 +02:00
JeanRochCoulon
9d02734bd1
Fix PMPCFG number (from 8 to 4, from which 2 are read-only zero) (#2232) 2024-06-11 11:15:27 +02:00
André Sintzoff
afb3265296
csr_regfile.sv: if no U-mode, mcounteren does not exist (fix #2221) (#2227) 2024-06-10 21:42:00 +02:00
JeanRochCoulon
7ccf82ce76
Add param to enable/disable Zihpm and Zicntr extensions for 65x (#2208) 2024-06-10 15:14:03 +02:00
JeanRochCoulon
dc000d6c37
Define a new param to constraint mtvec to be in direct mode only (#2226) 2024-06-10 11:59:54 +00:00
Jalali
feb35f2b88
Fix Csr instruction decode and change the message verbosity (#2225) 2024-06-10 13:22:05 +02:00
Côme
eac60af1a9
superscalar: add a second issue port (#2209) 2024-06-09 20:47:09 +02:00
dependabot[bot]
424eca6f63
Bump verif/core-v-verif from b92d30f to 835720b (#2215) 2024-06-09 20:40:00 +02:00
Mathieu Gouttenoire
ade4c85e13
Remove extra -v in smoke-tests.sh (#2207) 2024-06-06 16:51:17 +02:00
Zbigniew Chamski
592487ffa0
[riscv-config] Align CV32A65X spec on adoc, cleanup defs. Fix CSR updater. (#2206) 2024-06-06 11:19:41 +02:00
708 changed files with 87072 additions and 52179 deletions

View file

@ -17,6 +17,12 @@ jobs:
with:
submodules: recursive
- name: Get specific submodule hash
id: core-v-submodule-hash
run: |
cd verif/core-v-verif
echo "hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Cache toolchain
id: cache-toolchain
uses: actions/cache@v3
@ -42,9 +48,7 @@ jobs:
cache-name: cache-spike
with:
path: tools/spike/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/**/*',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/*') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh')}}-${{ steps.core-v-submodule-hash.outputs.hash }}
- name: Prepare
run: |
@ -59,12 +63,15 @@ jobs:
strategy:
matrix:
testcase: [ cv64a6_imafdc_tests ]
config: [ cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdc_sv39_wb, cv64a6_imafdc_sv39 ]
config: [ cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdc_sv39_hpdcache_wb, cv64a6_imafdc_sv39_wb, cv64a6_imafdc_sv39 ]
simulator: [ veri-testharness ]
include:
- testcase: dv-riscv-arch-test
config: cv64a6_imafdc_sv39_hpdcache
simulator: veri-testharness
- testcase: dv-riscv-arch-test
config: cv64a6_imafdc_sv39_hpdcache_wb
simulator: veri-testharness
needs:
build-riscv-tests
steps:
@ -72,6 +79,12 @@ jobs:
with:
submodules: recursive
- name: Get specific submodule hash
id: core-v-submodule-hash
run: |
cd verif/core-v-verif
echo "hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Cache toolchain
id: cache-toolchain
uses: actions/cache@v3
@ -97,9 +110,7 @@ jobs:
cache-name: cache-spike
with:
path: tools/spike/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/**/*',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/*') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh')}}-${{ steps.core-v-submodule-hash.outputs.hash }}
- name: Run Tests
run: |
@ -134,6 +145,12 @@ jobs:
with:
submodules: recursive
- name: Get specific submodule hash
id: core-v-submodule-hash
run: |
cd verif/core-v-verif
echo "hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Cache toolchain
id: cache-toolchain
uses: actions/cache@v3
@ -159,9 +176,7 @@ jobs:
cache-name: cache-spike
with:
path: tools/spike/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/**/*',
'verif/core-v-verif/vendor/riscv/riscv-isa-sim/*') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('verif/regress/install-spike.sh')}}-${{ steps.core-v-submodule-hash.outputs.hash }}
- name: Run Tests
run: |

View file

@ -21,3 +21,4 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
files: '$(find core -regex ".*\.\(v\|sv\)$" | grep -v "^core/include/.*_config_pkg.sv$")'
fail_on_formatting_suggestions: true

6
.gitignore vendored
View file

@ -1,3 +1,5 @@
*.swp
*.swo
site/*
*.ucdb
covhtmlreport/*
@ -45,8 +47,8 @@ __pycache__
.bender/
Bender.lock
/tools/
/util/gcc-toolchain-builder/src/
/util/gcc-toolchain-builder/build/
/util/toolchain-builder/src/
/util/toolchain-builder/build/
# Both following lines are needed to list contents of ISA manual build dir.
!/vendor/riscv/riscv-isa-manual/build/
!/vendor/riscv/riscv-isa-manual/build/*

View file

@ -25,6 +25,10 @@ include:
- project: '$CI_PROJECT_NAMESPACE/setup-ci'
ref: '$SETUP_CI_CVV_BRANCH'
file: 'cva6/core-v-verif-cva6.yml'
- local: '.gitlab-ci-custom.yml'
rules:
- exists:
- '.gitlab-ci-custom.yml'
workflow:
rules:
@ -34,6 +38,9 @@ workflow:
- if: $CI_COMMIT_BRANCH == "master"
variables:
CI_KIND: regress
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
CI_KIND: regress
- if: $CI_COMMIT_BRANCH =~ /.*_PR_.*/
variables:
CI_KIND: dev
@ -49,7 +56,7 @@ variables:
DV_TARGET: cv32a65x
default:
tags: [$TAGS_RUNNER]
tags: [$TAGS_RUNNER_SIMU]
artifacts:
when: always
paths:
@ -65,6 +72,7 @@ stages:
.setup_job:
stage: setup
tags: [$TAGS_RUNNER]
variables:
GIT_SUBMODULE_STRATEGY: none
rules: &on_dev
@ -107,28 +115,32 @@ build_tools:
- mkdir -p artifacts/tools/
- mv tools/spike artifacts/tools/
.copy_spike_artifacts: &copy_spike_artifacts
- mkdir -p tools
- mv artifacts/tools/spike tools
- /sbin/ldconfig -N tools/spike/lib
.fe_smoke_test:
stage: light tests
rules: *on_dev
before_script:
- git -C verif/core-v-verif fetch --unshallow
- mkdir -p tools
- mv artifacts/tools/spike tools
- git -C verif/core-v-verif fetch --unshallow || git -C verif/core-v-verif fetch --all
- !reference [.copy_spike_artifacts]
- rm -rf artifacts/
- mkdir -p artifacts/{reports,logs}
- python3 .gitlab-ci/scripts/report_fail.py
- echo $SYN_VCS_BASHRC; source $SYN_VCS_BASHRC
.simu_after_script: &simu_after_script
- for i in $(find verif/sim/out*/[vq]*_sim -type f \( -name "*.csv" -o -name "*.iss" \)) ; do head -10000 $i > artifacts/logs/$(basename $i).head ; done
- head -10000 verif/sim/logfile.log > artifacts/logs/logfile.log.head
- python3 .gitlab-ci/scripts/report_simu.py verif/sim/logfile.log
- for i in $(find verif/sim/out*/[vq]*_sim -type f \( -name "*.csv" -o -name "*.iss" -o -name "*.yaml" \)) ; do tail -10000 $i > artifacts/logs/$(basename $i) ; done
- tail -10000 verif/sim/logfile.log > artifacts/logs/logfile.log
- if [ -n "$SPIKE_TANDEM" ]; then python3 .gitlab-ci/scripts/report_tandem.py verif/sim/out*/"$DV_SIMULATORS"_sim; else python3 .gitlab-ci/scripts/report_simu.py verif/sim/logfile.log; fi
smoke:
smoke-tests:
extends:
- .fe_smoke_test
variables:
DASHBOARD_JOB_TITLE: "Smoke test $DV_SIMULATORS"
DASHBOARD_JOB_TITLE: "Smoke test $DV_SIMULATORS $DV_TARGET"
DASHBOARD_JOB_DESCRIPTION: "Short tests to challenge most architectures with most testbenchs configurations"
DASHBOARD_SORT_INDEX: 0
DASHBOARD_JOB_CATEGORY: "Basic"
@ -136,17 +148,16 @@ smoke:
COLLECT_SIMU_LOGS: 1
parallel:
matrix:
- DV_SIMULATORS:
- "veri-testharness,spike"
- "vcs-testharness,spike"
- "questa-testharness,spike"
- "vcs-uvm,spike"
- DV_SIMULATORS: ["vcs-testharness", "questa-testharness"]
DV_TARGET: ["cv32a6_imac_sv32", "cv64a6_imafdc_sv39"]
- DV_SIMULATORS: "vcs-uvm"
DV_TARGET: "cv32a65x"
script:
- source $QUESTA_BASHRC
- bash verif/regress/smoke-tests.sh
- if [[ $DV_SIMULATORS == *"questa"* ]]; then source $QUESTA_BASHRC; fi
- bash verif/regress/smoke-tests-$DV_TARGET.sh
- !reference [.simu_after_script]
gen_smoke:
smoke-gen:
extends:
- .fe_smoke_test
variables:
@ -154,25 +165,34 @@ gen_smoke:
DASHBOARD_JOB_DESCRIPTION: "Short generated tests to challenge the CVA6-DV on STEP1 configuration"
DASHBOARD_SORT_INDEX: 0
DASHBOARD_JOB_CATEGORY: "Basic"
DV_SIMULATORS: "vcs-uvm,spike"
DV_SIMULATORS: "vcs-uvm"
COLLECT_SIMU_LOGS: 1
SPIKE_TANDEM: 1
script:
- bash verif/regress/smoke-gen_tests.sh
- cp verif/sim/seedlist.yaml artifacts/logs/
- cp verif/sim/uvm_seed.log artifacts/logs/
- !reference [.simu_after_script]
coremark:
smoke-bench:
extends:
- .fe_smoke_test
variables:
DASHBOARD_JOB_TITLE: "CoreMark"
DASHBOARD_JOB_TITLE: "smoke-bench $DV_TARGET"
DASHBOARD_JOB_DESCRIPTION: "Performance indicator"
DASHBOARD_SORT_INDEX: 5
DASHBOARD_JOB_CATEGORY: "Performance"
SPIKE_TANDEM: 1
BENCH: "dhrystone"
parallel:
matrix:
- DV_TARGET: "cv32a60x"
- DV_TARGET: "cv32a65x"
script:
- bash verif/regress/coremark.sh --no-print
- python3 .gitlab-ci/scripts/report_benchmark.py --coremark verif/sim/out_*/veri-testharness_sim/core_main.*.log
- bash verif/regress/"$BENCH"_smoke.sh --no-print
- python3 .gitlab-ci/scripts/report_benchmark.py --"$BENCH"_"$DV_TARGET" verif/sim/out_*/vcs-uvm_sim/"$BENCH"_main.*.log
hwconfig:
smoke-hwconfig:
extends:
- .fe_smoke_test
variables:
@ -180,29 +200,14 @@ hwconfig:
DASHBOARD_JOB_DESCRIPTION: "Short tests to challenge target configurations"
DASHBOARD_SORT_INDEX: 1
DASHBOARD_JOB_CATEGORY: "Basic"
DV_SIMULATORS: "veri-testharness,spike"
DV_HWCONFIG_OPTS: "cv32a60x"
DV_SIMULATORS: "vcs-uvm"
SPIKE_TANDEM: 1
DV_TARGET: "hwconfig"
DV_HWCONFIG_OPTS: "cv32a65x"
script:
- source verif/regress/hwconfig_tests.sh
- python3 .gitlab-ci/scripts/report_pass.py
spyglass:
extends:
- .fe_smoke_test
variables:
DV_TARGET: cv32a65x
DASHBOARD_JOB_TITLE: "Report Spyglass Lint Errors"
DASHBOARD_JOB_DESCRIPTION: "Report lint errors and warnings detected by Spyglass"
DASHBOARD_SORT_INDEX: 5
DASHBOARD_JOB_CATEGORY: "Lint Check"
script:
- echo $SYN_SG_BASHRC; source $SYN_SG_BASHRC
- mkdir -p artifacts/lint_reports
- make -C spyglass design_read
- make -C spyglass lint_check
- mv spyglass/sg_run_results/cva6_sg_reports/cva6_lint_lint_rtl artifacts/lint_reports
- python3 .gitlab-ci/scripts/report_spyglass_lint.py spyglass/reference_summary.rpt artifacts/lint_reports/cva6_lint_lint_rtl/summary.rpt
.synthesis_test:
stage: heavy tests
timeout: 2 hours
@ -220,9 +225,42 @@ spyglass:
- when: manual
allow_failure: true
spyglass:
extends:
- .synthesis_test
variables:
DV_TARGET: cv32a65x
DASHBOARD_JOB_TITLE: "Report Spyglass Lint Errors"
DASHBOARD_JOB_DESCRIPTION: "Report lint errors and warnings detected by Spyglass"
DASHBOARD_SORT_INDEX: 5
DASHBOARD_JOB_CATEGORY: "Lint Check"
script:
- echo $SYN_SG_BASHRC; source $SYN_SG_BASHRC
- mkdir -p artifacts/lint_reports
- make -C spyglass design_read
- make -C spyglass lint_check
- mv spyglass/sg_run_results/cva6_sg_reports/cva6_lint_lint_rtl artifacts/lint_reports
- cp spyglass/reference_summary.rpt artifacts/lint_reports
- python3 .gitlab-ci/scripts/report_spyglass_lint.py spyglass/reference_summary.rpt artifacts/lint_reports/cva6_lint_lint_rtl/summary.rpt
cvxif-regression:
extends:
- .synthesis_test
variables:
DASHBOARD_JOB_TITLE: "CVXIF non-regression test $DV_SIMULATORS"
DASHBOARD_JOB_DESCRIPTION: "Short tests to challenge most CoreV-X-Interface in testharness"
DASHBOARD_SORT_INDEX: 5
DASHBOARD_JOB_CATEGORY: "Basic"
COLLECT_SIMU_LOGS: 1
script:
- bash verif/regress/cvxif_verif_regression.sh
- if [[ $DV_SIMULATORS == *"spike"* ]]; then unset SPIKE_TANDEM; fi # dirty hack to do trace comparison between tandem execution and spike standalone
- !reference [.simu_after_script]
asic-synthesis:
extends:
- .synthesis_test
tags: [$TAGS_RUNNER_SYNTH]
variables:
DASHBOARD_JOB_TITLE: "ASIC Synthesis $DV_TARGET"
DASHBOARD_JOB_DESCRIPTION: "Synthesis indicator with specific Techno"
@ -234,7 +272,8 @@ asic-synthesis:
- echo $PERIOD
- echo $DV_TARGET
- source ./verif/sim/setup-env.sh
- git clone ${SYNTH_SCRIPT} ${SYNTH_SCRIPT_PATH}
- git clone ${SYNTH_SCRIPT} ${SYNTH_SCRIPT_PATH} -b ${SYNTH_SCRIPT_BRANCH}
- git -C ${SYNTH_SCRIPT_PATH} checkout cce5ea41
- cp -r ${SYNTH_SCRIPT_PATH}/cva6/ ../
- git apply ${SYNTH_SCRIPT_PATH}/patches/*.patch
- echo $SYN_DCSHELL_BASHRC; source $SYN_DCSHELL_BASHRC
@ -255,15 +294,29 @@ fpga-build:
DASHBOARD_JOB_DESCRIPTION: "Test of FPGA build flow"
DASHBOARD_SORT_INDEX: 9
DASHBOARD_JOB_CATEGORY: "Synthesis"
TARGET: cv32a60x
TARGET: cv32a6_imac_sv32
script:
- source $VIVADO_SETUP
- source ./verif/sim/setup-env.sh
- mkdir -p artifacts/logs
- make fpga target=$TARGET |& tail -20 > artifacts/logs/logfile.log.tail
- make fpga target=$TARGET &> artifacts/logs/logfile.log
- mkdir -p artifacts/reports
- mv corev_apu/fpga/work-fpga/ariane_xilinx.bit artifacts/ariane_xilinx_$TARGET.bit
- python3 .gitlab-ci/scripts/report_fpga.py corev_apu/fpga/reports/ariane.utilization.rpt artifacts/logs/logfile.log.tail
- python3 .gitlab-ci/scripts/report_fpga.py corev_apu/fpga/reports/ariane.utilization.rpt
pmp_tests:
timeout : 2 hours
extends:
- .synthesis_test
variables:
DASHBOARD_JOB_TITLE: "PMP $DV_TARGET"
DASHBOARD_JOB_DESCRIPTION: "Physical Memory Protection tests"
DASHBOARD_SORT_INDEX: 2
DASHBOARD_JOB_CATEGORY: "Test suites"
DV_SIMULATORS: "vcs-uvm"
SPIKE_TANDEM: 1
script: source verif/regress/pmp_cv32a65x_tests.sh
after_script: *simu_after_script
.regress_test:
stage: heavy tests
@ -275,17 +328,32 @@ fpga-build:
- when: manual
allow_failure: true
dhrystone:
benchmarks:
extends:
- .regress_test
variables:
DASHBOARD_JOB_TITLE: "Dhrystone"
DASHBOARD_JOB_TITLE: "benchmark $BENCH $ISSUE"
DASHBOARD_JOB_DESCRIPTION: "Performance indicator"
DASHBOARD_SORT_INDEX: 5
DASHBOARD_JOB_CATEGORY: "Performance"
SPIKE_TANDEM: 1
parallel:
matrix:
- BENCH: "dhrystone"
ISSUE: "single"
DV_HWCONFIG_OPTS: ["cv32a60x IcacheByteSize=16384 IcacheSetAssoc=8 DcacheByteSize=32768 DcacheSetAssoc=8 BHTEntries=128 NrScoreboardEntries=8 DCacheType=config_pkg::WT"]
- BENCH: "dhrystone"
ISSUE: "dual"
DV_HWCONFIG_OPTS: ["cv32a65x IcacheByteSize=16384 IcacheSetAssoc=8 DcacheByteSize=32768 DcacheSetAssoc=8 BHTEntries=128 NrScoreboardEntries=8 DCacheType=config_pkg::WT"]
- BENCH: "coremark"
ISSUE: "single"
DV_HWCONFIG_OPTS: ["cv32a60x IcacheByteSize=16384 IcacheSetAssoc=8 DcacheByteSize=32768 DcacheSetAssoc=8 BHTEntries=128 NrScoreboardEntries=8 DCacheType=config_pkg::WT"]
- BENCH: "coremark"
ISSUE: "dual"
DV_HWCONFIG_OPTS: ["cv32a65x IcacheByteSize=16384 IcacheSetAssoc=8 DcacheByteSize=32768 DcacheSetAssoc=8 BHTEntries=128 NrScoreboardEntries=8 DCacheType=config_pkg::WT"]
script:
- bash verif/regress/dhrystone.sh
- python3 .gitlab-ci/scripts/report_benchmark.py --dhrystone verif/sim/out_*/veri-testharness_sim/dhrystone_main.*.log
- bash verif/regress/"$BENCH".sh
- python3 .gitlab-ci/scripts/report_benchmark.py --"$BENCH"_"$ISSUE" verif/sim/out_*/vcs-uvm_sim/"$BENCH"_main.*.log
riscv_arch_test:
extends:
@ -295,12 +363,13 @@ riscv_arch_test:
DASHBOARD_JOB_DESCRIPTION: "Compliance regression suite"
DASHBOARD_SORT_INDEX: 0
DASHBOARD_JOB_CATEGORY: "Test suites"
DV_SIMULATORS: "veri-testharness,spike"
COLLECT_SIMU_LOGS: 1
DV_SIMULATORS: "vcs-testharness"
SPIKE_TANDEM: 1
script: source verif/regress/dv-riscv-arch-test.sh
after_script: *simu_after_script
compliance:
timeout : 2 hours
extends:
- .regress_test
variables:
@ -308,12 +377,13 @@ compliance:
DASHBOARD_JOB_DESCRIPTION: "Compliance regression suite"
DASHBOARD_SORT_INDEX: 2
DASHBOARD_JOB_CATEGORY: "Test suites"
DV_SIMULATORS: "veri-testharness,spike"
COLLECT_SIMU_LOGS: 1
DV_SIMULATORS: "vcs-testharness"
SPIKE_TANDEM: 1
script: source verif/regress/dv-riscv-compliance.sh
after_script: *simu_after_script
riscv-tests-v:
timeout : 2 hours
extends:
- .regress_test
variables:
@ -324,7 +394,6 @@ riscv-tests-v:
DV_SIMULATORS: "veri-testharness,spike"
DV_TARGET: cv64a6_imafdc_sv39
DV_TESTLISTS: "../tests/testlist_riscv-tests-$DV_TARGET-v.yaml"
COLLECT_SIMU_LOGS: 1
script: source verif/regress/dv-riscv-tests.sh
after_script: *simu_after_script
@ -336,9 +405,9 @@ riscv-tests-p:
DASHBOARD_JOB_DESCRIPTION: "Riscv-test regression suite (physical)"
DASHBOARD_SORT_INDEX: 4
DASHBOARD_JOB_CATEGORY: "Test suites"
DV_SIMULATORS: "veri-testharness,spike"
DV_SIMULATORS: "vcs-testharness"
SPIKE_TANDEM: 1
DV_TESTLISTS: "../tests/testlist_riscv-tests-$DV_TARGET-p.yaml"
COLLECT_SIMU_LOGS: 1
script: source verif/regress/dv-riscv-tests.sh
after_script: *simu_after_script
@ -361,7 +430,7 @@ mmu_sv32_tests:
DASHBOARD_SORT_INDEX: 0
DASHBOARD_JOB_CATEGORY: "Test suites"
DV_SIMULATORS: "veri-testharness,spike"
DV_TARGET: cv32a60x
DV_TARGET: cv32a6_imac_sv32
script: source verif/regress/dv-riscv-mmu-sv32-test.sh
after_script: *simu_after_script
@ -371,6 +440,8 @@ generated_tests:
variables:
DASHBOARD_SORT_INDEX: 11
DASHBOARD_JOB_CATEGORY: "Code Coverage"
SPIKE_TANDEM: 1
DV_SIMULATORS: "vcs-uvm"
parallel:
matrix:
- list_num: 1
@ -396,14 +467,17 @@ generated_tests:
- source verif/regress/dv-generated-tests.sh
- mv verif/sim/vcs_results/default/vcs.d/simv.vdb artifacts/coverage
- mv verif/sim/seedlist.yaml artifacts/coverage
- mv verif/sim/uvm_seed.log artifacts/coverage
- python3 .gitlab-ci/scripts/report_pass.py
generated_xif_tests:
.generated_xif_tests:
extends:
- .verif_test
variables:
DASHBOARD_SORT_INDEX: 12
DASHBOARD_JOB_CATEGORY: "Code Coverage"
SPIKE_TANDEM: 1
DV_SIMULATORS: "vcs-uvm"
parallel:
matrix:
- list_num: 1
@ -414,6 +488,7 @@ generated_xif_tests:
- source verif/regress/dv-generated-xif-tests.sh
- mv verif/sim/vcs_results/default/vcs.d/simv.vdb artifacts/coverage
- mv verif/sim/seedlist.yaml artifacts/coverage
- mv verif/sim/uvm_seed.log artifacts/coverage
- python3 .gitlab-ci/scripts/report_pass.py
directed_isacov-tests:
@ -422,6 +497,8 @@ directed_isacov-tests:
variables:
DASHBOARD_SORT_INDEX: 13
DASHBOARD_JOB_CATEGORY: "Functional Coverage"
SPIKE_TANDEM: 1
DV_SIMULATORS: "vcs-uvm"
parallel:
matrix:
- list_num: 0
@ -431,6 +508,7 @@ directed_isacov-tests:
- mkdir -p artifacts/coverage
- source verif/regress/dv-generated-tests.sh
- mv verif/sim/vcs_results/default/vcs.d/simv.vdb artifacts/coverage
- mv verif/sim/uvm_seed.log artifacts/coverage
- python3 .gitlab-ci/scripts/report_pass.py
csr_embedded_tests:
@ -442,11 +520,13 @@ csr_embedded_tests:
DASHBOARD_SORT_INDEX: 15
DASHBOARD_JOB_CATEGORY: "CSR tests"
DV_SIMULATORS: "vcs-uvm"
SPIKE_TANDEM: 1
script:
- mkdir -p artifacts/coverage
- source verif/regress/dv-csr-embedded-tests.sh
- mv verif/sim/vcs_results/default/vcs.d/simv.vdb artifacts/coverage
- python3 .gitlab-ci/scripts/report_pass.py
- mv verif/sim/uvm_seed.log artifacts/coverage
- python3 .gitlab-ci/scripts/report_tandem.py verif/sim/out*/"$DV_SIMULATORS"_sim
.backend_test:
stage: backend tests
@ -463,8 +543,7 @@ simu-gate:
- asic-synthesis
parallel:
matrix:
- SIMU_PERIOD: ["20"] # 50 Mhz
PERIOD: ["15"] # 66 Mhz
- PROG_NAME: ["dhrystone_smoke"]
variables:
DASHBOARD_JOB_TITLE: "Gate Level Simulation $DV_TARGET"
DASHBOARD_JOB_DESCRIPTION: "Tests to check netlist from ASIC synthesis and power consumption over different patterns"
@ -472,29 +551,41 @@ simu-gate:
DASHBOARD_JOB_CATEGORY: "Post Synthesis"
DV_TARGET: cv32a65x
TARGET: $DV_TARGET
TOP: "cva6"
SPIKE_TANDEM: 1
SIMU_PERIOD: "20" # 50 Mhz
PERIOD: "15" # 66 Mhz
script:
- git -C verif/core-v-verif fetch --unshallow
- mkdir -p tools
- mv artifacts/tools/spike tools
- echo $SYN_VCS_BASHRC; source $SYN_VCS_BASHRC
- mkdir -p artifacts/{reports,logs}
- git -C verif/core-v-verif fetch --unshallow || git -C verif/core-v-verif fetch --all
- !reference [.copy_spike_artifacts]
- echo $PERIOD
- source ./verif/sim/setup-env.sh
- git clone ${SYNTH_SCRIPT} ${SYNTH_SCRIPT_PATH}
- git clone ${SYNTH_SCRIPT} ${SYNTH_SCRIPT_PATH} -b ${SYNTH_SCRIPT_BRANCH}
- git -C ${SYNTH_SCRIPT_PATH} checkout cce5ea41
- cp -r ${SYNTH_SCRIPT_PATH}/cva6/ ../
- git apply ${SYNTH_SCRIPT_PATH}/patches/*.patch
- source verif/regress/install-riscv-tests.sh
- mv artifacts/cva6_${DV_TARGET} pd/synth/
- mv artifacts/cva6_${DV_TARGET}_synth.v pd/synth/
- mv artifacts/cva6_${DV_TARGET}_synth.sdf pd/synth/
- mkdir -p pd/synth/cva6_${DV_TARGET}/outputs/
- python3 ${SYNTH_SCRIPT_PATH}/scharm -p configs/modules/CVA6.yml --runner=True --compaign="simu-gate" --name=$PROG_NAME
- mv artifacts/${TOP}_${DV_TARGET} pd/synth/
- mv artifacts/${TOP}_${DV_TARGET}_synth.v pd/synth/
- mv artifacts/${TOP}_${DV_TARGET}_synth.sdf pd/synth/
- mkdir -p pd/synth/${TOP}_${DV_TARGET}/outputs/
- export DV_SIMULATORS="spike"
- bash verif/regress/${PROG_NAME}.sh
- cp verif/sim/out_*/directed_tests/*.o verif/sim/testelf.o
- python3 ${SYNTH_SCRIPT_PATH}/scharm -p configs/modules/CVA6.yml --runner=True --compaign="simu-gate" --name=testelf
- grep "Simulation terminated" verif/sim/out_*/*/*.log.iss
- mv ${SYNTH_SCRIPT_PATH}/artifacts/ artifacts/artifacts_gate/
after_script: *simu_after_script
- rm artifacts/artifacts_gate/*/build/*.fsdb
- mkdir -p verif/sim/out_reports
- mkdir -p artifacts/sim_artifacts
- for i in verif/sim/out*/vcs-uvm-gate*/*; do cp $i $(dirname $(dirname $i))/vcs-uvm_sim/gate.$(basename $i); done
- python3 .gitlab-ci/scripts/report_tandem.py verif/sim/out*/vcs-uvm_sim
fpga-boot:
extends:
- .backend_test
tags: [fpga,shell]
tags: [$TAGS_RUNNER_FPGA]
needs:
- build_tools
- fpga-build
@ -507,11 +598,12 @@ fpga-boot:
- source ./verif/sim/setup-env.sh
- source $VIVADO2022_SETUP
- mkdir -p corev_apu/fpga/work-fpga
- mv artifacts/ariane_xilinx_cv32a60x.bit corev_apu/fpga/work-fpga/ariane_xilinx.bit
- mv artifacts/ariane_xilinx_cv32a6_imac_sv32.bit corev_apu/fpga/work-fpga/ariane_xilinx.bit
- cd corev_apu/fpga/scripts
- source check_fpga_boot.sh
- cd -
- python3 .gitlab-ci/scripts/report_fpga_boot.py corev_apu/fpga/scripts/fpga_boot.rpt
retry: 1
code_coverage-report:
extends:
@ -519,7 +611,7 @@ code_coverage-report:
needs:
- generated_tests
- directed_isacov-tests
- generated_xif_tests
# - generated_xif_tests
- csr_embedded_tests
variables:
DASHBOARD_JOB_TITLE: "Report merge coverage"
@ -532,12 +624,14 @@ code_coverage-report:
- mkdir -p verif/sim/vcs_results/default/vcs.d
- mv artifacts/coverage/simv.vdb verif/sim/vcs_results/default/vcs.d/
- mv artifacts/coverage/seedlist.yaml verif/sim/seedlist.yaml
- mv artifacts/coverage/uvm_seed.log verif/sim/uvm_seed.log
- make -C verif/sim generate_cov_dash
- mv verif/sim/urgReport artifacts/cov_reports/
- python3 .gitlab-ci/scripts/report_coverage.py artifacts/cov_reports/urgReport/hierarchy.txt artifacts/cov_reports/urgReport/"feature.CVA6 Verification Master Plan1.7.-1268999905.txt"
check gitlab jobs status:
stage: find failures
tags: [$TAGS_RUNNER]
rules:
- if: $DASHBOARD_URL && $CI_KIND != "none"
when: on_failure
@ -554,6 +648,7 @@ check gitlab jobs status:
merge reports:
stage: report
tags: [$TAGS_RUNNER]
variables:
GIT_SUBMODULE_STRATEGY: none
rules:

View file

@ -1,4 +1,2 @@
cv32a6_embedded:
gates: 110095
cv32a65x:
gates: 128136
gates: 184679

View file

@ -3,6 +3,7 @@ This module makes it possible to trigger GitHub workflows.
"""
from os import environ as env
import time
import requests
def api_url(owner, repo):
@ -52,6 +53,7 @@ class DashboardDone(Workflow):
'pr_number': str(pr),
'success': success,
}
time.sleep(120)
return self._trigger(inputs)
def send_success(self, pr):

View file

@ -7,7 +7,9 @@
#
# Original Author: Côme Allart
import os
import sys
import re
import report_builder as rb
path = None
@ -17,54 +19,57 @@ iterations = None
# Keep it up-to-date with compiler version and core performance improvements
# Will fail if the number of cycles is different from this one
valid_cycles = {
'dhrystone': 217900,
'coremark': 665193,
"dhrystone_dual": 18935,
"dhrystone_single": 24127,
"coremark_dual": 1001191,
"coremark_single": 1300030,
"dhrystone_cv32a65x": 31976,
"dhrystone_cv32a60x": 39449,
}
for arg in sys.argv[1:]:
if arg == '--dhrystone':
mode = 'dhrystone'
# Standard value for Dhrystone
iterations = 500
elif arg == '--coremark':
mode = 'coremark'
# Defined in verif/regress/coremark.sh
iterations = 2
if "--dhrystone" in arg or "--coremark" in arg:
if "--dhrystone" in arg:
iterations = 50
else:
if "--coremark" in arg:
iterations = 4
mode = arg.replace("-", "")
else:
path = arg
# We do not want to have a report without a check
assert mode is not None
with open(path, 'r') as f:
with open(path, "r") as f:
log = [l.strip() for l in f.readlines()]
stopwatch = []
for index, line in enumerate(log):
if line.split()[-1] == 'mcycle' or line.split()[-2] == 'mcycle,':
if line.split()[-1] == "mcycle" or line.split()[-2] == "mcycle,":
stopwatch.append(int(log[index + 1].split()[-1], 16))
# There might be > 2 matches, we use the two at the center
N = len(stopwatch)
assert N % 2 == 0
cycles = stopwatch[N//2] - stopwatch[N//2-1]
cycles = stopwatch[N // 2] - stopwatch[N // 2 - 1]
score_metric = rb.TableMetric('Performance results')
score_metric.add_value('cycles', cycles)
score_metric = rb.TableMetric("Performance results")
score_metric.add_value("cycles", cycles)
if iterations is not None:
ipmhz = iterations * 1000000 / cycles
if mode == 'dhrystone':
score_metric.add_value('Dhrystone/MHz', ipmhz)
score_metric.add_value('DMIPS/MHz', ipmhz / 1757)
if mode == 'coremark':
score_metric.add_value('CoreMark/MHz', ipmhz)
if "dhrystone" in mode:
score_metric.add_value("Dhrystone/MHz", ipmhz)
score_metric.add_value("DMIPS/MHz", ipmhz / 1757)
if "coremark" in mode:
score_metric.add_value("CoreMark/MHz", ipmhz)
diff = cycles - valid_cycles[mode]
if diff != 0:
score_metric.fail()
score_metric.add_value('Cycles diff', diff)
score_metric.add_value("Cycles diff", diff)
report = rb.Report(f'{cycles//1000} kCycles')
report = rb.Report(f"{cycles//1000} kCycles")
report.add_metric(score_metric)
report.dump()

View file

@ -172,12 +172,19 @@ class Report:
def dump(self, path=None):
"""
Create report file
Print results and create report file
By default the output path is build from $CI_JOB_NAME
"""
for metric in self.metrics:
print(metric.values)
if path is None:
filename = re.sub(r'[^\w\.\\\/]', '_', os.environ["CI_JOB_NAME"])
path = 'artifacts/reports/'+filename+'.yml'
with open(path, 'w') as f:
yaml.dump(self.to_doc(), f)
ci_job_name = os.environ.get("CI_JOB_NAME")
if ci_job_name is not None:
filename = re.sub(r'[^\w\.\\\/]', '_', ci_job_name)
path = 'artifacts/reports/'+filename+'.yml'
if path is not None:
with open(path, 'w') as f:
yaml.dump(self.to_doc(), f)

View file

@ -15,9 +15,6 @@ import report_builder as rb
with open(str(sys.argv[1]), "r") as f:
log = f.read()
with open(str(sys.argv[2]), "r") as f:
outputlog = f.read()
pattern = re.compile(
"\|(?P<ind> +)(?P<Instance>[\w()\[\].]+) +\| +(?P<Module>[\w()\[\].]+) \| +(?P<TotalLUTs>\d+) \| +(?P<LogicLUTs>\d+) \| +(?P<LUTRAMs>\d+) \| +(?P<SRLs>\d+) \| +(?P<FFs>\d+) \| +(?P<RAMB36>\d+) \| +(?P<RAMB18>\d+) \| +(?P<DSP48Blocks>\d+) \|"
)
@ -50,8 +47,5 @@ for i in data:
i["DSP48Blocks"] + " DSP48Blocks",
)
log_metric = rb.LogMetric("Last lines of logfile")
log_metric.values = outputlog.splitlines()
report.add_metric(metric, log_metric)
report.add_metric(metric)
report.dump()

View file

@ -18,7 +18,7 @@ with open(str(sys.argv[1]), 'r') as f:
with_logs = os.environ.get("COLLECT_SIMU_LOGS") != None
pattern = re.compile(
r'(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} INFO )(?:Processing regression test list : (?:.*)/testlist_(.*-.*)(?:.yaml), test: (\S*)$[\s\S]*?^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} INFO )Compiling (.*):.*$|Compiling (.*): .*(tests\S*))$[\s\S]*?^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} INFO )Found matching ISS: (\S*)$[\s\S]*?^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} INFO )Target: (\S*)$[\s\S]*?^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2}(?: INFO ))ISA (\S*)$[\s\S]*?^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (?:(?:INFO )\[(\w*)\]: (\d*) matched(?:, (\d*) mismatch)?)|(?:^(?:\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2})(?: ERROR )(\D{5})(?:.*)$))',
r'(?:.*Compiling test: (.*))$[\s\S]*?(?:^.*Target: (.*)$)$[\s\S]*?(?:^.*ISA (.*)$)[\s\S]*?(?:^.*Found matching ISS: (.*)$)[\s\S]*?(?:^.*\[(PASSED|FAILED)\].*$)',
re.MULTILINE)
list_of_tests = pattern.findall(log)
@ -27,7 +27,6 @@ metric = rb.TableStatusMetric('')
metric.add_column("TARGET", "text")
metric.add_column("ISA", "text")
metric.add_column("TEST", "text")
metric.add_column("TEST LIST", "text")
if with_logs:
metric.add_column("OUTPUT", "log")
@ -40,22 +39,20 @@ job_test_total = 0
for i in list_of_tests:
job_test_total += 1
target = i[6]
isa = i[7]
test = i[1] or i[4].split("/")[-1].split(".")[0]
testsuite = i[0] or "custom test"
test_type = i[2] or i[4]
target = i[1]
isa = i[2]
test = i[0]
if with_logs:
logsPath = "logs/" + os.environ.get("CI_JOB_ID") + "/artifacts/logs/"
output_log = logsPath + 'logfile.log.head'
tb_log = logsPath + test + "." + target + '.log.iss.head'
disassembly = logsPath + test + "." + target + '.csv.head'
col = [target, isa, test, testsuite, output_log, tb_log, disassembly]
output_log = logsPath + 'logfile.log'
tb_log = logsPath + test + "." + target + '.log.iss'
disassembly = logsPath + test + "." + target + '.csv'
col = [target, isa, test, output_log, tb_log, disassembly]
else:
col = [target, isa, test, testsuite]
col = [target, isa, test]
if i[8] == "PASSED":
if i[4] == "PASSED":
metric.add_pass(*col)
job_test_pass += 1
else:

View file

@ -11,7 +11,6 @@
import re
import sys
import report_builder as rb
@ -69,11 +68,17 @@ def compare_summaries(baseline_info, new_info):
message = (
f"Count changed from {baseline_dict[key][0]} to {new_dict[key][0]}"
)
comparison_results.append((*key, *value, "PASS", message))
if key[0] == "ERROR" and new_dict[key][0] > baseline_dict[key][0]:
comparison_results.append((*key, *value, "FAIL", message))
else:
comparison_results.append((*key, *value, "PASS", message))
severity_order = {"ERROR": 1, "WARNING": 2, "INFO": 3}
comparison_results.sort(key=lambda x: severity_order[x[0]])
return comparison_results
def report_spyglass_lint(comparison_results):
def generate_spyglass_lint_report(comparison_results):
metric = rb.TableStatusMetric("")
metric.add_column("SEVERITY", "text")
metric.add_column("RULE NAME", "text")
@ -90,7 +95,10 @@ def report_spyglass_lint(comparison_results):
report = rb.Report()
report.add_metric(metric)
report.dump()
for value in metric.values:
print(" | ".join(map(str, value)))
return report
if __name__ == "__main__":
@ -103,4 +111,8 @@ if __name__ == "__main__":
baseline_info = extract_info(summary_ref_results)
new_info = extract_info(summary_rpt)
comparison_results = compare_summaries(baseline_info, new_info)
report_spyglass_lint(comparison_results)
report = generate_spyglass_lint_report(comparison_results)
print(report.failed)
report.dump()
if report.failed:
sys.exit(1)

View file

@ -82,7 +82,7 @@ hier_metric = rb.TableMetric('Hierarchies details')
for i in hier:
hier_metric.add_value(
i[0], # hier
f"{int(float(i[1])/kgate_ratio)} kGates", # area
f"{float(i[1])/kgate_ratio:.3f} kGates", # area
f"{int(float(i[2]))} %", # %
#int(float(i[3]))/int(float(i[1])*100), # % combi
#int(float(i[4]))/int(float(i[1])*100), # % reg

View file

@ -0,0 +1,107 @@
# Copyright 2024 Thales DIS France SAS
#
# Licensed under the Solderpad Hardware Licence, Version 0.51 (the "License");
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
# You may obtain a copy of the License at https://solderpad.org/licenses/
#
# Original Author: Valentin Thomazic (valentin.thomazic@thalesgroup.com)
import sys
import report_builder
import os
import glob
import yaml
def main():
with_logs = os.environ.get("COLLECT_SIMU_LOGS") != None
metrics_table = report_builder.TableStatusMetric('')
check_provided_args()
add_table_legend(metrics_table, with_logs)
passed_tests_count, total_tests_count = fill_table(sys.argv[1], metrics_table, with_logs)
if not report(metrics_table, passed_tests_count, total_tests_count):
sys.exit(1)
def check_provided_args():
if len(sys.argv) != 2:
sys.exit("Usage : python report_tandem.py path/to/log/dir")
if not os.path.exists(sys.argv[1]):
sys.exit("No valid log directory provided!")
if len(list(glob.iglob(sys.argv[1] + "/*.yaml"))) == 0:
sys.exit("No reports in log directory!")
def add_table_legend(metrics_table, with_logs):
metrics_table.add_column("TARGET", "text")
metrics_table.add_column("ISA", "text")
metrics_table.add_column("TEST", "text")
metrics_table.add_column("TEST LIST", "text")
metrics_table.add_column("SIMULATOR", "text")
metrics_table.add_column("MISMATCHES", "text")
if with_logs:
metrics_table.add_column("OUTPUT", "log")
metrics_table.add_column("TANDEM REPORT", "log")
metrics_table.add_column("TB LOGS", "log")
metrics_table.add_column("DISASSEMBLY", "log")
def fill_table(reports_dir, metrics_table, with_logs):
simulation_reports = glob.iglob(reports_dir + "/*.yaml")
test_passed = 0
test_count = 0
for report in simulation_reports:
test_passed += add_test_row(report, metrics_table, with_logs)
test_count += 1
if test_passed != test_count:
metrics_table.fail()
return test_passed, test_count
def add_test_row(report_file, metrics_table, with_logs):
try:
with open(report_file) as f:
report = yaml.safe_load(f)
mismatches_count = str(report["mismatches_count"]) if "mismatches_count" in report else "Not found"
row = [report["target"], report["isa"], report["test"], report["testlist"], report["simulator"], mismatches_count]
if with_logs:
logs_path = "logs/" + os.environ.get("CI_JOB_ID") + "/artifacts/logs/"
output_log = logs_path + "logfile.log"
log_prefix = logs_path + report['test'] + "_" + str(report["iteration"]) + "." + report["target"] \
if "iteration" in report else logs_path + report['test'] + "." + report["target"]
tb_log = log_prefix + '.log.iss'
disassembly = log_prefix + '.log.csv'
tandem_report = log_prefix + '.log.yaml'
row.append(output_log)
row.append(tandem_report)
row.append(tb_log)
row.append(disassembly)
if report["exit_cause"] == "SUCCESS" and report["exit_code"] == 0:
metrics_table.add_pass(*row)
return 1
metrics_table.add_fail(*row)
return 0
except (TypeError, KeyError):
sys.exit("Invalid yaml file in log directory! Is the log directory correct?")
def report(metrics_table, passed_test_count, total_test_count):
report = report_builder.Report(f'{passed_test_count}/{total_test_count}')
report.add_metric(metrics_table)
report.dump()
return not report.failed
if __name__ == "__main__":
main()

8
.gitmodules vendored
View file

@ -47,5 +47,11 @@
path = verif/sim/dv
url = https://github.com/google/riscv-dv.git
[submodule "docs/06_cv32a65x_riscv/riscv-isa-manual"]
path = docs/06_cv32a65x_riscv/riscv-isa-manual
path = docs/riscv-isa/riscv-isa-manual
url = https://github.com/riscv/riscv-isa-manual.git
[submodule "corev_apu/fpga/src/apb"]
path = corev_apu/fpga/src/apb
url = https://github.com/pulp-platform/apb.git
[submodule "corev_apu/fpga/src/gpio"]
path = corev_apu/fpga/src/gpio
url = https://github.com/pulp-platform/gpio.git

View file

@ -4,10 +4,30 @@
version: 2
submodules:
include:
- docs/riscv-isa/riscv-isa-manual
recursive: true
build:
os: "ubuntu-20.04"
tools:
python: "3.9"
nodejs: "20"
ruby: "3.3"
apt_packages:
- cmake
- bison
- flex
- libpango1.0-dev
- libgdk-pixbuf2.0-0
- libgtk2.0-dev
jobs:
post_install:
- npm install docs/riscv-isa/riscv-isa-manual/dependencies
- gem install -g docs/riscv-isa/riscv-isa-manual/dependencies/Gemfile
pre_build:
- PATH=$PWD/node_modules/.bin:$PATH make -C docs prepare
# Build from the docs directory with Sphinx
sphinx:

View file

@ -1,5 +1,5 @@
package:
name: ariane
name: cva6
authors:
- "Florian Zaruba <zarubaf@iis.ee.ethz.ch>"
- "Michael Schaffner <schaffner@iis.ee.ethz.ch>"
@ -68,6 +68,7 @@ sources:
- target: any(cv64a6_imafdcv_sv39, cv64a6_imafdc_sv39, cv64a6_imafdc_sv39_wb, cv64a6_imafdch_sv39, cv64a6_imafdch_sv39_wb, cv32a6_imac_sv0, cv32a6_imac_sv32, cv32a6_imafc_sv32)
files:
- core/cva6_mmu/cva6_tlb.sv
- core/cva6_mmu/cva6_shared_tlb.sv
- core/cva6_mmu/cva6_mmu.sv
- core/cva6_mmu/cva6_ptw.sv
@ -76,9 +77,10 @@ sources:
- core/include/std_cache_pkg.sv
# Extension Interface
- core/include/cvxif_pkg.sv
- core/cvxif_example/include/cvxif_instr_pkg.sv
- core/cvxif_fu.sv
- core/cvxif_issue_register_commit_if_driver.sv
- core/cvxif_compressed_if_driver.sv
- core/cvxif_example/cvxif_example_coprocessor.sv
- core/cvxif_example/instr_decoder.sv
@ -96,6 +98,7 @@ sources:
- core/csr_regfile.sv
- core/decoder.sv
- core/ex_stage.sv
- core/acc_dispatcher.sv
- core/instr_realign.sv
- core/id_stage.sv
- core/issue_read_operands.sv
@ -119,6 +122,7 @@ sources:
# Frontend (i.e., fetch, decode, dispatch)
- core/frontend/btb.sv
- core/frontend/bht.sv
- core/frontend/bht2lvl.sv
- core/frontend/ras.sv
- core/frontend/instr_scan.sv
- core/frontend/instr_queue.sv
@ -143,6 +147,7 @@ sources:
# Physical Memory Protection
- core/pmp/src/pmp.sv
- core/pmp/src/pmp_entry.sv
- core/pmp/src/pmp_data_if.sv
- include_dirs:
- common/local/util
@ -154,12 +159,15 @@ sources:
- common/local/util
files:
- common/local/util/tc_sram_wrapper.sv
- common/local/util/sram_cache.sv
- target: all(fpga, xilinx)
include_dirs:
- common/local/util
files:
- common/local/util/sram_cache.sv
- common/local/util/tc_sram_fpga_wrapper.sv
- vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx64.sv
- target: not(synthesis)
include_dirs:

View file

@ -1,5 +1,5 @@
# Global Owners
* @JeanRochCoulon @zarubaf
* @JeanRochCoulon
# Core
@ -7,9 +7,18 @@ core/mmu_sv39 @sjthales
core/cvxif_example @Gchauvon
core/cvxif_fu.sv @Gchauvon
# APU
# HPDCache
core/cache_subsystem/hpdcache @cfuguet
core/cache_subsystem/cva6_hpdcache* @cfuguet
core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv @cfuguet
core/include/cv64a6_imafdc_sv39_hpdcache_wb_config_pkg.sv @cfuguet
# OpenPiton
corev_apu/openpiton @Jbalkind
core/cache_subsystem/wt_l15_adapter.sv @Jbalkind
core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv @Jbalkind
## Documentation

View file

@ -22,8 +22,8 @@ Therefore here are guidelines to help the CVA6 team accept new contributions:
* If you do not know how to contact us already, get in touch through info@openhwgroup.org or open an issue in GitHub.
- Specific recommendations:
* Always consider using the CV-X-IF interface if your contribution is an instruction-set extension.
- and talk to the team if it's not possible.
* For instruction set extensions, talk to the team to assess the relevance of including it into the core or as a coprocessor on the CV-X-IF interface.
- If the extension is custom (not a RISC-V specified extension), a coprocessor on CV-X-IF is definitely its place.
* Your contribution shall be optional and fully disabled by default.
- so that projects already using CVA6 are not impacted (no functionality change, no extra silicon...).
* To configure your contribution, System Verilog top-level parameters are preferred.
@ -34,6 +34,12 @@ Therefore here are guidelines to help the CVA6 team accept new contributions:
* Your complete contribution shall be identifiable with parameters (or `directives / templating if together we decide to go this way).
- If at some point we need to revert it, e.g. if there is no-one maintaining nor using it and it has become a burden to the project.
- We call this the "parachute" rule: The CVA6 team does not want to use it but is far more comfortable getting one.
- Also, this allows not to lose code coverage in verification when your contribution is not enabled (with some tweaks in the coverage tool).
- This rule also applies to CSRs which are specific to your contribution.
* To ease maintenance, all common code lines shall exist only once.
- Counter-example: CVA6 used to have two different MMU modules (Sv32 and Sv39) for CV32A6 and CV64A6.
- It took time to refactor both in a joint design to ease maintenance.
- Related reading for reference: [DRY principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
* Your contribution shall pass the Continuous Integration (CI) flow
- When the contribution is disabled: in all cases, to ensure you have not broken the design.
- When the contribution is disabled: the line and condition code coverage shall not be impacted.
@ -61,6 +67,12 @@ See the [Git Cheats](https://github.com/openhwgroup/core-v-verif/blob/master/Git
6. Push feature branch: `git push origin <my_branch>`
7. From GitHub: submit a pull request
Please note that we do not accept outdated pull requests.
This makes sure the CI flow has run in the to-be version of the master.
To allow us to update the pull request before merging it, please consider checking the "Allow edits from maintainers" checkbox.
Note that this can only be done with pull requests from your personal repository (it is impossible from organization repositories).
## Coding Style
For RTL coding, the OpenHW Group has adopted the [lowRISC Style Guides](https://github.com/lowRISC/style-guides/).

View file

@ -72,6 +72,7 @@ core/decoder.sv
core/ex_stage.sv
core/frontend/btb.sv
core/frontend/bht.sv
core/frontend/bht2lvl.sv
core/frontend/ras.sv
core/frontend/instr_scan.sv
core/frontend/instr_queue.sv
@ -160,6 +161,7 @@ vendor/openhwgroup/cvfpu/src/fpnew_rounding.sv
vendor/openhwgroup/cvfpu/src/fpnew_top.sv
core/pmp/src/pmp.sv
core/pmp/src/pmp_entry.sv
core/pmp/src/pmp_data_if.sv
common/local/util/instr_tracer.sv
core/cvxif_example/cvxif_example_coprocessor.sv
core/cvxif_example/instr_decoder.sv

190
Makefile
View file

@ -40,7 +40,10 @@ torture-logs :=
elf_file ?= tmp/riscv-tests/build/benchmarks/dhrystone.riscv
# board name for bitstream generation. Currently supported: kc705, genesys2, nexys_video
BOARD ?= genesys2
ALTERA_BOARD ?= DK-DEV-AGF014E3ES
ALTERA_FAMILY ?= "AGILEX"
ALTERA_PART ?= AGFB014R24B2E2V
PLATFORM = "PLAT_XILINX"
# root path
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
root-dir := $(dir $(mkfile_path))
@ -142,7 +145,7 @@ CFLAGS += -I$(QUESTASIM_HOME)/include \
-I$(VL_INC_DIR)/vltstd \
-I$(RISCV)/include \
-I$(SPIKE_INSTALL_DIR)/include \
-std=c++17 -I../corev_apu/tb/dpi -O3
-std=c++17 -I$(CVA6_REPO_DIR)/corev_apu/tb/dpi -O3
ifdef XCELIUM_HOME
CFLAGS += -I$(XCELIUM_HOME)/tools/include
@ -151,13 +154,13 @@ $(warning XCELIUM_HOME not set which is necessary for compiling DPIs when using
endif
# this list contains the standalone components
src := core/include/$(target)_config_pkg.sv \
$(if $(spike-tandem),verif/tb/core/uvma_core_cntrl_pkg.sv) \
src := $(if $(spike-tandem),verif/tb/core/uvma_core_cntrl_pkg.sv) \
$(if $(spike-tandem),verif/tb/core/uvma_cva6pkg_utils_pkg.sv) \
$(if $(spike-tandem),verif/tb/core/uvma_rvfi_pkg.sv) \
$(if $(spike-tandem),verif/tb/core/uvmc_rvfi_reference_model_pkg.sv) \
$(if $(spike-tandem),verif/tb/core/uvmc_rvfi_scoreboard_pkg.sv) \
$(if $(spike-tandem),corev_apu/tb/common/spike.sv) \
core/cva6_rvfi.sv \
corev_apu/src/ariane.sv \
$(wildcard corev_apu/bootrom/*.sv) \
$(wildcard corev_apu/clint/*.sv) \
@ -166,24 +169,18 @@ src := core/include/$(target)_config_pkg.sv
$(wildcard corev_apu/fpga/src/axi_slice/src/*.sv) \
$(wildcard corev_apu/src/axi_riscv_atomics/src/*.sv) \
$(wildcard corev_apu/axi_mem_if/src/*.sv) \
$(wildcard corev_apu/riscv-dbg/src/*.sv) \
corev_apu/rv_plic/rtl/rv_plic_target.sv \
corev_apu/rv_plic/rtl/rv_plic_gateway.sv \
corev_apu/rv_plic/rtl/plic_regmap.sv \
corev_apu/rv_plic/rtl/plic_top.sv \
corev_apu/riscv-dbg/src/dmi_cdc.sv \
corev_apu/riscv-dbg/src/dmi_jtag.sv \
corev_apu/riscv-dbg/src/dmi_jtag_tap.sv \
corev_apu/riscv-dbg/src/dm_csrs.sv \
corev_apu/riscv-dbg/src/dm_mem.sv \
corev_apu/riscv-dbg/src/dm_sba.sv \
corev_apu/riscv-dbg/src/dm_top.sv \
corev_apu/riscv-dbg/debug_rom/debug_rom.sv \
corev_apu/register_interface/src/apb_to_reg.sv \
vendor/pulp-platform/axi/src/axi_multicut.sv \
vendor/pulp-platform/common_cells/src/rstgen_bypass.sv \
vendor/pulp-platform/common_cells/src/rstgen.sv \
vendor/pulp-platform/common_cells/src/addr_decode.sv \
vendor/pulp-platform/common_cells/src/stream_register.sv \
vendor/pulp-platform/common_cells/src/stream_register.sv \
vendor/pulp-platform/axi/src/axi_cut.sv \
vendor/pulp-platform/axi/src/axi_join.sv \
vendor/pulp-platform/axi/src/axi_delayer.sv \
@ -217,11 +214,73 @@ copro_src := core/cvxif_example/include/cvxif_instr_pkg.sv \
$(wildcard core/cvxif_example/*.sv)
copro_src := $(addprefix $(root-dir), $(copro_src))
uart_src := $(wildcard corev_apu/fpga/src/apb_uart/src/*.vhd)
uart_src := $(wildcard corev_apu/fpga/src/apb_uart/src/vhdl_orig/*.vhd)
uart_src := $(addprefix $(root-dir), $(uart_src))
fpga_src := $(wildcard corev_apu/fpga/src/*.sv) $(wildcard corev_apu/fpga/src/ariane-ethernet/*.sv) common/local/util/tc_sram_fpga_wrapper.sv vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx64.sv
fpga_src := $(addprefix $(root-dir), $(fpga_src)) src/bootrom/bootrom_$(XLEN).sv
uart_src_sv:= corev_apu/fpga/src/apb_uart/src/slib_clock_div.sv \
corev_apu/fpga/src/apb_uart/src/slib_counter.sv \
corev_apu/fpga/src/apb_uart/src/slib_edge_detect.sv \
corev_apu/fpga/src/apb_uart/src/slib_fifo.sv \
corev_apu/fpga/src/apb_uart/src/slib_input_filter.sv \
corev_apu/fpga/src/apb_uart/src/slib_input_sync.sv \
corev_apu/fpga/src/apb_uart/src/slib_mv_filter.sv \
corev_apu/fpga/src/apb_uart/src/uart_baudgen.sv \
corev_apu/fpga/src/apb_uart/src/uart_interrupt.sv \
corev_apu/fpga/src/apb_uart/src/uart_receiver.sv \
corev_apu/fpga/src/apb_uart/src/uart_transmitter.sv \
corev_apu/fpga/src/apb_uart/src/apb_uart.sv \
corev_apu/fpga/src/apb_uart/src/apb_uart_wrap.sv
uart_src_sv := $(addprefix $(root-dir), $(uart_src_sv))
fpga_src := $(wildcard corev_apu/fpga/src/*.sv) $(wildcard corev_apu/fpga/src/ariane-ethernet/*.sv) common/local/util/tc_sram_fpga_wrapper.sv common/local/util/hpdcache_sram_1rw.sv common/local/util/hpdcache_sram_wbyteenable_1rw.sv vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx64.sv vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx32.sv vendor/pulp-platform/fpga-support/rtl/SyncSpRam.sv
altera_src := $(shell find $(root-dir)/corev_apu/altera/src -type f \( -name "*.v" -o -name "*.sv" -o -name "*.svh" \) -print | sed 's|//|/|g')
altera_src += $(src)
altera_src += $(shell find $(root-dir)/corev_apu/fpga/src -type f \( -name "*.v" -o -name "*.sv" \) -print | sed 's|//|/|g')
altera_src += $(shell find $(root-dir)core/cvfpu/src/common_cells/src/ -maxdepth 1 -type f \( -name "*.v" -o -name "*.sv" -o -name "*.vhd" -o -name "*.svh" \) -print)
altera_axi_src := $(shell find $(root-dir)/vendor/pulp-platform/axi/src -type f \( -name "*.v" -o -name "*.sv" \) -print | sed 's|//|/|g')
altera_src += $(root-dir)corev_apu/rv_plic/rtl/top_pkg.sv \
$(root-dir)corev_apu/rv_plic/rtl/tlul_pkg.sv \
$(root-dir)corev_apu/rv_plic/rtl/rv_plic_reg_top.sv \
$(root-dir)corev_apu/rv_plic/rtl/rv_plic_reg_pkg.sv \
$(root-dir)corev_apu/rv_plic/rtl/rv_plic.sv \
$(root-dir)corev_apu/rv_plic/rtl/prim_subreg_ext.sv \
$(root-dir)corev_apu/rv_plic/rtl/prim_subreg.sv \
$(root-dir)vendor/pulp-platform/common_cells/src/cdc_fifo_gray.sv \
$(root-dir)riscv-dbg/src/dm_obi_top.sv \
$(root-dir)core/include/instr_tracer_pkg.sv \
$(root-dir)core/cvfpu/src/fpu_div_sqrt_mvp/hdl/div_sqrt_mvp_wrapper.sv \
$(root-dir)core/cache_subsystem/amo_alu.sv
altera_filter := corev_apu/tb/ariane_testharness.sv \
corev_apu/tb/ariane_peripherals.sv \
corev_apu/tb/rvfi_tracer.sv \
corev_apu/tb/common/uart.sv \
corev_apu/tb/common/SimDTM.sv \
corev_apu/tb/common/SimJTAG.sv \
corev_apu/fpga/src/apb/src/apb_test.sv \
corev_apu/fpga/src/ariane_xilinx.sv \
corev_apu/fpga/ariane_peripherals_xilinx.sv \
corev_apu/fpga/src/apb/test/tb_apb_cdc.sv \
corev_apu/fpga/src/apb/test/tb_apb_regs.sv \
corev_apu/fpga/src/apb/test/tb_apb_demux.sv \
corev_apu/fpga/src/gpio/test/tb_gpio.sv \
vendor/pulp-platform/axi/src/axi_test.sv \
corev_apu/riscv-dbg/src/dm_pkg.sv \
corev_apu/riscv-dbg/src/dmi_jtag_tap.sv \
corev_apu/riscv-dbg/src/dmi_jtag.sv \
corev_apu/fpga/src/apb_uart/src/reg_uart_wrap.sv
altera_filter := $(addprefix $(root-dir), $(altera_filter))
xil_debug_filter = $(addprefix $(root-dir), corev_apu/riscv-dbg/src/dm_obi_top.sv)
xil_debug_filter += $(addprefix $(root-dir), corev_apu/riscv-dbg/src/dm_pkg.sv)
xil_debug_filter += $(addprefix $(root-dir), corev_apu/riscv-dbg/src/dmi_vjtag_tap.sv)
xil_debug_filter += $(addprefix $(root-dir), corev_apu/riscv-dbg/src/dmi_vjtag.sv)
src := $(filter-out $(xil_debug_filter), $(src))
fpga_src += corev_apu/fpga/src/bootrom/bootrom_$(XLEN).sv
fpga_src := $(addprefix $(root-dir), $(fpga_src))
# look for testbenches
tbs := $(top_level_path) corev_apu/tb/ariane_testharness.sv core/cva6_rvfi.sv
@ -256,11 +315,18 @@ incdir := $(CVA6_REPO_DIR)/vendor/pulp-platform/common_cells/include/ $(CVA6_REP
$(SPIKE_INSTALL_DIR)/include/disasm/
# Compile and sim flags
compile_flag += -incr -64 -nologo -quiet -suppress 13262 -suppress 8607 -permissive -svinputport=compat +define+$(defines) -suppress 8386 -suppress vlog-2577
compile_flag += -incr -64 -nologo -quiet -suppress 13262 -suppress 8607 +permissive -svinputport=compat +define+$(defines) -suppress 8386 -suppress vlog-2577
vopt_flag += -suppress 2085 -suppress 7063 -suppress 2698 -suppress 13262
ifdef config-file
spike-yaml-plusarg = +config_file=$(spike_yaml)
endif
uvm-flags += +UVM_NO_RELNOTES +UVM_VERBOSITY=UVM_LOW
questa-flags += -t 1ns -64 $(gui-sim) $(QUESTASIM_FLAGS) +tohost_addr=$(tohost_addr) +define+QUESTA -suppress 3356 -suppress 3579
questa-flags += -t 1ns -64 $(gui-sim) $(QUESTASIM_FLAGS) \
+tohost_addr=$(shell ${RISCV}/bin/${CV_SW_PREFIX}nm -B $(elf) | grep -w tohost | cut -d' ' -f1) \
+core_name=$(target) +define+QUESTA -suppress 3356 -suppress 3579 +report_file=$(report_file) \
$(spike-yaml-plusarg)
compile_flag_vhd += -64 -nologo -quiet -2008
# Iterate over all include directories and write them with +incdir+ prefixed
@ -290,7 +356,7 @@ ifdef preload
endif
ifdef spike-tandem
questa-cmd += -gblso $(SPIKE_INSTALL_DIR)/lib/libriscv.so
questa-cmd += -gblso $(SPIKE_INSTALL_DIR)/lib/libyaml-cpp.so -gblso $(SPIKE_INSTALL_DIR)/lib/libriscv.so
endif
# remote bitbang is enabled
@ -307,23 +373,23 @@ vcs_build: $(dpi-library)/ariane_dpi.so
cd $(vcs-library) &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog +define+$(defines) -assert svaext -f $(flist) $(list_incdir) ../corev_apu/tb/common/mock_uart.sv -timescale=1ns/1ns &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog +define+$(defines) $(filter %.sv,$(ariane_pkg)) +incdir+core/include/+$(VCS_HOME)/etc/uvm-1.2/dpi &&\
vhdlan $(if $(VERDI), -kdb,) -full64 -nc $(filter %.vhd,$(uart_src)) &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog $(uart_src_sv) &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -assert svaext +define+$(defines) +incdir+$(VCS_HOME)/etc/uvm/src $(VCS_HOME)/etc/uvm/src/uvm_pkg.sv $(filter %.sv,$(src)) $(list_incdir) &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -ntb_opts uvm-1.2 &&\
vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -ntb_opts uvm-1.2 $(tbs) +define+$(defines) $(list_incdir) &&\
vcs $(if $(DEBUG), -debug_access+all $(if $(VERDI), -kdb),) $(if $(TRACE_COMPACT),+vcs+fsdbon) -ignore initializer_driver_checks -timescale=1ns/1ns -ntb_opts uvm-1.2 work.$(top_level) -error="IWNF" \
vcs -full64 $(if $(DEBUG), -debug_access+all $(if $(VERDI), -kdb),) $(if $(TRACE_COMPACT),+vcs+fsdbon) -ignore initializer_driver_checks -timescale=1ns/1ns -ntb_opts uvm-1.2 work.$(top_level) -error="IWNF" \
$(if $(gate), -sdf Max:ariane_gate_tb.i_ariane.i_cva6:$(CVA6_REPO_DIR)/pd/synth/cva6_$(TARGET)_synth.sdf +neg_tchk, +notimingcheck)
vcs: vcs_build
cd $(vcs-library) && \
./simv +permissive $(if $(VERDI), -verdi -do $(root-dir)/init_testharness.do,) \
+elf_file=$(elf_file) ++$(elf_file) $(if $(spike-tandem),-sv_lib $(SPIKE_INSTALL_DIR)/libriscv) \
+elf_file=$(elf_file) ++$(elf_file) $(if $(spike-tandem), -sv_lib $(SPIKE_INSTALL_DIR)/libyaml-cpp) -sv_lib $(SPIKE_INSTALL_DIR)/libriscv \
-sv_lib ../work-dpi/ariane_dpi | tee vcs.log
# Build the TB and module using QuestaSim
build: $(library) $(library)/.build-srcs $(library)/.build-tb $(dpi-library)/ariane_dpi.so
# Optimize top level
$(VOPT) -64 -work $(library) $(top_level) -o $(top_level)_optimized +acc -check_synthesis -dpilib $(SPIKE_INSTALL_DIR)/lib/libriscv -dpilib $(SPIKE_INSTALL_DIR)/lib/lifesvr $(vopt_flag)
$(VOPT) -64 -work $(library) $(top_level) -o $(top_level)_optimized +acc -check_synthesis -dpilib $(SPIKE_INSTALL_DIR)/lib/libriscv -dpilib $(SPIKE_INSTALL_DIR)/lib/libfesvr -dpilib $(SPIKE_INSTALL_DIR)/lib/libyaml-cpp $(vopt_flag)
# src files
$(library)/.build-srcs: $(library)
@ -351,7 +417,13 @@ $(dpi-library)/%.o: corev_apu/tb/dpi/%.cc $(dpi_hdr)
$(dpi-library)/ariane_dpi.so: $(dpi)
mkdir -p $(dpi-library)
# Compile C-code and generate .so file
$(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv
$(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv -lyaml-cpp
$(dpi-library)/xrun_ariane_dpi.so: $(dpi)
# Make Dir work-dpi
mkdir -p $(dpi-library)
# Compile C-code and generate .so file
$(CXX) -shared -m64 -o $(dpi-library)/xrun_ariane_dpi.so $? -L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv -lyaml-cpp
# single test runs on Questa can be started by calling make <testname>, e.g. make towers.riscv
# the test names are defined in ci/riscv-asm-tests.list, and in ci/riscv-benchmarks.list
@ -363,8 +435,8 @@ generate-trace-vsim:
sim: build
$(VSIM) +permissive $(questa-flags) $(questa-cmd) -lib $(library) +MAX_CYCLES=$(max_cycles) +UVM_TESTNAME=$(test_case) \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) -sv_lib $(SPIKE_INSTALL_DIR)/lib/libriscv -sv_lib $(SPIKE_INSTALL_DIR)/lib/libfesvr \
-sv_lib $(SPIKE_INSTALL_DIR)/lib/libdisasm \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) -sv_lib $(SPIKE_INSTALL_DIR)/lib/libyaml-cpp -sv_lib $(SPIKE_INSTALL_DIR)/lib/libriscv -sv_lib $(SPIKE_INSTALL_DIR)/lib/libfesvr \
-sv_lib $(SPIKE_INSTALL_DIR)/lib/libdisasm \
${top_level}_optimized +permissive-off +elf_file=$(elf_file) ++$(elf_file) ++$(target-options)
$(riscv-asm-tests): build
@ -429,24 +501,25 @@ check-benchmarks:
XRUN ?= xrun
XRUN_WORK_DIR ?= xrun_work
XRUN_RESULTS_DIR ?= xrun_results
XRUN_UVMHOME_ARG ?= CDNS-1.2-ML
##XRUN_UVMHOME_ARG ?= CDNS-1.2-ML
XRUN_UVMHOME_ARG ?= CDNS-1.2
XRUN_COMPL_LOG ?= xrun_compl.log
XRUN_RUN_LOG ?= xrun_run.log
CVA6_HOME ?= $(realpath -s $(root-dir))
XRUN_INCDIR :=+incdir+$(CVA6_HOME)/src/axi_node \
+incdir+$(CVA6_HOME)/src/common_cells/include \
+incdir+$(CVA6_HOME)/src/util
XRUN_INCDIR :=+incdir+$(CVA6_HOME)/core/include \
+incdir+$(CVA6_HOME)/vendor/pulp-platform/axi/include/ \
+incdir+$(CVA6_HOME)/corev_apu/register_interface/include
XRUN_TB := $(addprefix $(CVA6_HOME)/, corev_apu/tb/ariane_tb.sv)
XRUN_COMP_FLAGS ?= -64bit -disable_sem2009 -access +rwc \
-sv -v93 -uvm -uvmhome $(XRUN_UVMHOME_ARG) \
-sv_lib $(CVA6_HOME)/$(dpi-library)/ariane_dpi.so \
XRUN_COMP_FLAGS ?= -64bit -v200x -disable_sem2009 -access +rwc \
-sv -uvm -uvmhome $(XRUN_UVMHOME_ARG) \
-sv_lib $(CVA6_HOME)/$(dpi-library)/xrun_ariane_dpi.so \
-smartorder -sv -top worklib.$(top_level) \
-xceligen on=1903 +define+$(defines) -timescale 1ns/1ps \
-timescale 1ns/1ps
XRUN_RUN_FLAGS := -R -64bit -disable_sem2009 -access +rwc -timescale 1ns/1ps \
-sv_lib $(CVA6_HOME)/$(dpi-library)/ariane_dpi.so -xceligen on=1903 \
XRUN_RUN_FLAGS := -R -messages -status -64bit -licqueue -noupdate -uvmhome CDNS-1.2 -sv_lib $(CVA6_HOME)/$(dpi-library)/xrun_ariane_dpi.so +UVM_VERBOSITY=UVM_LOW
XRUN_DISABLED_WARNINGS := BIGWIX \
ZROMCW \
@ -460,21 +533,21 @@ XRUN_DISABLED_WARNINGS := $(patsubst %, -nowarn %, $(XRUN_DISABLED_WARNINGS))
XRUN_COMP = $(XRUN_COMP_FLAGS) \
$(XRUN_DISABLED_WARNINGS) \
$(XRUN_INCDIR) \
-f ../core/Flist.cva6 \
$(filter %.sv, $(ariane_pkg)) \
$(filter %.vhd, $(uart_src)) \
$(filter %.sv, $(src)) \
-f ../core/Flist.cva6 \
$(filter %.sv, $(XRUN_TB)) \
$(filter %.vhd, $(uart_src)) \
$(filter %.sv, $(XRUN_TB))
XRUN_RUN = $(XRUN_RUN_FLAGS) \
$(XRUN_DISABLED_WARNINGS) \
$(XRUN_DISABLED_WARNINGS)
xrun_clean:
@echo "[XRUN] clean up"
rm -rf $(XRUN_RESULTS_DIR)
rm -rf $(dpi-library)
xrun_comp: $(dpi-library)/ariane_dpi.so
xrun_comp: $(dpi-library)/xrun_ariane_dpi.so
@echo "[XRUN] Building Model"
mkdir -p $(XRUN_RESULTS_DIR)
cd $(XRUN_RESULTS_DIR) && $(XRUN) \
@ -491,11 +564,13 @@ xrun_sim: xrun_comp
$(XRUN_RUN) \
+MAX_CYCLES=$(max_cycles) \
+UVM_TESTNAME=$(test_case) \
-l $(XRUN_RUN_LOG) \
+time_out=200000000000 \
+tohost_addr=$(shell ${RISCV}/bin/${CV_SW_PREFIX}nm -B $(elf) | grep -w tohost | cut -d' ' -f1) \
-log $(XRUN_RUN_LOG) \
+gui \
+permissive-off \
++$(elf_file)
#-e "set_severity_pack_assert_off {warning}; set_pack_assert_off {numeric_std}" TODO: This will remove assertion warning at the beginning of the simulation.
+elf_file=$(elf) \
++$(elf)
xrun_all: xrun_clean xrun_comp xrun_sim
@ -592,7 +667,7 @@ verilate_command := $(verilator) --no-timing verilator_config.vlt
$(if $(DEBUG), --trace-structs,) \
$(if $(TRACE_COMPACT), --trace-fst $(VL_INC_DIR)/verilated_fst_c.cpp) \
$(if $(TRACE_FAST), --trace $(VL_INC_DIR)/verilated_vcd_c.cpp) \
-LDFLAGS "-L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv -ldisasm $(if $(PROFILE), -g -pg,) -lpthread $(if $(TRACE_COMPACT), -lz,)" \
-LDFLAGS "-L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv -ldisasm -lyaml-cpp $(if $(PROFILE), -g -pg,) -lpthread $(if $(TRACE_COMPACT), -lz,)" \
-CFLAGS "$(CFLAGS)$(if $(PROFILE), -g -pg,) -DVL_DEBUG -I$(SPIKE_INSTALL_DIR)" \
$(if $(SPIKE_TANDEM), +define+SPIKE_TANDEM, ) \
--cc --vpi \
@ -700,9 +775,14 @@ fpga_filter += $(addprefix $(root-dir), src/util/instr_trace_item.sv)
fpga_filter += $(addprefix $(root-dir), common/local/util/instr_tracer.sv)
fpga_filter += $(addprefix $(root-dir), vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv)
fpga_filter += $(addprefix $(root-dir), common/local/util/tc_sram_wrapper.sv)
fpga_filter += $(addprefix $(root-dir), corev_apu/tb/ariane_peripherals.sv)
fpga_filter += $(addprefix $(root-dir), corev_apu/tb/ariane_testharness.sv)
fpga_filter += $(addprefix $(root-dir), core/cache_subsystem/hpdcache/rtl/src/common/macros/behav/hpdcache_sram_1rw.sv)
fpga_filter += $(addprefix $(root-dir), core/cache_subsystem/hpdcache/rtl/src/common/macros/behav/hpdcache_sram_wbyteenable_1rw.sv)
fpga_filter += $(addprefix $(root-dir), core/cache_subsystem/hpdcache/rtl/src/common/macros/behav/hpdcache_sram_wmask_1rw.sv)
src/bootrom/bootrom_$(XLEN).sv:
$(MAKE) -C corev_apu/fpga/src/bootrom BOARD=$(BOARD) XLEN=$(XLEN) bootrom_$(XLEN).sv
$(addprefix $(root-dir), corev_apu/fpga/src/bootrom/bootrom_$(XLEN).sv):
$(MAKE) -C corev_apu/fpga/src/bootrom BOARD=$(BOARD) XLEN=$(XLEN) PLATFORM=$(PLATFORM) bootrom_$(XLEN).sv
fpga: $(ariane_pkg) $(src) $(fpga_src) $(uart_src) $(src_flist)
@echo "[FPGA] Generate sources"
@ -714,6 +794,19 @@ fpga: $(ariane_pkg) $(src) $(fpga_src) $(uart_src) $(src_flist)
@echo "[FPGA] Generate Bitstream"
$(MAKE) -C corev_apu/fpga BOARD=$(BOARD) XILINX_PART=$(XILINX_PART) XILINX_BOARD=$(XILINX_BOARD) CLK_PERIOD_NS=$(CLK_PERIOD_NS)
altera: PLATFORM := "PLAT_AGILEX"
altera: $(ariane_pkg) $(src) $(fpga_src) $(src_flist)
@echo "[FPGA] Generate sources"
@echo $(ariane_pkg) > corev_apu/altera/sourcelist.txt
@echo $(filter-out $(fpga_filter), $(src_flist)) >> corev_apu/altera/sourcelist.txt
@echo $(filter-out $(fpga_filter) $(altera_filter), $(src)) >> corev_apu/altera/sourcelist.txt
@echo $(filter-out $(altera_filter), $(fpga_src)) >> corev_apu/altera/sourcelist.txt
@echo $(filter-out $(fpga_filter) $(altera_filter) $(uart_src_sv), $(altera_src)) >> corev_apu/altera/sourcelist.txt
@echo $(filter-out $(fpga_filter) $(altera_filter), $(altera_axi_src)) >> corev_apu/altera/sourcelist.txt
@echo "[FPGA] Generate Bitstream"
$(MAKE) -C corev_apu/altera ALTERA_PART=$(ALTERA_PART) ALTERA_BOARD=$(ALTERA_BOARD) CLK_PERIOD_NS=$(CLK_PERIOD_NS)
.PHONY: fpga
build-spike:
@ -726,6 +819,9 @@ clean:
$(MAKE) -C corev_apu/fpga clean
$(MAKE) -C corev_apu/fpga/src/bootrom BOARD=$(BOARD) XLEN=$(XLEN) clean
clean-altera: clean
$(MAKE) -C corev_apu/altera clean
.PHONY:
build sim sim-verilate clean \
$(riscv-asm-tests) $(addsuffix _verilator,$(riscv-asm-tests)) \

171
README.md
View file

@ -1,12 +1,12 @@
![Build Status](https://github.com/openhwgroup/cva6/actions/workflows/ci.yml/badge.svg?branch=master)
# CVA6 RISC-V CPU
# CVA6 RISC-V CPU [![Build Status](https://github.com/openhwgroup/cva6/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/openhwgroup/cva6/actions/workflows/ci.yml) [![CVA6 dashboard](https://riscv-ci.pages.thales-invia.fr/dashboard/badge_master.svg)](https://riscv-ci.pages.thales-invia.fr/dashboard/dashboard_cva6.html) [![Documentation Status](https://readthedocs.com/projects/openhw-group-cva6-user-manual/badge/?version=latest)](https://docs.openhwgroup.org/projects/cva6-user-manual/?badge=latest) [![GitHub release](https://img.shields.io/github/release/openhwgroup/cva6?include_prereleases=&sort=semver&color=blue)](https://github.com/openhwgroup/cva6/releases/)
CVA6 is a 6-stage, single-issue, in-order CPU which implements the 64-bit RISC-V instruction set. It fully implements I, M, A and C extensions as specified in Volume I: User-Level ISA V 2.3 as well as the draft privilege extension 1.10. It implements three privilege levels M, S, U to fully support a Unix-like operating system. Furthermore, it is compliant to the draft external debug spec 0.13.
It has a configurable size, separate TLBs, a hardware PTW and branch-prediction (branch target buffer and branch history table). The primary design goal was on reducing critical path length.
A performance model of CVA6 is available in the `perf-model/` folder of this repository.
It can be used to investigate performance-related micro-architecture changes.
<img src="docs/03_cva6_design/_static/ariane_overview.drawio.png"/>
@ -27,16 +27,18 @@ cd cva6
git submodule update --init --recursive
```
2. Install the GCC Toolchain [build prerequisites](util/gcc-toolchain-builder/README.md#Prerequisites) then [the toolchain itself](util/gcc-toolchain-builder/README.md#Getting-started).
2. Install the GCC Toolchain [build prerequisites](util/toolchain-builder/README.md#Prerequisites) then [the toolchain itself](util/toolchain-builder/README.md#Getting-started).
:warning: It is **strongly recommended** to use the toolchain built with the provided scripts.
3. Set the RISCV environment variable.
3. Install `cmake`, version 3.14 or higher.
4. Set the RISCV environment variable.
```sh
export RISCV=/path/to/toolchain/installation/directory
```
4. Install `help2man` and `device-tree-compiler` packages.
5. Install `help2man` and `device-tree-compiler` packages.
For Debian-based Linux distributions, run :
@ -44,13 +46,13 @@ For Debian-based Linux distributions, run :
sudo apt-get install help2man device-tree-compiler
```
5. Install the riscv-dv requirements:
6. Install the riscv-dv requirements:
```sh
pip3 install -r verif/sim/dv/requirements.txt
```
6. Run these commands to install a custom Spike and Verilator (i.e. these versions must be used to simulate the CVA6) and [these](#running-regression-tests-simulations) tests suites.
7. Run these commands to install a custom Spike and Verilator (i.e. these versions must be used to simulate the CVA6) and [these](#running-regression-tests-simulations) tests suites.
```sh
# DV_SIMULATORS is detailed in the next section
export DV_SIMULATORS=veri-testharness,spike
@ -93,7 +95,7 @@ cd ./verif/sim
python3 cva6.py --target cv32a60x --iss=$DV_SIMULATORS --iss_yaml=cva6.yaml \
--c_tests ../tests/custom/hello_world/hello_world.c \
--linker=../tests/custom/common/test.ld \
--linker=../../config/gen_from_riscv_config/linker/link.ld \
--gcc_opts="-static -mcmodel=medany -fvisibility=hidden -nostdlib \
-nostartfiles -g ../tests/custom/common/syscalls.c \
../tests/custom/common/crt.S -lgcc \
@ -168,9 +170,14 @@ To generate VCD waveforms of the `smoke-tests` regression suite using Verilator,
```sh
export DV_SIMULATORS=veri-testharness,spike
export TRACE_FAST=1
bash verif/regress/smoke-tests.sh
bash verif/regress/smoke-tests-<cpu_version>.sh
```
Where `<cpu_version>` is one of the following, depending on the CPU variant you want to use.
- `cv32a65x`.
- `cv32a6_imac_sv32`.
- `cv64a6_imafdc_sv39`.
After each simulation run involving Verilator or VCS, the generated waveforms
will be copied to the directory containing the log files (see above,) with
the name of the current HW configuration added to the file name right before
@ -206,29 +213,67 @@ python3 cva6.py --testlist=../tests/testlist_riscv-tests-cv64a6_imafdc_sv39-p.ya
# COREV-APU FPGA Emulation
We currently only provide support for the [Genesys 2 board](https://reference.digilentinc.com/reference/programmable-logic/genesys-2/reference-manual). We provide pre-build bitstream and memory configuration files for the Genesys 2 [here](https://github.com/openhwgroup/cva6/releases).
We currently provide support for the [Genesys 2 board](https://reference.digilentinc.com/reference/programmable-logic/genesys-2/reference-manual) and the [Agilex 7 Development Kit](https://www.intel.la/content/www/xl/es/products/details/fpga/development-kits/agilex/agf014.html).
Tested on Vivado 2018.2. The FPGA currently contains the following peripherals:
- **Genesys 2**
We provide pre-build bitstream and memory configuration files for the Genesys 2 [here](https://github.com/openhwgroup/cva6/releases).
- DDR3 memory controller
- SPI controller to conncet to an SDCard
- Ethernet controller
- JTAG port (see debugging section below)
- Bootrom containing zero stage bootloader and device tree.
Tested on Vivado 2018.2. The FPGA currently contains the following peripherals:
- DDR3 memory controller
- SPI controller to conncet to an SDCard
- Ethernet controller
- JTAG port (see debugging section below)
- Bootrom containing zero stage bootloader and device tree.
- UART
- GPIOs connected to LEDs
> The ethernet controller and the corresponding network connection is still work in progress and not functional at the moment. Expect some updates soon-ish.
- **Agilex 7**
Tested on Quartus Prime Version 24.1.0 Pro Edition. The FPGA currently contains the following peripherals:
- DDR4 memory controller
- JTAG port (see debugging section below)
- Bootrom containing zero stage bootloader
- UART
- GPIOs connected to LEDs
## Programming the Memory Configuration File
> The ethernet controller and the corresponding network connection, as well as the SD Card connection and the capability to boot linux are still work in progress and not functional at the moment. Expect some updates soon-ish.
- Open Vivado
- Open the hardware manager and open the target board (Genesys II - `xc7k325t`)
- Tools - Add Configuration Memory Device
- Select the following Spansion SPI flash `s25fl256xxxxxx0`
- Add `ariane_xilinx.mcs`
- Press Ok. Flashing will take a couple of minutes.
- Right click on the FPGA device - Boot from Configuration Memory Device (or press the program button on the FPGA)
## Programming the Memory Configuration File or bitstream
- **Genesys 2**
- Open Vivado
- Open the hardware manager and open the target board (Genesys II - `xc7k325t`)
- Tools - Add Configuration Memory Device
- Select the following Spansion SPI flash `s25fl256xxxxxx0`
- Add `ariane_xilinx.mcs`
- Press Ok. Flashing will take a couple of minutes.
- Right click on the FPGA device - Boot from Configuration Memory Device (or press the program button on the FPGA)
- **Agilex 7**
- Open Quartus programmer
- Configure HW Setup by selecting the AGF FPGA Development Kit
- Click Auto-Detect to scan the JTAG chain
- In the device list, right click over device AGFB014R24B and add file (.sof)
- Click on Start button to program the FPGA
- Right now only baremetal is supported, so right after programming you can connect to the UART and see your CVA6 alive on Agilex!
- For this you need to use the JTAG UART provided with Quartus installation
```
.$quartus_installation_path/qprogrammer/quartus/bin/juart-terminal
juart-terminal: connected to hardware target using JTAG UART on cable
juart-terminal: "AGF FPGA Development Kit [1-3]", device 1, instance 0
juart-terminal: (Use the IDE stop button or Ctrl-C to terminate)
Hello World!
```
## Preparing the SD Card
@ -246,6 +291,8 @@ After you've inserted the SD Card and programmed the FPGA you can connect to the
## Generating a Bitstream
- **Genesys 2**
To generate the FPGA bitstream (and memory configuration) yourself for the Genesys II board run:
```
@ -254,9 +301,27 @@ make fpga
This will produce a bitstream file and memory configuration file (in `fpga/work-fpga`) which you can permanently flash by running the above commands.
- **Agilex 7**
To generate the FPGA bitstream yourself for the Agilex 7 board run:
```
make altera
```
We recommend to set the parameter FpgaAlteraEn (and also FpgaEn) to benefit from the FPGA optimizations.
This will produce a bitstream file (in `altera/output_files`) which you can program following the previous instructions. **Note: Bear in mind that you need a Quartus Pro Licence to be able to generate this bitstream**
To clean the project after generating the bitstream, use
```
make clean-altera
```
## Debugging
- **Genesys 2**
You can debug (and program) the FPGA using [OpenOCD](http://openocd.org/doc/html/Architecture-and-Core-Commands.html). We provide two example scripts for OpenOCD below.
To get started, connect the micro USB port that is labeled with JTAG to your machine. This port is attached to the FTDI 2232 USB-to-serial chip on the Genesys 2 board, and is usually used to access the native JTAG interface of the Kintex-7 FPGA (e.g. to program the device using Vivado). However, the FTDI chip also exposes a second serial link that is routed to GPIO pins on the FPGA, and we leverage this to wire up the JTAG from the RISC-V debug module.
@ -294,11 +359,59 @@ Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333
```
- **Agilex 7**
You can debug (and program) the FPGA using a modified version of OpenOCD included with Quartus installation ($quartus_installation_path/qprogrammer/quartus/bin/openocd).
To get started, connect the micro USB port that is labeled with J13 to your machine. It is the same port that is used for the UART. Both use the JTAG interface and connect to the System Level Debugging (SLD) Hub instantiated inside the FPGA. Then the debugger connection goes to the virtual JTAG IP (vJTAG) which can be accessed with the modified version of OpenOCD.
You can start openocd with the `altera/cva6.cfg` configuration file:
```
./$quartus_installation_path/qprogrammer/quartus/bin/openocd -f altera/cva6.cfg
Open On-Chip Debugger 0.11.0-R22.4
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Info : Application name is OpenOCD.20241016093010
Info : No cable specified, so will be searching for cables
Info : At present, The first hardware cable will be used [1 cable(s) detected]
Info : Cable 1: device_name=(null), hw_name=AGF FPGA Development Kit, server=(null), port=1-3, chain_id=0x559319c8cde0, persistent_id=1, chain_type=1, features=34816, server_version_info=Version 24.1.0 Build 115 03/21/2024 SC Pro Edition
Info : TAP position 0 (C341A0DD) has 3 SLD nodes
Info : node 0 idcode=00406E00 position_n=0
Info : node 1 idcode=30006E00 position_n=0
Info : node 2 idcode=0C006E00 position_n=0
Info : TAP position 1 (20D10DD) has 1 SLD nodes
Info : node 0 idcode=0C206E00 position_n=0
Info : Discovered 2 TAP devices
Info : Detected device (tap_position=0) device_id=c341a0dd, instruction_length=10, features=12, device_name=AGFB014R24A(.|R1|R2)/..
Info : Found an Intel device at tap_position 0.Currently assuming it is SLD Hub
Info : Detected device (tap_position=1) device_id=020d10dd, instruction_length=10, features=4, device_name=VTAP10
Info : Found an Intel device at tap_position 1.Currently assuming it is SLD Hub
Info : This adapter doesn't support configurable speed
Info : JTAG tap: agilex7.fpga.tap tap/device found: 0xc341a0dd (mfg: 0x06e (Altera), part: 0x341a, ver: 0xc)
Info : JTAG tap: auto0.tap tap/device found: 0x020d10dd (mfg: 0x06e (Altera), part: 0x20d1, ver: 0x0)
Info : JTAG tap: agilex7.fpga.tap Parent Tap found: 0xc341a0dd (mfg: 0x06e (Altera), part: 0x341a, ver: 0xc)
Info : Virtual Tap/SLD node 0x00406E00 found at tap position 0 vtap position 0
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 10 -expected-id 0x020d10dd"
Info : datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x40141107
Info : starting gdb server for agilex7.cva6.0 on 3333
Info : Listening on port 3333 for gdb connections
Ready for Remote Connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
```
- **Common for both boards**
Then you will be able to either connect through `telnet` or with `gdb`:
```
riscv64-unknown-elf-gdb /path/to/elf
risc-none-elf-gdb /path/to/elf
(gdb) target remote localhost:3333
(gdb) load
@ -413,6 +526,10 @@ If you use CVA6 in your academic work you can cite us:
<br/>
# Resources and Ecosystem
The CVA6 core is part of a vivid ecosystem. In [this document](RESOURCES.md), we gather pointers to this ecosystem (building blocks, designs, partners...)
# Acknowledgements
Check out the [acknowledgements](ACKNOWLEDGEMENTS.md).

131
RESOURCES.md Normal file
View file

@ -0,0 +1,131 @@
# CVA6 Ecosystem and Resources
The CORE-V CVA6 core is part of a large open-source ecosystem. In this page, we collect pointers to this ecosystem, so that CVA6 users can find their way.
Please help improve this page, by filing an [issue](https://github.com/openhwgroup/cva6/issues) or a [pull request](https://github.com/openhwgroup/cva6/pulls). For pull requests, you need to sign the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/ECA.php).
> [!NOTE]
> We only collect here pointers to resources that are mature enough to be used by external users.
> Resources that reach the TRL-5 maturity (ready to integrate into productions ICs) are clearly mentioned.
> Otherwise, you can assume a TRL-4 maturity.
> [!WARNING]
> The CVA6 team is not liable for the other repositories.
> Assess their content and make sure they fit your needs and are mature enough for your design.
> Plese direct your issues or pull requests to these external repositories.
## Our legacy
CVA6 was designed by the **[PULP Platform team](https://www.pulp-platform.org/)**. You can integrate it with many other PULP designs from [github.com/pulp-platform](https://github.com/pulp-platform).
## Technical resources
### SW Tools and OSes
**RISC-V tools** for CVA6 and **Buildroot Linux** support are available [here](https://github.com/openhwgroup/cva6-sdk).
**Yocto Linux** support for CVA6 is available [here](https://github.com/openhwgroup/meta-cva6-yocto).
**FreeRTOS** support for CVA6 is available [here](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main/RISC-V_cva6).
**Zephyr** support for CV64A6 will soon be available.
**Bao** ([repository](https://github.com/bao-project/bao-hypervisor), [documentation](https://github.com/bao-project/bao-docs)) is an embedded hypervisor targetting strong isolation and real-time guarantees, leveraging CV64A6 optional hypervisor support.
**seL4**, secure, formally verified microkernel supports CVA6 (still by its old ARIANE name) [here](https://docs.sel4.systems/Hardware/ariane.html).
This [tutorial](https://github.com/ThalesGroup/cva6-eclipse-demo) offers resources to debug CVA6 under **Eclipse IDE**.
The OS ports above are usually on Digilent Genesys 2 board.
### Related building blocks
These building blocks fit very nicely with CVA6:
**[OpenPiton](https://github.com/PrincetonUniversity/openpiton)** is a many-core framework that supports CVA6.
**[Culsans/CV-TCCC](https://github.com/pulp-platform/culsans)** is a multi-core infrastructure for a few CVA6 cores.
**[ARA/CV-VEC](https://github.com/pulp-platform/ara)** is a vector unit for CVA6.
**[HPDcache](https://github.com/openhwgroup/cv-hpdcache)** is a flexible (highly configurable) and high-throughput L1 cache.
**[IOMMU](https://github.com/zero-day-labs/riscv-iommu)** supports the RISC-V Input/Output Memory Management Unit (IOMMU) Specification, including the hypervisor privilege.
**[IOPMP](https://github.com/zero-day-labs/riscv-iopmp)** supports the RISC-V Input/Output Physical Memory Protection (IOPMP) Specification.
**[AIA](https://github.com/zero-day-labs/riscv-aia)** supports the RISC-V Advanced Interrupt Architecture (AIA) specification.
### Design examples (FPGA)
The CVA6 repository contains the CVA6 core and a basic CPU design, the "APU" and its implementation on a Digilent Genesys 2 FPGA board. Here is a list of other CVA6-based FPGA designs:
The [technical kits](https://github.com/thalesgroup/cva6-softcore-contest) of a **student contest** organized in France can be used as educational resources or as an easy way to get CVA6 up and running with a cheaper Digilent Zybo Z7-20 board. You will find in it:
- The 2020-2021 contest, focusing on PPA optimization;
- The 2021-2022 contest, focusing on energy optimization;
- The 2022-2023 contest, focusing on cybersecurity, including a port of Zephyr OS;
- The 2023-2024 contest, focusing on the acceleration of the MNIST digit recognition with custom extensions;
- The 2024-2025 contest, focusing on the frequency increase;
- A treat with the support of Linux and a VGA output.
**[CVA6 with Xilinx Ethernet](https://github.com/cispa/CVA6-Vivado-Project-with-Xilinx-AXI-Ethernet/)** is an alternative design which implements Xilinx 1G/2.5G Ethernet Subsystem on the Digilent Genesys 2 FPGA board. It has been tested with TFTP boot in u-boot and SSH in Linux.
### Platforms, subsystems and systems
These are large subsystems and systems that are more complex than the "APU". They can be a starting point for your design:
**Cheshire** ([repository](https://github.com/pulp-platform/cheshire), [documentation](https://pulp-platform.github.io/cheshire/))
is a light-weight, open-source (including peripherals), linux-capable RISC-V system built around CVA6.
It can be integrated as Linux-capable host in larger, heterogeneous systems.
**Carfield** ([repository](https://github.com/pulp-platform/carfield), [documentation](https://pulp-platform.github.io/carfield/))
is a mixed-criticality platform targeting automotive applications with several safety, security,
and predictability features built around Cheshire and CVA6.
**AlSaqr** ([repository](https://github.com/AlSaqr-platform/he-soc/tree/master))
is as secure system for Nano-UAV navigation based on CVA6 and Culsans.
### Designs (ASIC) and chiplets
Here are open-source ASIC designs based on CVA6, that have been prototyped on silicon:
**[Polara APU](https://github.com/openhwgroup/core-v-polara-apu)**
is a 4-core processor made with OpenPiton, ARA and CVA6.
**[Basilisk](https://github.com/pulp-platform/cheshire-ihp130-o)**
is an end-to-end open-source, Linux-capable chip based on Cheshire, CVA6, Yosys and OpenRoad.
**Occamy** ([repository](https://github.com/pulp-platform/occamy),
[article](https://pulp-platform.org/occamy/),
[paper](https://doi.org/10.1109/VLSITechnologyandCir46783.2024.10631529))
is a 432-core, 2.5D chiplet RISC-V system with CVA6 as manager core.
## Business resources
### Service offer
These companies are OpenHW members, have a good CVA6 knowledge, and offer CVA6-related service:
**Zero-Day Labs** provides design and development services primarily related to embedded software/firmware security and hardware (RTL) for RISC-V.
With major contributions in the scope of RISC-V virtualization, the company has developed and maintains the RISC-V Hypervisor extension in CVA6
and has recently made open-source the RISC-V AIA and IOMMU IPs.
Contact: [geral@zero-day-labs.com](mailto:geral@zero-day-labs.com).
RISC-V made easy - experienced ASIC/FPGA service providers, [**PlanV**](https://planv.tech/) will help you navigate the IP landscape,
optimize your design workflows, and bring your RISC-V chip to life.
[**MU-Electronics**](https://www.mu-e.com/) is a services company having its design center in Rabat-Morocco since 2003, specialized in ICs design from datasheet to GDSII generation
(RTL design, DFT, verification, full custom layout, place and route), firmware, driver & application development, test & validation, security implementation & support to certification.
MU-E has designed IPs and Chips down to 7nm. MU-E is participating in the European TRISTAN project and working for Thales on the verification of CVA6.
[**10xEngineers**](https://10xengineers.ai/) is a design and verification services company focused on RISC-V. We contribute to compiler enablement, RTL design,
and verification efforts within the OpenHW ecosystem. Our work on CVA6 includes architectural and microarchitectural verification of MMU
and implementation of multiple RISC-V extensions, such as Bitmanip, Zicond, Zcb, and Zcmp. Our expert team assists companies in integrating,
customizing, and optimizing CVA6 to meet their unique requirements.
_(To be completed based on companies's requests. Max 1 URL and 70 words per company)_
### Product ICs
If you have integrated CVA6 into a production IC, we'd like to hear from you and mention it here.

View file

@ -1,7 +1,7 @@
#!/bin/bash
echo 'deb http://download.opensuse.org/repositories/home:/phiwag:/edatools/xUbuntu_20.04/ /' | sudo tee /etc/apt/sources.list.d/home:phiwag:edatools.list
curl -fsSL https://download.opensuse.org/repositories/home:phiwag:edatools/xUbuntu_20.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_phiwag_edatools.gpg > /dev/null
curl -fsSL https://download.opensuse.org/repositories/home:phiwag:edatools/Debian_Unstable/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_phiwag_edatools.gpg > /dev/null
sudo apt update
sudo apt install device-tree-compiler libfl-dev help2man

View file

@ -0,0 +1,46 @@
// Copyright 2025 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Yannick Casamatta - Thales
// Date: 22/10/2024
module hpdcache_sram_1rw
#(
parameter int unsigned ADDR_SIZE = 0,
parameter int unsigned DATA_SIZE = 0,
parameter int unsigned DEPTH = 2**ADDR_SIZE
)
(
input logic clk,
input logic rst_n,
input logic cs,
input logic we,
input logic [ADDR_SIZE-1:0] addr,
input logic [DATA_SIZE-1:0] wdata,
output logic [DATA_SIZE-1:0] rdata
);
SyncSpRam #(
.ADDR_WIDTH(ADDR_SIZE),
.DATA_DEPTH(DEPTH), // usually 2**ADDR_WIDTH, but can be lower
.DATA_WIDTH(DATA_SIZE),
.OUT_REGS (0),
.SIM_INIT (1) // for simulation only, will not be synthesized
// 0: no init, 1: zero init, 2: random init
// note: on verilator, 2 is not supported. define the VERILATOR macro to work around.
)SyncSpRam_i(
.Clk_CI (clk),
.Rst_RBI (rst_n),
.CSel_SI (cs),
.WrEn_SI (we),
.Addr_DI (addr),
.WrData_DI(wdata),
.RdData_DO(rdata)
);
endmodule : hpdcache_sram_1rw

View file

@ -0,0 +1,114 @@
// Copyright 2025 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Yannick Casamatta - Thales
// Date: 22/10/2024
module hpdcache_sram_wbyteenable_1rw
#(
parameter int unsigned ADDR_SIZE = 0,
parameter int unsigned DATA_SIZE = 0,
parameter int unsigned DEPTH = 2**ADDR_SIZE
)
(
input logic clk,
input logic rst_n,
input logic cs,
input logic we,
input logic [ADDR_SIZE-1:0] addr,
input logic [DATA_SIZE-1:0] wdata,
input logic [DATA_SIZE/8-1:0] wbyteenable,
output logic [DATA_SIZE-1:0] rdata
);
if (DATA_SIZE == 128) begin
// Découpage des données en deux moitiés de 64 bits
logic [DATA_SIZE/2-1:0] wdata_low, wdata_high;
logic [DATA_SIZE/2-1:0] rdata_low, rdata_high;
logic [7:0] be_low, be_high;
assign wdata_low = wdata[63:0];
assign wdata_high = wdata[127:64];
assign be_low = wbyteenable[7:0];
assign be_high = wbyteenable[15:8];
SyncSpRamBeNx64 #(
.ADDR_WIDTH(ADDR_SIZE),
.DATA_DEPTH(DEPTH),
.OUT_REGS (0),
.SIM_INIT (1)
) SyncSpRam_0 (
.Clk_CI (clk),
.Rst_RBI (rst_n),
.CSel_SI (cs),
.WrEn_SI (we), // Ecriture sur la banque basse
.BEn_SI (be_low),
.Addr_DI (addr),
.WrData_DI(wdata_low),
.RdData_DO(rdata_low)
);
SyncSpRamBeNx64 #(
.ADDR_WIDTH(ADDR_SIZE),
.DATA_DEPTH(DEPTH),
.OUT_REGS (0),
.SIM_INIT (1)
) SyncSpRam_1 (
.Clk_CI (clk),
.Rst_RBI (rst_n),
.CSel_SI (cs),
.WrEn_SI (we), // Ecriture sur la banque haute
.BEn_SI (be_high),
.Addr_DI (addr),
.WrData_DI(wdata_high),
.RdData_DO(rdata_high)
);
assign rdata = {rdata_high, rdata_low};
end else if (DATA_SIZE == 64) begin
SyncSpRamBeNx64 #(
.ADDR_WIDTH(ADDR_SIZE),
.DATA_DEPTH(DEPTH), // usually 2**ADDR_WIDTH, but can be lower
.OUT_REGS (0),
.SIM_INIT (1) // for simulation only, will not be synthesized
// 0: no init, 1: zero init, 2: random init
// note: on verilator, 2 is not supported. define the VERILATOR macro to work around.
)SyncSpRam_i(
.Clk_CI (clk),
.Rst_RBI (rst_n),
.CSel_SI (cs),
.WrEn_SI (we),
.BEn_SI (wbyteenable),
.Addr_DI (addr),
.WrData_DI(wdata),
.RdData_DO(rdata)
);
end else if (DATA_SIZE == 32) begin
SyncSpRamBeNx32 #(
.ADDR_WIDTH(ADDR_SIZE),
.DATA_DEPTH(DEPTH), // usually 2**ADDR_WIDTH, but can be lower
.OUT_REGS (0),
.SIM_INIT (1) // for simulation only, will not be synthesized
// 0: no init, 1: zero init, 2: random init
// note: on verilator, 2 is not supported. define the VERILATOR macro to work around.
)SyncSpRam_i(
.Clk_CI (clk),
.Rst_RBI (rst_n),
.CSel_SI (cs),
.WrEn_SI (we),
.BEn_SI (wbyteenable),
.Addr_DI (addr),
.WrData_DI(wdata),
.RdData_DO(rdata)
);
end else begin
$fatal(1, "DATASIZE=%d, in not supported " ,DATA_SIZE);
end
endmodule : hpdcache_sram_wbyteenable_1rw

View file

@ -20,37 +20,37 @@
module instr_tracer #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type bp_resolve_t = logic,
parameter type scoreboard_entry_t = logic,
parameter type scoreboard_entry_t = logic[303:0], // Fix for xcelium bug at runtime: does not have enough memory space reserved for scoreboard_entry
parameter type interrupts_t = logic,
parameter type exception_t = logic,
parameter interrupts_t INTERRUPTS = '0
)(
input logic pck,
input logic rstn,
input logic flush_unissued,
input logic flush_all,
input logic [31:0] instruction,
input logic fetch_valid,
input logic fetch_ack,
input logic issue_ack, // issue acknowledged
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
input logic [1:0][4:0] waddr, // WB stage
input logic [1:0][63:0] wdata,
input logic [1:0] we_gpr,
input logic [1:0] we_fpr,
input scoreboard_entry_t [1:0] commit_instr, // commit instruction
input logic [1:0] commit_ack,
input logic st_valid, // stores - address translation
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
input logic ld_valid, // loads
input logic ld_kill,
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
input bp_resolve_t resolve_branch, // misprediction
input exception_t commit_exception,
input riscv::priv_lvl_t priv_lvl, // current privilege level
input logic debug_mode,
input logic pck,
input logic rstn,
input logic flush_unissued,
input logic flush_all,
input logic [31:0] instruction [CVA6Cfg.NrIssuePorts-1:0],
input logic [CVA6Cfg.NrIssuePorts-1:0] fetch_valid,
input logic [CVA6Cfg.NrIssuePorts-1:0] fetch_ack,
input logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack, // issue acknowledged
input scoreboard_entry_t [CVA6Cfg.NrIssuePorts-1:0] issue_sbe, // issue scoreboard entry
input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr, // WB stage
input logic [CVA6Cfg.NrCommitPorts-1:0][63:0] wdata,
input logic [CVA6Cfg.NrCommitPorts-1:0] we_gpr,
input logic [CVA6Cfg.NrCommitPorts-1:0] we_fpr,
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr, // commit instruction
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack,
input logic st_valid, // stores - address translation
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
input logic ld_valid, // loads
input logic ld_kill,
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
input bp_resolve_t resolve_branch, // misprediction
input exception_t commit_exception,
input riscv::priv_lvl_t priv_lvl, // current privilege level
input logic debug_mode,
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
);
// keep the decoded instructions in a queue
@ -94,7 +94,7 @@ module instr_tracer #(
forever begin
automatic bp_resolve_t bp_instruction = '0;
// new cycle, we are only interested if reset is de-asserted
@(pck) if (rstn !== 1'b1) begin
@(posedge pck) if (rstn !== 1'b1) begin
flush();
continue;
end
@ -106,20 +106,24 @@ module instr_tracer #(
// Instruction Decode
// -------------------
// we are decoding an instruction
if (fetch_valid && fetch_ack) begin
decode_instruction = instruction;
decode_queue.push_back(decode_instruction);
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; ++i) begin
if (fetch_valid[i] && fetch_ack[i]) begin
decode_instruction = instruction[i];
decode_queue.push_back(decode_instruction);
end
end
// -------------------
// Instruction Issue
// -------------------
// we got a new issue ack, so put the element from the decode queue to
// the issue queue
if (issue_ack && !flush_unissued) begin
issue_instruction = decode_queue.pop_front();
issue_queue.push_back(issue_instruction);
// also save the scoreboard entry to a separate issue queue
issue_sbe_queue.push_back(scoreboard_entry_t'(issue_sbe));
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; ++i) begin
if (issue_ack[i] && !flush_unissued) begin
issue_instruction = decode_queue.pop_front();
issue_queue.push_back(issue_instruction);
// also save the scoreboard entry to a separate issue queue
issue_sbe_queue.push_back(scoreboard_entry_t'(issue_sbe[i]));
end
end
// --------------------

View file

@ -106,8 +106,8 @@ end
// synthesis translate_off
begin: i_tc_sram_wrapper_user
begin: i_tc_sram
logic init_val;
localparam type data_t = logic [63:0];
data_t init_val [0:0];
data_t sram [NUM_WORDS-1:0] /* verilator public_flat */;
end
end

View file

@ -33,21 +33,29 @@ pip3 install -r requirements.txt
## Usage
```bash
#Generate the Markdown-text /Restructred-text documentation for Control and Status Registers (CSR)
python3 <scripts/riscv_config_gen>.py -s <../riscv-config/Config_Name/generated/isa_gen>.yaml -m <updaters/Config_Name/csr_updater>.yaml -t < Config_Name>
#Generate Restructred-text documentation for Control and Status Registers (CSR)
python3 <scripts/riscv_config_gen>.py -s <../riscv-config/Config_Name/generated/isa_gen>.yaml -c <../riscv-config/Config_Name/generated/custom_gen>.yaml -d <../riscv-config/Config_Name/generated/debug_gen>.yaml -m <updaters/Config_Name/csr_updater>.yaml -t < Config_Name>
#Generate the Markdown-text /Restructred-text documentation for ISA extensions
#Generate Restructred-text documentation for ISA extensions
python3 <scripts/riscv_config_gen>.py -s <../riscv-config/Config_Name/generated/isa_gen>.yaml -i <templates/isa_template>.yaml -m <updaters/Config_Name/isa_updater>.yaml -t < Config_Name>
#Generate the Yaml spike configuration file
python3 <scripts/riscv_config_gen>.py -s <../riscv-config/Config_Name/generated/isa_gen>.yaml -c <../riscv-config/Config_Name/generated/custom_gen>.yaml -i <templates/spike>.mako -m <updaters/Config_Name/spike_updater>.yaml -t < Config_Name>
```
## Usage with cv32a65x
```bash
#Generate the Markdown-text /Restructred-text documentation for Control and Status Registers (CSR)
python3 scripts/riscv_config_gen.py -s ../riscv-config/cv32a65x/generated/isa_gen.yaml -m updaters/cv32a65x/csr_updater.yaml -t cv32a65x
#Generate the Restructred-text documentation for Control and Status Registers (CSR)
python3 scripts/riscv_config_gen.py -s ../riscv-config/cv32a65x/generated/isa_gen.yaml -c ../riscv-config/cv32a65x/generated/custom_gen.yaml -d ../riscv-config/cv32a65x/generated/debug_gen.yaml -m updaters/cv32a65x/csr_updater.yaml -t cv32a65x
#Generate the Markdown-text /Restructred-text documentation for ISA extensions
#Generate the Restructred-text documentation for ISA extensions
python3 scripts/riscv_config_gen.py -s ../riscv-config/cv32a65x/generated/isa_gen.yaml -i templates/isa_template.yaml -m updaters/cv32a65x/isa_updater.yaml -t cv32a65x
#Generate the Yaml spike configuration file
python3 scripts/riscv_config_gen.py -s ../riscv-config/cv32a65x/generated/isa_gen.yaml -c ../riscv-config/cv32a65x/generated/custom_gen.yaml -i templates/spike.mako -m updaters/cv32a65x/spike_updater.yaml -t cv32a65x
```
You could find your output files in this directory :
@ -58,10 +66,18 @@ if the output is ISA Documentation:
if the output is CSR Documentation :
`<Config_Name>/csr/`
for more details about How to write CSR or ISA Updater,see [UPDATERS](##Updaters) section
if the output is Spike yaml :
`<Config_Name>/spike/`
for more details about How to write CSR or ISA Updater,see [Updaters](#updaters) section
for more details about How to write ISA template ,see [Annexes2](#annexes2) section
for more details about How to write spike template , see [mako](https://www.makotemplates.org/) section
for more details about How to write ISA template ,see [Annexes2](##Annexes2) section
@ -126,7 +142,7 @@ Example : ISA_Updater.yaml
-If you want to modify any parameter for registers in RISC CONFIG YAML :
Format :
- Format :
Register name :
sub_feature :
@ -142,7 +158,7 @@ Example : ISA_Updater.yaml
-If you want to exclude any registers base on condition :
Format :
- Format :
exclude :
@ -151,7 +167,7 @@ Example : ISA_Updater.yaml
sub_key : sub_value (if exist if not dont include it )
cond: value
Exemple :
- Exemple :
exclude :
@ -164,12 +180,12 @@ Example : ISA_Updater.yaml
Example : (PMPADDR , MHPMCOUNTER, ...)
Format :
- Format :
Register Name :
range : number
Exemple :
- Exemple :
pmpaddr :
@ -180,6 +196,56 @@ CSR/ISA Updater read RISC-CONFIG.yaml and update the registers so if you want to
### SPIKE Updater
-If you want to modify any parameter Spike yaml:
- Format :
<parameter name> : <parameter value>
- Example :
bootrom: false
-If you want to to modify any parameter in core config in Spike yaml :
- Format :
cores:
<parameter name> : <parameter value>
- Exemple :
Bootroom : true
- Exemple :
cores:
isa: rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
boot_addr: 0x80000000
marchid: 0x3
misa_we: false
misa_we_enable: true
pmpaddr0: 0x0
pmpcfg0: 0x0
pmpregions: 0x40
usable_pmpregions : 0x8
priv: M
status_fs_field_we: false
status_fs_field_we_enable: false
status_vs_field_we: false
status_vs_field_we_enable: false
misa_we: false
mstatus_write_mask: 0x00000088
mstatus_override_mask: 0x00001800
mtval_write_mask: 0x00000000
unified_traps: true
Spike Updater read spike.yaml and update the parameters so if you want to add parameter in spike.yaml you need to respect it architecture.
## Annexes

View file

@ -23,13 +23,29 @@ SECTIONS
/* text: test code section */
. = 0x80000000;
_start_text = .;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.uvmif : { *(.uvmif) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.text.startup : { *(.text.startup) }
. = ALIGN(0x1000);
_end_text = .;
. = ALIGN(0x1000);
.rodata : { *(.rodata*)}
. = ALIGN(0x8);
. = ALIGN(0x1000);
.page_table : { *(.page_table) }
.user_stack : { *(.user_stack) }
.kernel_data : { *(.kernel_data) }
.kernel_stack : { *(.kernel_stack) }
/* data segment */
.data : { *(.data) }

View file

@ -0,0 +1,54 @@
spike_param_tree:
bootrom: true
bootrom_base: 65536
bootrom_size: 4096
dram: true
dram_base: 2147483648
dram_size: 1073741824
generic_core_config: false
max_steps: 200000
max_steps_enabled: false
isa: rv32imczicsr_zcb_zba_zbb_zbc_zbs
priv: M
core_configs:
-
isa: rv32imczicsr_zcb_zba_zbb_zbc_zbs
extensions: cv32a60x,cvxif
boot_addr: 2147483648
marchid_override_mask: 0xFFFFFFFF
marchid_override_value: 0x3
misa_write_mask: 0x0
pmp_granularity: 8
pmpaddr0: 0
pmpcfg0: 0
pmpregions_max: 64
pmpregions_writable: 8
priv: M
status_fs_field_we: false
status_fs_field_we_enable: false
status_vs_field_we: false
status_vs_field_we_enable: false
mstatus_write_mask: 136
mstatus_override_mask: 6144
mie_write_mask: 0x00000880
mie_override_mask: 0xfffff77f
mie_override_value: 0x00000000
mip_write_mask: 0x00000000
mip_override_mask: 0xfffff77f
mip_override_value: 0x00000000
mtval_write_mask: 0
tinfo_accessible: 0
mscontext_accessible: 0
mcontext_accessible: 0
tdata1_accessible: 0
tdata2_accessible: 0
tdata3_accessible: 0
tselect_accessible: 0
mhartid: 0
mvendorid_override_mask : 0xFFFFFFFF
mvendorid_override_value: 1538
csr_counters_injection: true
interrupts_injection: true
unified_traps: true
mcycleh_implemented: false
mhpmevent31_implemented: false

View file

@ -0,0 +1,537 @@
////
Copyright (c) 2024 OpenHW Group
Copyright (c) 2024 Thales
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
Author: Abdessamii Oukalrazqou
////
=== csr
==== Conventions
In the subsequent sections, register fields are labeled with one of the following abbreviations:
* WPRI (Writes Preserve Values, Reads Ignore Values): read/write field reserved
for future use. For forward compatibility, implementations that do not
furnish these fields must make them read-only zero.
* WLRL (Write/Read Only Legal Values): read/write CSR field that specifies
behavior for only a subset of possible bit encodings, with other bit encodings
reserved.
* WARL (Write Any Values, Reads Legal Values): read/write CSR fields which are
only defined for a subset of bit encodings, but allow any value to be written
while guaranteeing to return a legal value whenever read.
* ROCST (Read-Only Constant): A special case of WARL field which admits only one
legal value, and therefore, behaves as a constant field that silently ignores
writes.
* ROVAR (Read-Only Variable): A special case of WARL field which can take
multiple legal values but cannot be modified by software and depends only on
the architectural state of the hart.
In particular, a register that is not internally divided
into multiple fields can be considered as containing a single field of XLEN bits.
This allows to clearly represent read-write registers holding a single legal value
(typically zero).
==== Register Summary
|===
|Address | Register Name | Privilege | Description
|0x300| `<<_MSTATUS,MSTATUS>>`|MRW|The mstatus register keeps track of and controls the hart's current operating state.
|0x301| `<<_MISA,MISA>>`|MRW|misa is a read-write register reporting the ISA supported by the hart.
|0x304| `<<_MIE,MIE>>`|MRW|The mie register is an MXLEN-bit read/write register containing interrupt enable bits.
|0x305| `<<_MTVEC,MTVEC>>`|MRW|MXLEN-bit read/write register that holds trap vector configuration.
|0x310| `<<_MSTATUSH,MSTATUSH>>`|MRW|The mstatush register keeps track of and controls the harts current operating state.
|0x323-0x33f| `<<_MHPMEVENT3-31,MHPMEVENT[3-31]>>`|MRW|The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.
|0x340| `<<_MSCRATCH,MSCRATCH>>`|MRW|The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.
|0x341| `<<_MEPC,MEPC>>`|MRW|The mepc is a warl register that must be able to hold all valid physical and virtual addresses.
|0x342| `<<_MCAUSE,MCAUSE>>`|MRW|The mcause register stores the information regarding the trap.
|0x343| `<<_MTVAL,MTVAL>>`|MRW|The mtval is a warl register that holds the address of the instruction which caused the exception.
|0x344| `<<_MIP,MIP>>`|MRW|The mip register is an MXLEN-bit read/write register containing information on pending interrupts.
|0x3a0-0x3a1| `<<_PMPCFG0-1,PMPCFG[0-1]>>`|MRW|PMP configuration register
|0x3a2-0x3af| `<<_PMPCFG2-15,PMPCFG[2-15]>>`|MRW|PMP configuration register
|0x3b0-0x3b7| `<<_PMPADDR0-7,PMPADDR[0-7]>>`|MRW|Physical memory protection address register
|0x3b8-0x3ef| `<<_PMPADDR8-63,PMPADDR[8-63]>>`|MRW|Physical memory protection address register
|0x7c0| `<<_ICACHE,ICACHE>>`|MRW|the register controls the operation of the i-cache unit.
|0x7c1| `<<_DCACHE,DCACHE>>`|MRW|the register controls the operation of the d-cache unit.
|0xb00| `<<_MCYCLE,MCYCLE>>`|MRW|Counts the number of clock cycles executed from an arbitrary point in time.
|0xb02| `<<_MINSTRET,MINSTRET>>`|MRW|Counts the number of instructions completed from an arbitrary point in time.
|0xb03-0xb1f| `<<_MHPMCOUNTER3-31,MHPMCOUNTER[3-31]>>`|MRW|The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.
|0xb80| `<<_MCYCLEH,MCYCLEH>>`|MRW|upper 32 bits of mcycle
|0xb82| `<<_MINSTRETH,MINSTRETH>>`|MRW|Upper 32 bits of minstret.
|0xb83-0xb9f| `<<_MHPMCOUNTER3-31H,MHPMCOUNTER[3-31]H>>`|MRW|The mhpmcounterh returns the upper half word in RV32I systems.
|0xf11| `<<_MVENDORID,MVENDORID>>`|MRO|32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.
|0xf12| `<<_MARCHID,MARCHID>>`|MRO|MXLEN-bit read-only register encoding the base microarchitecture of the hart.
|0xf13| `<<_MIMPID,MIMPID>>`|MRO|Provides a unique encoding of the version of the processor implementation.
|0xf14| `<<_MHARTID,MHARTID>>`|MRO|MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.
|0xf15| `<<_MCONFIGPTR,MCONFIGPTR>>`|MRO|MXLEN-bit read-only register that holds the physical address of a configuration data structure.
|===
==== Register Description
[[_MSTATUS]]
===== MSTATUS
Address:: 0x300
Reset Value:: 0x00001800
Privilege:: MRW
Description:: The mstatus register keeps track of and controls the hart's current operating state.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| 0 | UIE | 0x0 | ROCST | 0x0 | Stores the state of the user mode interrupts.
| 1 | SIE | 0x0 | ROCST | 0x0 | Stores the state of the supervisor mode interrupts.
| 2 | RESERVED_2 | 0x0 | WPRI | | _Reserved_
| 3 | MIE | 0x0 | WLRL | 0x0 - 0x1 | Stores the state of the machine mode interrupts.
| 4 | UPIE | 0x0 | ROCST | 0x0 | Stores the state of the user mode interrupts prior to the trap.
| 5 | SPIE | 0x0 | ROCST | 0x0 | Stores the state of the supervisor mode interrupts prior to the trap.
| 6 | UBE | 0x0 | ROCST | 0x0 | control the endianness of memory accesses other than instruction fetches for user mode
| 7 | MPIE | 0x0 | WLRL | 0x0 - 0x1 | Stores the state of the machine mode interrupts prior to the trap.
| 8 | SPP | 0x0 | ROCST | 0x0 | Stores the previous priority mode for supervisor.
| [10:9] | RESERVED_9 | 0x0 | WPRI | | _Reserved_
| [12:11] | MPP | 0x3 | WARL | 0x3 | Stores the previous priority mode for machine.
| [14:13] | FS | 0x0 | ROCST | 0x0 | Encodes the status of the floating-point unit, including the CSR fcsr and floating-point data registers.
| [16:15] | XS | 0x0 | ROCST | 0x0 | Encodes the status of additional user-mode extensions and associated state.
| 17 | MPRV | 0x0 | ROCST | 0x0 | Modifies the privilege level at which loads and stores execute in all privilege modes.
| 18 | SUM | 0x0 | ROCST | 0x0 | Modifies the privilege with which S-mode loads and stores access virtual memory.
| 19 | MXR | 0x0 | ROCST | 0x0 | Modifies the privilege with which loads access virtual memory.
| 20 | TVM | 0x0 | ROCST | 0x0 | Supports intercepting supervisor virtual-memory management operations.
| 21 | TW | 0x0 | ROCST | 0x0 | Supports intercepting the WFI instruction.
| 22 | TSR | 0x0 | ROCST | 0x0 | Supports intercepting the supervisor exception return instruction.
| 23 | SPELP | 0x0 | ROCST | 0x0 | Supervisor mode previous expected-landing-pad (ELP) state.
| [30:24] | RESERVED_24 | 0x0 | WPRI | | _Reserved_
| 31 | SD | 0x0 | ROCST | 0x0 | Read-only bit that summarizes whether either the FS field or XS field signals the presence of some dirty state.
|===
[[_MISA]]
===== MISA
Address:: 0x301
Reset Value:: 0x40001106
Privilege:: MRW
Description:: misa is a read-write register reporting the ISA supported by the hart.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [25:0] | EXTENSIONS | 0x1106 | ROCST | 0x1106 | Encodes the presence of the standard extensions, with a single bit per letter of the alphabet.
| [29:26] | RESERVED_26 | 0x0 | WPRI | | _Reserved_
| [31:30] | MXL | 0x1 | WARL | 0x1 | Encodes the native base integer ISA width.
|===
[[_MIE]]
===== MIE
Address:: 0x304
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mie register is an MXLEN-bit read/write register containing interrupt enable bits.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| 0 | USIE | 0x0 | ROCST | 0x0 | User Software Interrupt enable.
| 1 | SSIE | 0x0 | ROCST | 0x0 | Supervisor Software Interrupt enable.
| 2 | VSSIE | 0x0 | ROCST | 0x0 | VS-level Software Interrupt enable.
| 3 | MSIE | 0x0 | ROCST | 0x0 | Machine Software Interrupt enable.
| 4 | UTIE | 0x0 | ROCST | 0x0 | User Timer Interrupt enable.
| 5 | STIE | 0x0 | ROCST | 0x0 | Supervisor Timer Interrupt enable.
| 6 | VSTIE | 0x0 | ROCST | 0x0 | VS-level Timer Interrupt enable.
| 7 | MTIE | 0x0 | WLRL | 0x0 - 0x1 | Machine Timer Interrupt enable.
| 8 | UEIE | 0x0 | ROCST | 0x0 | User External Interrupt enable.
| 9 | SEIE | 0x0 | ROCST | 0x0 | Supervisor External Interrupt enable.
| 10 | VSEIE | 0x0 | ROCST | 0x0 | VS-level External Interrupt enable.
| 11 | MEIE | 0x0 | WLRL | 0x0 - 0x1 | Machine External Interrupt enable.
| 12 | SGEIE | 0x0 | ROCST | 0x0 | HS-level External Interrupt enable.
| [31:13] | RESERVED_13 | 0x0 | WPRI | | _Reserved_
|===
[[_MTVEC]]
===== MTVEC
Address:: 0x305
Reset Value:: 0x80010000
Privilege:: MRW
Description:: MXLEN-bit read/write register that holds trap vector configuration.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [1:0] | MODE | 0x0 | WARL | 0x0 | Vector mode.
| [31:2] | BASE | 0x20004000 | WARL | 0x00000000 - 0x3FFFFFFF | Vector base address.
|===
[[_MSTATUSH]]
===== MSTATUSH
Address:: 0x310
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mstatush register keeps track of and controls the harts current operating state.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [3:0] | RESERVED_0 | 0x0 | WPRI | | _Reserved_
| 4 | SBE | 0x0 | ROCST | 0x0 | control the endianness of memory accesses other than instruction fetches for supervisor mode
| 5 | MBE | 0x0 | ROCST | 0x0 | control the endianness of memory accesses other than instruction fetches for machine mode
| 6 | GVA | 0x0 | ROCST | 0x0 | Stores the state of the supervisor mode interrupts.
| 7 | MPV | 0x0 | ROCST | 0x0 | Stores the state of the user mode interrupts.
| 8 | RESERVED_8 | 0x0 | WPRI | | _Reserved_
| 9 | MPELP | 0x0 | ROCST | 0x0 | Machine mode previous expected-landing-pad (ELP) state.
| [31:10] | RESERVED_10 | 0x0 | WPRI | | _Reserved_
|===
[[_MHPMEVENT3-31]]
===== MHPMEVENT[3-31]
Address:: 0x323-0x33f
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MHPMEVENT[I] | 0x00000000 | ROCST | 0x0 | The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.
|===
[[_MSCRATCH]]
===== MSCRATCH
Address:: 0x340
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MSCRATCH | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.
|===
[[_MEPC]]
===== MEPC
Address:: 0x341
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mepc is a warl register that must be able to hold all valid physical and virtual addresses.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MEPC | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | The mepc is a warl register that must be able to hold all valid physical and virtual addresses.
|===
[[_MCAUSE]]
===== MCAUSE
Address:: 0x342
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mcause register stores the information regarding the trap.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [30:0] | EXCEPTION_CODE | 0x0 | WLRL | 0x0 - 0x8, 0xb | Encodes the exception code.
| 31 | INTERRUPT | 0x0 | WLRL | 0x0 - 0x1 | Indicates whether the trap was due to an interrupt.
|===
[[_MTVAL]]
===== MTVAL
Address:: 0x343
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mtval is a warl register that holds the address of the instruction which caused the exception.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MTVAL | 0x00000000 | ROCST | 0x0 | The mtval is a warl register that holds the address of the instruction which caused the exception.
|===
[[_MIP]]
===== MIP
Address:: 0x344
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mip register is an MXLEN-bit read/write register containing information on pending interrupts.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| 0 | USIP | 0x0 | ROCST | 0x0 | User Software Interrupt Pending.
| 1 | SSIP | 0x0 | ROCST | 0x0 | Supervisor Software Interrupt Pending.
| 2 | VSSIP | 0x0 | ROCST | 0x0 | VS-level Software Interrupt Pending.
| 3 | MSIP | 0x0 | ROCST | 0x0 | Machine Software Interrupt Pending.
| 4 | UTIP | 0x0 | ROCST | 0x0 | User Timer Interrupt Pending.
| 5 | STIP | 0x0 | ROCST | 0x0 | Supervisor Timer Interrupt Pending.
| 6 | VSTIP | 0x0 | ROCST | 0x0 | VS-level Timer Interrupt Pending.
| 7 | MTIP | 0x0 | ROVAR | 0x0 - 0x1 | Machine Timer Interrupt Pending.
| 8 | UEIP | 0x0 | ROCST | 0x0 | User External Interrupt Pending.
| 9 | SEIP | 0x0 | ROCST | 0x0 | Supervisor External Interrupt Pending.
| 10 | VSEIP | 0x0 | ROCST | 0x0 | VS-level External Interrupt Pending.
| 11 | MEIP | 0x0 | ROVAR | 0x0 - 0x1 | Machine External Interrupt Pending.
| 12 | SGEIP | 0x0 | ROCST | 0x0 | HS-level External Interrupt Pending.
| [31:13] | RESERVED_13 | 0x0 | WPRI | | _Reserved_
|===
[[_PMPCFG0-1]]
===== PMPCFG[0-1]
Address:: 0x3a0-0x3a1
Reset Value:: 0x00000000
Privilege:: MRW
Description:: PMP configuration register
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [2:0] | PMP[I*4 +0]CFG.RWX | 0x0 | WARL | 0x0, 0x1, 0x3, 0x4, 0x5, 0x7 | PMP[I*4 +0]CFG collective R, W and X field (R is bit 0, X is bit 2)
| [5:4] | PMP[I*4 +0]CFG.A | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +0]CFG address-matching mode (A)
| 7 | PMP[I*4 +0]CFG.L | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +0]CFG entry locked (L)
| [2:0] | PMP[I*4 +1]CFG | 0x0 | WARL | 0x0, 0x1, 0x3, 0x4, 0x5, 0x7 | PMP[I*4 +1]CFG collective R, W and X field (R is bit 0, X is bit 2)
| [13:12] | PMP[I*4 +1]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +1]CFG address-matching mode (A)
| 15 | PMP[I*4 +1]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +1]CFG entry locked (L)
| [18:16] | PMP[I*4 +2]CFG | 0x0 | WARL | 0x0, 0x1, 0x3, 0x4, 0x5, 0x7 | PMP[I*4 +2]CFG collective R, W and X field (R is bit 0, X is bit 2)
| [21:20] | PMP[I*4 +2]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +2]CFG address-matching mode (A)
| 23 | PMP[I*4 +2]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +2]CFG entry locked (L)
| [26:24] | PMP[I*4 +3]CFG | 0x0 | WARL | 0x0, 0x1, 0x3, 0x4, 0x5, 0x7 | PMP[I*4 +3]CFG collective R, W and X field (R is bit 0, X is bit 2)
| [29:28] | PMP[I*4 +3]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +3]CFG address matching mode (A)
| 31 | PMP[I*4 +3]CFG | 0x0 | WARL | 0x0 - 0x1 | PMP[I*4 +3]CFG entry locked (L)
|===
[[_PMPCFG2-15]]
===== PMPCFG[2-15]
Address:: 0x3a2-0x3af
Reset Value:: 0x00000000
Privilege:: MRW
Description:: PMP configuration register
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [7:0] | PMP[I*4 +0]CFG | 0x0 | ROCST | 0x0 | pmp configuration bits
| [15:8] | PMP[I*4 +1]CFG | 0x0 | ROCST | 0x0 | pmp configuration bits
| [23:16] | PMP[I*4 +2]CFG | 0x0 | ROCST | 0x0 | pmp configuration bits
| [31:24] | PMP[I*4 +3]CFG | 0x0 | ROCST | 0x0 | pmp configuration bits
|===
[[_PMPADDR0-7]]
===== PMPADDR[0-7]
Address:: 0x3b0-0x3b7
Reset Value:: 0x00000000
Privilege:: MRW
Description:: Physical memory protection address register
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | PMPADDR[I] | 0x00000000 | WARL | masked: & 0xFFFFFFFE \| 0x0 | Physical memory protection address register
|===
[[_PMPADDR8-63]]
===== PMPADDR[8-63]
Address:: 0x3b8-0x3ef
Reset Value:: 0x00000000
Privilege:: MRW
Description:: Physical memory protection address register
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | PMPADDR[I] | 0x00000000 | ROCST | 0x0 | Physical memory protection address register
|===
[[_ICACHE]]
===== ICACHE
Address:: 0x7c0
Reset Value:: 0x00000001
Privilege:: MRW
Description:: the register controls the operation of the i-cache unit.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| 0 | ICACHE | 0x1 | RW | 0x1 | bit for cache-enable of instruction cache
| [31:1] | RESERVED_1 | 0x0 | WPRI | | _Reserved_
|===
[[_DCACHE]]
===== DCACHE
Address:: 0x7c1
Reset Value:: 0x00000001
Privilege:: MRW
Description:: the register controls the operation of the d-cache unit.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| 0 | DCACHE | 0x1 | RW | 0x1 | bit for cache-enable of data cache
| [31:1] | RESERVED_1 | 0x0 | WPRI | | _Reserved_
|===
[[_MCYCLE]]
===== MCYCLE
Address:: 0xb00
Reset Value:: 0x00000000
Privilege:: MRW
Description:: Counts the number of clock cycles executed from an arbitrary point in time.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MCYCLE | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | Counts the number of clock cycles executed from an arbitrary point in time.
|===
[[_MINSTRET]]
===== MINSTRET
Address:: 0xb02
Reset Value:: 0x00000000
Privilege:: MRW
Description:: Counts the number of instructions completed from an arbitrary point in time.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MINSTRET | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | Counts the number of instructions completed from an arbitrary point in time.
|===
[[_MHPMCOUNTER3-31]]
===== MHPMCOUNTER[3-31]
Address:: 0xb03-0xb1f
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MHPMCOUNTER[I] | 0x00000000 | ROCST | 0x0 | The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.
|===
[[_MCYCLEH]]
===== MCYCLEH
Address:: 0xb80
Reset Value:: 0x00000000
Privilege:: MRW
Description:: upper 32 bits of mcycle
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MCYCLEH | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | upper 32 bits of mcycle
|===
[[_MINSTRETH]]
===== MINSTRETH
Address:: 0xb82
Reset Value:: 0x00000000
Privilege:: MRW
Description:: Upper 32 bits of minstret.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MINSTRETH | 0x00000000 | WARL | 0x00000000 - 0xFFFFFFFF | Upper 32 bits of minstret.
|===
[[_MHPMCOUNTER3-31H]]
===== MHPMCOUNTER[3-31]H
Address:: 0xb83-0xb9f
Reset Value:: 0x00000000
Privilege:: MRW
Description:: The mhpmcounterh returns the upper half word in RV32I systems.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MHPMCOUNTER[I]H | 0x00000000 | ROCST | 0x0 | The mhpmcounterh returns the upper half word in RV32I systems.
|===
[[_MVENDORID]]
===== MVENDORID
Address:: 0xf11
Reset Value:: 0x00000602
Privilege:: MRO
Description:: 32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MVENDORID | 0x00000602 | ROCST | 0x602 | 32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.
|===
[[_MARCHID]]
===== MARCHID
Address:: 0xf12
Reset Value:: 0x00000003
Privilege:: MRO
Description:: MXLEN-bit read-only register encoding the base microarchitecture of the hart.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MARCHID | 0x00000003 | ROCST | 0x3 | MXLEN-bit read-only register encoding the base microarchitecture of the hart.
|===
[[_MIMPID]]
===== MIMPID
Address:: 0xf13
Reset Value:: 0x00000000
Privilege:: MRO
Description:: Provides a unique encoding of the version of the processor implementation.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MIMPID | 0x00000000 | ROCST | 0x0 | Provides a unique encoding of the version of the processor implementation.
|===
[[_MHARTID]]
===== MHARTID
Address:: 0xf14
Reset Value:: 0x00000000
Privilege:: MRO
Description:: MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MHARTID | 0x00000000 | ROCST | 0x0 | MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.
|===
[[_MCONFIGPTR]]
===== MCONFIGPTR
Address:: 0xf15
Reset Value:: 0x00000000
Privilege:: MRO
Description:: MXLEN-bit read-only register that holds the physical address of a configuration data structure.
|===
| Bits | Field Name | Reset Value | Type | Legal Values | Description
| [31:0] | MCONFIGPTR | 0x00000000 | ROCST | 0x0 | MXLEN-bit read-only register that holds the physical address of a configuration data structure.
|===

View file

@ -1,353 +0,0 @@
<!--Copyright (c) 2024 OpenHW Group
Copyright (c) 2024 Thales
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
Author: Abdessamii Oukalrazqou
-->
# csr
## Registers Summary
|Address|Register Name|Description|
| :--- | :--- | :--- |
|0x300|[MSTATUS](#MSTATUS)|The mstatus register keeps track of and controls the harts current operating state.|
|0x300|[MSTATUSH](#MSTATUSH)|The mstatush register keeps track of and controls the harts current operating state.|
|0x301|[MISA](#MISA)|misa is a read-write register reporting the ISA supported by the hart.|
|0x304|[MIE](#MIE)|The mie register is an MXLEN-bit read/write register containing interrupt enable bits.|
|0x305|[MTVEC](#MTVEC)|MXLEN-bit read/write register that holds trap vector configuration.|
|0x323-0x33f|[MHPMEVENT[3-31]](#MHPMEVENT[3-31])|The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.|
|0x340|[MSCRATCH](#MSCRATCH)|The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.|
|0x341|[MEPC](#MEPC)|The mepc is a warl register that must be able to hold all valid physical and virtual addresses.|
|0x342|[MCAUSE](#MCAUSE)|The mcause register stores the information regarding the trap.|
|0x343|[MTVAL](#MTVAL)|The mtval is a warl register that holds the address of the instruction which caused the exception.|
|0x344|[MIP](#MIP)|The mip register is an MXLEN-bit read/write register containing information on pending interrupts.|
|0x3a0-0x3a1|[PMPCFG[0-1]](#PMPCFG[0-1])|PMP configuration register|
|0x3b0-0x3b7|[PMPADDR[0-7]](#PMPADDR[0-7])|Physical memory protection address register|
|0xb00|[MCYCLE](#MCYCLE)|Counts the number of clock cycles executed from an arbitrary point in time.|
|0xb02|[MINSTRET](#MINSTRET)|Counts the number of instructions completed from an arbitrary point in time.|
|0xb03-0xb1f|[MHPMCOUNTER[3-31]](#MHPMCOUNTER[3-31])|The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.|
|0xb80|[MCYCLEH](#MCYCLEH)|upper 32 bits of mcycle|
|0xb82|[MINSTRETH](#MINSTRETH)|Upper 32 bits of minstret.|
|0xb83-0xb9f|[MHPMCOUNTER[3-31]H](#MHPMCOUNTER[3-31]H)|The mhpmcounterh returns the upper half word in RV32I systems.|
|0xf11|[MVENDORID](#MVENDORID)|32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.|
|0xf12|[MARCHID](#MARCHID)|MXLEN-bit read-only register encoding the base microarchitecture of the hart.|
|0xf13|[MIMPID](#MIMPID)|Provides a unique encoding of the version of the processor implementation.|
|0xf14|[MHARTID](#MHARTID)|MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.|
### Registers Description
#### MSTATUS
---
**Address** 0x300
**Reset Value** 0x1800
**Privilege Mode** M
**Description** The mstatus register keeps track of and controls the harts current operating state.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|0|UIE||0x0|WARL|Stores the state of the user mode interrupts.|
|1|SIE||0x0|WARL|Stores the state of the supervisor mode interrupts.|
|2|RESERVED_2||0x0|WPRI|RESERVED|
|3|MIE|[0 , 1]|0x0|WLRL|Stores the state of the machine mode interrupts.|
|4|UPIE||0x0|WARL|Stores the state of the user mode interrupts prior to the trap.|
|5|SPIE||0x0|WARL|Stores the state of the supervisor mode interrupts prior to the trap.|
|6|RESERVED_6||0x0|WPRI|RESERVED|
|7|MPIE|[0 , 1]|0x0|WLRL|Stores the state of the machine mode interrupts prior to the trap.|
|8|SPP||0x0|WARL|Stores the previous priority mode for supervisor.|
|[10:9]|RESERVED_9||0x0|WPRI|RESERVED|
|[12:11]|MPP|[0x3]|0x3|WARL|Stores the previous priority mode for machine.|
|[14:13]|FS||0x0|WARL|Encodes the status of the floating-point unit, including the CSR fcsr and floating-point data registers.|
|[16:15]|XS||0x0|WARL|Encodes the status of additional user-mode extensions and associated state.|
|17|MPRV||0x0|WARL|Modifies the privilege level at which loads and stores execute in all privilege modes.|
|18|SUM||0x0|WARL|Modifies the privilege with which S-mode loads and stores access virtual memory.|
|19|MXR||0x0|WARL|Modifies the privilege with which loads access virtual memory.|
|20|TVM||0x0|WARL|Supports intercepting supervisor virtual-memory management operations.|
|21|TW||0x0|WARL|Supports intercepting the WFI instruction.|
|22|TSR||0x0|WARL|Supports intercepting the supervisor exception return instruction.|
|23|SPELP||0x0|WARL|Supervisor mode previous expected-landing-pad (ELP) state.|
|[30:24]|RESERVED_24||0x0|WPRI|RESERVED|
|31|SD||0x0|WARL|Read-only bit that summarizes whether either the FS field or XS field signals the presence of some dirty state.|
#### MSTATUSH
---
**Address** 0x300
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mstatush register keeps track of and controls the harts current operating state.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[3:0]|RESERVED_0||0x0|WPRI|RESERVED|
|4|SBE||0x0|WARL|control the endianness of memory accesses other than instruction fetches for supervisor mode|
|5|MBE||0x0|WARL|control the endianness of memory accesses other than instruction fetches for machine mode|
|6|GVA||0x0|WARL|Stores the state of the supervisor mode interrupts.|
|7|MPV||0x0|WARL|Stores the state of the user mode interrupts.|
|8|RESERVED_8||0x0|WPRI|RESERVED|
|9|MPELP||0x0|WARL|Machine mode previous expected-landing-pad (ELP) state.|
|[31:10]|RESERVED_10||0x0|WPRI|RESERVED|
#### MISA
---
**Address** 0x301
**Reset Value** 0x40001106
**Privilege Mode** M
**Description** misa is a read-write register reporting the ISA supported by the hart.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[25:0]|EXTENSIONS|[0x0000000:0x3FFFFFF]|0x1106|WARL|Encodes the presence of the standard extensions, with a single bit per letter of the alphabet.|
|[29:26]|RESERVED_26||0x0|WPRI|RESERVED|
|[31:30]|MXL|[0x1]|0x1|WARL|Encodes the native base integer ISA width.|
#### MIE
---
**Address** 0x304
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mie register is an MXLEN-bit read/write register containing interrupt enable bits.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|0|USIE||0x0|WARL|User Software Interrupt enable.|
|1|SSIE||0x0|WARL|Supervisor Software Interrupt enable.|
|2|VSSIE||0x0|WARL|VS-level Software Interrupt enable.|
|3|MSIE|[0x0 , 0x1]|0x0|WLRL|Machine Software Interrupt enable.|
|4|UTIE||0x0|WARL|User Timer Interrupt enable.|
|5|STIE||0x0|WARL|Supervisor Timer Interrupt enable.|
|6|VSTIE||0x0|WARL|VS-level Timer Interrupt enable.|
|7|MTIE|[0 , 1]|0x0|WLRL|Machine Timer Interrupt enable.|
|8|UEIE||0x0|WARL|User External Interrupt enable.|
|9|SEIE||0x0|WARL|Supervisor External Interrupt enable.|
|10|VSEIE||0x0|WARL|VS-level External Interrupt enable.|
|11|MEIE|[0 , 1]|0x0|WLRL|Machine External Interrupt enable.|
|12|SGEIE||0x0|WARL|HS-level External Interrupt enable.|
|[31:13]|RESERVED_13||0x0|WPRI|RESERVED|
#### MTVEC
---
**Address** 0x305
**Reset Value** 0x80010000
**Privilege Mode** M
**Description** MXLEN-bit read/write register that holds trap vector configuration.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[1:0]|MODE|[0x0]|0x0|WARL|Vector mode.|
|[31:2]|BASE|[0x3FFFFFFF, 0x00000000]|0x20004000|WARL|Vector base address.|
#### MHPMEVENT[3-31]
---
**Address** 0x323-0x33f
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MHPMEVENT[I]|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mhpmevent is a MXLEN-bit event register which controls mhpmcounter3.|
#### MSCRATCH
---
**Address** 0x340
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MSCRATCH|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mscratch register is an MXLEN-bit read/write register dedicated for use by machine mode.|
#### MEPC
---
**Address** 0x341
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mepc is a warl register that must be able to hold all valid physical and virtual addresses.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MEPC|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mepc is a warl register that must be able to hold all valid physical and virtual addresses.|
#### MCAUSE
---
**Address** 0x342
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mcause register stores the information regarding the trap.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[30:0]|EXCEPTION_CODE|[0 , 15]|0x0|WLRL|Encodes the exception code.|
|31|INTERRUPT|[0x0 , 0x1]|0x0|WLRL|Indicates whether the trap was due to an interrupt.|
#### MTVAL
---
**Address** 0x343
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mtval is a warl register that holds the address of the instruction which caused the exception.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MTVAL|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mtval is a warl register that holds the address of the instruction which caused the exception.|
#### MIP
---
**Address** 0x344
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mip register is an MXLEN-bit read/write register containing information on pending interrupts.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|0|USIP||0x0|WARL|User Software Interrupt Pending.|
|1|SSIP||0x0|WARL|Supervisor Software Interrupt Pending.|
|2|VSSIP||0x0|WARL|VS-level Software Interrupt Pending.|
|3|MSIP|0x1|0x0|RO_VARIABLE|Machine Software Interrupt Pending.|
|4|UTIP||0x0|WARL|User Timer Interrupt Pending.|
|5|STIP||0x0|WARL|Supervisor Timer Interrupt Pending.|
|6|VSTIP||0x0|WARL|VS-level Timer Interrupt Pending.|
|7|MTIP|0x1|0x0|RO_VARIABLE|Machine Timer Interrupt Pending.|
|8|UEIP||0x0|WARL|User External Interrupt Pending.|
|9|SEIP||0x0|WARL|Supervisor External Interrupt Pending.|
|10|VSEIP||0x0|WARL|VS-level External Interrupt Pending.|
|11|MEIP|0x1|0x0|RO_VARIABLE|Machine External Interrupt Pending.|
|12|SGEIP||0x0|WARL|HS-level External Interrupt Pending.|
|[31:13]|RESERVED_13||0x0|WPRI|RESERVED|
#### PMPCFG[0-1]
---
**Address** 0x3a0-0x3a1
**Reset Value** 0x0
**Privilege Mode** M
**Description** PMP configuration register
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[7:0]|PMP[I*4 + 0]CFG|[0x00:0xFF]|0x0|WARL|pmp configuration bits|
|[15:8]|PMP[I*4 + 1]CFG|[0x00:0xFF]|0x0|WARL|pmp configuration bits|
|[23:16]|PMP[I*4 + 2]CFG|[0x00:0xFF]|0x0|WARL|pmp configuration bits|
|[31:24]|PMP[I*4 + 3]CFG|[0x00:0xFF]|0x0|WARL|pmp configuration bits|
#### PMPADDR[0-7]
---
**Address** 0x3b0-0x3b7
**Reset Value** 0x0
**Privilege Mode** M
**Description** Physical memory protection address register
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|PMPADDR[I]|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|Physical memory protection address register|
#### MCYCLE
---
**Address** 0xb00
**Reset Value** 0x0
**Privilege Mode** M
**Description** Counts the number of clock cycles executed from an arbitrary point in time.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MCYCLE|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|Counts the number of clock cycles executed from an arbitrary point in time.|
#### MINSTRET
---
**Address** 0xb02
**Reset Value** 0x0
**Privilege Mode** M
**Description** Counts the number of instructions completed from an arbitrary point in time.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MINSTRET|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|Counts the number of instructions completed from an arbitrary point in time.|
#### MHPMCOUNTER[3-31]
---
**Address** 0xb03-0xb1f
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MHPMCOUNTER[I]|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mhpmcounter is a 64-bit counter. Returns lower 32 bits in RV32I mode.|
#### MCYCLEH
---
**Address** 0xb80
**Reset Value** 0x0
**Privilege Mode** M
**Description** upper 32 bits of mcycle
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MCYCLEH|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|upper 32 bits of mcycle|
#### MINSTRETH
---
**Address** 0xb82
**Reset Value** 0x0
**Privilege Mode** M
**Description** Upper 32 bits of minstret.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MINSTRETH|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|Upper 32 bits of minstret.|
#### MHPMCOUNTER[3-31]H
---
**Address** 0xb83-0xb9f
**Reset Value** 0x0
**Privilege Mode** M
**Description** The mhpmcounterh returns the upper half word in RV32I systems.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MHPMCOUNTER[I]H|[0x00000000 , 0xFFFFFFFF]|0x00000000|WARL|The mhpmcounterh returns the upper half word in RV32I systems.|
#### MVENDORID
---
**Address** 0xf11
**Reset Value** 0x602
**Privilege Mode** M
**Description** 32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MVENDORID|0x00000602|0x00000602|RO_CONSTANT|32-bit read-only register providing the JEDEC manufacturer ID of the provider of the core.|
#### MARCHID
---
**Address** 0xf12
**Reset Value** 0x3
**Privilege Mode** M
**Description** MXLEN-bit read-only register encoding the base microarchitecture of the hart.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MARCHID|0x00000003|0x00000003|RO_CONSTANT|MXLEN-bit read-only register encoding the base microarchitecture of the hart.|
#### MIMPID
---
**Address** 0xf13
**Reset Value** 0x0
**Privilege Mode** M
**Description** Provides a unique encoding of the version of the processor implementation.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MIMPID|0x00000000|0x00000000|RO_CONSTANT|Provides a unique encoding of the version of the processor implementation.|
#### MHARTID
---
**Address** 0xf14
**Reset Value** 0x0
**Privilege Mode** M
**Description** MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.
|Bits|Field Name|Legal Values|Reset|Type|Description|
| :--- | :--- | :--- | :--- | :--- | :--- |
|[31:0]|MHARTID|0x00000000|0x00000000|RO_CONSTANT|MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.|

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,223 @@
////
Copyright (c) 2024 OpenHW Group
Copyright (c) 2024 Thales
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
Author: Abdessamii Oukalrazqou
////
=== isa
==== Instructions
|===
|Subset Name | Name | Description
|I | RV32I Base Integer Instructions | the base integer instruction set, also known as the 'RV32I' or 'RV64I' instruction set , depending on the address space size, provides the core functionality required for general-purpose computing .it includes instructions for arithmetic, logical, and control operations, as well as memory accessand manipulation
|M | RV32M Multiplication and Division Instructions | the standard integer multiplication and division instruction extension, which is named “M” and contains instructions that multiply or divide values held in two integer registers.
|C | RV32C Compressed Instructions | RVC uses a simple compression scheme that offers shorter 16-bit versions of common 32-bit RISC-V instructions when: the immediate or address offset is small; one of the registers is the zero register (x0), the ABI link register (x1), or the ABI stack pointer (x2); the destination register and the first source register are identical; the registers used are the 8 most popular ones.The C extension is compatible with all other standard instruction extensions. The C extension allows 16-bit instructions to be freely intermixed with 32-bit instructions, with the latter now able to start on any 16-bit boundary. With the addition of the C extension, JAL and JALR instructions will no longer raise an instruction misaligned exception
|Zicsr | RV32Zicsr Control and Status Register Instructions | All CSR instructions atomically read-modify-write a single CSR, whose CSR specifier is encoded in the 12-bit csr field of the instruction held in bits 3120. The immediate forms use a 5-bit zero-extended immediate encoded in the rs1 field.
|Zcb | RV32Zcb Code Size Reduction Instructions | Zcb belongs to the group of extensions called RISC-V Code Size Reduction Extension (Zc*). Zc* has become the superset of the Standard C extension adding more 16-bit instructions to the ISA. Zcb includes the 16-bit version of additional Integer (I), Multiply (M), and Bit-Manipulation (Zbb) Instructions. All the Zcb instructions require at least standard C extension support as a prerequisite, along with M and Zbb extensions for the 16-bit version of the respective instructions.
|Zba | RVZba Address generation instructions | The Zba instructions can be used to accelerate the generation of addresses that index into arrays of basic types (halfword, word, doubleword) using both unsigned word-sized and XLEN-sized indices: a shifted index is added to a base address. The shift and add instructions do a left shift of 1, 2, or 3 because these are commonly found in real-world code and because they can be implemented with a minimal amount of additional hardware beyond that of the simple adder. This avoids lengthening the critical path in implementations. While the shift and add instructions are limited to a maximum left shift of 3, the slli instruction (from the base ISA) can be used to perform similar shifts for indexing into arrays of wider elements. The slli.uw added in this extension can be used when the index is to be interpreted as an unsigned word.
|Zbb | RVZbb Basic bit-manipulation | The bit-manipulation (bitmanip) extension collection is comprised of several component extensions to the base RISC-V architecture that are intended to provide some combination of code size reduction, performance improvement, and energy reduction. While the instructions are intended to have general use, some instructions are more useful in some domains than others. Hence, several smaller bitmanip extensions are provided. Each of these smaller extensions is grouped by common function and use case, and each has its own Zb*-extension name.
|Zbc | RVZbc Carry-less multiplication | Carry-less multiplication is the multiplication in the polynomial ring over GF(2).clmul produces the lower half of the carry-less product and clmulh produces the upper half of the 2✕XLEN carry-less product.clmulr produces bits 2✕XLEN2:XLEN-1 of the 2✕XLEN carry-less product.
|Zbs | RVZbs Single bit Instructions | The single-bit instructions provide a mechanism to set, clear, invert, or extract a single bit in a register. The bit is specified by its index.
|Zicntr | Zicntr | No info found yet for extension Zicntr
|Zbkb | RVZbkb Bitmanip instructions for Cryptography | The Zbkb extension is a part of the RISC-V Bit-Manipulation (bitmanip) extensions, specifically targeting cryptographic applications. It introduces a set of instructions designed to facilitate operations commonly used in cryptographic algorithms, such as interleaving, packing, and reordering of bits.
|===
==== RV32I Base Integer Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| ADDI | addi rd, rs1, imm[11:0] | x[rd] = x[rs1] + sext(imm[11:0]) | NONE | NONE | add sign-extended 12-bit immediate to register rs1, and store the result in register rd. | Integer_Register_Immediate_Operations
| ANDI | andi rd, rs1, imm[11:0] | x[rd] = x[rs1] & sext(imm[11:0]) | NONE | NONE | perform bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd. | Integer_Register_Immediate_Operations
| ORI | ori rd, rs1, imm[11:0] | x[rd] = x[rs1] \| sext(imm[11:0]) | NONE | NONE | perform bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd. | Integer_Register_Immediate_Operations
| XORI | xori rd, rs1, imm[11:0] | x[rd] = x[rs1] ^ sext(imm[11:0]) | NONE | NONE | perform bitwise XOR on register rs1 and the sign-extended 12-bit immediate and place the result in rd. | Integer_Register_Immediate_Operations
| SLTI | slti rd, rs1, imm[11:0] | if (x[rs1] < sext(imm[11:0])) x[rd] = 1 else x[rd] = 0 | NONE | NONE | set register rd to 1 if register rs1 is less than the sign extended immediate when both are treated as signed numbers, else 0 is written to rd. | Integer_Register_Immediate_Operations
| SLTIU | sltiu rd, rs1, imm[11:0] | if (x[rs1] <u sext(imm[11:0])) x[rd] = 1 else x[rd] = 0 | NONE | NONE | set register rd to 1 if register rs1 is less than the sign extended immediate when both are treated as unsigned numbers, else 0 is written to rd." | Integer_Register_Immediate_Operations
| SLLI | slli rd, rs1, imm[4:0] | x[rd] = x[rs1] << imm[4:0] | NONE | NONE | logical left shift (zeros are shifted into the lower bits). | Integer_Register_Immediate_Operations
| SRLI | srli rd, rs1, imm[4:0] | x[rd] = x[rs1] >> imm[4:0] | NONE | NONE | logical right shift (zeros are shifted into the upper bits). | Integer_Register_Immediate_Operations
| SRAI | srai rd, rs1, imm[4:0] | x[rd] = x[rs1] >>s imm[4:0] | NONE | NONE | arithmetic right shift (the original sign bit is copied into the vacated upper bits). | Integer_Register_Immediate_Operations
| LUI | lui rd, imm[19:0] | x[rd] = sext(imm[31:12] << 12) | NONE | NONE | place the immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros. | Integer_Register_Immediate_Operations
| AUIPC | auipc rd, imm[19:0] | x[rd] = pc + sext(immediate[31:12] << 12) | NONE | NONE | form a 32-bit offset from the 20-bit immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then place the result in register rd. | Integer_Register_Immediate_Operations
| ADD | add rd, rs1, rs2 | x[rd] = x[rs1] + x[rs2] | NONE | NONE | add rs2 to register rs1, and store the result in register rd. | Integer_Register_Register_Operations
| SUB | sub rd, rs1, rs2 | x[rd] = x[rs1] - x[rs2] | NONE | NONE | subtract rs2 from register rs1, and store the result in register rd. | Integer_Register_Register_Operations
| AND | and rd, rs1, rs2 | x[rd] = x[rs1] & x[rs2] | NONE | NONE | perform bitwise AND on register rs1 and rs2 and place the result in rd. | Integer_Register_Register_Operations
| OR | or rd, rs1, rs2 | x[rd] = x[rs1] \| x[rs2] | NONE | NONE | perform bitwise OR on register rs1 and rs2 and place the result in rd. | Integer_Register_Register_Operations
| XOR | xor rd, rs1, rs2 | x[rd] = x[rs1] ^ x[rs2] | NONE | NONE | perform bitwise XOR on register rs1 and rs2 and place the result in rd. | Integer_Register_Register_Operations
| SLT | slt rd, rs1, rs2 | if (x[rs1] < x[rs2]) x[rd] = 1 else x[rd] = 0 | NONE | NONE | set register rd to 1 if register rs1 is less than rs2 when both are treated as signed numbers, else 0 is written to rd. | Integer_Register_Register_Operations
| SLTU | sltu rd, rs1, rs2 | if (x[rs1] <u x[rs2]) x[rd] = 1 else x[rd] = 0 | NONE | NONE | set register rd to 1 if register rs1 is less than rs2 when both are treated as unsigned numbers, else 0 is written to rd. | Integer_Register_Register_Operations
| SLL | sll rd, rs1, rs2 | x[rd] = x[rs1] << x[rs2] | NONE | NONE | logical left shift (zeros are shifted into the lower bits). | Integer_Register_Register_Operations
| SRL | srl rd, rs1, rs2 | x[rd] = x[rs1] >> x[rs2] | NONE | NONE | logical right shift (zeros are shifted into the upper bits). | Integer_Register_Register_Operations
| SRA | sra rd, rs1, rs2 | x[rd] = x[rs1] >>s x[rs2] | NONE | NONE | arithmetic right shift (the original sign bit is copied into the vacated upper bits). | Integer_Register_Register_Operations
| JAL | jal rd, imm[20:1] | x[rd] = pc+4; pc += sext(imm[20:1]) | NONE | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | offset is sign-extended and added to the pc to form the jump target address (pc is calculated using signed arithmetic), then setting the least-significant bit of the result to zero, and store the address of instruction following the jump (pc+4) into register rd. | Control_Transfer_Operations-Unconditional_Jumps
| JALR | jalr rd, rs1, imm[11:0] | t = pc+4; pc = (x[rs1]+sext(imm[11:0]))&1 ; x[rd] = t | NONE | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | target address is obtained by adding the 12-bit signed immediate to the register rs1 (pc is calculated using signed arithmetic), then setting the least-significant bit of the result to zero, and store the address of instruction following the jump (pc+4) into register rd. | Control_Transfer_Operations-Unconditional_Jumps
| BEQ | beq rs1, rs2, imm[12:1] | if (x[rs1] == x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 and rs2 are equal. | Control_Transfer_Operations-Conditional_Branches
| BNE | bne rs1, rs2, imm[12:1] | if (x[rs1] != x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 and rs2 are not equal. | Control_Transfer_Operations-Conditional_Branches
| BLT | blt rs1, rs2, imm[12:1] | if (x[rs1] < x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 less than rs2 (using signed comparison). | Control_Transfer_Operations-Conditional_Branches
| BLTU | bltu rs1, rs2, imm[12:1] | if (x[rs1] <u x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 less than rs2 (using unsigned comparison). | Control_Transfer_Operations-Conditional_Branches
| BGE | bge rs1, rs2, imm[12:1] | if (x[rs1] >= x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 is greater than or equal rs2 (using signed comparison). | Control_Transfer_Operations-Conditional_Branches
| BGEU | bgeu rs1, rs2, imm[12:1] | if (x[rs1] >=u x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4 | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | takes the branch (pc is calculated using signed arithmetic) if registers rs1 is greater than or equal rs2 (using unsigned comparison). | Control_Transfer_Operations-Conditional_Branches
| LB | lb rd, imm(rs1) | x[rd] = sext(M[x[rs1] + sext(imm[11:0])][7:0]) | NONE | loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded. | loads a 8-bit value from memory, then sign-extends to 32-bit before storing in rd (rd is calculated using signed arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| LH | lh rd, imm(rs1) | x[rd] = sext(M[x[rs1] + sext(imm[11:0])][15:0]) | NONE | loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (2-byte boundary). | loads a 16-bit value from memory, then sign-extends to 32-bit before storing in rd (rd is calculated using signed arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| LW | lw rd, imm(rs1) | x[rd] = sext(M[x[rs1] + sext(imm[11:0])][31:0]) | NONE | loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (4-byte boundary). | loads a 32-bit value from memory, then storing in rd (rd is calculated using signed arithmetic). The effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| LBU | lbu rd, imm(rs1) | x[rd] = zext(M[x[rs1] + sext(imm[11:0])][7:0]) | NONE | loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded. | loads a 8-bit value from memory, then zero-extends to 32-bit before storing in rd (rd is calculated using unsigned arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| LHU | lhu rd, imm(rs1) | x[rd] = zext(M[x[rs1] + sext(imm[11:0])][15:0]) | NONE | loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (2-byte boundary). | loads a 16-bit value from memory, then zero-extends to 32-bit before storing in rd (rd is calculated using unsigned arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| SB | sb rs2, imm(rs1) | M[x[rs1] + sext(imm[11:0])][7:0] = x[rs2][7:0] | NONE | NONE | stores a 8-bit value from the low bits of register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| SH | sh rs2, imm(rs1) | M[x[rs1] + sext(imm[11:0])][15:0] = x[rs2][15:0] | NONE | an exception is raised if the memory address isn't aligned (2-byte boundary). | stores a 16-bit value from the low bits of register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| SW | sw rs2, imm(rs1) | M[x[rs1] + sext(imm[11:0])][31:0] = x[rs2][31:0] | NONE | an exception is raised if the memory address isn't aligned (4-byte boundary). | stores a 32-bit value from register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset. | Load_and_Store_Instructions
| FENCE | fence pre, succ | No operation (nop) | NONE | NONE | order device I/O and memory accesses as viewed by other RISC-V harts and external devices or coprocessors. Any combination of device input (I), device output (O), memory reads (R), and memory writes (W) may be ordered with respect to any combination of the same. Informally, no other RISC-V hart or external device can observe any operation in the successor set following a FENCE before any operation in the predecessor set preceding the FENCE, as the core support 1 hart, the fence instruction has no effect so we can considerate it as a nop instruction. | Memory_Ordering
| ECALL | ecall | RaiseException(EnvironmentCall) | NONE | Raise an Environment Call exception. | make a request to the supporting execution environment, which is usually an operating system. The ABI for the system will define how parameters for the environment request are passed, but usually these will be in defined locations in the integer register file. | Environment_Call_and_Breakpoints
| EBREAK | ebreak | x[8 + rd'] = sext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Environment_Call_and_Breakpoints
|===
==== RV32M Multiplication and Division Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| MUL | mul rd, rs1, rs2 | x[rd] = x[rs1] * x[rs2] | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rs1 and rs2 treated as signed numbers). | Multiplication Operations
| MULH | mulh rd, rs1, rs2 | x[rd] = (x[rs1] s*s x[rs2]) >>s 32 | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (Both rs1 and rs2 treated as signed numbers). | Multiplication Operations
| MULHU | mulhu rd, rs1, rs2 | x[rd] = (x[rs1] u*u x[rs2]) >>u 32 | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (Both rs1 and rs2 treated as unsigned numbers). | Multiplication Operations
| MULHSU | mulhsu rd, rs1, rs2 | x[rd] = (x[rs1] s*u x[rs2]) >>s 32 | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (rs1 treated as signed number, rs2 treated as unsigned number). | Multiplication Operations
| DIV | div rd, rs1, rs2 | x[rd] = x[rs1] /s x[rs2] | NONE | NONE | perform signed integer division of 32 bits by 32 bits (rounding towards zero). | Division Operations
| DIVU | divu rd, rs1, rs2 | x[rd] = x[rs1] /u x[rs2] | NONE | NONE | perform unsigned integer division of 32 bits by 32 bits (rounding towards zero). | Division Operations
| REM | rem rd, rs1, rs2 | x[rd] = x[rs1] %s x[rs2] | NONE | NONE | provide the remainder of the corresponding division operation DIV (the sign of rd equals the sign of rs1). | Division Operations
| REMU | rem rd, rs1, rs2 | x[rd] = x[rs1] %u x[rs2] | NONE | NONE | provide the remainder of the corresponding division operation DIVU. | Division Operations
|===
==== RV32C Compressed Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| C.LI | c.li rd, imm[5:0] | x[rd] = sext(imm[5:0]) | rd = x0 | NONE | loads the sign-extended 6-bit immediate, imm, into register rd. | Integer Computational Instructions
| C.LUI | c.lui rd, nzimm[17:12] | x[rd] = sext(nzimm[17:12] << 12) | rd = x0 & rd = x2 & nzimm = 0 | NONE | loads the non-zero 6-bit immediate field into bits 1712 of the destination register, clears the bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination. | Integer Computational Instructions
| C.ADDI | c.addi rd, nzimm[5:0] | x[rd] = x[rd] + sext(nzimm[5:0]) | rd = x0 & nzimm = 0 | NONE | adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd. | Integer Computational Instructions
| C.ADDI16SP | c.addi16sp nzimm[9:4] | x[2] = x[2] + sext(nzimm[9:4]) | rd != x2 & nzimm = 0 | NONE | adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). C.ADDI16SP is used to adjust the stack pointer in procedure prologues and epilogues. C.ADDI16SP shares the opcode with C.LUI, but has a destination field of x2. | Integer Computational Instructions
| C.ADDI4SPN | c.addi4spn rd', nzimm[9:2] | x[8 + rd'] = x[2] + zext(nzimm[9:2]) | nzimm = 0 | NONE | adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd'. This instruction is used to generate pointers to stack-allocated variables. | Integer Computational Instructions
| C.SLLI | c.slli rd, uimm[5:0] | x[rd] = x[rd] << uimm[5:0] | rd = x0 & uimm[5] = 0 | NONE | performs a logical left shift (zeros are shifted into the lower bits). | Integer Computational Instructions
| C.SRLI | c.srli rd', uimm[5:0] | x[8 + rd'] = x[8 + rd'] >> uimm[5:0] | uimm[5] = 0 | NONE | performs a logical right shift (zeros are shifted into the upper bits). | Integer Computational Instructions
| C.SRAI | c.srai rd', uimm[5:0] | x[8 + rd'] = x[8 + rd'] >>s uimm[5:0] | uimm[5] = 0 | NONE | performs an arithmetic right shift (sign bits are shifted into the upper bits). | Integer Computational Instructions
| C.ANDI | c.andi rd', imm[5:0] | x[8 + rd'] = x[8 + rd'] & sext(imm[5:0]) | NONE | NONE | computes the bitwise AND of the value in register rd', and the sign-extended 6-bit immediate, then writes the result to rd'. | Integer Computational Instructions
| C.ADD | c.add rd, rs2 | x[rd] = x[rd] + x[rs2] | rd = x0 & rs2 = x0 | NONE | adds the values in registers rd and rs2 and writes the result to register rd. | Integer Computational Instructions
| C.MV | c.mv rd, rs2 | x[rd] = x[rs2] | rd = x0 & rs2 = x0 | NONE | copies the value in register rs2 into register rd. | Integer Computational Instructions
| C.AND | c.and rd', rs2' | x[8 + rd'] = x[8 + rd'] & x[8 + rs2'] | NONE | NONE | computes the bitwise AND of of the value in register rd', and register rs2', then writes the result to rd'. | Integer Computational Instructions
| C.OR | c.or rd', rs2' | x[8 + rd'] = x[8 + rd'] \| x[8 + rs2'] | NONE | NONE | computes the bitwise OR of of the value in register rd', and register rs2', then writes the result to rd'. | Integer Computational Instructions
| C.XOR | c.and rd', rs2' | x[8 + rd'] = x[8 + rd'] ^ x[8 + rs2'] | NONE | NONE | computes the bitwise XOR of of the value in register rd', and register rs2', then writes the result to rd'. | Integer Computational Instructions
| C.SUB | c.sub rd', rs2' | x[8 + rd'] = x[8 + rd'] - x[8 + rs2'] | NONE | NONE | subtracts the value in registers rs2' from value in rd' and writes the result to register rd'. | Integer Computational Instructions
| C.EBREAK | c.ebreak | RaiseException(Breakpoint) | NONE | Raise a Breakpoint exception. | cause control to be transferred back to the debugging environment. | Integer Computational Instructions
| C.J | c.j imm[11:1] | pc += sext(imm[11:1]) | NONE | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | performs an unconditional control transfer. The offset is sign-extended and added to the pc to form the jump target address. | Control Transfer Instructions
| C.JAL | c.jal imm[11:1] | x[1] = pc+2; pc += sext(imm[11:1]) | NONE | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | performs the same operation as C.J, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. | Control Transfer Instructions
| C.JR | c.jr rs1 | pc = x[rs1] | rs1 = x0 | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | performs an unconditional control transfer to the address in register rs1. | Control Transfer Instructions
| C.JALR | c.jalr rs1 | t = pc+2; pc = x[rs1]; x[1] = t | rs1 = x0 | jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception. | performs the same operation as C.JR, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. | Control Transfer Instructions
| C.BEQZ | c.beqz rs1', imm[8:1] | if (x[8+rs1'] == 0) pc += sext(imm[8:1]) | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. C.BEQZ takes the branch if the value in register rs1' is zero. | Control Transfer Instructions
| C.BNEZ | c.bnez rs1', imm[8:1] | if (x[8+rs1'] != 0) pc += sext(imm[8:1]) | NONE | no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions. | performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. C.BEQZ takes the branch if the value in register rs1' isn't zero. | Control Transfer Instructions
| C.LWSP | c.lwsp rd, uimm(x2) | x[rd] = M[x[2] + zext(uimm[7:2])][31:0] | rd = x0 | loads with a destination of x0 must still raise any exceptions, also an exception if the memory address isn't aligned (4-byte boundary). | loads a 32-bit value from memory into register rd. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2. | Load and Store Instructions
| C.SWSP | c.swsp rd, uimm(x2) | M[x[2] + zext(uimm[7:2])][31:0] = x[rs2] | NONE | an exception raised if the memory address isn't aligned (4-byte boundary). | stores a 32-bit value in register rs2 to memory. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2. | Load and Store Instructions
| C.LW | c.lw rd', uimm(rs1') | x[8+rd'] = M[x[8+rs1'] + zext(uimm[6:2])][31:0]) | NONE | an exception raised if the memory address isn't aligned (4-byte boundary). | loads a 32-bit value from memory into register rd'. It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1'. | Load and Store Instructions
| C.SW | c.sw rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[6:2])][31:0] = x[8+rs2'] | NONE | an exception raised if the memory address isn't aligned (4-byte boundary). | stores a 32-bit value from memory into register rd'. It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1'. | Load and Store Instructions
|===
==== RV32Zicsr Control and Status Register Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| CSRRW | csrrw rd, csr, rs1 | t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the old value of the CSR, zero-extends the value to 32 bits, then writes it to integer register rd. The initial value in rs1 is written to the CSR. If rd=x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read. | Control and Status Register Operations
| CSRRS | csrrs rd, csr, rs1 | t = CSRs[csr]; CSRs[csr] = t \| x[rs1]; x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The initial value in integer register rs1 is treated as a bit mask that specifies bit positions to be set in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSRs. | Control and Status Register Operations
| CSRRC | csrrc rd, csr, rs1 | t = CSRs[csr]; CSRs[csr] = t & x[rs1]; x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The initial value in integer register rs1 is treated as a bit mask that specifies bit positions to be cleared in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSRs. | Control and Status Register Operations
| CSRRWI | csrrwi rd, csr, uimm[4:0] | x[rd] = CSRs[csr]; CSRs[csr] = zext(uimm[4:0]) | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the old value of the CSR, zero-extends the value to 32 bits, then writes it to integer register rd. The zero-extends immediate is written to the CSR. If rd=x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read. | Control and Status Register Operations
| CSRRSI | csrrsi rd, csr, uimm[4:0] | t = CSRs[csr]; CSRs[csr] = t \| zext(uimm[4:0]); x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The zero-extends immediate value is treated as a bit mask that specifies bit positions to be set in the CSR. Any bit that is high in zero-extends immediate will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If the uimm[4:0] field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write. | Control and Status Register Operations
| CSRRCI | csrrci rd, csr, uimm[4:0] | t = CSRs[csr]; CSRs[csr] = t & zext(uimm[4:0]); x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The zero-extends immediate value is treated as a bit mask that specifies bit positions to be cleared in the CSR. Any bit that is high in zero-extends immediate will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If the uimm[4:0] field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write. | Control and Status Register Operations
|===
==== RV32Zcb Code Size Reduction Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| C.ZEXT.B | c.zext.b rd' | x[8 + rd'] = zext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant byte of the operand by inserting zeros into all of the bits more significant than 7. | Code Size Reduction Operations
| C.SEXT.B | c.sext.b rd' | x[8 + rd'] = sext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations
| C.ZEXT.H | c.zext.h rd' | x[8 + rd'] = zext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant halfword of the operand by inserting zeros into all of the bits more significant than 15. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations
| C.SEXT.H | c.sext.h rd' | x[8 + rd'] = sext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant halfword in the operand by copying the most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations
| C.NOT | c.not rd' | x[8 + rd'] = x[8 + rd'] ^ -1 | NONE | NONE | This instruction takes the ones complement of rd'/rs1' and writes the result to the same register. | Code Size Reduction Operations
| C.MUL | c.mul rd', rs2' | x[8 + rd'] = (x[8 + rd'] * x[8 + rs2'])[31:0] | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rd' and rs2' treated as signed numbers). It also requires M extension support. | Code Size Reduction Operations
| C.LHU | c.lhu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is zero extended and is written to rd'. | Code Size Reduction Operations
| C.LH | c.lh rd', uimm(rs1') | x[8+rd'] = sext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is sign extended and is written to rd'. | Code Size Reduction Operations
| C.LBU | c.lbu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1:0])][7:0]) | NONE | NONE | This instruction loads a byte from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting byte is zero extended and is written to rd'. | Code Size Reduction Operations
| C.SH | c.sh rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1])][15:0] = x[8+rs2'] | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction stores the least significant halfword of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations
| C.SB | c.sb rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1:0])][7:0] = x[8+rs2'] | NONE | NONE | This instruction stores the least significant byte of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations
|===
==== RVZba Address generation instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| ADD.UW | add.uw rd, rs1, rs2 | X(rd) = rs2 + EXTZ(X(rs1)[31..0]) | NONE | NONE | This instruction performs an XLEN-wide addition between rs2 and the zero-extended least-significant word of rs1. | Address generation instructions
| SH1ADD | sh1add rd, rs1, rs2 | X(rd) = X(rs2) + (X(rs1) << 1) | NONE | NONE | This instruction shifts rs1 to the left by 1 bit and adds it to rs2. | Address generation instructions
| SH1ADD.UW | sh1add.uw rd, rs1, rs2 | X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 1) | NONE | NONE | This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 1 place. | Address generation instructions
| SH2ADD | sh2add rd, rs1, rs2 | X(rd) = X(rs2) + (X(rs1) << 2) | NONE | NONE | This instruction shifts rs1 to the left by 2 bit and adds it to rs2. | Address generation instructions
| SH2ADD.UW | sh2add.uw rd, rs1, rs2 | X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 2) | NONE | NONE | This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 2 places. | Address generation instructions
| SH3ADD | sh3add rd, rs1, rs2 | X(rd) = X(rs2) + (X(rs1) << 3) | NONE | NONE | This instruction shifts rs1 to the left by 3 bit and adds it to rs2. | Address generation instructions
| SH3ADD.UW | sh3add.uw rd, rs1, rs2 | X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 3) | NONE | NONE | This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 3 places. | Address generation instructions
| SLLI.UW | slli.uw rd, rs1, imm | X(rd) = (EXTZ(X(rs)[31..0]) << imm) | NONE | NONE | This instruction takes the least-significant word of rs1, zero-extends it, and shifts it left by the immediate. | Address generation instructions
|===
==== RVZbb Basic bit-manipulation
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| ANDN | andn rd, rs1, rs2 | X(rd) = X(rs1) & ~X(rs2) | NONE | NONE | Performs bitwise AND operation between rs1 and bitwise inversion of rs2. | Logical_with_negate
| ORN | orn rd, rs1, rs2 | X(rd) = X(rs1) \| ~X(rs2) | NONE | NONE | Performs bitwise OR operation between rs1 and bitwise inversion of rs2. | Logical_with_negate
| XNOR | xnor rd, rs1, rs2 | X(rd) = ~(X(rs1) ^ X(rs2)) | NONE | NONE | Performs bitwise XOR operation between rs1 and rs2, then complements the result. | Logical_with_negate
| CLZ | clz rd, rs | if [x[i]] == 1 then return(i) else return -1 | NONE | NONE | Counts leading zero bits in rs. | Count_leading_trailing_zero_bits
| CTZ | ctz rd, rs | if [x[i]] == 1 then return(i) else return xlen; | NONE | NONE | Counts trailing zero bits in rs. | Count_leading_trailing_zero_bits
| CLZW | clzw rd, rs | if [x[i]] == 1 then return(i) else return -1 | NONE | NONE | Counts leading zero bits in the least-significant word of rs. | Count_leading_trailing_zero_bits
| CTZW | ctzw rd, rs | if [x[i]] == 1 then return(i) else return 32; | NONE | NONE | Counts trailing zero bits in the least-significant word of rs. | Count_leading_trailing_zero_bits
| CPOP | cpop rd, rs | if rs[i] == 1 then bitcount = bitcount + 1 else () | NONE | NONE | Counts set bits in rs. | Count_population
| CPOPW | cpopw rd, rs | if rs[i] == 0b1 then bitcount = bitcount + 1 else () | NONE | NONE | Counts set bits in the least-significant word of rs. | Count_population
| MAX | max rd, rs1, rs2 | if rs1_val <_s rs2_val then rs2_val else rs1_val | NONE | NONE | Returns the larger of two signed integers. | Integer_minimum_maximum
| MAXU | maxu rd, rs1, rs2 | if rs1_val <_u rs2_val then rs2_val else rs1_val | NONE | NONE | Returns the larger of two unsigned integers. | Integer_minimum_maximum
| MIN | min rd, rs1, rs2 | if rs1_val <_s rs2_val then rs1_val else rs2_val | NONE | NONE | Returns the smaller of two signed integers. | Integer_minimum_maximum
| MINU | minu rd, rs1, rs2 | if rs1_val <_u rs2_val then rs1_val else rs2_val | NONE | NONE | Returns the smaller of two unsigned integers. | Integer_minimum_maximum
| SEXT.B | sext.b rd, rs | X(rd) = EXTS(X(rs)[7..0]) | NONE | NONE | Sign-extends the least-significant byte in the source to XLEN. | Sign_and_zero_extension
| SEXT.H | sext.h rd, rs | X(rd) = EXTS(X(rs)[15..0]) | NONE | NONE | Sign-extends the least-significant halfword in rs to XLEN. | Sign_and_zero_extension
| ZEXT.H | zext.h rd, rs | X(rd) = EXTZ(X(rs)[15..0]) | NONE | NONE | Zero-extends the least-significant halfword of the source to XLEN. | Sign_and_zero_extension
| ROL | rol rd, rs1, rs2 | (X(rs1) << log2(XLEN)) \| (X(rs1) >> (xlen - log2(XLEN))) | NONE | NONE | Performs a rotate left of rs1 by the amount in least-significant log2(XLEN) bits of rs2. | Bitwise_rotation
| ROR | ror rd, rs1, rs2 | (X(rs1) >> log2(XLEN)) \| (X(rs1) << (xlen - log2(XLEN))) | NONE | NONE | Performs a rotate right of rs1 by the amount in least-significant log2(XLEN) bits of rs2. | Bitwise_rotation
| RORI | rori rd, rs1, shamt | (X(rs1) >> log2(XLEN)) \| (X(rs1) << (xlen - log2(XLEN))) | NONE | NONE | Performs a rotate right of rs1 by the amount in least-significant log2(XLEN) bits of shamt. | Bitwise_rotation
| ROLW | rolw rd, rs1, rs2 | EXTS((rs1 << X(rs2)[4..0]) \| (rs1 >> (32 - X(rs2)[4..0]))) | NONE | NONE | Performs a rotate left on the least-significant word of rs1 by the amount in least-significant 5 bits of rs2. | Bitwise_rotation
| RORIW | roriw rd, rs1, shamt | (rs1_data >> shamt[4..0]) \| (rs1_data << (32 - shamt[4..0])) | NONE | NONE | Performs a rotate right on the least-significant word of rs1 by the amount in least-significant log2(XLEN) bits of shamt. | Bitwise_rotation
| RORW | rorw rd, rs1, rs2 | (rs1 >> X(rs2)[4..0]) \| (rs1 << (32 - X(rs2)[4..0])) | NONE | NONE | Performs a rotate right on the least-significant word of rs1 by the amount in least-significant 5 bits of rs2. | Bitwise_rotation
| ORC.b | orc.b rd, rs | if { input[(i + 7)..i] == 0 then 0b00000000 else 0b11111111 | NONE | NONE | Sets the bits of each byte in rd to all zeros if no bit within the respective byte of rs is set, or to all ones if any bit within the respective byte of rs is set. | OR_Combine
| REV8 | rev8 rd, rs | output[i..(i + 7)] = input[(j - 7)..j] | NONE | NONE | Reverses the order of the bytes in rs. | Byte_reverse
|===
==== RVZbc Carry-less multiplication
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| CLMUL | clmul rd, rs1, rs2 | foreach (i from 1 to xlen by 1) { output = if ((rs2 >> i) & 1) then output ^ (rs1 << i); else output;} | NONE | NONE | clmul produces the lower half of the 2.XLEN carry-less product. | Carry-less multiplication Operations
| CLMULH | clmulh rd, rs1, rs2 | foreach (i from 1 to xlen by 1) { output = if ((rs2_val >> i) & 1) then output ^ (rs1_val >> (xlen - i)) else output} | NONE | NONE | clmulh produces the upper half of the 2.XLEN carry-less product. | Carry-less multiplication Operations
| CLMULR | clmulr rd, rs1, rs2 | foreach (i from 0 to (xlen - 1) by 1) { output = if ((rs2_val >> i) & 1) then output ^ (rs1_val >> (xlen - i - 1)) else output} | NONE | NONE | clmulr produces bits 2.XLEN-2:XLEN-1 of the 2.XLEN carry-less product. | Carry-less multiplication Operations
|===
==== RVZbs Single bit Instructions
|===
| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name
| BCLR | bclr rd, rs1, rs2 | X(rd) = X(rs1) & ~(1 << (X(rs2) & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit cleared at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. | Single_bit_Operations
| BCLRI | bclri rd, rs1, shamt | X(rd) = X(rs1) & ~(1 << (shamt & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit cleared at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. | Single_bit_Operations
| BEXT | bext rd, rs1, rs2 | X(rd) = (X(rs1) >> (X(rs2) & (XLEN - 1))) & 1 | NONE | NONE | This instruction returns a single bit extracted from rs1 at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. | Single_bit_Operations
| BEXTI | bexti rd, rs1, shamt | X(rd) = (X(rs1) >> (shamt & (XLEN - 1))) & 1 | NONE | NONE | This instruction returns a single bit extracted from rs1 at the index specified in rs2. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. | Single_bit_Operations
| BINV | binv rd, rs1, rs2 | X(rd) = X(rs1) ^ (1 << (X(rs2) & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit inverted at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. | Single_bit_Operations
| BINVI | binvi rd, rs1, shamt | X(rd) = X(rs1) ^ (1 << (shamt & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit inverted at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. | Single_bit_Operations
| BSET | bset rd, rs1, rs2 | X(rd) = X(rs1) \| (1 << (X(rs2) & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit set at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. | Single_bit_Operations
| BSETI | bseti rd, rs1, shamt | X(rd) = X(rs1) \| (1 << (shamt & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit set at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. | Single_bit_Operations
|===

View file

@ -1,210 +0,0 @@
<!--Copyright (c) 2024 OpenHW Group
Copyright (c) 2024 Thales
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
Author: Abdessamii Oukalrazqou
-->
# isa
## Instructions
|Subset Name|Name |Description|
| :--- | :--- | :--- |
|I|[RV32I Base Integer Instructions](#RV32I Base Integer Instructions)|the base integer instruction set, also known as the 'RV32I' or 'RV64I' instruction set , depending on the address space size, provides the core functionality required for general-purpose computing . it includes instructions for arithmetic, logical, and control operations, as well as memory access and manipulation |
|M|[RV32M Multiplication and Division Instructions](#RV32M Multiplication and Division Instructions)|the standard integer multiplication and division instruction extension, which is named “M” and contains instructions that multiply or divide values held in two integer registers. |
|C|[RV32C Compressed Instructions](#RV32C Compressed Instructions)|RVC uses a simple compression scheme that offers shorter 16-bit versions of common 32-bit RISC-V instructions when: the immediate or address offset is small; one of the registers is the zero register (x0), the ABI link register (x1), or the ABI stack pointer (x2); the destination register and the first source register are identical; the registers used are the 8 most popular ones. The C extension is compatible with all other standard instruction extensions. The C extension allows 16-bit instructions to be freely intermixed with 32-bit instructions, with the latter now able to start on any 16-bit boundary. With the addition of the C extension, JAL and JALR instructions will no longer raise an instruction misaligned exception |
|Zicsr|[RV32Zicsr Control and Status Register Instructions](#RV32Zicsr Control and Status Register Instructions)|All CSR instructions atomically read-modify-write a single CSR, whose CSR specifier is encoded in the 12-bit csr field of the instruction held in bits 3120. The immediate forms use a 5-bit zero-extended immediate encoded in the rs1 field. |
|Zifencei|[RVZifencei Instruction Fetch Fence](#RVZifencei Instruction Fetch Fence)|FENCE.I instruction that provides explicit synchronization between writes to instruction memory and instruction fetches on the same hart. Currently, this instruction is the only standard mechanism to ensure that stores visible to a hart will also be visible to it instruction fetches. |
|Zba|[RVZba Address generation instructions](#RVZba Address generation instructions)|The Zba instructions can be used to accelerate the generation of addresses that index into arrays of basic types (halfword, word, doubleword) using both unsigned word-sized and XLEN-sized indices: a shifted index is added to a base address. The shift and add instructions do a left shift of 1, 2, or 3 because these are commonly found in real-world code and because they can be implemented with a minimal amount of additional hardware beyond that of the simple adder. This avoids lengthening the critical path in implementations. While the shift and add instructions are limited to a maximum left shift of 3, the slli instruction (from the base ISA) can be used to perform similar shifts for indexing into arrays of wider elements. The slli.uw added in this extension can be used when the index is to be interpreted as an unsigned word. |
|Zbb|[RVZbb Basic bit-manipulation](#RVZbb Basic bit-manipulation)|The bit-manipulation (bitmanip) extension collection is comprised of several component extensions to the base RISC-V architecture that are intended to provide some combination of code size reduction, performance improvement, and energy reduction. While the instructions are intended to have general use, some instructions are more useful in some domains than others. Hence, several smaller bitmanip extensions are provided. Each of these smaller extensions is grouped by common function and use case, and each has its own Zb*-extension name. |
|Zbc|[RVZbc Carry-less multiplication](#RVZbc Carry-less multiplication)|Carry-less multiplication is the multiplication in the polynomial ring over GF(2). clmul produces the lower half of the carry-less product and clmulh produces the upper half of the 2✕XLEN carry-less product. clmulr produces bits 2✕XLEN2:XLEN-1 of the 2✕XLEN carry-less product. |
|Zbs|[RVZbs Single bit Instructions](#RVZbs Single bit Instructions)|The single-bit instructions provide a mechanism to set, clear, invert, or extract a single bit in a register. The bit is specified by its index. |
|Zcb|[RV32Zcb Code Size Reduction Instructions](#RV32Zcb Code Size Reduction Instructions)|Zcb belongs to the group of extensions called RISC-V Code Size Reduction Extension (Zc*). Zc* has become the superset of the Standard C extension adding more 16-bit instructions to the ISA. Zcb includes the 16-bit version of additional Integer (I), Multiply (M), and Bit-Manipulation (Zbb) Instructions. All the Zcb instructions require at least standard C extension support as a prerequisite, along with M and Zbb extensions for the 16-bit version of the respective instructions. |
|Zicntr|[Zicntr](#Zicntr)|No info found yet for extension Zicntr|
### RV32I Base Integer Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|ADDI |[addi rd, rs1, imm[11:0]](#addi rd, rs1, imm[11:0])|x[rd] = x[rs1] + sext(imm[11:0])|NONE|NONE |add sign-extended 12-bit immediate to register rs1, and store the result in register rd.|Integer_Register_Immediate_Operations|
|ANDI |[andi rd, rs1, imm[11:0]](#andi rd, rs1, imm[11:0])|x[rd] = x[rs1] & sext(imm[11:0])|NONE|NONE |perform bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd.|Integer_Register_Immediate_Operations|
|ORI |[ori rd, rs1, imm[11:0]](#ori rd, rs1, imm[11:0])|x[rd] = x[rs1] \| sext(imm[11:0])|NONE|NONE |perform bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.|Integer_Register_Immediate_Operations|
|XORI |[xori rd, rs1, imm[11:0]](#xori rd, rs1, imm[11:0])|x[rd] = x[rs1] ^ sext(imm[11:0])|NONE|NONE |perform bitwise XOR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.|Integer_Register_Immediate_Operations|
|SLTI |[slti rd, rs1, imm[11:0]](#slti rd, rs1, imm[11:0])|if (x[rs1] < sext(imm[11:0])) x[rd] = 1 else x[rd] = 0|NONE|NONE |set register rd to 1 if register rs1 is less than the sign extended immediate when both are treated as signed numbers, else 0 is written to rd.|Integer_Register_Immediate_Operations|
|SLTIU |[sltiu rd, rs1, imm[11:0]](#sltiu rd, rs1, imm[11:0])|if (x[rs1] <u sext(imm[11:0])) x[rd] = 1 else x[rd] = 0|NONE|NONE |set register rd to 1 if register rs1 is less than the sign extended immediate when both are treated as unsigned numbers, else 0 is written to rd."|Integer_Register_Immediate_Operations|
|SLLI |[slli rd, rs1, imm[4:0]](#slli rd, rs1, imm[4:0])|x[rd] = x[rs1] << imm[4:0]|NONE|NONE |logical left shift (zeros are shifted into the lower bits).|Integer_Register_Immediate_Operations|
|SRLI |[srli rd, rs1, imm[4:0]](#srli rd, rs1, imm[4:0])|x[rd] = x[rs1] >> imm[4:0]|NONE|NONE |logical right shift (zeros are shifted into the upper bits).|Integer_Register_Immediate_Operations|
|SRAI |[srai rd, rs1, imm[4:0]](#srai rd, rs1, imm[4:0])|x[rd] = x[rs1] >>s imm[4:0]|NONE|NONE |arithmetic right shift (the original sign bit is copied into the vacated upper bits).|Integer_Register_Immediate_Operations|
|LUI |[lui rd, imm[19:0]](#lui rd, imm[19:0])|x[rd] = sext(imm[31:12] << 12)|NONE|NONE |place the immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros.|Integer_Register_Immediate_Operations|
|AUIPC |[auipc rd, imm[19:0]](#auipc rd, imm[19:0])|x[rd] = pc + sext(immediate[31:12] << 12)|NONE|NONE |form a 32-bit offset from the 20-bit immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then place the result in register rd.|Integer_Register_Immediate_Operations|
|ADD |[add rd, rs1, rs2](#add rd, rs1, rs2)|x[rd] = x[rs1] + x[rs2]|NONE|NONE |add rs2 to register rs1, and store the result in register rd.|Integer_Register_Register_Operations|
|SUB |[sub rd, rs1, rs2](#sub rd, rs1, rs2)|x[rd] = x[rs1] - x[rs2]|NONE|NONE |subtract rs2 from register rs1, and store the result in register rd.|Integer_Register_Register_Operations|
|AND |[and rd, rs1, rs2](#and rd, rs1, rs2)|x[rd] = x[rs1] & x[rs2]|NONE|NONE |perform bitwise AND on register rs1 and rs2 and place the result in rd.|Integer_Register_Register_Operations|
|OR |[or rd, rs1, rs2](#or rd, rs1, rs2)|x[rd] = x[rs1] \| x[rs2]|NONE|NONE |perform bitwise OR on register rs1 and rs2 and place the result in rd.|Integer_Register_Register_Operations|
|XOR |[xor rd, rs1, rs2](#xor rd, rs1, rs2)|x[rd] = x[rs1] ^ x[rs2]|NONE|NONE |perform bitwise XOR on register rs1 and rs2 and place the result in rd.|Integer_Register_Register_Operations|
|SLT |[slt rd, rs1, rs2](#slt rd, rs1, rs2)|if (x[rs1] < x[rs2]) x[rd] = 1 else x[rd] = 0|NONE|NONE |set register rd to 1 if register rs1 is less than rs2 when both are treated as signed numbers, else 0 is written to rd.|Integer_Register_Register_Operations|
|SLTU |[sltu rd, rs1, rs2](#sltu rd, rs1, rs2)|if (x[rs1] <u x[rs2]) x[rd] = 1 else x[rd] = 0|NONE|NONE |set register rd to 1 if register rs1 is less than rs2 when both are treated as unsigned numbers, else 0 is written to rd.|Integer_Register_Register_Operations|
|SLL |[sll rd, rs1, rs2](#sll rd, rs1, rs2)|x[rd] = x[rs1] << x[rs2]|NONE|NONE |logical left shift (zeros are shifted into the lower bits).|Integer_Register_Register_Operations|
|SRL |[srl rd, rs1, rs2](#srl rd, rs1, rs2)|x[rd] = x[rs1] >> x[rs2]|NONE|NONE |logical right shift (zeros are shifted into the upper bits).|Integer_Register_Register_Operations|
|SRA |[sra rd, rs1, rs2](#sra rd, rs1, rs2)|x[rd] = x[rs1] >>s x[rs2]|NONE|NONE |arithmetic right shift (the original sign bit is copied into the vacated upper bits).|Integer_Register_Register_Operations|
|JAL |[jal rd, imm[20:1]](#jal rd, imm[20:1])|x[rd] = pc+4; pc += sext(imm[20:1])|NONE|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|offset is sign-extended and added to the pc to form the jump target address (pc is calculated using signed arithmetic), then setting the least-significant bit of the result to zero, and store the address of instruction following the jump (pc+4) into register rd.|Control_Transfer_Operations-Unconditional_Jumps|
|JALR |[jalr rd, rs1, imm[11:0]](#jalr rd, rs1, imm[11:0])|t = pc+4; pc = (x[rs1]+sext(imm[11:0]))&1 ; x[rd] = t|NONE|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|target address is obtained by adding the 12-bit signed immediate to the register rs1 (pc is calculated using signed arithmetic), then setting the least-significant bit of the result to zero, and store the address of instruction following the jump (pc+4) into register rd.|Control_Transfer_Operations-Unconditional_Jumps|
|BEQ |[beq rs1, rs2, imm[12:1]](#beq rs1, rs2, imm[12:1])|if (x[rs1] == x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 and rs2 are equal.|Control_Transfer_Operations-Conditional_Branches|
|BNE |[bne rs1, rs2, imm[12:1]](#bne rs1, rs2, imm[12:1])|if (x[rs1] != x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 and rs2 are not equal.|Control_Transfer_Operations-Conditional_Branches|
|BLT |[blt rs1, rs2, imm[12:1]](#blt rs1, rs2, imm[12:1])|if (x[rs1] < x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 less than rs2 (using signed comparison).|Control_Transfer_Operations-Conditional_Branches|
|BLTU |[bltu rs1, rs2, imm[12:1]](#bltu rs1, rs2, imm[12:1])|if (x[rs1] <u x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 less than rs2 (using unsigned comparison).|Control_Transfer_Operations-Conditional_Branches|
|BGE |[bge rs1, rs2, imm[12:1]](#bge rs1, rs2, imm[12:1])|if (x[rs1] >= x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 is greater than or equal rs2 (using signed comparison).|Control_Transfer_Operations-Conditional_Branches|
|BGEU |[bgeu rs1, rs2, imm[12:1]](#bgeu rs1, rs2, imm[12:1])|if (x[rs1] >=u x[rs2]) pc += sext({imm[12:1], 1b0}) else pc += 4|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|takes the branch (pc is calculated using signed arithmetic) if registers rs1 is greater than or equal rs2 (using unsigned comparison).|Control_Transfer_Operations-Conditional_Branches|
|LB |[lb rd, imm(rs1)](#lb rd, imm(rs1))|x[rd] = sext(M[x[rs1] + sext(imm[11:0])][7:0])|NONE|loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded.|loads a 8-bit value from memory, then sign-extends to 32-bit before storing in rd (rd is calculated using signed arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|LH |[lh rd, imm(rs1)](#lh rd, imm(rs1))|x[rd] = sext(M[x[rs1] + sext(imm[11:0])][15:0])|NONE|loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (2-byte boundary).|loads a 16-bit value from memory, then sign-extends to 32-bit before storing in rd (rd is calculated using signed arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|LW |[lw rd, imm(rs1)](#lw rd, imm(rs1))|x[rd] = sext(M[x[rs1] + sext(imm[11:0])][31:0])|NONE|loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (4-byte boundary).|loads a 32-bit value from memory, then storing in rd (rd is calculated using signed arithmetic). The effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|LBU |[lbu rd, imm(rs1)](#lbu rd, imm(rs1))|x[rd] = zext(M[x[rs1] + sext(imm[11:0])][7:0])|NONE|loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded.|loads a 8-bit value from memory, then zero-extends to 32-bit before storing in rd (rd is calculated using unsigned arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|LHU |[lhu rd, imm(rs1)](#lhu rd, imm(rs1))|x[rd] = zext(M[x[rs1] + sext(imm[11:0])][15:0])|NONE|loads with a destination of x0 must still raise any exceptions and action any other side effects even though the load value is discarded, also an exception is raised if the memory address isn't aligned (2-byte boundary).|loads a 16-bit value from memory, then zero-extends to 32-bit before storing in rd (rd is calculated using unsigned arithmetic), the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|SB |[sb rs2, imm(rs1)](#sb rs2, imm(rs1))|M[x[rs1] + sext(imm[11:0])][7:0] = x[rs2][7:0]|NONE|NONE |stores a 8-bit value from the low bits of register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|SH |[sh rs2, imm(rs1)](#sh rs2, imm(rs1))|M[x[rs1] + sext(imm[11:0])][15:0] = x[rs2][15:0]|NONE|an exception is raised if the memory address isn't aligned (2-byte boundary).|stores a 16-bit value from the low bits of register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|SW |[sw rs2, imm(rs1)](#sw rs2, imm(rs1))|M[x[rs1] + sext(imm[11:0])][31:0] = x[rs2][31:0]|NONE|an exception is raised if the memory address isn't aligned (4-byte boundary).|stores a 32-bit value from register rs2 to memory, the effective address is obtained by adding register rs1 to the sign-extended 12-bit offset.|Load_and_Store_Instructions|
|FENCE |[fence pre, succ](#fence pre, succ)|No operation (nop)|NONE|NONE |order device I/O and memory accesses as viewed by other RISC-V harts and external devices or coprocessors. Any combination of device input (I), device output (O), memory reads (R), and memory writes (W) may be ordered with respect to any combination of the same. Informally, no other RISC-V hart or external device can observe any operation in the successor set following a FENCE before any operation in the predecessor set preceding the FENCE, as the core support 1 hart, the fence instruction has no effect so we can considerate it as a nop instruction.|Memory_Ordering|
|ECALL |[ecall](#ecall)|RaiseException(EnvironmentCall)|NONE|Raise an Environment Call exception. |make a request to the supporting execution environment, which is usually an operating system. The ABI for the system will define how parameters for the environment request are passed, but usually these will be in defined locations in the integer register file.|Environment_Call_and_Breakpoints|
|EBREAK |[ebreak](#ebreak)|x[8 + rd'] = sext(x[8 + rd'][7:0])|NONE|NONE |This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. |Environment_Call_and_Breakpoints|
### RV32M Multiplication and Division Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|MUL |[mul rd, rs1, rs2](#mul rd, rs1, rs2)|x[rd] = x[rs1] * x[rs2]|NONE|NONE |performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rs1 and rs2 treated as signed numbers).|Multiplication Operations|
|MULH |[mulh rd, rs1, rs2](#mulh rd, rs1, rs2)|x[rd] = (x[rs1] s*s x[rs2]) >>s 32|NONE|NONE |performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (Both rs1 and rs2 treated as signed numbers).|Multiplication Operations|
|MULHU |[mulhu rd, rs1, rs2](#mulhu rd, rs1, rs2)|x[rd] = (x[rs1] u*u x[rs2]) >>u 32|NONE|NONE |performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (Both rs1 and rs2 treated as unsigned numbers).|Multiplication Operations|
|MULHSU |[mulhsu rd, rs1, rs2](#mulhsu rd, rs1, rs2)|x[rd] = (x[rs1] s*u x[rs2]) >>s 32|NONE|NONE |performs a 32-bit × 32-bit multiplication and places the upper 32 bits in the destination register of the 64-bit product (rs1 treated as signed number, rs2 treated as unsigned number).|Multiplication Operations|
|DIV |[div rd, rs1, rs2](#div rd, rs1, rs2)|x[rd] = x[rs1] /s x[rs2]|NONE|NONE |perform signed integer division of 32 bits by 32 bits (rounding towards zero).|Division Operations|
|DIVU |[divu rd, rs1, rs2](#divu rd, rs1, rs2)|x[rd] = x[rs1] /u x[rs2]|NONE|NONE |perform unsigned integer division of 32 bits by 32 bits (rounding towards zero).|Division Operations|
|REM |[rem rd, rs1, rs2](#rem rd, rs1, rs2)|x[rd] = x[rs1] %s x[rs2]|NONE|NONE |provide the remainder of the corresponding division operation DIV (the sign of rd equals the sign of rs1).|Division Operations|
|REMU |[rem rd, rs1, rs2](#rem rd, rs1, rs2)|x[rd] = x[rs1] %u x[rs2]|NONE|NONE |provide the remainder of the corresponding division operation DIVU.|Division Operations|
### RV32C Compressed Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|C.LI |[c.li rd, imm[5:0]](#c.li rd, imm[5:0])|x[rd] = sext(imm[5:0])|rd = x0|NONE |loads the sign-extended 6-bit immediate, imm, into register rd.|Integer Computational Instructions|
|C.LUI |[c.lui rd, nzimm[17:12]](#c.lui rd, nzimm[17:12])|x[rd] = sext(nzimm[17:12] << 12)|rd = x0 & rd = x2 & nzimm = 0|NONE |loads the non-zero 6-bit immediate field into bits 1712 of the destination register, clears the bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination.|Integer Computational Instructions|
|C.ADDI |[c.addi rd, nzimm[5:0]](#c.addi rd, nzimm[5:0])|x[rd] = x[rd] + sext(nzimm[5:0])|rd = x0 & nzimm = 0|NONE |adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd.|Integer Computational Instructions|
|C.ADDI16SP |[c.addi16sp nzimm[9:4]](#c.addi16sp nzimm[9:4])|x[2] = x[2] + sext(nzimm[9:4])|rd != x2 & nzimm = 0|NONE |adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). C.ADDI16SP is used to adjust the stack pointer in procedure prologues and epilogues. C.ADDI16SP shares the opcode with C.LUI, but has a destination field of x2.|Integer Computational Instructions|
|C.ADDI4SPN |[c.addi4spn rd', nzimm[9:2]](#c.addi4spn rd', nzimm[9:2])|x[8 + rd'] = x[2] + zext(nzimm[9:2])|nzimm = 0|NONE |adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd'. This instruction is used to generate pointers to stack-allocated variables.|Integer Computational Instructions|
|C.SLLI |[c.slli rd, uimm[5:0]](#c.slli rd, uimm[5:0])|x[rd] = x[rd] << uimm[5:0]|rd = x0 & uimm[5] = 0|NONE |performs a logical left shift (zeros are shifted into the lower bits).|Integer Computational Instructions|
|C.SRLI |[c.srli rd', uimm[5:0]](#c.srli rd', uimm[5:0])|x[8 + rd'] = x[8 + rd'] >> uimm[5:0]|uimm[5] = 0|NONE |performs a logical right shift (zeros are shifted into the upper bits).|Integer Computational Instructions|
|C.SRAI |[c.srai rd', uimm[5:0]](#c.srai rd', uimm[5:0])|x[8 + rd'] = x[8 + rd'] >>s uimm[5:0]|uimm[5] = 0|NONE |performs an arithmetic right shift (sign bits are shifted into the upper bits).|Integer Computational Instructions|
|C.ANDI |[c.andi rd', imm[5:0]](#c.andi rd', imm[5:0])|x[8 + rd'] = x[8 + rd'] & sext(imm[5:0])|NONE|NONE |computes the bitwise AND of the value in register rd', and the sign-extended 6-bit immediate, then writes the result to rd'.|Integer Computational Instructions|
|C.ADD |[c.add rd, rs2](#c.add rd, rs2)|x[rd] = x[rd] + x[rs2]|rd = x0 & rs2 = x0|NONE |adds the values in registers rd and rs2 and writes the result to register rd.|Integer Computational Instructions|
|C.MV |[c.mv rd, rs2](#c.mv rd, rs2)|x[rd] = x[rs2]|rd = x0 & rs2 = x0|NONE |copies the value in register rs2 into register rd.|Integer Computational Instructions|
|C.AND |[c.and rd', rs2'](#c.and rd', rs2')|x[8 + rd'] = x[8 + rd'] & x[8 + rs2']|NONE|NONE |computes the bitwise AND of of the value in register rd', and register rs2', then writes the result to rd'.|Integer Computational Instructions|
|C.OR |[c.or rd', rs2'](#c.or rd', rs2')|x[8 + rd'] = x[8 + rd'] \| x[8 + rs2']|NONE|NONE |computes the bitwise OR of of the value in register rd', and register rs2', then writes the result to rd'.|Integer Computational Instructions|
|C.XOR |[c.and rd', rs2'](#c.and rd', rs2')|x[8 + rd'] = x[8 + rd'] ^ x[8 + rs2']|NONE|NONE |computes the bitwise XOR of of the value in register rd', and register rs2', then writes the result to rd'.|Integer Computational Instructions|
|C.SUB |[c.sub rd', rs2'](#c.sub rd', rs2')|x[8 + rd'] = x[8 + rd'] - x[8 + rs2']|NONE|NONE |subtracts the value in registers rs2' from value in rd' and writes the result to register rd'.|Integer Computational Instructions|
|C.EBREAK |[c.ebreak](#c.ebreak)|RaiseException(Breakpoint)|NONE|Raise a Breakpoint exception. |cause control to be transferred back to the debugging environment.|Integer Computational Instructions|
|C.J |[c.j imm[11:1]](#c.j imm[11:1])|pc += sext(imm[11:1])|NONE|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|performs an unconditional control transfer. The offset is sign-extended and added to the pc to form the jump target address.|Control Transfer Instructions|
|C.JAL |[c.jal imm[11:1]](#c.jal imm[11:1])|x[1] = pc+2; pc += sext(imm[11:1])|NONE|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|performs the same operation as C.J, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1.|Control Transfer Instructions|
|C.JR |[c.jr rs1](#c.jr rs1)|pc = x[rs1]|rs1 = x0|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|performs an unconditional control transfer to the address in register rs1.|Control Transfer Instructions|
|C.JALR |[c.jalr rs1](#c.jalr rs1)|t = pc+2; pc = x[rs1]; x[1] = t|rs1 = x0|jumps to an unaligned address (4-byte or 2-byte boundary) will usually raise an exception.|performs the same operation as C.JR, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1.|Control Transfer Instructions|
|C.BEQZ |[c.beqz rs1', imm[8:1]](#c.beqz rs1', imm[8:1])|if (x[8+rs1'] == 0) pc += sext(imm[8:1])|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. C.BEQZ takes the branch if the value in register rs1' is zero.|Control Transfer Instructions|
|C.BNEZ |[c.bnez rs1', imm[8:1]](#c.bnez rs1', imm[8:1])|if (x[8+rs1'] != 0) pc += sext(imm[8:1])|NONE|no instruction fetch misaligned exception is generated for a conditional branch that is not taken. An Instruction address misaligned exception is raised if the target address is not aligned on 4-byte or 2-byte boundary, because the core supports compressed instructions.|performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. C.BEQZ takes the branch if the value in register rs1' isn't zero.|Control Transfer Instructions|
|C.LWSP |[c.lwsp rd, uimm(x2)](#c.lwsp rd, uimm(x2))|x[rd] = M[x[2] + zext(uimm[7:2])][31:0]|rd = x0|loads with a destination of x0 must still raise any exceptions, also an exception if the memory address isn't aligned (4-byte boundary).|loads a 32-bit value from memory into register rd. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.|Load and Store Instructions|
|C.SWSP |[c.swsp rd, uimm(x2)](#c.swsp rd, uimm(x2))|M[x[2] + zext(uimm[7:2])][31:0] = x[rs2]|NONE|an exception raised if the memory address isn't aligned (4-byte boundary).|stores a 32-bit value in register rs2 to memory. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.|Load and Store Instructions|
|C.LW |[c.lw rd', uimm(rs1')](#c.lw rd', uimm(rs1'))|x[8+rd'] = M[x[8+rs1'] + zext(uimm[6:2])][31:0])|NONE|an exception raised if the memory address isn't aligned (4-byte boundary).|loads a 32-bit value from memory into register rd'. It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1'.|Load and Store Instructions|
|C.SW |[c.sw rs2', uimm(rs1')](#c.sw rs2', uimm(rs1'))|M[x[8+rs1'] + zext(uimm[6:2])][31:0] = x[8+rs2']|NONE|an exception raised if the memory address isn't aligned (4-byte boundary).|stores a 32-bit value from memory into register rd'. It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1'.|Load and Store Instructions|
### RV32Zicsr Control and Status Register Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|CSRRW |[csrrw rd, csr, rs1](#csrrw rd, csr, rs1)|t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the old value of the CSR, zero-extends the value to 32 bits, then writes it to integer register rd. The initial value in rs1 is written to the CSR. If rd=x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read. |Control and Status Register Operations|
|CSRRS |[csrrs rd, csr, rs1](#csrrs rd, csr, rs1)|t = CSRs[csr]; CSRs[csr] = t \| x[rs1]; x[rd] = t|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The initial value in integer register rs1 is treated as a bit mask that specifies bit positions to be set in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSRs. |Control and Status Register Operations|
|CSRRC |[csrrc rd, csr, rs1](#csrrc rd, csr, rs1)|t = CSRs[csr]; CSRs[csr] = t & x[rs1]; x[rd] = t|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The initial value in integer register rs1 is treated as a bit mask that specifies bit positions to be cleared in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSRs. |Control and Status Register Operations|
|CSRRWI |[csrrwi rd, csr, uimm[4:0]](#csrrwi rd, csr, uimm[4:0])|x[rd] = CSRs[csr]; CSRs[csr] = zext(uimm[4:0])|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the old value of the CSR, zero-extends the value to 32 bits, then writes it to integer register rd. The zero-extends immediate is written to the CSR. If rd=x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read. |Control and Status Register Operations|
|CSRRSI |[csrrsi rd, csr, uimm[4:0]](#csrrsi rd, csr, uimm[4:0])|t = CSRs[csr]; CSRs[csr] = t \| zext(uimm[4:0]); x[rd] = t|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The zero-extends immediate value is treated as a bit mask that specifies bit positions to be set in the CSR. Any bit that is high in zero-extends immediate will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If the uimm[4:0] field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write. |Control and Status Register Operations|
|CSRRCI |[csrrci rd, csr, uimm[4:0]](#csrrci rd, csr, uimm[4:0])|t = CSRs[csr]; CSRs[csr] = t & zext(uimm[4:0]); x[rd] = t|NONE|Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. |Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The zero-extends immediate value is treated as a bit mask that specifies bit positions to be cleared in the CSR. Any bit that is high in zero-extends immediate will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If the uimm[4:0] field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write. |Control and Status Register Operations|
### RVZifencei Instruction Fetch Fence
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|FENCE.I |[fence.i](#fence.i)|Fence(Store, Fetch)|NONE|NONE |The FENCE.I instruction is used to synchronize the instruction and data streams. RISC-V does not guarantee that stores to instruction memory will be made visible to instruction fetches on the same RISC-V hart until a FENCE.I instruction is executed. A FENCE.I instruction only ensures that a subsequent instruction fetch on a RISC-V hart will see any previous data stores already visible to the same RISC-V hart. |Fetch Fence Operations|
### RVZba Address generation instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|ADD.UW |[add.uw rd, rs1, rs2](#add.uw rd, rs1, rs2)|X(rd) = rs2 + EXTZ(X(rs1)[31..0])|NONE|NONE |This instruction performs an XLEN-wide addition between rs2 and the zero-extended least-significant word of rs1. |Address generation instructions|
|SH1ADD |[sh1add rd, rs1, rs2](#sh1add rd, rs1, rs2)|X(rd) = X(rs2) + (X(rs1) << 1)|NONE|NONE |This instruction shifts rs1 to the left by 1 bit and adds it to rs2. |Address generation instructions|
|SH1ADD.UW |[sh1add.uw rd, rs1, rs2](#sh1add.uw rd, rs1, rs2)|X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 1)|NONE|NONE |This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 1 place. |Address generation instructions|
|SH2ADD |[sh2add rd, rs1, rs2](#sh2add rd, rs1, rs2)|X(rd) = X(rs2) + (X(rs1) << 2)|NONE|NONE |This instruction shifts rs1 to the left by 2 bit and adds it to rs2. |Address generation instructions|
|SH2ADD.UW |[sh2add.uw rd, rs1, rs2](#sh2add.uw rd, rs1, rs2)|X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 2)|NONE|NONE |This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 2 places. |Address generation instructions|
|SH3ADD |[sh3add rd, rs1, rs2](#sh3add rd, rs1, rs2)|X(rd) = X(rs2) + (X(rs1) << 3)|NONE|NONE |This instruction shifts rs1 to the left by 3 bit and adds it to rs2. |Address generation instructions|
|SH3ADD.UW |[sh3add.uw rd, rs1, rs2](#sh3add.uw rd, rs1, rs2)|X(rd) = rs2 + (EXTZ(X(rs1)[31..0]) << 3)|NONE|NONE |This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. The second addend is the unsigned value formed by extracting the least-significant word of rs1 and shifting it left by 3 places. |Address generation instructions|
|SLLI.UW |[slli.uw rd, rs1, imm](#slli.uw rd, rs1, imm)|X(rd) = (EXTZ(X(rs)[31..0]) << imm)|NONE|NONE |This instruction takes the least-significant word of rs1, zero-extends it, and shifts it left by the immediate. |Address generation instructions|
### RVZbb Basic bit-manipulation
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|ANDN |[andn rd, rs1, rs2](#andn rd, rs1, rs2)|X(rd) = X(rs1) & ~X(rs2)|NONE|NONE |Performs bitwise AND operation between rs1 and bitwise inversion of rs2.|Logical_with_negate|
|ORN |[orn rd, rs1, rs2](#orn rd, rs1, rs2)|X(rd) = X(rs1) \| ~X(rs2)|NONE|NONE |Performs bitwise OR operation between rs1 and bitwise inversion of rs2.|Logical_with_negate|
|XNOR |[xnor rd, rs1, rs2](#xnor rd, rs1, rs2)|X(rd) = ~(X(rs1) ^ X(rs2))|NONE|NONE |Performs bitwise XOR operation between rs1 and rs2, then complements the result.|Logical_with_negate|
|CLZ |[clz rd, rs](#clz rd, rs)|if [x[i]] == 1 then return(i) else return -1|NONE|NONE |Counts leading zero bits in rs.|Count_leading_trailing_zero_bits|
|CTZ |[ctz rd, rs](#ctz rd, rs)|if [x[i]] == 1 then return(i) else return xlen;|NONE|NONE |Counts trailing zero bits in rs.|Count_leading_trailing_zero_bits|
|CLZW |[clzw rd, rs](#clzw rd, rs)|if [x[i]] == 1 then return(i) else return -1|NONE|NONE |Counts leading zero bits in the least-significant word of rs.|Count_leading_trailing_zero_bits|
|CTZW |[ctzw rd, rs](#ctzw rd, rs)|if [x[i]] == 1 then return(i) else return 32;|NONE|NONE |Counts trailing zero bits in the least-significant word of rs.|Count_leading_trailing_zero_bits|
|CPOP |[cpop rd, rs](#cpop rd, rs)|if rs[i] == 1 then bitcount = bitcount + 1 else ()|NONE|NONE |Counts set bits in rs.|Count_population|
|CPOPW |[cpopw rd, rs](#cpopw rd, rs)|if rs[i] == 0b1 then bitcount = bitcount + 1 else ()|NONE|NONE |Counts set bits in the least-significant word of rs.|Count_population|
|MAX |[max rd, rs1, rs2](#max rd, rs1, rs2)|if rs1_val <_s rs2_val then rs2_val else rs1_val|NONE|NONE |Returns the larger of two signed integers.|Integer_minimum_maximum|
|MAXU |[maxu rd, rs1, rs2](#maxu rd, rs1, rs2)|if rs1_val <_u rs2_val then rs2_val else rs1_val|NONE|NONE |Returns the larger of two unsigned integers.|Integer_minimum_maximum|
|MIN |[min rd, rs1, rs2](#min rd, rs1, rs2)|if rs1_val <_s rs2_val then rs1_val else rs2_val|NONE|NONE |Returns the smaller of two signed integers.|Integer_minimum_maximum|
|MINU |[minu rd, rs1, rs2](#minu rd, rs1, rs2)|if rs1_val <_u rs2_val then rs1_val else rs2_val|NONE|NONE |Returns the smaller of two unsigned integers.|Integer_minimum_maximum|
|SEXT.B |[sext.b rd, rs](#sext.b rd, rs)|X(rd) = EXTS(X(rs)[7..0])|NONE|NONE |Sign-extends the least-significant byte in the source to XLEN.|Sign_and_zero_extension|
|SEXT.H |[sext.h rd, rs](#sext.h rd, rs)|X(rd) = EXTS(X(rs)[15..0])|NONE|NONE |Sign-extends the least-significant halfword in rs to XLEN.|Sign_and_zero_extension|
|ZEXT.H |[zext.h rd, rs](#zext.h rd, rs)|X(rd) = EXTZ(X(rs)[15..0])|NONE|NONE |Zero-extends the least-significant halfword of the source to XLEN.|Sign_and_zero_extension|
|ROL |[rol rd, rs1, rs2](#rol rd, rs1, rs2)|(X(rs1) << log2(XLEN)) \| (X(rs1) >> (xlen - log2(XLEN)))|NONE|NONE |Performs a rotate left of rs1 by the amount in least-significant log2(XLEN) bits of rs2.|Bitwise_rotation|
|ROR |[ror rd, rs1, rs2](#ror rd, rs1, rs2)|(X(rs1) >> log2(XLEN)) \| (X(rs1) << (xlen - log2(XLEN)))|NONE|NONE |Performs a rotate right of rs1 by the amount in least-significant log2(XLEN) bits of rs2.|Bitwise_rotation|
|RORI |[rori rd, rs1, shamt](#rori rd, rs1, shamt)|(X(rs1) >> log2(XLEN)) \| (X(rs1) << (xlen - log2(XLEN)))|NONE|NONE |Performs a rotate right of rs1 by the amount in least-significant log2(XLEN) bits of shamt.|Bitwise_rotation|
|ROLW |[rolw rd, rs1, rs2](#rolw rd, rs1, rs2)|EXTS((rs1 << X(rs2)[4..0]) \| (rs1 >> (32 - X(rs2)[4..0])))|NONE|NONE |Performs a rotate left on the least-significant word of rs1 by the amount in least-significant 5 bits of rs2.|Bitwise_rotation|
|RORIW |[roriw rd, rs1, shamt](#roriw rd, rs1, shamt)|(rs1_data >> shamt[4..0]) \| (rs1_data << (32 - shamt[4..0]))|NONE|NONE |Performs a rotate right on the least-significant word of rs1 by the amount in least-significant log2(XLEN) bits of shamt.|Bitwise_rotation|
|RORW |[rorw rd, rs1, rs2](#rorw rd, rs1, rs2)|(rs1 >> X(rs2)[4..0]) \| (rs1 << (32 - X(rs2)[4..0]))|NONE|NONE |Performs a rotate right on the least-significant word of rs1 by the amount in least-significant 5 bits of rs2.|Bitwise_rotation|
|ORC.b |[orc.b rd, rs](#orc.b rd, rs)|if { input[(i + 7)..i] == 0 then 0b00000000 else 0b11111111|NONE|NONE |Sets the bits of each byte in rd to all zeros if no bit within the respective byte of rs is set, or to all ones if any bit within the respective byte of rs is set.|OR_Combine|
|REV8 |[rev8 rd, rs](#rev8 rd, rs)|output[i..(i + 7)] = input[(j - 7)..j]|NONE|NONE |Reverses the order of the bytes in rs.|Byte_reverse|
### RVZbc Carry-less multiplication
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|CLMUL |[clmul rd, rs1, rs2](#clmul rd, rs1, rs2)|foreach (i from 1 to xlen by 1) { output = if ((rs2 >> i) & 1) then output ^ (rs1 << i); else output; } |NONE|NONE |clmul produces the lower half of the 2.XLEN carry-less product. |Carry-less multiplication Operations|
|CLMULH |[clmulh rd, rs1, rs2](#clmulh rd, rs1, rs2)|foreach (i from 1 to xlen by 1) { output = if ((rs2_val >> i) & 1) then output ^ (rs1_val >> (xlen - i)) else output } |NONE|NONE |clmulh produces the upper half of the 2.XLEN carry-less product. |Carry-less multiplication Operations|
|CLMULR |[clmulr rd, rs1, rs2](#clmulr rd, rs1, rs2)|foreach (i from 0 to (xlen - 1) by 1) { output = if ((rs2_val >> i) & 1) then output ^ (rs1_val >> (xlen - i - 1)) else output } |NONE|NONE |clmulr produces bits 2.XLEN-2:XLEN-1 of the 2.XLEN carry-less product. |Carry-less multiplication Operations|
### RVZbs Single bit Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|BCLR |[bclr rd, rs1, rs2](#bclr rd, rs1, rs2)|X(rd) = X(rs1) & ~(1 << (X(rs2) & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit cleared at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. |Single_bit_Operations|
|BCLRI |[bclri rd, rs1, shamt](#bclri rd, rs1, shamt)|X(rd) = X(rs1) & ~(1 << (shamt & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit cleared at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. |Single_bit_Operations|
|BEXT |[bext rd, rs1, rs2](#bext rd, rs1, rs2)|X(rd) = (X(rs1) >> (X(rs2) & (XLEN - 1))) & 1|NONE|NONE |This instruction returns a single bit extracted from rs1 at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. |Single_bit_Operations|
|BEXTI |[bexti rd, rs1, shamt](#bexti rd, rs1, shamt)|X(rd) = (X(rs1) >> (shamt & (XLEN - 1))) & 1|NONE|NONE |This instruction returns a single bit extracted from rs1 at the index specified in rs2. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. |Single_bit_Operations|
|BINV |[binv rd, rs1, rs2](#binv rd, rs1, rs2)|X(rd) = X(rs1) ^ (1 << (X(rs2) & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit inverted at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. |Single_bit_Operations|
|BINVI |[binvi rd, rs1, shamt](#binvi rd, rs1, shamt)|X(rd) = X(rs1) ^ (1 << (shamt & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit inverted at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. |Single_bit_Operations|
|BSET |[bset rd, rs1, rs2](#bset rd, rs1, rs2)|X(rd) = X(rs1) \| (1 << (X(rs2) & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit set at the index specified in rs2. The index is read from the lower log2(XLEN) bits of rs2. |Single_bit_Operations|
|BSETI |[bseti rd, rs1, shamt](#bseti rd, rs1, shamt)|X(rd) = X(rs1) \| (1 << (shamt & (XLEN - 1)))|NONE|NONE |This instruction returns rs1 with a single bit set at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. |Single_bit_Operations|
### RV32Zcb Code Size Reduction Instructions
|Name|Format|Pseudocode|Invalid_values|Exception_raised|Description|Op Name|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|C.ZEXT.B |[c.zext.b rd'](#c.zext.b rd')|x[8 + rd'] = zext(x[8 + rd'][7:0])|NONE|NONE |This instruction takes a single source/destination operand. It zero-extends the least-significant byte of the operand by inserting zeros into all of the bits more significant than 7. |Code Size Reduction Operations|
|C.SEXT.B |[c.sext.b rd'](#c.sext.b rd')|x[8 + rd'] = sext(x[8 + rd'][7:0])|NONE|NONE |This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. |Code Size Reduction Operations|
|C.ZEXT.H |[c.zext.h rd'](#c.zext.h rd')|x[8 + rd'] = zext(x[8 + rd'][15:0])|NONE|NONE |This instruction takes a single source/destination operand. It zero-extends the least-significant halfword of the operand by inserting zeros into all of the bits more significant than 15. It also requires Bit-Manipulation (Zbb) extension support. |Code Size Reduction Operations|
|C.SEXT.H |[c.sext.h rd'](#c.sext.h rd')|x[8 + rd'] = sext(x[8 + rd'][15:0])|NONE|NONE |This instruction takes a single source/destination operand. It sign-extends the least-significant halfword in the operand by copying the most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. |Code Size Reduction Operations|
|C.NOT |[c.not rd'](#c.not rd')|x[8 + rd'] = x[8 + rd'] ^ -1|NONE|NONE |This instruction takes the ones complement of rd'/rs1' and writes the result to the same register. |Code Size Reduction Operations|
|C.MUL |[c.mul rd', rs2'](#c.mul rd', rs2')|x[8 + rd'] = (x[8 + rd'] * x[8 + rs2'])[31:0]|NONE|NONE |performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rd' and rs2' treated as signed numbers). It also requires M extension support. |Code Size Reduction Operations|
|C.LHU |[c.lhu rd', uimm(rs1')](#c.lhu rd', uimm(rs1'))|x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1])][15:0])|NONE|an exception raised if the memory address isn't aligned (2-byte boundary).|This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is zero extended and is written to rd'. |Code Size Reduction Operations|
|C.LH |[c.lh rd', uimm(rs1')](#c.lh rd', uimm(rs1'))|x[8+rd'] = sext(M[x[8+rs1'] + zext(uimm[1])][15:0])|NONE|an exception raised if the memory address isn't aligned (2-byte boundary).|This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is sign extended and is written to rd'. |Code Size Reduction Operations|
|C.LBU |[c.lbu rd', uimm(rs1')](#c.lbu rd', uimm(rs1'))|x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1:0])][7:0])|NONE|NONE |This instruction loads a byte from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting byte is zero extended and is written to rd'. |Code Size Reduction Operations|
|C.SH |[c.sh rs2', uimm(rs1')](#c.sh rs2', uimm(rs1'))|M[x[8+rs1'] + zext(uimm[1])][15:0] = x[8+rs2']|NONE|an exception raised if the memory address isn't aligned (2-byte boundary).|This instruction stores the least significant halfword of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. |Code Size Reduction Operations|
|C.SB |[c.sb rs2', uimm(rs1')](#c.sb rs2', uimm(rs1'))|M[x[8+rs1'] + zext(uimm[1:0])][7:0] = x[8+rs2']|NONE|NONE |This instruction stores the least significant byte of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. |Code Size Reduction Operations|

View file

@ -32,8 +32,7 @@ Instructions
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zicsr | RV32Zicsr Control and Status Register Instructions_ | All CSR instructions atomically read-modify-write a single CSR, whose CSR specifier is encoded in the 12-bit csr field of the instruction held in bits 3120. The immediate forms use a 5-bit zero-extended immediate encoded in the rs1 field. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zifencei | RVZifencei Instruction Fetch Fence_ | FENCE.I instruction that provides explicit synchronization between writes to instruction memory and instruction fetches on the same hart. |
| | | Currently, this instruction is the only standard mechanism to ensure that stores visible to a hart will also be visible to it instruction fetches. |
| Zcb | RV32Zcb Code Size Reduction Instructions_ | Zcb belongs to the group of extensions called RISC-V Code Size Reduction Extension (Zc*). Zc* has become the superset of the Standard C extension adding more 16-bit instructions to the ISA. Zcb includes the 16-bit version of additional Integer (I), Multiply (M), and Bit-Manipulation (Zbb) Instructions. All the Zcb instructions require at least standard C extension support as a prerequisite, along with M and Zbb extensions for the 16-bit version of the respective instructions. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zba | RVZba Address generation instructions_ | The Zba instructions can be used to accelerate the generation of addresses that index into arrays of basic types (halfword, word, doubleword) using both unsigned word-sized and XLEN-sized indices: a shifted index is added to a base address. The shift and add instructions do a left shift of 1, 2, or 3 because these are commonly found in real-world code and because they can be implemented with a minimal amount of additional hardware beyond that of the simple adder. This avoids lengthening the critical path in implementations. While the shift and add instructions are limited to a maximum left shift of 3, the slli instruction (from the base ISA) can be used to perform similar shifts for indexing into arrays of wider elements. The slli.uw added in this extension can be used when the index is to be interpreted as an unsigned word. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@ -46,10 +45,10 @@ Instructions
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zbs | RVZbs Single bit Instructions_ | The single-bit instructions provide a mechanism to set, clear, invert, or extract a single bit in a register. The bit is specified by its index. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zcb | RV32Zcb Code Size Reduction Instructions_ | Zcb belongs to the group of extensions called RISC-V Code Size Reduction Extension (Zc*). Zc* has become the superset of the Standard C extension adding more 16-bit instructions to the ISA. Zcb includes the 16-bit version of additional Integer (I), Multiply (M), and Bit-Manipulation (Zbb) Instructions. All the Zcb instructions require at least standard C extension support as a prerequisite, along with M and Zbb extensions for the 16-bit version of the respective instructions. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zicntr | Zicntr_ | No info found yet for extension Zicntr |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Zbkb | RVZbkb Bitmanip instructions for Cryptography_ | The Zbkb extension is a part of the RISC-V Bit-Manipulation (bitmanip) extensions, specifically targeting cryptographic applications. It introduces a set of instructions designed to facilitate operations commonly used in cryptographic algorithms, such as interleaving, packing, and reordering of bits. |
+---------------+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
RV32I Base Integer Instructions
-------------------------------
@ -243,15 +242,35 @@ RV32Zicsr Control and Status Register Instructions
| CSRRCI | csrrci rd, csr, uimm[4:0] | t = CSRs[csr]; CSRs[csr] = t & zext(uimm[4:0]); x[rd] = t | NONE | Attempts to access a non-existent CSR raise an illegal instruction exception. Attempts to access a CSR without appropriate privilege level or to write a read-only register also raise illegal instruction exceptions. | Reads the value of the CSR, zero-extends the value to 32 bits, and writes it to integer register rd. The zero-extends immediate value is treated as a bit mask that specifies bit positions to be cleared in the CSR. Any bit that is high in zero-extends immediate will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). If the uimm[4:0] field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write. | Control and Status Register Operations |
+--------+---------------------------+------------------------------------------------------------+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------+
RVZifencei Instruction Fetch Fence
----------------------------------
RV32Zcb Code Size Reduction Instructions
----------------------------------------
+---------+----------+---------------------+------------------+--------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+
| Name | Format | Pseudocode | Invalid_values | Exception_raised | Description | Op Name |
+=========+==========+=====================+==================+====================+==============================================================================================================================================================================================================================================================================================================================================================================================================================+========================+
| FENCE.I | fence.i | Fence(Store, Fetch) | NONE | NONE | The FENCE.I instruction is used to synchronize the instruction and data streams. RISC-V does not guarantee that stores to instruction memory will be made visible to instruction fetches on the same RISC-V hart until a FENCE.I instruction is executed. A FENCE.I instruction only ensures that a subsequent instruction fetch on a RISC-V hart will see any previous data stores already visible to the same RISC-V hart. | Fetch Fence Operations |
+---------+----------+---------------------+------------------+--------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| Name | Format | Pseudocode | Invalid_values | Exception_raised | Description | Op Name |
+==========+=======================+======================================================+==================+============================================================================+==============================================================================================================================================================================================================================================================================================+================================+
| C.ZEXT.B | c.zext.b rd' | x[8 + rd'] = zext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant byte of the operand by inserting zeros into all of the bits more significant than 7. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SEXT.B | c.sext.b rd' | x[8 + rd'] = sext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.ZEXT.H | c.zext.h rd' | x[8 + rd'] = zext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant halfword of the operand by inserting zeros into all of the bits more significant than 15. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SEXT.H | c.sext.h rd' | x[8 + rd'] = sext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant halfword in the operand by copying the most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.NOT | c.not rd' | x[8 + rd'] = x[8 + rd'] ^ -1 | NONE | NONE | This instruction takes the ones complement of rd'/rs1' and writes the result to the same register. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.MUL | c.mul rd', rs2' | x[8 + rd'] = (x[8 + rd'] * x[8 + rs2'])[31:0] | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rd' and rs2' treated as signed numbers). It also requires M extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LHU | c.lhu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is zero extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LH | c.lh rd', uimm(rs1') | x[8+rd'] = sext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is sign extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LBU | c.lbu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1:0])][7:0]) | NONE | NONE | This instruction loads a byte from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting byte is zero extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SH | c.sh rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1])][15:0] = x[8+rs2'] | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction stores the least significant halfword of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SB | c.sb rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1:0])][7:0] = x[8+rs2'] | NONE | NONE | This instruction stores the least significant byte of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
RVZba Address generation instructions
-------------------------------------
@ -376,34 +395,3 @@ RVZbs Single bit Instructions
+--------+----------------------+------------------------------------------------+------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
| BSETI | bseti rd, rs1, shamt | X(rd) = X(rs1) | (1 << (shamt & (XLEN - 1))) | NONE | NONE | This instruction returns rs1 with a single bit set at the index specified in shamt. The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding to shamt[5]=1 are reserved. | Single_bit_Operations |
+--------+----------------------+------------------------------------------------+------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
RV32Zcb Code Size Reduction Instructions
----------------------------------------
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| Name | Format | Pseudocode | Invalid_values | Exception_raised | Description | Op Name |
+==========+=======================+======================================================+==================+============================================================================+==============================================================================================================================================================================================================================================================================================+================================+
| C.ZEXT.B | c.zext.b rd' | x[8 + rd'] = zext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant byte of the operand by inserting zeros into all of the bits more significant than 7. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SEXT.B | c.sext.b rd' | x[8 + rd'] = sext(x[8 + rd'][7:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant byte in the operand by copying the most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.ZEXT.H | c.zext.h rd' | x[8 + rd'] = zext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It zero-extends the least-significant halfword of the operand by inserting zeros into all of the bits more significant than 15. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SEXT.H | c.sext.h rd' | x[8 + rd'] = sext(x[8 + rd'][15:0]) | NONE | NONE | This instruction takes a single source/destination operand. It sign-extends the least-significant halfword in the operand by copying the most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. It also requires Bit-Manipulation (Zbb) extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.NOT | c.not rd' | x[8 + rd'] = x[8 + rd'] ^ -1 | NONE | NONE | This instruction takes the ones complement of rd'/rs1' and writes the result to the same register. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.MUL | c.mul rd', rs2' | x[8 + rd'] = (x[8 + rd'] * x[8 + rs2'])[31:0] | NONE | NONE | performs a 32-bit × 32-bit multiplication and places the lower 32 bits in the destination register (Both rd' and rs2' treated as signed numbers). It also requires M extension support. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LHU | c.lhu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is zero extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LH | c.lh rd', uimm(rs1') | x[8+rd'] = sext(M[x[8+rs1'] + zext(uimm[1])][15:0]) | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction loads a halfword from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting halfword is sign extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.LBU | c.lbu rd', uimm(rs1') | x[8+rd'] = zext(M[x[8+rs1'] + zext(uimm[1:0])][7:0]) | NONE | NONE | This instruction loads a byte from the memory address formed by adding rs1' to the zero extended immediate uimm. The resulting byte is zero extended and is written to rd'. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SH | c.sh rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1])][15:0] = x[8+rs2'] | NONE | an exception raised if the memory address isn't aligned (2-byte boundary). | This instruction stores the least significant halfword of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
| C.SB | c.sb rs2', uimm(rs1') | M[x[8+rs1'] + zext(uimm[1:0])][7:0] = x[8+rs2'] | NONE | NONE | This instruction stores the least significant byte of rs2' to the memory address formed by adding rs1' to the zero extended immediate uimm. | Code Size Reduction Operations |
+----------+-----------------------+------------------------------------------------------+------------------+----------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+

View file

@ -0,0 +1,82 @@
/*======================================================================*/
/* Proxy kernel linker script */
/*======================================================================*/
/* This is the linker script used when building the proxy kernel. */
/*----------------------------------------------------------------------*/
/* Setup */
/*----------------------------------------------------------------------*/
/* The OUTPUT_ARCH command specifies the machine architecture where the
argument is one of the names used in the BFD library. More
specifically one of the entires in bfd/cpu-mips.c */
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
/*----------------------------------------------------------------------*/
/* Sections */
/*----------------------------------------------------------------------*/
SECTIONS
{
/* text: test code section */
. = 0x80000000;
_start_text = .;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.uvmif : { *(.uvmif) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.text.startup : { *(.text.startup) }
. = ALIGN(0x1000);
_end_text = .;
. = ALIGN(0x1000);
.rodata : { *(.rodata*)}
. = ALIGN(0x8);
. = ALIGN(0x1000);
.page_table : { *(.page_table) }
.user_stack : { *(.user_stack) }
.kernel_data : { *(.kernel_data) }
.kernel_stack : { *(.kernel_stack) }
/* data segment */
.data : { *(.data) }
.sdata : {
__global_pointer$ = . + 0x800;
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
/* bss segment */
.sbss : {
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss : { *(.bss) }
/* thread-local data segment */
.tdata :
{
_tdata_begin = .;
*(.tdata)
_tdata_end = .;
}
.tbss :
{
*(.tbss)
_tbss_end = .;
}
/* End of uninitalized data segement */
_end = .;
}

View file

@ -1,28 +1,63 @@
spike_param_tree:
bootrom: true
bootrom_base: 0x10000
bootrom_size: 0x1000
bootrom_base: 65536
bootrom_size: 4096
dram: true
dram_base: 0x80000000
dram_size: 0x40000000
dram_base: 2147483648
dram_size: 1073741824
generic_core_config: false
max_steps: 200000
max_steps_enabled: false
isa: rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
priv: MSU
isa: rv32imczicsr_zcb_zba_zbb_zbc_zbs
priv: M
core_configs:
- isa: rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
marchid: 0x3
misa_we: false
misa_we_enable: true
misaligned: false
mmu_mode: sv39
mvendorid: 0x00000602
pmpaddr0: 0x0
pmpcfg0: 0x0
pmpregions: 0x0
priv: MSU
-
isa: rv32imczicsr_zcb_zba_zbb_zbc_zbs
extensions: cv32a60x,cvxif
boot_addr: 2147483648
marchid_override_mask: 0xFFFFFFFF
marchid_override_value: 0x3
misa_write_mask: 0x0
pmp_granularity: 8
pmpaddr0: 0
pmpcfg0: 0
pmpregions_max: 64
pmpregions_writable: 8
priv: M
status_fs_field_we: false
status_fs_field_we_enable: false
status_vs_field_we: false
status_vs_field_we_enable: false
mstatus_write_mask: 136
mstatus_override_mask: 6144
mie_write_mask: 0x00000880
mie_override_mask: 0xfffff77f
mie_override_value: 0x00000000
mip_write_mask: 0x00000000
mip_override_mask: 0xfffff77f
mip_override_value: 0x00000000
mtval_write_mask: 0
tinfo_accessible: 0
mscontext_accessible: 0
mcontext_accessible: 0
tdata1_accessible: 0
tdata2_accessible: 0
tdata3_accessible: 0
tselect_accessible: 0
pmpaddr0_write_mask: 0xFFFFFFFE
pmpaddr1_write_mask: 0xFFFFFFFE
pmpaddr2_write_mask: 0xFFFFFFFE
pmpaddr3_write_mask: 0xFFFFFFFE
pmpaddr4_write_mask: 0xFFFFFFFE
pmpaddr5_write_mask: 0xFFFFFFFE
pmpaddr6_write_mask: 0xFFFFFFFE
pmpaddr7_write_mask: 0xFFFFFFFE
mtvec_write_mask: 0xFFFFFFFE
mhartid: 0
mvendorid_override_mask : 0xFFFFFFFF
mvendorid_override_value: 1538
csr_counters_injection: true
interrupts_injection: true
unified_traps: true
mcycleh_implemented: false
mhpmevent31_implemented: false

View file

@ -24,6 +24,8 @@ SECTIONS
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.uvmif : { *(.uvmif) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.text.startup : { *(.text.startup) }

View file

@ -3,4 +3,5 @@ pyyaml
mdutils
restructuredtext-lint
rstcloth
regex
regex
Mako

View file

@ -1,478 +0,0 @@
[BASIC]
# Naming style matching correct argument names.
argument-naming-style= any
variable-naming-style= any
# Regular expression matching correct argument names. Overrides argument-
# naming-style. If left empty, argument names will be checked with the set
# naming style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=any
# Regular expression matching correct attribute names. Overrides attr-naming-
# style. If left empty, attribute names will be checked with the set naming
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Bad variable names regexes, separated by a comma. If names match any regex,
# they will always be refused
bad-names-rgxs=
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style. If left empty, class attribute names will be checked
# with the set naming style.
#class-attribute-rgx=
# Naming style matching correct class constant names.
class-const-naming-style=UPPER_CASE
# Regular expression matching correct class constant names. Overrides class-
# const-naming-style. If left empty, class constant names will be checked with
# the set naming style.
#class-const-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style. If left empty, class names will be checked with the set naming style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style= any
# Regular expression matching correct constant names. Overrides const-naming-
# style. If left empty, constant names will be checked with the set naming
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=any
# Regular expression matching correct function names. Overrides function-
# naming-style. If left empty, function names will be checked with the set
# naming style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
good-names-rgxs=
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style. If left empty, inline iteration names will be checked
# with the set naming style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style= any
# Regular expression matching correct method names. Overrides method-naming-
# style. If left empty, method names will be checked with the set naming style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style= any
[DESIGN]
# List of regular expressions of class ancestor names to ignore when counting
# public methods (see R0903)
exclude-too-few-public-methods= yes
# List of qualified class names to ignore when counting class parents (see
# R0901)
ignored-parents=
# Maximum number of arguments for function / method.
max-args=50
# Maximum number of attributes for a class (see R0902).
max-attributes=10
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=50
# Maximum number of locals for function / method body.
max-locals=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=150
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[EXCEPTIONS]
# Exceptions that will emit a warning when caught.
overgeneral-exceptions=builtins.BaseException,builtins.Exception
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=3000
# Maximum number of lines in a module.
max-module-lines=1000
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow explicit reexports by alias from a package __init__.
allow-reexport-from-package=no
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=
# Output a graph (.gv or any supported image format) of external dependencies
# to the given file (report RP0402 must not be disabled).
ext-import-graph=
# Output a graph (.gv or any supported image format) of all (i.e. internal and
# external) dependencies to the given file (report RP0402 must not be
# disabled).
import-graph=
# Output a graph (.gv or any supported image format) of internal dependencies
# to the given file (report RP0402 must not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[LOGGING]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
use-implicit-booleaness-not-comparison-to-string,
use-implicit-booleaness-not-comparison-to-zero
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=
[METHOD_ARGS]
# List of qualified names (i.e., library.method) which require a timeout
# parameter e.g. 'requests.api.get,requests.api.post'
timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
# Regular expression of note tags to take in consideration.
notes-rgx=
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=25
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit,argparse.parse_error
# Let 'consider-using-join' be raised when the separator to join on would be
# non-empty (resulting in expected fixes of the type: ``"- " + " -
# ".join(items)``)
suggest-join-with-non-empty-separator=yes
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each
# category, as well as 'statement' which is the total number of statements
# analyzed. This score is used by the global evaluation report (RP0004).
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
msg-template=
# Set the output format. Available formats are: text, parseable, colorized,
# json2 (improved json format), json (old json format) and msvs (visual
# studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
#output-format=
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[SIMILARITIES]
# Comments are removed from the similarity computation
ignore-comments=yes
# Docstrings are removed from the similarity computation
ignore-docstrings=yes
# Imports are removed from the similarity computation
ignore-imports=yes
# Signatures are removed from the similarity computation
ignore-signatures=yes
# Minimum lines number of a similarity.
min-similarity-lines=4
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. No available dictionaries : You need to install
# both the python package and the system dependency for enchant to work.
spelling-dict=
# List of comma separated words that should be considered directives if they
# appear at the beginning of a comment and should not be checked.
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of symbolic message names to ignore for Mixin members.
ignored-checks-for-mixins=no-member,
not-async-context-manager,
not-context-manager,
attribute-defined-outside-init
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# Regex pattern to define which classes are considered mixins.
mixin-class-rgx=.*[Mm]ixin
# List of decorators that change the signature of a decorated function.
signature-mutators=
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of names allowed to shadow builtins
allowed-redefined-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[MASTER]
disable = C0116,

View file

@ -24,6 +24,7 @@ def address_to_key(address):
def factorizer(yaml_data):
privname = None
legalname= None
fieldname = []
regname = []
regdescr = []
@ -37,9 +38,9 @@ def factorizer(yaml_data):
suffix_address = []
suffix_number = []
key_to_remove = []
for key, value in yaml_data["hart0"].items():
for key, value in yaml_data.items():
if isinstance(value, dict):
regelement = yaml_data["hart0"].get(key, {})
regelement = yaml_data.get(key, {})
if regelement.get("address", None):
regaddress = hex(regelement.get("address", None))
else:
@ -49,11 +50,16 @@ def factorizer(yaml_data):
else:
desc = ""
if regelement.get("rv32", "")["accessible"]:
fields = regelement.get("rv32", "").get("fields", [])
if not fields :
legal = regelement.get("rv32", "").get("type", None).keys() if regelement.get("rv32", "").get("type", None) is not None else None
else :
legal = [regelement.get("rv32", "").get(item, {}).get("type").keys()for item in fields if not isinstance(item, list) and regelement.get("rv32", "").get(item, {}).get("type") is not None]
pattern = r"(\D+)(\d+)(.*)"
match = re.search(pattern, key)
if match:
key_to_remove.append(key)
if privname and match.group(1) == privname.group(1):
if privname and match.group(1) == privname.group(1) and legalname == legal:
if len(match.group(3)) > 0:
suffix_name.append(match.group(0))
field_suffix.append(match.group(1))
@ -75,7 +81,7 @@ def factorizer(yaml_data):
start_address = hex(int(regadress[0], 16))
desc = str(regdescr[0])
desc = re.sub(str(regname[0]), fieldname[0], desc)
modified_data = yaml_data["hart0"][regname[0]].copy()
modified_data = yaml_data[regname[0]].copy()
modified_data["address"] = (
f"{str(start_address)}-{str(regadress[-1])}"
)
@ -98,13 +104,14 @@ def factorizer(yaml_data):
suffix_address = sorted(suffix_address, key=address_to_key)
desc = str(suffix_descr[0])
desc = re.sub(str(suffix_name[0]), field_suffix[0], desc)
modified_data = yaml_data["hart0"][suffix_name[0]].copy()
modified_data = yaml_data[suffix_name[0]].copy()
modified_data["address"] = (
f"{str(suffix_address[0])}-{str(suffix_address[-1])}"
)
new_regname.append(
f"{field_suffix[0]}[{suffix_number[0]}-{suffix_number[-1]}]h"
)
print(new_regname)
data.append(modified_data)
suffix_name = []
field_suffix = []
@ -112,12 +119,13 @@ def factorizer(yaml_data):
suffix_number = [match.group(2)]
suffix_address = []
privname = match
legalname = legal
if regname:
start_address = hex(int(regadress[0], 16))
end_address = str(regadress[-1])
desc = str(regdescr[0])
desc = re.sub(str(regname[0]), fieldname[0], desc)
modified_data = yaml_data["hart0"][regname[0]].copy()
modified_data = yaml_data[regname[0]].copy()
modified_data["description"] = desc
modified_data["address"] = f"{str(start_address)}-{str(end_address)}"
new_regname.append(f"{fieldname[0]}[{reg_number[0]}-{reg_number[-1]}]")
@ -129,7 +137,7 @@ def factorizer(yaml_data):
if suffix_name:
desc = str(suffix_descr[0])
desc = re.sub(str(suffix_name[0]), field_suffix[0], desc)
modified_data = yaml_data["hart0"][suffix_name[0]].copy()
modified_data = yaml_data[suffix_name[0]].copy()
modified_data["description"] = desc
modified_data["address"] = (
f"{str(hex(int(suffix_address[0],16)))}-{str(suffix_address[-1])}"
@ -143,7 +151,7 @@ def factorizer(yaml_data):
regdescr = []
regadress = []
for index, reg in enumerate(new_regname):
yaml_data["hart0"][reg] = data[index]
yaml_data[reg] = data[index]
for key in key_to_remove:
del yaml_data["hart0"][key]
return yaml_data["hart0"]
del yaml_data[key]
return yaml_data

View file

@ -1,19 +1,3 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Oukalrazqou Abdessamii
""" Module is used to update csr based on yaml file called csr updater """
import re
import yaml
@ -22,45 +6,46 @@ def csr_recursive_update(original_dict, csr_update):
"""
Gets the data of the RISC-V Config Yaml file and
update the value of sub key in RISC-V Config Yaml file
(ex: reset-val , shadow_type)
(ex: reset-val , address)
:param original_dict : parsed data of RISC-V Config Yaml file
csr_update : parsed data of CSR updater
:return: data of RISC-V Config Yaml file updated
"""
for key, value in csr_update.items():
if key in original_dict.keys():
if isinstance(value, dict):
csr_recursive_update(original_dict[key], value)
elif isinstance(value, bool):
if isinstance(original_dict[key], dict):
for k in original_dict[key]:
print(k)
if isinstance(original_dict[key][k], dict):
for sub_key in original_dict[key][k]:
original_dict[key][k][sub_key] = value
else:
original_dict[key][k] = value
else:
if key in original_dict:
if isinstance(value, dict) and isinstance(original_dict[key], dict):
if key == "rv32":
original_dict[key] = value
else:
csr_recursive_update(original_dict[key], value)
else:
original_dict[key] = value
def csr_formatter(srcfile, modifile):
# Read original dictionary from YAML Source file
def csr_formatter(srcfile, customfile, debugfile, modifile):
# Read original dictionary from YAML source file
with open(srcfile, "r", encoding="utf-8") as file:
original_dict = yaml.safe_load(file)
updated_values = {}
with open(customfile, "r", encoding="utf-8") as file:
custom_dict = yaml.safe_load(file)
debug_dict = {}
riscv_config_data = original_dict.copy()
if debugfile is not None:
with open(debugfile, "r", encoding="utf-8") as file:
debug_dict = yaml.safe_load(file)
if debug_dict["hart0"]["debug_mode"]:
riscv_config_data["hart0"].update(debug_dict["hart0"])
riscv_config_data["hart0"].update(custom_dict["hart0"])
update_dict = {}
if modifile is not None:
with open(modifile, "r", encoding="utf-8") as file:
updated_values = yaml.safe_load(file)
update_dict = yaml.safe_load(file)
print(riscv_config_data["hart0"])
# Update original_dict with values from updated_values recursively
csr_recursive_update(original_dict["hart0"], updated_values)
csr_recursive_update(riscv_config_data["hart0"], update_dict)
# Identify and remove keys within the range specified for each register
keys_to_remove = []
for key, value in updated_values.items():
for key, value in update_dict.items():
if "range" in value:
range_value = value["range"]
pattern = rf"{key}(\d+)"
@ -71,7 +56,7 @@ def csr_formatter(srcfile, modifile):
if index >= range_value:
keys_to_remove.append(k)
# Remove excluded keys based on the condition
exclude_data = updated_values.get("exclude")
exclude_data = update_dict.get("exclude")
if exclude_data:
exclude_key = exclude_data.get("key")
sub_key = exclude_data.get("sub_key")
@ -91,12 +76,12 @@ def csr_formatter(srcfile, modifile):
for k in keys_to_remove:
dictionary.pop(k)
remove_keys_recursive(original_dict["hart0"])
remove_keys_recursive(original_dict["hart0"])
remove_keys_recursive(riscv_config_data["hart0"])
remove_keys_recursive(riscv_config_data["hart0"])
# Remove keys from original_dict
for k in keys_to_remove:
original_dict["hart0"].pop(k, None)
riscv_config_data["hart0"].pop(k, None)
# Remove keys from original_dict
for k in keys_to_remove:
original_dict.pop(k, None)
return original_dict
riscv_config_data.pop(k, None)
return riscv_config_data["hart0"]

View file

@ -0,0 +1,74 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Oukalrazqou Abdessamii
""" Module is used to update Spike based on yaml file called spike updater """
import re
import yaml
from yaml import BaseLoader
def spike_recursive_update(original_dict, spike_update):
"""
Gets the data of the RISC-V Config Yaml file and
update the value of sub key in RISC-V Config Yaml file
(ex: priv , pmpaddr)
:param original_dict : parsed data of Spike Yaml file
spike_update : parsed data of Spike updaters
:return: data of Spike Yaml file updated
"""
for key, value in spike_update.items():
if key in original_dict:
if isinstance(value, dict) and isinstance(original_dict[key], dict):
if key == "cores":
original_dict[key] = value
else:
csr_recursive_update(original_dict[key], value)
else:
original_dict[key] = value
def is_hex_string(s):
return bool(re.match(r"'?(0x[0-9a-fA-F]+)'?", s))
def custom_convert(data):
if isinstance(data, dict):
return {k: custom_convert(v) for k, v in data.items()}
elif isinstance(data, list):
return [custom_convert(item) for item in data]
elif isinstance(data, str):
if data.lower() == "true":
return True
elif data.lower() == "false":
return False
elif data.isdigit():
return int(data)
elif is_hex_string(data.strip()):
return int(data, 16)
return data
def spike_formatter(original_dict, modifile):
# Read original dictionary from YAML Source file
updated_values = {}
if modifile is not None:
with open(modifile, "r", encoding="utf-8") as file:
updated_values = yaml.load(file, Loader=BaseLoader)
# Update original_dict with values from updated_values recursively
spike_recursive_update(original_dict["spike_param_tree"], updated_values)
original_dict = custom_convert(original_dict)
return original_dict

View file

@ -14,28 +14,31 @@
#
# Original Author: Oukalrazqou Abdessamii
""" Module is used to gather all utils and function to generate the csr and isa documents"""
"""Module is used to gather all utils and function to generate the csr and isa documents"""
import io
import os
import re
import yaml
from yaml import BaseLoader
import rstcloth
import json
from mako.template import Template
import libs.isa_updater
import libs.csr_updater
import libs.spike_updater
import libs.csr_factorizer
from rstcloth import RstCloth
from mdutils.mdutils import MdUtils
from libs.isa_updater import isa_filter
from libs.csr_updater import csr_formatter
from libs.spike_updater import spike_formatter
from libs.csr_factorizer import factorizer
pattern_warl = (
r"\b(?:warl|wlrl|ro_constant|ro_variable)\b" # pattern to detect warl in field
)
pattern_warl = r"\b(?:warl|wlrl|ro_constant|ro_variable|rw|ro)\b" # pattern to detect warl in field
pattern_legal_dict = r"\[(0x[0-9A-Fa-f]+)(.*?(0x[0-9A-Fa-f]+))?\]" # pattern to detect if warl field is dict
pattern_legal_list = r"\[(0x[0-9A-Fa-f]+)(.*?(0x[0-9A-Fa-f]+))?\]" # pattern to detect if warl field is a list
Factorizer_pattern = r".*(\d).*" # pattern to detect factorized fields
Factorizer_pattern = r"\d+" # pattern to detect factorized fields
class DocumentClass:
@ -111,6 +114,8 @@ class Field:
bitWidth,
fieldDesc,
fieldaccess,
andMask=None,
orMask=None,
):
self.name = name
self.bitlegal = bitlegal
@ -120,6 +125,126 @@ class Field:
self.bitWidth = bitWidth
self.fieldDesc = fieldDesc
self.fieldaccess = fieldaccess
self.andMask = andMask
self.orMask = orMask
# --------------------------------------------------------------#
class Render:
"""Collection of general rendering methods which can be overridden if needed
for a specific output format."""
@staticmethod
def is_decimal(value):
"""return a bool checking if value is decimal"""
try:
int(
value
) # Alternatively, use float(value) if you want to check for floating point numbers
return True
except ValueError:
return False
@staticmethod
def range(start, end):
"""Return a string representing the range START..END, inclusive.
START and END are strings representing numerical values."""
if Render.is_decimal(start):
start = hex(int(start))
if Render.is_decimal(end):
end = hex(int(end))
return f"{start} - {end}"
@staticmethod
def value_set(values):
"""Return a string representing the set of values in VALUES.
VALUES is a list of strings."""
# values = [hex(int(value, 16)) if '0x' in value and '-' not in value else value for value in values]
return ", ".join(values)
@staticmethod
def bitmask(andMask, orMask):
"""Return a string representing the masking pattern defined by ANDMASK and ORMASK.
ANDMASK and ORMASK are strings representing AND and OR mask values, respectively.
"""
return f"masked: & {andMask} | {orMask}"
@staticmethod
def fieldtype(typ):
"""Return a string representing the printable type of a register field."""
upcased = typ.upper()
if upcased == "RO_CONSTANT":
return "ROCST"
elif upcased == "RO_VARIABLE":
return "ROVAR"
else:
return upcased
class CoreConfig:
def __init__(
self,
isa,
marchid,
misa_we,
misa_we_enable,
misaligned,
mmu_mode,
mvendorid,
pmpaddr0,
pmpcfg0,
pmpregions,
priv,
status_fs_field_we,
status_fs_field_we_enable,
status_vs_field_we,
status_vs_field_we_enable,
):
self.isa = isa
self.marchid = marchid
self.misa_we = misa_we
self.misa_we_enable = misa_we_enable
self.misaligned = misaligned
self.mmu_mode = mmu_mode
self.mvendorid = mvendorid
self.pmpaddr0 = pmpaddr0
self.pmpcfg0 = pmpcfg0
self.pmpregions = pmpregions
self.priv = priv
self.status_fs_field_we = status_fs_field_we
self.status_fs_field_we_enable = status_fs_field_we_enable
self.status_vs_field_we = status_vs_field_we
self.status_vs_field_we_enable = status_vs_field_we_enable
class Spike:
def __init__(
self,
bootrom,
bootrom_base,
bootrom_size,
dram,
dram_base,
dram_size,
generic_core_config,
max_steps,
max_steps_enabled,
isa,
priv,
core_configs,
):
self.bootrom = bootrom
self.bootrom_base = bootrom_base
self.bootrom_size = bootrom_size
self.dram = dram
self.dram_base = dram_base
self.dram_size = dram_size
self.generic_core_config = generic_core_config
self.max_steps = max_steps
self.max_steps_enabled = max_steps_enabled
self.isa = isa
self.priv = priv
self.core_configs = core_configs
# --------------------------------------------------------------#
@ -135,7 +260,7 @@ class ISAdocumentClass:
class InstructionMapClass:
"""ISA instruction map class"""
"""ISA instruction map c.2n lass"""
def __init__(self, name):
self.name = name
@ -210,11 +335,22 @@ class RstAddressBlock(AddressBlockClass):
return int(start, 16), int(end, 16)
return int(reg.address, 16), int(reg.address, 16)
def get_access_privilege(self, reg):
"""Registers with address bits [11:10] == 2'b11 are Read-Only
as per privileged ISA spec."""
# Handle register address ranges separated by dashes.
if (int(reg.address.split("-")[0], 0) & 0xC00) == 0xC00:
return "RO"
else:
return "RW"
def returnAsString(self):
registerlist = sorted(self.registerList, key=lambda reg: reg.address)
r = RstCloth(io.StringIO()) # with default parameter, sys.stdout is used
regNameList = [reg.name for reg in registerlist]
regNameList = [reg.name.upper() for reg in registerlist]
regAddressList = [reg.address for reg in registerlist]
regPrivModeList = [reg.access for reg in registerlist]
regPrivAccessList = [self.get_access_privilege(reg) for reg in registerlist]
regDescrList = [reg.desc for reg in registerlist]
regRV32List = [reg.RV32 for reg in registerlist]
regRV64List = [reg.RV64 for reg in registerlist]
@ -229,6 +365,47 @@ class RstAddressBlock(AddressBlockClass):
)
r.title(self.name) # Use the name of the addressBlock as title
r.newline()
r.h2("Conventions")
r.newline()
r.content(
"""In the subsequent sections, register fields are labeled with one of the
following abbreviations:
"""
)
r.newline()
r.li(
"""WPRI (Writes Preserve Values, Reads Ignore Values): read/write field reserved
for future use. For forward compatibility, implementations that do not
furnish these fields must make them read-only zero."""
)
r.li(
"""WLRL (Write/Read Only Legal Values): read/write CSR field that specifies
behavior for only a subset of possible bit encodings, with other bit encodings
reserved."""
)
r.li(
"""WARL (Write Any Values, Reads Legal Values): read/write CSR fields which are
only defined for a subset of bit encodings, but allow any value to be written
while guaranteeing to return a legal value whenever read."""
)
r.li(
"""ROCST (Read-Only Constant): A special case of WARL field which admits only one
legal value, and therefore, behaves as a constant field that silently ignores
writes."""
)
r.li(
"""ROVAR (Read-Only Variable): A special case of WARL field which can take
multiple legal values but cannot be modified by software and depends only on
the architectural state of the hart."""
)
r.newline()
r.content(
"""In particular, a register that is not internally divided
into multiple fields can be considered as containing a single field of XLEN bits.
This allows to clearly represent read-write registers holding a single legal value
(typically zero)."""
)
r.newline()
r.h2("Register Summary")
summary_table = []
for i, _ in enumerate(regNameList):
@ -236,17 +413,26 @@ class RstAddressBlock(AddressBlockClass):
summary_table.append(
[
regAddressList[i],
str(regNameList[i]).upper(),
f"`{regNameList[i]} <#{regNameList[i]}>`_",
# RW or RO privileges are set in the official RISC-V specification
# and are encoded in bits [11:10] of the reg's address (2'b11 == "RO").
# See Tables 4 through 8 in section 2.2 of the Priv spec v20240411.
regPrivModeList[i] + regPrivAccessList[i],
str(regDescrList[i]),
]
)
r.table(header=["Address", "Register Name", "Description"], data=summary_table)
r.table(
header=["Address", "Register Name", "Privilege", "Description"],
data=summary_table,
)
r.h2("Register Description")
for reg in registerlist:
if reg.RV32 | reg.RV64:
reg_table = []
r.h2(reg.name.upper())
r.newline()
r.directive(".. _" + reg.name.upper() + ":")
r.h3(reg.name.upper())
r.newline()
r.field("Address", (reg.address))
if reg.resetValue:
@ -255,7 +441,8 @@ class RstAddressBlock(AddressBlockClass):
"Reset Value",
"0x" + f"{reg.resetValue[2:].zfill(int(reg.size/4))}",
)
r.field("Privilege Mode", reg.access)
# RO/RW privileges are encoded in register address.
r.field("Privilege", reg.access + self.get_access_privilege(reg))
r.field("Description", reg.desc)
for field in reg.field:
if field.bitWidth == 1: # only one bit -> no range needed
@ -265,13 +452,13 @@ class RstAddressBlock(AddressBlockClass):
_line = [
bits,
field.name.upper(),
field.bitlegal,
field.fieldreset,
field.fieldaccess,
field.bitlegal,
]
_line.append(field.fieldDesc)
reg_table.append(_line)
_headers = ["Bits", "Field Name", "Legal Values", "Reset", "Type"]
_headers = ["Bits", "Field Name", "Reset Value", "Type", "Legal Values"]
_headers.append("Description")
reg_table = sorted(
reg_table, key=lambda x: int(x[0].strip("[]").split(":")[0])
@ -348,9 +535,196 @@ class InstrstBlock(InstructionBlockClass):
r.table(header=_headers, data=reg_table)
return r.data
class AdocAddressBlock(AddressBlockClass):
"""Generates an AsciiDoc file from a IP-XACT register description"""
def __init__(self, name):
super().__init__("csr")
self.name = name
self.registerList = []
self.suffix = ".adoc"
def get_access_privilege(self, reg):
"""Registers with address bits [11:10] == 2'b11 are Read-Only
as per privileged ISA spec."""
# Handle register address ranges separated by dashes.
if (int(reg.address.split("-")[0], 0) & 0xC00) == 0xC00:
return "RO"
else:
return "RW"
def generate_label(self, name):
return "_" + name.replace('[','').replace(']','').upper()
def returnAsString(self):
registerlist = sorted(self.registerList, key=lambda reg: reg.address)
r = ""
regNameList = [reg.name.upper() for reg in registerlist]
regAddressList = [reg.address for reg in registerlist]
regPrivModeList = [reg.access for reg in registerlist]
regPrivAccessList = [self.get_access_privilege(reg) for reg in registerlist]
regDescrList = [reg.desc for reg in registerlist]
regRV32List = [reg.RV32 for reg in registerlist]
regRV64List = [reg.RV64 for reg in registerlist]
r += "////\n"
r += " Copyright (c) 2024 OpenHW Group\n"
r += " Copyright (c) 2024 Thales\n"
r += " SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1\n"
r += " Author: Abdessamii Oukalrazqou\n"
r += "////\n\n"
r += "=== %s\n\n"%self.name
r += "==== Conventions\n\n"
r += "In the subsequent sections, register fields are labeled with one of the following abbreviations:\n\n"
r += "* WPRI (Writes Preserve Values, Reads Ignore Values): read/write field reserved\n"
r += "for future use. For forward compatibility, implementations that do not\n"
r += "furnish these fields must make them read-only zero.\n"
r += "* WLRL (Write/Read Only Legal Values): read/write CSR field that specifies\n"
r += "behavior for only a subset of possible bit encodings, with other bit encodings\n"
r += "reserved.\n"
r += "* WARL (Write Any Values, Reads Legal Values): read/write CSR fields which are\n"
r += "only defined for a subset of bit encodings, but allow any value to be written\n"
r += "while guaranteeing to return a legal value whenever read.\n"
r += "* ROCST (Read-Only Constant): A special case of WARL field which admits only one\n"
r += "legal value, and therefore, behaves as a constant field that silently ignores\n"
r += "writes.\n"
r += "* ROVAR (Read-Only Variable): A special case of WARL field which can take\n"
r += "multiple legal values but cannot be modified by software and depends only on\n"
r += "the architectural state of the hart.\n\n"
r += "In particular, a register that is not internally divided\n"
r += "into multiple fields can be considered as containing a single field of XLEN bits.\n"
r += "This allows to clearly represent read-write registers holding a single legal value\n"
r += "(typically zero).\n\n"
r += "==== Register Summary\n\n"
r += "|===\n"
r += "|Address | Register Name | Privilege | Description\n\n"
for i, _ in enumerate(regNameList):
if regRV32List[i] | regRV64List[i]:
r += "|" + regAddressList[i] + \
f"| `<<{self.generate_label(regNameList[i])},{regNameList[i].upper()}>>`" + \
"|" + regPrivModeList[i] + regPrivAccessList[i] + \
"|" + str(regDescrList[i]) + "\n"
r += "|===\n\n"
r += "==== Register Description\n\n"
for reg in registerlist:
if reg.RV32 | reg.RV64:
r += "[[%s]]\n"%self.generate_label(reg.name)
r += "===== %s\n\n"%reg.name.upper()
r += "Address:: %s\n"%reg.address
if reg.resetValue:
# display the resetvalue in hex notation in the full length of the register
r += "Reset Value:: 0x%s\n"%f"{reg.resetValue[2:].zfill(int(reg.size/4))}"
# RO/RW privileges are encoded in register address.
r += "Privilege:: %s\n"%(reg.access + self.get_access_privilege(reg))
r += "Description:: %s\n\n"%(reg.desc)
reg_table = []
for field in reg.field:
if field.bitWidth == 1: # only one bit -> no range needed
bits = f"{field.bitlsb}"
else:
bits = f"[{field.bitmsb}:{field.bitlsb}]"
_line = [
bits,
field.name.upper(),
field.fieldreset,
field.fieldaccess,
(
Render.bitmask(field.andMask, field.orMask)
if field.andMask and field.orMask
else field.bitlegal
),
]
_line.append(field.fieldDesc)
reg_table.append(_line)
reg_table = sorted(
reg_table, key=lambda x: int(x[0].strip("[]").split(":")[0])
)
# table of the register
r += "|===\n"
r += "| Bits | Field Name | Reset Value | Type | Legal Values | Description\n\n"
for reg in reg_table:
for col in reg:
if col == 'Reserved':
col = "_Reserved_"
r +="| %s "%col.replace('\n','').replace('|', '\|')
r += "\n"
r += "|===\n\n"
return r
class InstadocBlock(InstructionBlockClass):
"""Generates a ISA AsciiDoc file from RISC-V Config Yaml register description"""
def __init__(self, name):
super().__init__("isa")
self.name = name
self.Instructionlist = []
self.suffix = ".adoc"
def returnAsString(self):
r = ""
InstrNameList = [reg.key for reg in self.Instructionlist]
InstrDescrList = [reg.descr for reg in self.Instructionlist]
InstrExtList = [reg.Extension_Name for reg in self.Instructionlist]
r += "////\n"
r += " Copyright (c) 2024 OpenHW Group\n"
r += " Copyright (c) 2024 Thales\n"
r += " SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1\n"
r += " Author: Abdessamii Oukalrazqou\n"
r += "////\n\n"
r += "=== %s\n\n"%self.name
r += "==== Instructions\n\n"
r += "|===\n"
r += "|Subset Name | Name | Description\n\n"
for i, _ in enumerate(InstrNameList):
r += "|%s | %s | %s\n"%(str(InstrExtList[i]),
str(InstrNameList[i]),
str(InstrDescrList[i]).replace('\n',''))
r += "|===\n\n"
for reg in self.Instructionlist:
reg_table = []
if len(reg.Name) > 0:
r += "==== %s\n\n"%reg.key
r += "|===\n"
r += "| Name | Format | Pseudocode|Invalid_values | Exception_raised | Description| Op Name\n\n"
for fieldIndex in list(range(len(reg.Name))):
_line = [
reg.Name[fieldIndex],
reg.Format[fieldIndex],
reg.pseudocode[fieldIndex].replace('|','\|'),
reg.invalid_values[fieldIndex],
reg.exception_raised[fieldIndex],
reg.Description[fieldIndex],
]
_line.append(reg.OperationName[fieldIndex])
for col in _line:
r +="| %s "%col.replace('\n','')
r += "\n"
r += "|===\n\n"
return r
class InstmdBlock(InstructionBlockClass):
"""Generates a ISA Markdown file from a RISC Config Yaml register description"""
"""Generates an ISA Markdown file from a RISC Config Yaml register description"""
def __init__(self, name):
super().__init__("isa")
@ -466,6 +840,12 @@ class MdAddressBlock(AddressBlockClass):
regNameList = [reg.name for reg in registerlist if reg.RV32 | reg.RV64]
regAddressList = [reg.address for reg in registerlist if reg.RV32 | reg.RV64]
regDescrList = [reg.desc for reg in registerlist if reg.RV32 | reg.RV64]
regAccessList = [
self.get_access_privilege(reg)
for reg in registerlist
if reg.RV32 | reg.RV64
]
regPrivModeList = [reg.access for reg in registerlist if reg.RV32 | reg.RV64]
licence = [
"<!--Copyright (c) 2024 OpenHW Group",
"Copyright (c) 2024 Thales",
@ -480,8 +860,9 @@ class MdAddressBlock(AddressBlockClass):
) # Use the name of the addressBlock as title
self.mdFile.new_paragraph()
self.mdFile.new_header(level=2, title="Registers Summary")
self.mdFile.new_paragraph()
# summary
header = ["Address", "Register Name", "Description"]
header = ["Address", "Register Name", "Privilege", "Description"]
rows = []
for i, _ in enumerate(regNameList):
regDescrList[i] = str(regDescrList[i]).replace("\n", " ")
@ -489,6 +870,7 @@ class MdAddressBlock(AddressBlockClass):
[
regAddressList[i],
f"[{regNameList[i].upper()}](#{regNameList[i].upper()})",
regPrivModeList[i] + regAccessList[i],
str(regDescrList[i]),
]
)
@ -503,7 +885,11 @@ class MdAddressBlock(AddressBlockClass):
for reg in registerlist:
if reg.RV64 | reg.RV32:
self.returnMdRegDesc(
reg.name, reg.address, reg.resetValue, reg.desc, reg.access
reg.name,
reg.address,
reg.resetValue,
reg.desc,
reg.access + self.get_access_privilege(reg),
)
reg_table = []
_line = []
@ -516,13 +902,13 @@ class MdAddressBlock(AddressBlockClass):
[
bits,
field.name.upper(),
field.bitlegal,
field.fieldreset,
field.fieldaccess,
field.bitlegal,
field.fieldDesc,
]
)
_headers = ["Bits", "Field Name", "Legal Values", "Reset", "Type"]
_headers = ["Bits", "Field Name", "Reset Value", "Type", "Legal Values"]
_headers.append("Description")
reg_table = sorted(
reg_table, key=lambda x: int(x[0].strip("[]").split(":")[0])
@ -546,7 +932,7 @@ class MdAddressBlock(AddressBlockClass):
if resetValue:
# display the resetvalue in hex notation in the full length of the register
self.mdFile.new_line("**Reset Value** " + resetValue)
self.mdFile.new_line("**Privilege Mode** " + access)
self.mdFile.new_line("**Privilege** " + access)
self.mdFile.new_line("**Description** " + desc)
@ -554,8 +940,10 @@ class MdAddressBlock(AddressBlockClass):
class CsrParser:
"""parse CSR RISC-V config yaml file"""
def __init__(self, srcFile, target, modiFile=None):
def __init__(self, srcFile, customFile, debugfile, target, modiFile=None):
self.srcFile = srcFile
self.customFile = customFile
self.debugfile = debugfile
self.modiFile = modiFile
self.target = target
@ -576,6 +964,8 @@ class CsrParser:
field = []
if len(fieldList) > 0:
for item in fieldList:
andMask = None
orMask = None
if not isinstance(item, list):
fieldDesc = registerElem.get("rv32", "")[item].get(
"description", ""
@ -592,14 +982,20 @@ class CsrParser:
)
fieldaccess = ""
legal = registerElem.get("rv32", "")[item].get("type", None)
implemented = registerElem.get("rv32", "")[item].get(
"implemented", None
)
if legal is None:
bitlegal = ""
fieldaccess = "WARL"
if not implemented:
bitlegal = "0x0"
else:
bitlegal = ""
fieldaccess = "ROCST"
fieldDesc = fieldDesc
else:
warl = re.findall(pattern_warl, str(legal.keys()))
if warl:
fieldaccess = warl[0].upper()
fieldaccess = Render.fieldtype(warl[0])
legal_2 = (
registerElem.get("rv32", "")[item]
.get("type", None)
@ -609,21 +1005,68 @@ class CsrParser:
bitlegal = "No Legal values"
else:
if isinstance(legal_2, dict):
pattern = r"([\w\[\]:]+\s*\w+\s*)(\[\s*((?:0x)?[0-9A-Fa-f]+)\s*\D+\s*(?:((?:0x)?[0-9A-Fa-f]+))?\s*])"
# TODO: Need a pattern that supports arbitrary lists of values in matches(3).
pattern = r"([\w\[\]:]+)\s*(\w+)\s*(\[\s*((?:0x)?[0-9A-Fa-f]+)\s*\D+\s*(?:((?:0x)?[0-9A-Fa-f]+))?\s*])"
matches = re.search(
pattern, str(legal_2["legal"][0])
)
if matches:
legal_value = matches.group(2)
expr_type = str(matches.group(2))
if expr_type == "bitmask":
andMask = str(matches.group(4))
orMask = str(matches.group(5))
legal_value = Render.bitmask(
andMask, orMask
)
elif expr_type == "in":
if matches.group(3).find(",") >= 0:
# list ==> set of values
legal_value = Render.value_set(
matches.group(3)
.strip("[]")
.split(",")
)
elif matches.group(3).find(":") >= 0:
# Range
(start, end) = (
matches.group(3)
.strip("[]")
.split(":")
)
legal_value = Render.range(start, end)
else:
# Singleton
legal_value = matches.group(3).strip(
"[]"
)
else:
legal_value = matches.group(3)
bitlegal = legal_value
elif isinstance(legal_2, list):
pattern = r"\s*((?:0x)?[0-9A-Fa-f]+)\s*(.)\s*((?:0x)?[0-9A-Fa-f]+)\s*"
matches = re.search(pattern, legal_2[0])
if matches:
legal_value = (
f"[{matches.group(1)} , {matches.group(3)}]"
)
pattern = r"\s*((?:0x)?[0-9A-Fa-f]+)\s*(:|,?)\s*((?:0x)?[0-9A-Fa-f]+)?"
for value in legal_2:
value_list = value.split(",")
processed_values = []
for val in value_list:
matches = re.search(pattern, val)
if matches:
first_value = matches.group(1)
separator = matches.group(2)
second_value = (
matches.group(3)
if matches.group(3)
else first_value
)
if separator == ":":
processed_value = Render.range(
first_value, second_value
)
else:
processed_value = hex(
int(first_value)
)
processed_values.append(processed_value)
legal_value = Render.value_set(processed_values)
bitlegal = legal_value
else:
legal_value = hex(legal_2)
@ -633,9 +1076,13 @@ class CsrParser:
if match:
match_field = re.search(Factorizer_pattern, str(item))
if match_field:
if match_field.group(0) not in {"0", "1", "2", "3"}:
field_number = int(match_field.group(0)) - 8
else:
field_number = match_field.group(0)
fieldName = re.sub(
match_field.group(1),
f"[i*4 + {match_field.group(1)}]",
Factorizer_pattern,
f"[i*4 +{field_number}]",
item,
)
else:
@ -649,6 +1096,8 @@ class CsrParser:
bitWidth,
fieldDesc,
fieldaccess,
andMask,
orMask,
)
field.append(f)
elif isinstance(item, list):
@ -659,7 +1108,7 @@ class CsrParser:
legal = ""
fieldaccess = "WPRI"
bitWidth = int(item_[len(item_) - 1]) - int(item_[0]) + 1
fieldDesc = "RESERVED"
fieldDesc = "Reserved"
bitlegal = legal
fieldreset = hex(
int(resetValue, 16) >> (bitlsb) & ((1 << ((bitWidth))) - 1)
@ -699,6 +1148,8 @@ class CsrParser:
bitlsb = registerElem.get("rv32", None).get("lsb", None)
legal = registerElem.get("rv32", "").get("type", None)
fieldaccess = ""
andMask = None
orMask = None
if legal is None:
bitlegal = ""
bitmask = ""
@ -706,7 +1157,7 @@ class CsrParser:
else:
warl = re.findall(pattern_warl, str(legal.keys()))
if warl:
fieldaccess = warl[0].upper()
fieldaccess = Render.fieldtype(warl[0])
legal_2 = (
registerElem.get("rv32", "")
.get("type", None)
@ -716,28 +1167,64 @@ class CsrParser:
bitlegal = "No Legal values"
else:
if isinstance(legal_2, dict):
pattern = r"([\w\[\]:]+\s*\w+\s*)(\[\s*((?:0x)?[0-9A-Fa-f]+)\s*\D+\s*(?:((?:0x)?[0-9A-Fa-f]+))?\s*])"
pattern = r"([\w\[\]:]+\s*(\w+)\s*)(\[\s*((?:0x)?[0-9A-Fa-f]+)\s*\D+\s*(?:((?:0x)?[0-9A-Fa-f]+))?\s*])"
matches = re.search(pattern, str(legal_2["legal"][0]))
if matches:
legal_value = (
f"[{matches.group(3)} , {matches.group(4)}]"
legal_value = Render.range(
matches.group(4), matches.group(5)
)
mask = matches.group(4)
expr_type = str(matches.group(2))
mask = matches.group(5)
bitmask = mask
bitlegal = legal_value
if expr_type == "bitmask":
andMask = str(matches.group(4))
orMask = str(matches.group(5))
elif expr_type == "in":
if matches.group(3).find(",") >= 0:
# list ==> set of values
legal_value = Render.value_set(
matches.group(3).strip("[]").split(",")
)
elif matches.group(3).find(":") >= 0:
# Range
(start, end) = (
matches.group(3).strip("[]").split(":")
)
legal_value = Render.range(start, end)
else:
# Singleton
legal_value = matches.group(3).strip("[]")
else:
legal_value = matches.group(3)
bitlegal = legal_value
elif isinstance(legal_2, list):
pattern = r"([0-9A-Fa-f]+).*([0-9A-Fa-f]+)"
matches = re.search(pattern, legal_2[0])
if matches:
legal_value = (
f"[{matches.group(1)} , {matches.group(2)}]"
)
mask = matches.group(2)
bitmask = mask
pattern = r"\s*((?:0x)?[0-9A-Fa-f]+)\s*(:|,?)\s*((?:0x)?[0-9A-Fa-f]+)?"
for value in legal_2:
value_list = value.split(",")
processed_values = []
for val in value_list:
matches = re.search(pattern, val)
if matches:
first_value = matches.group(1)
separator = matches.group(2)
second_value = (
matches.group(3)
if matches.group(3)
else first_value
)
if separator == ":":
processed_value = Render.range(
first_value, second_value
)
else:
processed_value = hex(int(first_value))
processed_values.append(processed_value)
legal_value = Render.value_set(processed_values)
bitlegal = legal_value
else:
bitmask = 0
bitlegal = "0x" + hex(legal_2)[2:].zfill(int(size / 4))
legal_value = hex(legal_2)
bitlegal = legal_value
fieldDesc = regDesc
fieldreset = "0x" + hex(int(resetValue, 16))[2:].zfill(int(size / 4))
if bitlsb is None:
@ -766,9 +1253,14 @@ class CsrParser:
def returnDocument(self):
with open(self.srcFile, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
data = csr_formatter(self.srcFile, self.modiFile)
Registers = factorizer(data)
docName = data["hart0"]
size = int(
data["hart0"].get("supported_xlen", "")[0]
) # depends on architecture
data = csr_formatter(
self.srcFile, self.customFile, self.debugfile, self.modiFile
)
Registers = factorizer(data)
d = DocumentClass(docName)
m = MemoryMapClass(docName)
a = AddressBlockClass("csr")
@ -782,7 +1274,7 @@ class CsrParser:
else hex(RegElement.get("address", None))
)
reset = hex(RegElement.get("reset-val", ""))
size = int(data["hart0"].get("supported_xlen", "")[0])
access = RegElement.get("priv_mode", "")
if Registers.get(register, {}).get("description", "") is not None:
desc = Registers.get(register, {}).get("description", "")
@ -898,6 +1390,96 @@ class IsaParser:
return Inst
class SpikeParser:
"""A class to parse data related to Spike."""
def __init__(self, srcFile, target):
self.srcFile = srcFile
self.target = target
def returnDocument(self):
with open(self.srcFile, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
core_configs = []
pattern = r"pmpaddr(\d+)"
index = 0
bitWidth = 32
isa = ""
for entry in data["hart_ids"]:
M = (
"M"
if data[f"hart{entry}"]
.get("mstatus", {})
.get("rv32", "")
.get("accessible", [])
else ""
)
S = (
"S"
if data[f"hart{entry}"]
.get("sstatus", {})
.get("rv32", "")
.get("accessible", [])
else ""
)
U = (
"U"
if data[f"hart{entry}"]
.get("ustatus", {})
.get("rv32", "")
.get("accessible", [])
else ""
)
for k in data[f"hart{entry}"].keys():
match = re.search(pattern, str(k))
if match:
index += int(match.group(1))
isa = data[f"hart{entry}"]["ISA"].lower()
core_config = CoreConfig(
isa=data[f"hart{entry}"]["ISA"].lower(),
marchid=data[f"hart{entry}"].get("marchid", {}).get("reset-val", ""),
misa_we=False,
misa_we_enable=True,
misaligned=data[f"hart{entry}"].get("hw_data_misaligned_support", ""),
mmu_mode=(
"bare"
if not (
(int(data[f"hart{entry}"].get("satp", {}).get("reset-val", "")))
>> 31
)
else "sv32"
),
mvendorid=data[f"hart{entry}"]
.get("mvendorid", {})
.get("reset-val", ""),
pmpaddr0=data[f"hart{entry}"].get("pmpaddr0", {}).get("reset-val", ""),
pmpcfg0=data[f"hart{entry}"].get("pmpcfg0", {}).get("reset-val", ""),
pmpregions=index,
priv=f"{M}{S}{U}".format(M, S, U),
status_fs_field_we=False,
status_fs_field_we_enable=False,
status_vs_field_we=False,
status_vs_field_we_enable=False,
)
core_configs.append(core_config)
S = Spike(
bootrom=True,
bootrom_base=0x10000,
bootrom_size=0x1000,
dram=True,
dram_base=0x80000000,
dram_size=0x40000000,
generic_core_config=False,
max_steps=200000,
max_steps_enabled=False,
isa=isa,
priv=f"{M}{S}{U}".format(M, S, U),
core_configs=core_configs,
)
return S
class IsaGenerator:
"""generate isa folder with isa docs"""
@ -937,7 +1519,6 @@ class CsrGenerator:
def write(self, file_name, string):
path = f"./{self.target}/csr/"
print(path)
if not os.path.exists(path):
os.makedirs(path)
_dest = os.path.join(path, file_name)
@ -957,3 +1538,28 @@ class CsrGenerator:
s = block.returnAsString()
file_name = blockName + block.suffix
self.write(file_name, s)
class SpikeGenerator:
"""Generate spike folder with spike docs"""
def __init__(self, target, temp, modiFile=None):
self.target = target
self.temp = temp
self.modiFile = modiFile
def write(self, file_name, string):
path = f"./{self.target}/spike/"
if not os.path.exists(path):
os.makedirs(path)
_dest = os.path.join(path, file_name)
print("writing file " + _dest)
with open(_dest, "w", encoding="utf-8") as f:
yaml.dump(string, f, default_flow_style=False, sort_keys=False)
def generateSpike(self, document):
template = Template(filename=self.temp)
s = template.render(spike=document)
data = spike_formatter(yaml.load(s, Loader=BaseLoader), self.modiFile)
file_name = "spike.yaml"
self.write(file_name, data)

View file

@ -13,36 +13,64 @@
# limitations under the License.
#
# Original Author: Oukalrazqou Abdessamii
""" Module is used to factorize multiples registers with the same name to
a specific format of registers """
"""Module is used to factorize multiples registers with the same name to
a specific format of registers"""
import argparse
from libs.utils import CsrParser
from libs.utils import IsaParser
from libs.utils import SpikeParser
from libs.utils import IsaGenerator
from libs.utils import CsrGenerator
from libs.utils import SpikeGenerator
from libs.utils import RstAddressBlock
from libs.utils import AdocAddressBlock
from libs.utils import MdAddressBlock
from libs.utils import InstrstBlock
from libs.utils import InstadocBlock
from libs.utils import InstmdBlock
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="ipxact2rst")
parser.add_argument("-s", "--srcFile", help="yaml input file")
parser.add_argument("-d", "--destDir", help="write generated file to dir")
parser = argparse.ArgumentParser(description="GEN From RISC-V Config")
parser.add_argument("-s", "--srcFile", help="isa_gen yaml input file")
parser.add_argument("-c", "--customFile", help=" custom_gen yaml input file")
parser.add_argument("-d", "--debugFile", help=" debug_gen yaml input file")
parser.add_argument("-m", "--modif", help="ISA /CSR Formatter if exist")
parser.add_argument("-i", "--temp", help="Full ISA Template")
parser.add_argument("-i", "--temp", help="Full ISA /SPIKETemplate")
parser.add_argument("-t", "--target", help="Specifiy Config Name")
parser.add_argument("-f", "--format", help="Specifiy format output")
args, unknown_args = parser.parse_known_args()
if args.temp:
e = IsaParser(args.srcFile, args.temp, args.target, args.modif)
document = e.returnDocument()
generator = IsaGenerator(args.target)
generator.generateISA(InstrstBlock, document)
generator.generateISA(InstmdBlock, document)
if args.format in ['rst']:
C_instrBlock = InstrstBlock
C_AddressBlock = RstAddressBlock
elif args.format in ['adoc']:
C_instrBlock = InstadocBlock
C_AddressBlock = AdocAddressBlock
elif args.format in ['md']:
C_instrBlock = InstmdBlock
C_AddressBlock = MdAddressBlock
else:
e = CsrParser(args.srcFile, args.target, args.modif)
C_instrBlock = InstrstBlock
C_AddressBlock = RstAddressBlock
if args.temp:
if "isa" in args.temp:
e = IsaParser(args.srcFile, args.temp, args.target, args.modif)
document = e.returnDocument()
generator = IsaGenerator(args.target)
generator.generateISA(C_instrBlock, document)
elif "spike" in args.temp:
e = SpikeParser(args.srcFile, args.target)
document = e.returnDocument()
spike_generator = SpikeGenerator(args.target, args.temp, args.modif)
spike_generator.generateSpike(document)
else:
e = CsrParser(
args.srcFile, args.customFile, args.debugFile, args.target, args.modif
)
document = e.returnDocument()
generator = CsrGenerator(args.target)
generator.generateCSR(RstAddressBlock, document)
generator.generateCSR(MdAddressBlock, document)
generator.generateCSR(C_AddressBlock, document)

View file

@ -0,0 +1,53 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Oukalrazqou Abdessamii
<%!
def format_hex(value):
return f"0x{value:X}"
def format_bool(value):
return "true" if value else "false"
%>
spike_param_tree:
bootrom: ${format_bool(spike.bootrom)}
bootrom_base: ${format_hex(spike.bootrom_base)}
bootrom_size: ${format_hex(spike.bootrom_size)}
dram: ${format_bool(spike.dram)}
dram_base: ${format_hex(spike.dram_base)}
dram_size: ${format_hex(spike.dram_size)}
generic_core_config: ${format_bool(spike.generic_core_config)}
max_steps: ${spike.max_steps}
max_steps_enabled: ${format_bool(spike.max_steps_enabled)}
isa: ${spike.isa}
priv: ${spike.priv}
core_configs:
% for core in spike.core_configs:
- isa: ${core.isa}
marchid: ${format_hex(core.marchid)}
misa_we: ${format_bool(core.misa_we)}
misa_we_enable: ${format_bool(core.misa_we_enable)}
misaligned: ${format_bool(core.misaligned)}
mmu_mode: ${core.mmu_mode}
mvendorid: ${format_hex(core.mvendorid)}
pmpaddr0: ${format_hex(core.pmpaddr0)}
pmpcfg0: ${format_hex(core.pmpcfg0)}
pmpregions: ${format_hex(core.pmpregions)}
priv: ${core.priv}
status_fs_field_we: ${format_bool(core.status_fs_field_we)}
status_fs_field_we_enable: ${format_bool(core.status_fs_field_we_enable)}
status_vs_field_we: ${format_bool(core.status_vs_field_we)}
status_vs_field_we_enable: ${format_bool(core.status_vs_field_we_enable)}
% endfor

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
# Copyright (c) 2024 OpenHW Group
# Copyright (c) 2024 Thales
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
# Author: Abdessamii Oukalrazqou
cores:
- isa: rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
boot_addr: 0x80000000
marchid: 0x3
misa_we: false
misa_we_enable: true
pmpaddr0: 0x0
pmpcfg0: 0x0
pmpregions: 0x40
usable_pmpregions : 0x8
priv: M
status_fs_field_we: false
status_fs_field_we_enable: false
status_vs_field_we: false
status_vs_field_we_enable: false
priv: M
misa_we: false
mstatus_write_mask: 0x00000088
mstatus_override_mask: 0x00001800
mtval_write_mask: 0x00000000
unified_traps: true

View file

@ -27,22 +27,16 @@ hart0:
type:
rw: true
description: bit for cache-enable of instruction cache
shadow:
shadow_type:
msb: 0
lsb: 0
reserved_0:
implemented: true
description: reserved for future use
type:
ro_constant: 0x0
shadow:
shadow_type:
msb: 31
lsb: 1
fields:
- icache
- reserved_0
-
-
- 1
- 31
description: the register controls the operation of the i-cache unit.
address: 0x7c0
priv_mode: M
@ -61,18 +55,12 @@ hart0:
shadow_type:
msb: 0
lsb: 0
reserved_0:
implemented: true
description: reserved for future use
type:
ro_constant: 0x0
shadow:
shadow_type:
msb: 31
lsb: 1
fields:
- dcache
- reserved_0
-
-
- 1
- 31
description: the register controls the operation of the d-cache unit.
address: 0x7c1
priv_mode: M

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,27 @@ reset:
mtime:
implemented: true
address: 0x20000
memory_map:
-
memory_region:
name: bootrom
base_addr: 0x10000
size: 0x10000
description: System boot ROM
attributes:
read_only: true
cached: false
-
memory_region:
name: dram
base_addr: 0x80000000
size: 0x40000000
description: System (D)RAM
attributes:
executable: true
cached: true
non_idempotent: false
read_only: false
mtimecmp:
implemented: false
mtval_condition_writes:

View file

@ -27,19 +27,10 @@ hart0:
type:
rw: true
description: bit for cache-enable of instruction cache
shadow:
shadow_type:
msb: 0
lsb: 0
reserved_0:
implemented: true
description: reserved for future use
type:
ro_constant: 0x0
shadow:
shadow_type:
msb: 31
lsb: 1
description: the register controls the operation of the i-cache unit.
address: 0x7c0
priv_mode: M
@ -58,15 +49,6 @@ hart0:
shadow_type:
msb: 0
lsb: 0
reserved_0:
implemented: true
description: reserved for future use
type:
ro_constant: 0x0
shadow:
shadow_type:
msb: 31
lsb: 1
description: the register controls the operation of the d-cache unit.
address: 0x7c1
priv_mode: M

File diff suppressed because it is too large Load diff

View file

@ -19,5 +19,19 @@ nmi:
reset:
label: reset_vector
mtime:
implemented: True
implemented: true
address: 0x20000
memory_map:
- memory_region:
name: bootrom
base_addr: 0x10000
size: 0x10000
description: System boot ROM
attributes:
read_only: true
cached: false
- memory_region:
name: dram
base_addr: 0x80000000
size: 0x40000000
description: System (D)RAM

View file

@ -0,0 +1,55 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Zbigniew CHAMSKI - Thales
hart_ids: [0]
hart0:
icache:
reset-val: 0x1
rv32:
accessible: false
rv64:
accessible: true
icache:
implemented: true
type:
rw: true
description: bit for cache-enable of instruction cache
msb: 0
lsb: 0
shadow:
shadow_type:
description: the register controls the operation of the i-cache unit.
address: 0x7c0
priv_mode: M
dcache:
reset-val: 0x1
rv32:
accessible: false
rv64:
accessible: true
dcache:
implemented: true
type:
rw: true
description: bit for cache-enable of data cache
shadow:
shadow_type:
msb: 0
lsb: 0
description: the register controls the operation of the d-cache unit.
address: 0x7c1
priv_mode: M

View file

@ -0,0 +1,168 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Zbigniew CHAMSKI - Thales
# Updated from CV66 64 CEA - Tanuj Khandelwal - Thales
hart_ids: [0]
hart0: &hart0
Debug_Spec_Version: '1.0.0'
supported_xlen: [64]
debug_mode: true
parking_loop: 0x800
dcsr:
reset-val: 0x40000413
rv64:
accessible: true
debugver:
implemented: true
type:
ro_constant: 0x4
ebreakvs:
implemented: false
ebreakvu:
implemented: false
ebreakm:
implemented: true
ebreaks:
implemented: true
ebreaku:
implemented: true
stepie:
implemented: true
stopcount:
implemented: true
stoptime:
implemented: true
cause:
implemented: true
type:
ro_variable: true
v:
implemented: true
mprven:
implemented: true
nmip:
implemented: true
type:
ro_variable: true
step:
implemented: true
prv:
implemented: true
rv32:
accessible: false
dpc:
rv64:
accessible: true
rv32:
accessible: false
tselect:
rv32:
accessible: False
rv64:
accessible: True
type:
warl:
dependency_fields: []
legal:
- tselect[63:0] in [0x00000000:0x3]
wr_illegal:
- unchanged
tinfo: #FIXME
rv32:
accessible: False
rv64:
accessible: True
index_select_reg: tselect
index_list:
- reset-val: 0x78
index_val: 0
shadow:
shadow_type:
type:
ro_constant: 0x78
- reset-val: 0x8
index_val: 1
shadow:
shadow_type:
type:
ro_constant: 0x8
- reset-val: 0x10
index_val: 2
shadow:
shadow_type:
type:
ro_constant: 0x10
tdata1:
rv32:
accessible: False
rv64:
accessible: True
index_select_reg: tselect
index_list:
- reset-val: 0xdeadbeef
index_val: 0
shadow:
shadow_type:
type:
ro_constant: 0xdeadbeef
- reset-val: 0
index_val: 1
shadow:
shadow_type:
type: &mywarl
warl:
dependency_fields: []
legal:
- writeval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
- reset-val: 0
index_val: 2
shadow:
shadow_type:
type:
warl:
dependency_fields: []
legal:
- writeval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
#FIXME NTO SUPPORTED BY RISCV CNFIG
# tdata2:
# rv64:
# accessible: true
# type:
# ro_variable: true
# rv32:
# accessible: false
# tdata3:
# rv64:
# accessible: true
# type:
# ro_variable: true
# rv32:
# accessible: false
dscratch0:
rv64:
accessible: true
rv32:
accessible: false
dscratch1:
rv64:
accessible: true
rv32:
accessible: false

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
# Copyright 2024 Thales DIS France SAS
#
# 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.
#
# Original Author: Tanuj Khandelwal CEA (copied from riscv-config examples)
nmi:
label: nmi_vector
# address: 12288
reset:
label: reset_vector
# address: 16384
mtime:
implemented: false
mtimecmp:
implemented: false
#mcause_non_standard:
# implemented: true
mtval_condition_writes:
implemented: false
scause_non_standard:
implemented: false
stval_condition_writes:
implemented: false
zicbo_cache_block_sz :
implemented: true
zicbom_sz: 64
zicboz_sz: 64
#memory_map:
# - memory_region:
# name: bootrom
# base_addr: 0x10000
# size: 0x10000
# description: System boot ROM
# attributes:
# read_only: true
# cached: false
# - memory_region:
# name: dram
# base_addr: 0x80000000
# size: 0x40000000
# description: System (D)RAM

View file

@ -29,6 +29,8 @@
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/SyncDpRam.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/AsyncDpRam.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/AsyncThreePortRam.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/SyncDpRam_ind_r_w.sv
+incdir+${CVA6_REPO_DIR}/core/include/
+incdir+${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/include/
@ -71,11 +73,14 @@ ${CVA6_REPO_DIR}/core/include/instr_tracer_pkg.sv
${CVA6_REPO_DIR}/core/include/build_config_pkg.sv
//CVXIF
${CVA6_REPO_DIR}/core/include/cvxif_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_compressed_if_driver.sv
${CVA6_REPO_DIR}/core/cvxif_issue_register_commit_if_driver.sv
${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_fu.sv
${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv
${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/compressed_instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/copro_alu.sv
// Common Cells
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
@ -107,6 +112,7 @@ ${CVA6_REPO_DIR}/core/branch_unit.sv
${CVA6_REPO_DIR}/core/compressed_decoder.sv
${CVA6_REPO_DIR}/core/macro_decoder.sv
${CVA6_REPO_DIR}/core/controller.sv
${CVA6_REPO_DIR}/core/zcmt_decoder.sv
${CVA6_REPO_DIR}/core/csr_buffer.sv
${CVA6_REPO_DIR}/core/csr_regfile.sv
${CVA6_REPO_DIR}/core/decoder.sv
@ -138,6 +144,7 @@ ${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv
// What is "frontend"?
${CVA6_REPO_DIR}/core/frontend/btb.sv
${CVA6_REPO_DIR}/core/frontend/bht.sv
${CVA6_REPO_DIR}/core/frontend/bht2lvl.sv
${CVA6_REPO_DIR}/core/frontend/ras.sv
${CVA6_REPO_DIR}/core/frontend/instr_scan.sv
${CVA6_REPO_DIR}/core/frontend/instr_queue.sv
@ -160,14 +167,13 @@ ${CVA6_REPO_DIR}/core/cache_subsystem/cva6_icache_axi_wrapper.sv
${CVA6_REPO_DIR}/core/cache_subsystem/std_cache_subsystem.sv
${CVA6_REPO_DIR}/core/cache_subsystem/std_nbdcache.sv
-F ${HPDCACHE_DIR}/rtl/hpdcache.Flist
${HPDCACHE_DIR}/rtl/src/utils/hpdcache_mem_req_read_arbiter.sv
${HPDCACHE_DIR}/rtl/src/utils/hpdcache_mem_req_write_arbiter.sv
${HPDCACHE_DIR}/rtl/src/utils/hpdcache_mem_resp_demux.sv
${HPDCACHE_DIR}/rtl/src/utils/hpdcache_mem_to_axi_read.sv
${HPDCACHE_DIR}/rtl/src/utils/hpdcache_mem_to_axi_write.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_subsystem.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_subsystem_axi_arbiter.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_if_adapter.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_wrapper.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_1rw.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_wbyteenable_1rw.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_wmask_1rw.sv
@ -176,6 +182,7 @@ ${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_wmask_1rw.sv
// NOTE: pmp.sv modified for DSIM (unchanged for other simulators)
${CVA6_REPO_DIR}/core/pmp/src/pmp.sv
${CVA6_REPO_DIR}/core/pmp/src/pmp_entry.sv
${CVA6_REPO_DIR}/core/pmp/src/pmp_data_if.sv
// Tracer (behavioral code, not RTL)
${CVA6_REPO_DIR}/common/local/util/instr_tracer.sv

View file

@ -27,12 +27,11 @@ ${CVA6_REPO_DIR}/core/include/instr_tracer_pkg.sv
${CVA6_REPO_DIR}/core/include/build_config_pkg.sv
//CVXIF
${CVA6_REPO_DIR}/core/include/cvxif_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_fu.sv
${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv
${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv
${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv
${CVA6_REPO_DIR}/core/cvxif_example/compressed_instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/copro_alu.sv
// Common Cells
@ -63,7 +62,7 @@ ${CVA6_REPO_DIR}/pd/synth/cva6_${TARGET_CFG}_synth.v
# Dedicated to black box in caches, cv32a65x only
${CVA6_REPO_DIR}/pd/synth/tc_sram_wrapper_256_64_00000008_00000001_00000001_none_0.sv
${CVA6_REPO_DIR}/pd/synth/hpdcache_sram_wbyteenable_1rw_00000007_00000040_00000080.sv
${CVA6_REPO_DIR}/pd/synth/hpdcache_sram_1rw_00000006_0000001a_00000040.sv
${CVA6_REPO_DIR}/pd/synth/hpdcache_sram_1rw_00000006_0000001c_00000040.sv
${CVA6_REPO_DIR}/common/local/util/tc_sram_wrapper.sv
${CVA6_REPO_DIR}/common/local/util/tc_sram_wrapper_cache_techno.sv

View file

@ -23,36 +23,12 @@ module acc_dispatcher
parameter type exception_t = logic,
parameter type fu_data_t = logic,
parameter type scoreboard_entry_t = logic,
localparam type accelerator_req_t = struct packed {
logic req_valid;
logic resp_ready;
riscv::instruction_t insn;
logic [CVA6Cfg.XLEN-1:0] rs1;
logic [CVA6Cfg.XLEN-1:0] rs2;
fpnew_pkg::roundmode_e frm;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
logic store_pending;
// Invalidation interface
logic acc_cons_en;
logic inval_ready;
},
parameter type acc_req_t = accelerator_req_t,
parameter type acc_resp_t = struct packed {
logic req_ready;
logic resp_valid;
logic [CVA6Cfg.XLEN-1:0] result;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
logic error;
// Metadata
logic store_pending;
logic store_complete;
logic load_complete;
logic [4:0] fflags;
logic fflags_valid;
// Invalidation interface
logic inval_valid;
logic [63:0] inval_addr;
},
parameter type acc_req_t = logic,
parameter type acc_resp_t = logic,
parameter type accelerator_req_t = logic,
parameter type accelerator_resp_t = logic,
parameter type acc_mmu_req_t = logic,
parameter type acc_mmu_resp_t = logic,
parameter type acc_cfg_t = logic,
parameter acc_cfg_t AccCfg = '0
) (
@ -65,10 +41,11 @@ module acc_dispatcher
// Interface with the CSRs
input priv_lvl_t ld_st_priv_lvl_i,
input logic sum_i,
input pmpcfg_t [15:0] pmpcfg_i,
input logic [15:0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input logic [2:0] fcsr_frm_i,
output logic dirty_v_state_o,
input logic acc_mmu_en_i,
// Interface with the issue stage
input scoreboard_entry_t issue_instr_i,
input logic issue_instr_hs_i,
@ -88,6 +65,9 @@ module acc_dispatcher
output logic acc_stall_st_pending_o,
input logic acc_no_st_pending_i,
input dcache_req_i_t [2:0] dcache_req_ports_i,
// Interface with the MMU
output acc_mmu_req_t acc_mmu_req_o,
input acc_mmu_resp_t acc_mmu_resp_i,
// Interface with the controller
output logic ctrl_halt_o,
input logic [11:0] csr_addr_i,
@ -219,7 +199,7 @@ module acc_dispatcher
end
// An accelerator instruction was issued.
if (acc_req_o.req_valid) insn_ready_d[acc_req_o.trans_id] = 1'b0;
if (acc_req_o.acc_req.req_valid) insn_ready_d[acc_req_o.acc_req.trans_id] = 1'b0;
end : p_non_speculative_ff
/*************************
@ -231,29 +211,31 @@ module acc_dispatcher
logic acc_req_ready;
accelerator_req_t acc_req_int;
fall_through_register #(
spill_register #(
.T(accelerator_req_t)
) i_accelerator_req_register (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (1'b0),
.testmode_i(1'b0),
.data_i (acc_req),
.valid_i (acc_req_valid),
.ready_o (acc_req_ready),
.data_o (acc_req_int),
.valid_o (acc_req_o.req_valid),
.ready_i (acc_resp_i.req_ready)
.clk_i (clk_i),
.rst_ni (rst_ni),
.data_i (acc_req),
.valid_i(acc_req_valid),
.ready_o(acc_req_ready),
.data_o (acc_req_int),
.valid_o(acc_req_o.acc_req.req_valid),
.ready_i(acc_resp_i.acc_resp.req_ready)
);
assign acc_req_o.insn = acc_req_int.insn;
assign acc_req_o.rs1 = acc_req_int.rs1;
assign acc_req_o.rs2 = acc_req_int.rs2;
assign acc_req_o.frm = acc_req_int.frm;
assign acc_req_o.trans_id = acc_req_int.trans_id;
assign acc_req_o.store_pending = !acc_no_st_pending_i && acc_cons_en_i;
assign acc_req_o.acc_cons_en = acc_cons_en_i;
assign acc_req_o.inval_ready = inval_ready_i;
assign acc_req_o.acc_req.insn = acc_req_int.insn;
assign acc_req_o.acc_req.rs1 = acc_req_int.rs1;
assign acc_req_o.acc_req.rs2 = acc_req_int.rs2;
assign acc_req_o.acc_req.frm = acc_req_int.frm;
assign acc_req_o.acc_req.trans_id = acc_req_int.trans_id;
assign acc_req_o.acc_req.store_pending = !acc_no_st_pending_i && acc_cons_en_i;
assign acc_req_o.acc_req.acc_cons_en = acc_cons_en_i;
assign acc_req_o.acc_req.inval_ready = inval_ready_i;
// MMU interface
assign acc_req_o.acc_mmu_resp = acc_mmu_resp_i;
assign acc_req_o.acc_mmu_en = acc_mmu_en_i;
always_comb begin : accelerator_req_dispatcher
// Do not fetch from the instruction queue
@ -263,7 +245,7 @@ module acc_dispatcher
acc_req = '0;
acc_req_valid = 1'b0;
// Unpack fu_data_t into accelerator_req_t
// Unpack fu_data_t into acc_req_t
if (!acc_insn_queue_empty) begin
acc_req = '{
// Instruction is forwarded from the decoder as an immediate
@ -285,7 +267,7 @@ module acc_dispatcher
};
// Wait until the instruction is no longer speculative.
acc_req_valid = insn_ready_q[acc_insn_queue_o.trans_id] ||
(acc_commit && insn_pending_q[acc_commit_trans_id]);
(acc_commit && insn_pending_q[acc_commit_trans_id] && !flush_unissued_instr_i);
acc_insn_queue_pop = acc_req_valid && acc_req_ready;
end
end
@ -297,30 +279,27 @@ module acc_dispatcher
logic acc_ld_disp;
logic acc_st_disp;
assign acc_trans_id_o = acc_resp_i.acc_resp.trans_id;
assign acc_result_o = acc_resp_i.acc_resp.result;
assign acc_valid_o = acc_resp_i.acc_resp.resp_valid;
assign acc_exception_o = acc_resp_i.acc_resp.exception;
// Unpack the accelerator response
assign acc_trans_id_o = acc_resp_i.trans_id;
assign acc_result_o = acc_resp_i.result;
assign acc_valid_o = acc_resp_i.resp_valid;
assign acc_exception_o = '{
cause: riscv::ILLEGAL_INSTR,
tval : '0,
tval2 : '0,
tinst : '0,
gva : '0,
valid: acc_resp_i.error
};
assign acc_fflags_valid_o = acc_resp_i.fflags_valid;
assign acc_fflags_o = acc_resp_i.fflags;
assign acc_fflags_valid_o = acc_resp_i.acc_resp.fflags_valid;
assign acc_fflags_o = acc_resp_i.acc_resp.fflags;
// MMU interface
assign acc_mmu_req_o = acc_resp_i.acc_mmu_req;
// Always ready to receive responses
assign acc_req_o.resp_ready = 1'b1;
assign acc_req_o.acc_req.resp_ready = 1'b1;
// Signal dispatched load/store to issue stage
assign acc_ld_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
assign acc_st_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);
// Cache invalidation
assign inval_valid_o = acc_resp_i.inval_valid;
assign inval_addr_o = acc_resp_i.inval_addr;
assign inval_valid_o = acc_resp_i.acc_resp.inval_valid;
assign inval_addr_o = acc_resp_i.acc_resp.inval_addr;
/**************************
* Accelerator commit *
@ -358,8 +337,8 @@ module acc_dispatcher
`FF(wait_acc_store_q, wait_acc_store_d, '0)
// Set on store barrier. Clear when no store is pending.
assign wait_acc_store_d = (wait_acc_store_q | commit_st_barrier_i) & acc_resp_i.store_pending;
assign ctrl_halt_o = wait_acc_store_q;
assign wait_acc_store_d = (wait_acc_store_q | commit_st_barrier_i) & acc_resp_i.acc_resp.store_pending;
assign ctrl_halt_o = wait_acc_store_q;
/**************************
* Load/Store tracking *
@ -397,9 +376,9 @@ module acc_dispatcher
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (1'b0),
.en_i (acc_ld_disp ^ acc_resp_i.load_complete),
.en_i (acc_ld_disp ^ acc_resp_i.acc_resp.load_complete),
.load_i (1'b0),
.down_i (acc_resp_i.load_complete),
.down_i (acc_resp_i.acc_resp.load_complete),
.d_i ('0),
.q_o (acc_disp_loads_pending),
.overflow_o(acc_disp_loads_overflow)
@ -442,9 +421,9 @@ module acc_dispatcher
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (1'b0),
.en_i (acc_st_disp ^ acc_resp_i.store_complete),
.en_i (acc_st_disp ^ acc_resp_i.acc_resp.store_complete),
.load_i (1'b0),
.down_i (acc_resp_i.store_complete),
.down_i (acc_resp_i.acc_resp.store_complete),
.d_i ('0),
.q_o (acc_disp_stores_pending),
.overflow_o(acc_disp_stores_overflow)

View file

@ -22,6 +22,7 @@ module alu
import ariane_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter bit HasBranch = 1'b1,
parameter type fu_data_t = logic
) (
// Subsystem Clock - SUBSYSTEM
@ -50,6 +51,9 @@ module alu
logic lz_tz_empty, lz_tz_wempty;
logic [CVA6Cfg.XLEN-1:0] orcbw_result, rev8w_result;
logic [CVA6Cfg.XLEN-1:0] brev8_reversed;
logic [ 31:0] unzip_gen;
logic [ 31:0] zip_gen;
// bit reverse operand_a for left shifts and bit counting
generate
genvar k;
@ -68,15 +72,7 @@ module alu
logic [CVA6Cfg.XLEN-1:0] adder_result;
logic [CVA6Cfg.XLEN-1:0] operand_a_bitmanip, bit_indx;
always_comb begin
adder_op_b_negate = 1'b0;
unique case (fu_data_i.operation)
// ADDER OPS
EQ, NE, SUB, SUBW, ANDN, ORN, XNOR: adder_op_b_negate = 1'b1;
default: ;
endcase
end
assign adder_op_b_negate = fu_data_i.operation inside {EQ, NE, SUB, SUBW, ANDN, ORN, XNOR};
always_comb begin
operand_a_bitmanip = fu_data_i.operand_a;
@ -110,21 +106,24 @@ module alu
assign adder_in_b = operand_b_neg;
// actual adder
assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
assign adder_result_ext_o = adder_in_a + adder_in_b;
assign adder_result = adder_result_ext_o[CVA6Cfg.XLEN:1];
assign adder_z_flag = ~|adder_result;
// get the right branch comparison result
always_comb begin : branch_resolve
// set comparison by default
alu_branch_res_o = 1'b1;
case (fu_data_i.operation)
EQ: alu_branch_res_o = adder_z_flag;
NE: alu_branch_res_o = ~adder_z_flag;
LTS, LTU: alu_branch_res_o = less;
GES, GEU: alu_branch_res_o = ~less;
default: alu_branch_res_o = 1'b1;
endcase
if (HasBranch) begin
always_comb begin : branch_resolve
// set comparison by default
case (fu_data_i.operation)
EQ: alu_branch_res_o = adder_z_flag;
NE: alu_branch_res_o = ~adder_z_flag;
LTS, LTU: alu_branch_res_o = less;
GES, GEU: alu_branch_res_o = ~less;
default: alu_branch_res_o = 1'b1;
endcase
end
end else begin
assign alu_branch_res_o = 1'b0;
end
// ---------
@ -150,9 +149,9 @@ module alu
assign shift_amt = fu_data_i.operand_b;
assign shift_left = (fu_data_i.operation == SLL) | (fu_data_i.operation == SLLW);
assign shift_left = (fu_data_i.operation == SLL) | (CVA6Cfg.IS_XLEN64 && fu_data_i.operation == SLLW);
assign shift_arithmetic = (fu_data_i.operation == SRA) | (fu_data_i.operation == SRAW);
assign shift_arithmetic = (fu_data_i.operation == SRA) | (CVA6Cfg.IS_XLEN64 && fu_data_i.operation == SRAW);
// right shifts, we let the synthesizer optimize this
logic [CVA6Cfg.XLEN:0] shift_op_a_64;
@ -267,6 +266,29 @@ module alu
end
end
// ZKN gen block
if (CVA6Cfg.ZKN && CVA6Cfg.RVB) begin : zkn_gen_block
genvar i, m, n;
// Generate brev8_reversed by reversing bits within each byte
for (i = 0; i < (CVA6Cfg.XLEN / 8); i++) begin : brev8_gen
for (m = 0; m < 8; m++) begin : reverse_bits
// Reversing the order of bits within a single byte
assign brev8_reversed[(i<<3)+m] = fu_data_i.operand_a[(i<<3)+(7-m)];
end
end
// Generate zip and unzip results
if (CVA6Cfg.IS_XLEN32) begin
for (n = 0; n < 16; n++) begin : zip_unzip_gen
// Assigning lower and upper half of operand into the even and odd positions of result
assign zip_gen[n<<1] = fu_data_i.operand_a[n];
assign zip_gen[(n<<1)+1] = fu_data_i.operand_a[n+16];
// Assigning even and odd bits of operand into lower and upper halves of result
assign unzip_gen[n] = fu_data_i.operand_a[n<<1];
assign unzip_gen[n+16] = fu_data_i.operand_a[(n<<1)+1];
end
end
end
// -----------
// Result MUX
// -----------
@ -300,10 +322,10 @@ module alu
if (CVA6Cfg.RVB) begin
// Index for Bitwise Rotation
bit_indx = 1 << (fu_data_i.operand_b & (CVA6Cfg.XLEN - 1));
// rolw, roriw, rorw
rolw = ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << fu_data_i.operand_b[4:0]) | ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> (CVA6Cfg.XLEN-32-fu_data_i.operand_b[4:0]));
rorw = ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> fu_data_i.operand_b[4:0]) | ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << (CVA6Cfg.XLEN-32-fu_data_i.operand_b[4:0]));
if (CVA6Cfg.IS_XLEN64) begin
// rolw, roriw, rorw
rolw = ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << fu_data_i.operand_b[4:0]) | ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> (CVA6Cfg.XLEN-32-fu_data_i.operand_b[4:0]));
rorw = ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} >> fu_data_i.operand_b[4:0]) | ({{CVA6Cfg.XLEN-32{1'b0}},fu_data_i.operand_a[31:0]} << (CVA6Cfg.XLEN-32-fu_data_i.operand_b[4:0]));
unique case (fu_data_i.operation)
CLZW, CTZW:
result_o = (lz_tz_wempty) ? 32 : {{CVA6Cfg.XLEN - 5{1'b0}}, lz_tz_wcount}; // change
@ -362,5 +384,22 @@ module alu
default: ; // default case to suppress unique warning
endcase
end
// ZKN instructions
if (CVA6Cfg.ZKN && CVA6Cfg.RVB) begin
unique case (fu_data_i.operation)
PACK:
result_o = (CVA6Cfg.IS_XLEN32) ? ({fu_data_i.operand_b[15:0], fu_data_i.operand_a[15:0]}) : ({fu_data_i.operand_b[31:0], fu_data_i.operand_a[31:0]});
PACK_H:
result_o = (CVA6Cfg.IS_XLEN32) ? ({16'b0, fu_data_i.operand_b[7:0], fu_data_i.operand_a[7:0]}) : ({48'b0, fu_data_i.operand_b[7:0], fu_data_i.operand_a[7:0]});
BREV8: result_o = brev8_reversed;
default: ;
endcase
if (fu_data_i.operation == PACK_W && CVA6Cfg.IS_XLEN64)
result_o = {
{32{fu_data_i.operand_b[15]}}, {fu_data_i.operand_b[15:0]}, {fu_data_i.operand_a[15:0]}
};
if (fu_data_i.operation == UNZIP && CVA6Cfg.IS_XLEN32) result_o = unzip_gen;
if (fu_data_i.operation == ZIP && CVA6Cfg.IS_XLEN32) result_o = zip_gen;
end
end
endmodule

View file

@ -1,4 +1,5 @@
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright 2024 - PlanV Technologies for additionnal contribution.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
@ -15,7 +16,7 @@
// Noam Gallmann - gnoam@live.com
// Felipe Lisboa Malaquias
// Henry Suzukawa
//
// Angela Gonzalez - PlanV Technologies
//
// Description: This register file is optimized for implementation on
// FPGAs. The register file features one distributed RAM block per implemented
@ -50,11 +51,16 @@ module ariane_regfile_fpga #(
localparam LOG_NR_WRITE_PORTS = CVA6Cfg.NrCommitPorts == 1 ? 1 : $clog2(CVA6Cfg.NrCommitPorts);
// Distributed RAM usually supports one write port per block - duplicate for each write port.
logic [ NUM_WORDS-1:0][ DATA_WIDTH-1:0] mem [CVA6Cfg.NrCommitPorts];
logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] mem[CVA6Cfg.NrCommitPorts];
logic [CVA6Cfg.NrCommitPorts-1:0][ NUM_WORDS-1:0] we_dec;
logic [ NUM_WORDS-1:0][LOG_NR_WRITE_PORTS-1:0] mem_block_sel;
logic [ NUM_WORDS-1:0][LOG_NR_WRITE_PORTS-1:0] mem_block_sel_q;
logic [CVA6Cfg.NrCommitPorts-1:0][NUM_WORDS-1:0] we_dec;
logic [NUM_WORDS-1:0][LOG_NR_WRITE_PORTS-1:0] mem_block_sel;
logic [NUM_WORDS-1:0][LOG_NR_WRITE_PORTS-1:0] mem_block_sel_q;
logic [CVA6Cfg.NrCommitPorts-1:0][DATA_WIDTH-1:0] wdata_reg;
logic [NR_READ_PORTS-1:0] read_after_write;
logic [NR_READ_PORTS-1:0][4:0] raddr_q;
logic [NR_READ_PORTS-1:0][4:0] raddr;
// write adress decoder (for block selector)
always_comb begin
@ -88,36 +94,55 @@ module ariane_regfile_fpga #(
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
mem_block_sel_q <= '0;
raddr_q <= '0;
end else begin
mem_block_sel_q <= mem_block_sel;
if (CVA6Cfg.FpgaAlteraEn) raddr_q <= raddr_i;
else raddr_q <= '0;
end
end
// distributed RAM blocks
logic [NR_READ_PORTS-1:0][DATA_WIDTH-1:0] mem_read[CVA6Cfg.NrCommitPorts];
logic [NR_READ_PORTS-1:0][DATA_WIDTH-1:0] mem_read_sync[CVA6Cfg.NrCommitPorts];
for (genvar j = 0; j < CVA6Cfg.NrCommitPorts; j++) begin : regfile_ram_block
always_ff @(posedge clk_i) begin
if (we_i[j] && ~waddr_i[j] != 0) begin
mem[j][waddr_i[j]] <= wdata_i[j];
if (CVA6Cfg.FpgaAlteraEn)
wdata_reg[j] <= wdata_i[j]; // register data written in case is needed to read next cycle
else wdata_reg[j] <= '0;
end
if (CVA6Cfg.FpgaAlteraEn) begin
for (int k = 0; k < NR_READ_PORTS; k++) begin : block_read
mem_read_sync[j][k] = mem[j][raddr_i[k]]; // synchronous RAM
read_after_write[k] <= '0;
if (waddr_i[j] == raddr_i[k])
read_after_write[k] <= we_i[j] && ~waddr_i[j] != 0; // Identify if we need to read the content that was written
end
end
end
for (genvar k = 0; k < NR_READ_PORTS; k++) begin : block_read
assign mem_read[j][k] = mem[j][raddr_i[k]];
assign mem_read[j][k] = CVA6Cfg.FpgaAlteraEn ? ( read_after_write[k] ? wdata_reg[j]: mem_read_sync[j][k]) : mem[j][raddr_i[k]];
end
end
//with synchronous ram there is the need to adjust which address is used at the output MUX
assign raddr = CVA6Cfg.FpgaAlteraEn ? raddr_q : raddr_i;
// output MUX
logic [NR_READ_PORTS-1:0][LOG_NR_WRITE_PORTS-1:0] block_addr;
for (genvar k = 0; k < NR_READ_PORTS; k++) begin : regfile_read_port
assign block_addr[k] = mem_block_sel_q[raddr_i[k]];
assign rdata_o[k] = (ZERO_REG_ZERO && raddr_i[k] == '0) ? '0 : mem_read[block_addr[k]][k];
assign block_addr[k] = mem_block_sel_q[raddr[k]];
assign rdata_o[k] = (ZERO_REG_ZERO && raddr[k] == '0) ? '0 : mem_read[block_addr[k]][k];
end
// random initialization of the memory to suppress assert warnings on Questa.
initial begin
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
for (int j = 0; j < NUM_WORDS; j++) begin
mem[i][j] = $random();
if (!CVA6Cfg.FpgaAlteraEn)
mem[i][j] = $random(); //quartus does not support this random statement on synthesis
else mem[i][j] = '0;
end
end
end

View file

@ -31,10 +31,10 @@ module branch_unit #(
input fu_data_t fu_data_i,
// Instruction PC - ISSUE_STAGE
input logic [CVA6Cfg.VLEN-1:0] pc_i,
// Is zcmt instruction - ISSUE_STAGE
input logic is_zcmt_i,
// Instruction is compressed - ISSUE_STAGE
input logic is_compressed_instr_i,
// any functional unit is valid, check that there is no accidental mis-predict - TO_BE_COMPLETED
input logic fu_valid_i,
// Branch unit instruction is valid - ISSUE_STAGE
input logic branch_valid_i,
// ALU branch compare result - ALU
@ -60,7 +60,6 @@ module branch_unit #(
// TODO(zarubaf): The ALU can be used to calculate the branch target
jump_base = (fu_data_i.operation == ariane_pkg::JALR) ? fu_data_i.operand_a[CVA6Cfg.VLEN-1:0] : pc_i;
target_address = {CVA6Cfg.VLEN{1'b0}};
resolve_branch_o = 1'b0;
resolved_branch_o.target_address = {CVA6Cfg.VLEN{1'b0}};
resolved_branch_o.is_taken = 1'b0;
@ -77,13 +76,21 @@ module branch_unit #(
// we need to put the branch target address into rd, this is the result of this unit
branch_result_o = next_pc;
resolved_branch_o.pc = pc_i;
// There are only two sources of mispredicts:
// There are only three sources of mispredicts:
// 1. Branches
// 2. Jumps to register addresses
// 3. Zcmt instructions
if (branch_valid_i) begin
// write target address which goes to PC Gen
// write target address which goes to PC Gen or select target address if zcmt
resolved_branch_o.target_address = (branch_comp_res_i) ? target_address : next_pc;
resolved_branch_o.is_taken = branch_comp_res_i;
if (CVA6Cfg.RVZCMT) begin
if (is_zcmt_i) begin
// Unconditional jump handling
resolved_branch_o.is_mispredict = 1'b1; // miss prediction for ZCMT
resolved_branch_o.cf_type = ariane_pkg::JumpR;
end
end
// check the outcome of the branch speculation
if (ariane_pkg::op_is_branch(fu_data_i.operation)) begin
// Set the `cf_type` of the output as `branch`, this will update the BHT.
@ -110,8 +117,6 @@ module branch_unit #(
always_comb begin : exception_handling
// Do a jump if it is either unconditional jump (JAL | JALR) or `taken` conditional jump
jump_taken = !(ariane_pkg::op_is_branch(fu_data_i.operation)) ||
((ariane_pkg::op_is_branch(fu_data_i.operation)) && branch_comp_res_i);
branch_exception_o.cause = riscv::INSTR_ADDR_MISALIGNED;
branch_exception_o.valid = 1'b0;
if (CVA6Cfg.TvalEn)
@ -122,8 +127,12 @@ module branch_unit #(
branch_exception_o.gva = CVA6Cfg.RVH ? v_i : 1'b0;
// Only throw instruction address misaligned exception if this is indeed a `taken` conditional branch or
// an unconditional jump
if (branch_valid_i && (target_address[0] || (!CVA6Cfg.RVC && target_address[1])) && jump_taken) begin
branch_exception_o.valid = 1'b1;
if (!CVA6Cfg.RVC) begin
jump_taken = !(ariane_pkg::op_is_branch(fu_data_i.operation)) ||
((ariane_pkg::op_is_branch(fu_data_i.operation)) && branch_comp_res_i);
if (branch_valid_i && (target_address[0] || target_address[1]) && jump_taken) begin
branch_exception_o.valid = 1'b1;
end
end
end
endmodule

View file

@ -201,7 +201,7 @@ module axi_adapter #(
end else begin
// bursts of AMOs unsupported
assert (amo_i == ariane_pkg::AMO_NONE)
else $fatal("Bursts of atomic operations are not supported");
else $fatal(1, "Bursts of atomic operations are not supported");
axi_req_o.aw.len = BURST_SIZE[7:0]; // number of bursts to do
axi_req_o.w.data = wdata_i[0];
@ -232,7 +232,7 @@ module axi_adapter #(
gnt_o = axi_resp_i.ar_ready;
if (type_i != ariane_pkg::SINGLE_REQ) begin
assert (amo_i == ariane_pkg::AMO_NONE)
else $fatal("Bursts of atomic operations are not supported");
else $fatal(1, "Bursts of atomic operations are not supported");
axi_req_o.ar.len = BURST_SIZE[7:0];
cnt_d = BURST_SIZE[ADDR_INDEX-1:0];

View file

@ -117,7 +117,8 @@ module cache_ctrl
// cache-line offset -> multiple of XLEN
cl_offset = mem_req_q.index[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:$clog2(CVA6Cfg.XLEN/8)] <<
$clog2(CVA6Cfg.XLEN); // shift by log2(XLEN) to the left
axi_offset = '0;
// XLEN offset within AXI request
axi_offset = (mem_req_q.index >> $clog2(CVA6Cfg.XLEN / 8)) << $clog2(CVA6Cfg.XLEN);
// default assignments
state_d = state_q;
mem_req_d = mem_req_q;
@ -138,11 +139,6 @@ module cache_ctrl
mem_req_d.killed |= req_port_i.kill_req;
if (CVA6Cfg.XLEN == 32) begin
axi_offset = mem_req_q.index[$clog2(CVA6Cfg.AxiDataWidth/8)-1:$clog2(CVA6Cfg.XLEN/8)] <<
$clog2(CVA6Cfg.XLEN);
end
case (state_q)
IDLE: begin
@ -311,9 +307,9 @@ module cache_ctrl
// two memory look-ups on a single-ported SRAM and therefore is non-atomic
if (!mshr_index_matches_i) begin
// store data, write dirty bit
req_o = hit_way_q;
addr_o = mem_req_q.index;
we_o = 1'b1;
req_o = hit_way_q;
addr_o = mem_req_q.index;
we_o = 1'b1;
be_o.vldrty = hit_way_q;

View file

@ -14,7 +14,7 @@ module cva6_hpdcache_if_adapter
// {{{
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter hpdcache_pkg::hpdcache_cfg_t hpdcacheCfg = '0,
parameter hpdcache_pkg::hpdcache_cfg_t HPDcacheCfg = '0,
parameter type hpdcache_tag_t = logic,
parameter type hpdcache_req_offset_t = logic,
parameter type hpdcache_req_sid_t = logic,
@ -22,7 +22,8 @@ module cva6_hpdcache_if_adapter
parameter type hpdcache_rsp_t = logic,
parameter type dcache_req_i_t = logic,
parameter type dcache_req_o_t = logic,
parameter bit is_load_port = 1'b1
parameter bit InvalidateOnFlush = 1'b0,
parameter bit IsLoadPort = 1'b1
)
// }}}
@ -42,6 +43,10 @@ module cva6_hpdcache_if_adapter
input ariane_pkg::amo_req_t cva6_amo_req_i,
output ariane_pkg::amo_resp_t cva6_amo_resp_o,
// Dcache flush signal
input logic cva6_dcache_flush_i,
output logic cva6_dcache_flush_ack_o,
// Request port to the L1 Dcache
output logic hpdcache_req_valid_o,
input logic hpdcache_req_ready_i,
@ -58,8 +63,13 @@ module cva6_hpdcache_if_adapter
// Internal nets and registers
// {{{
logic forward_store, forward_amo;
typedef enum {
FLUSH_IDLE,
FLUSH_PEND
} flush_fsm_t;
logic hpdcache_req_is_uncacheable;
hpdcache_req_t hpdcache_req;
// }}}
// Request forwarding
@ -67,7 +77,7 @@ module cva6_hpdcache_if_adapter
generate
// LOAD request
// {{{
if (is_load_port == 1'b1) begin : load_port_gen
if (IsLoadPort == 1'b1) begin : load_port_gen
assign hpdcache_req_is_uncacheable = !config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{
@ -78,29 +88,41 @@ module cva6_hpdcache_if_adapter
);
// Request forwarding
assign hpdcache_req_valid_o = cva6_req_i.data_req,
hpdcache_req_o.addr_offset = cva6_req_i.address_index,
hpdcache_req_o.wdata = '0,
hpdcache_req_o.op = hpdcache_pkg::HPDCACHE_REQ_LOAD,
hpdcache_req_o.be = cva6_req_i.data_be,
hpdcache_req_o.size = cva6_req_i.data_size,
hpdcache_req_o.sid = hpdcache_req_sid_i,
hpdcache_req_o.tid = cva6_req_i.data_id,
hpdcache_req_o.need_rsp = 1'b1,
hpdcache_req_o.phys_indexed = 1'b0,
hpdcache_req_o.addr_tag = '0, // unused on virtually indexed request
hpdcache_req_o.pma = '0; // unused on virtually indexed request
assign hpdcache_req_valid_o = cva6_req_i.data_req;
assign hpdcache_req.addr_offset = cva6_req_i.address_index;
assign hpdcache_req.wdata = '0;
assign hpdcache_req.op = hpdcache_pkg::HPDCACHE_REQ_LOAD;
assign hpdcache_req.be = cva6_req_i.data_be;
assign hpdcache_req.size = cva6_req_i.data_size;
assign hpdcache_req.sid = hpdcache_req_sid_i;
assign hpdcache_req.tid = cva6_req_i.data_id;
assign hpdcache_req.need_rsp = 1'b1;
assign hpdcache_req.phys_indexed = 1'b0;
assign hpdcache_req.addr_tag = '0; // unused on virtually indexed request
assign hpdcache_req.pma.uncacheable = 1'b0;
assign hpdcache_req.pma.io = 1'b0;
assign hpdcache_req.pma.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
assign hpdcache_req_abort_o = cva6_req_i.kill_req,
hpdcache_req_tag_o = cva6_req_i.address_tag,
hpdcache_req_pma_o.uncacheable = hpdcache_req_is_uncacheable,
hpdcache_req_pma_o.io = 1'b0;
assign hpdcache_req_abort_o = cva6_req_i.kill_req;
assign hpdcache_req_tag_o = cva6_req_i.address_tag;
assign hpdcache_req_pma_o.uncacheable = hpdcache_req_is_uncacheable;
assign hpdcache_req_pma_o.io = 1'b0;
assign hpdcache_req_pma_o.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
// Response forwarding
assign cva6_req_o.data_rvalid = hpdcache_rsp_valid_i,
cva6_req_o.data_rdata = hpdcache_rsp_i.rdata,
cva6_req_o.data_rid = hpdcache_rsp_i.tid,
cva6_req_o.data_gnt = hpdcache_req_ready_i;
assign cva6_req_o.data_rvalid = hpdcache_rsp_valid_i;
assign cva6_req_o.data_rdata = hpdcache_rsp_i.rdata;
assign cva6_req_o.data_rid = hpdcache_rsp_i.tid;
assign cva6_req_o.data_gnt = hpdcache_req_ready_i;
// Assertions
// {{{
// pragma translate_off
flush_on_load_port_assert :
assert property (@(posedge clk_i) disable iff (rst_ni !== 1'b1) (cva6_dcache_flush_i == 1'b0))
else $error("Flush unsupported on load adapters");
// pragma translate_on
// }}}
end // }}}
// {{{
@ -116,12 +138,59 @@ module cva6_hpdcache_if_adapter
logic [31:0] amo_resp_word;
logic amo_pending_q;
hpdcache_req_t hpdcache_req_amo;
hpdcache_req_t hpdcache_req_store;
hpdcache_req_t hpdcache_req_flush;
flush_fsm_t flush_fsm_q, flush_fsm_d;
logic forward_store, forward_amo, forward_flush;
// DCACHE flush request
// {{{
always_ff @(posedge clk_i or negedge rst_ni) begin : flush_ff
if (!rst_ni) begin
flush_fsm_q <= FLUSH_IDLE;
end else begin
flush_fsm_q <= flush_fsm_d;
end
end
always_comb begin : flush_comb
forward_flush = 1'b0;
cva6_dcache_flush_ack_o = 1'b0;
flush_fsm_d = flush_fsm_q;
case (flush_fsm_q)
FLUSH_IDLE: begin
if (cva6_dcache_flush_i) begin
forward_flush = 1'b1;
if (hpdcache_req_ready_i) begin
flush_fsm_d = FLUSH_PEND;
end
end
end
FLUSH_PEND: begin
if (hpdcache_rsp_valid_i) begin
if (hpdcache_rsp_i.tid == '0) begin
cva6_dcache_flush_ack_o = 1'b1;
flush_fsm_d = FLUSH_IDLE;
end
end
end
default: begin
end
endcase
end
// }}}
// AMO logic
// {{{
always_comb begin : amo_op_comb
amo_addr = cva6_amo_req_i.operand_a;
amo_addr_offset = amo_addr[0+:hpdcacheCfg.reqOffsetWidth];
amo_tag = amo_addr[hpdcacheCfg.reqOffsetWidth+:hpdcacheCfg.tagWidth];
amo_addr_offset = amo_addr[0+:HPDcacheCfg.reqOffsetWidth];
amo_tag = amo_addr[HPDcacheCfg.reqOffsetWidth+:HPDcacheCfg.tagWidth];
unique case (cva6_amo_req_i.amo_op)
ariane_pkg::AMO_LR: amo_op = hpdcache_pkg::HPDCACHE_REQ_AMO_LR;
ariane_pkg::AMO_SC: amo_op = hpdcache_pkg::HPDCACHE_REQ_AMO_SC;
@ -145,7 +214,7 @@ module cva6_hpdcache_if_adapter
CVA6Cfg,
{
{64 - CVA6Cfg.DCACHE_TAG_WIDTH{1'b0}}
, hpdcache_req_o.addr_tag,
, hpdcache_req.addr_tag,
{CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);
@ -160,25 +229,78 @@ module cva6_hpdcache_if_adapter
assign amo_data_be = 8'h0f;
end
assign hpdcache_req_amo = '{
addr_offset: amo_addr_offset,
wdata: amo_data,
op: amo_op,
be: amo_data_be,
size: cva6_amo_req_i.size,
sid: hpdcache_req_sid_i,
tid: '1,
need_rsp: 1'b1,
phys_indexed: 1'b1,
addr_tag: amo_tag,
pma: '{
uncacheable: hpdcache_req_is_uncacheable,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign hpdcache_req_store = '{
addr_offset: cva6_req_i.address_index,
wdata: cva6_req_i.data_wdata,
op: hpdcache_pkg::HPDCACHE_REQ_STORE,
be: cva6_req_i.data_be,
size: cva6_req_i.data_size,
sid: hpdcache_req_sid_i,
tid: '0,
need_rsp: 1'b0,
phys_indexed: 1'b1,
addr_tag: cva6_req_i.address_tag,
pma: '{
uncacheable: hpdcache_req_is_uncacheable,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign hpdcache_req_flush = '{
addr_offset: '0,
addr_tag: '0,
wdata: '0,
op:
InvalidateOnFlush
?
hpdcache_pkg::HPDCACHE_REQ_CMO_FLUSH_INVAL_ALL
:
hpdcache_pkg::HPDCACHE_REQ_CMO_FLUSH_ALL,
be: '0,
size: '0,
sid: hpdcache_req_sid_i,
tid: '0,
need_rsp: 1'b1,
phys_indexed: 1'b0,
pma: '{
uncacheable: 1'b0,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign forward_store = cva6_req_i.data_req;
assign forward_amo = cva6_amo_req_i.req;
assign hpdcache_req_valid_o = forward_store | (forward_amo & ~amo_pending_q);
assign hpdcache_req_o.addr_offset = forward_amo ? amo_addr_offset : cva6_req_i.address_index;
assign hpdcache_req_o.wdata = forward_amo ? amo_data : cva6_req_i.data_wdata;
assign hpdcache_req_o.op = forward_amo ? amo_op : hpdcache_pkg::HPDCACHE_REQ_STORE;
assign hpdcache_req_o.be = forward_amo ? amo_data_be : cva6_req_i.data_be;
assign hpdcache_req_o.size = forward_amo ? cva6_amo_req_i.size : cva6_req_i.data_size;
assign hpdcache_req_o.sid = hpdcache_req_sid_i;
assign hpdcache_req_o.tid = forward_amo ? '1 : '0;
assign hpdcache_req_o.need_rsp = forward_amo;
assign hpdcache_req_o.phys_indexed = 1'b1;
assign hpdcache_req_o.addr_tag = forward_amo ? amo_tag : cva6_req_i.address_tag;
assign hpdcache_req_o.pma.uncacheable = hpdcache_req_is_uncacheable;
assign hpdcache_req_o.pma.io = 1'b0;
assign hpdcache_req_valid_o = (forward_amo & ~amo_pending_q) | forward_store | forward_flush;
assign hpdcache_req = forward_amo ? hpdcache_req_amo :
forward_store ? hpdcache_req_store : hpdcache_req_flush;
assign hpdcache_req_abort_o = 1'b0; // unused on physically indexed requests
assign hpdcache_req_tag_o = '0; // unused on physically indexed requests
assign hpdcache_req_pma_o = '0; // unused on physically indexed requests
assign hpdcache_req_pma_o.uncacheable = 1'b0;
assign hpdcache_req_pma_o.io = 1'b0;
assign hpdcache_req_pma_o.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
// }}}
// Response forwarding
@ -210,17 +332,21 @@ module cva6_hpdcache_if_adapter
(~cva6_amo_resp_o.ack & amo_pending_q);
end
end
// Assertions
// {{{
// pragma translate_off
forward_one_request_assert :
assert property (@(posedge clk_i) disable iff (rst_ni !== 1'b1) ($onehot0(
{forward_store, forward_amo, forward_flush}
)))
else $error("Only one request shall be forwarded");
// pragma translate_on
// }}}
end
// }}}
endgenerate
// }}}
// Assertions
// {{{
// pragma translate_off
forward_one_request_assert :
assert property (@(posedge clk_i) ($onehot0({forward_store, forward_amo})))
else $error("Only one request shall be forwarded");
// pragma translate_on
assign hpdcache_req_o = hpdcache_req;
// }}}
endmodule

View file

@ -189,46 +189,58 @@ module cva6_hpdcache_subsystem
// NumPorts + 1: Hardware Memory Prefetcher (hwpf)
localparam int HPDCACHE_NREQUESTERS = NumPorts + 2;
localparam hpdcache_pkg::hpdcache_user_cfg_t hpdcacheUserCfg = '{
nRequesters: HPDCACHE_NREQUESTERS,
paWidth: CVA6Cfg.PLEN,
wordWidth: CVA6Cfg.XLEN,
sets: CVA6Cfg.DCACHE_NUM_WORDS,
ways: CVA6Cfg.DCACHE_SET_ASSOC,
clWords: CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.XLEN,
reqWords: 1,
reqTransIdWidth: CVA6Cfg.DcacheIdWidth,
reqSrcIdWidth: 3, // Up to 8 requesters
victimSel: hpdcache_pkg::HPDCACHE_VICTIM_RANDOM,
dataWaysPerRamWord: __minu(CVA6Cfg.DCACHE_SET_ASSOC, 128 / CVA6Cfg.XLEN),
dataSetsPerRam: CVA6Cfg.DCACHE_NUM_WORDS,
dataRamByteEnable: 1'b1,
accessWords: __maxu(CVA6Cfg.DCACHE_LINE_WIDTH / (2 * CVA6Cfg.XLEN), 1),
mshrSets: CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2,
mshrWays: CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2,
mshrWaysPerRamWord: CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2,
mshrSetsPerRam: CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2,
mshrRamByteEnable: 1'b1,
mshrUseRegbank: (CVA6Cfg.NrLoadBufEntries < 16),
refillCoreRspFeedthrough: 1'b1,
refillFifoDepth: 2,
wbufDirEntries: CVA6Cfg.WtDcacheWbufDepth,
wbufDataEntries: CVA6Cfg.WtDcacheWbufDepth,
wbufWords: 1,
wbufTimecntWidth: 3,
wbufSendFeedThrough: 1'b0,
rtabEntries: 4,
memAddrWidth: CVA6Cfg.AxiAddrWidth,
memIdWidth: CVA6Cfg.MEM_TID_WIDTH,
memDataWidth: CVA6Cfg.AxiDataWidth
};
function automatic hpdcache_pkg::hpdcache_user_cfg_t hpdcacheSetConfig();
hpdcache_pkg::hpdcache_user_cfg_t userCfg;
userCfg.nRequesters = HPDCACHE_NREQUESTERS;
userCfg.paWidth = CVA6Cfg.PLEN;
userCfg.wordWidth = CVA6Cfg.XLEN;
userCfg.sets = CVA6Cfg.DCACHE_NUM_WORDS;
userCfg.ways = CVA6Cfg.DCACHE_SET_ASSOC;
userCfg.clWords = CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.XLEN;
userCfg.reqWords = 1;
userCfg.reqTransIdWidth = CVA6Cfg.DcacheIdWidth;
userCfg.reqSrcIdWidth = 3; // Up to 8 requesters
userCfg.victimSel = hpdcache_pkg::HPDCACHE_VICTIM_RANDOM;
userCfg.dataWaysPerRamWord = __minu(CVA6Cfg.DCACHE_SET_ASSOC, 128 / CVA6Cfg.XLEN);
userCfg.dataSetsPerRam = CVA6Cfg.DCACHE_NUM_WORDS;
userCfg.dataRamByteEnable = 1'b1;
userCfg.accessWords = __maxu(CVA6Cfg.AxiDataWidth / CVA6Cfg.XLEN, 1 /*reqWords*/);
userCfg.mshrSets = CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2;
userCfg.mshrWays = CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2;
userCfg.mshrWaysPerRamWord = CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2;
userCfg.mshrSetsPerRam = CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2;
userCfg.mshrRamByteEnable = 1'b1;
userCfg.mshrUseRegbank = (CVA6Cfg.NrLoadBufEntries < 16);
userCfg.refillCoreRspFeedthrough = 1'b1;
userCfg.refillFifoDepth = 2;
userCfg.wbufDirEntries = CVA6Cfg.WtDcacheWbufDepth;
userCfg.wbufDataEntries = CVA6Cfg.WtDcacheWbufDepth;
userCfg.wbufWords = 1;
userCfg.wbufTimecntWidth = 3;
userCfg.rtabEntries = 4;
/*FIXME we should add additional CVA6 config parameters (flushEntries)*/
userCfg.flushEntries = CVA6Cfg.WtDcacheWbufDepth;
/*FIXME we should add additional CVA6 config parameters (flushFifoDepth)*/
userCfg.flushFifoDepth = CVA6Cfg.WtDcacheWbufDepth;
userCfg.memAddrWidth = CVA6Cfg.AxiAddrWidth;
userCfg.memIdWidth = CVA6Cfg.MEM_TID_WIDTH;
userCfg.memDataWidth = CVA6Cfg.AxiDataWidth;
userCfg.wtEn =
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT) ||
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT_WB);
userCfg.wbEn =
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WB) ||
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT_WB);
return userCfg;
endfunction
localparam hpdcache_pkg::hpdcache_cfg_t hpdcacheCfg = hpdcache_pkg::hpdcacheBuildConfig(
hpdcacheUserCfg
localparam hpdcache_pkg::hpdcache_user_cfg_t HPDcacheUserCfg = hpdcacheSetConfig();
localparam hpdcache_pkg::hpdcache_cfg_t HPDcacheCfg = hpdcache_pkg::hpdcacheBuildConfig(
HPDcacheUserCfg
);
`HPDCACHE_TYPEDEF_MEM_ATTR_T(hpdcache_mem_addr_t, hpdcache_mem_id_t, hpdcache_mem_data_t,
hpdcache_mem_be_t, hpdcacheCfg);
hpdcache_mem_be_t, HPDcacheCfg);
`HPDCACHE_TYPEDEF_MEM_REQ_T(hpdcache_mem_req_t, hpdcache_mem_addr_t, hpdcache_mem_id_t);
`HPDCACHE_TYPEDEF_MEM_RESP_R_T(hpdcache_mem_resp_r_t, hpdcache_mem_id_t, hpdcache_mem_data_t);
`HPDCACHE_TYPEDEF_MEM_REQ_W_T(hpdcache_mem_req_w_t, hpdcache_mem_data_t, hpdcache_mem_be_t);
@ -236,379 +248,110 @@ module cva6_hpdcache_subsystem
`HPDCACHE_TYPEDEF_REQ_ATTR_T(hpdcache_req_offset_t, hpdcache_data_word_t, hpdcache_data_be_t,
hpdcache_req_data_t, hpdcache_req_be_t, hpdcache_req_sid_t,
hpdcache_req_tid_t, hpdcache_tag_t, hpdcacheCfg);
hpdcache_req_tid_t, hpdcache_tag_t, HPDcacheCfg);
`HPDCACHE_TYPEDEF_REQ_T(hpdcache_req_t, hpdcache_req_offset_t, hpdcache_req_data_t,
hpdcache_req_be_t, hpdcache_req_sid_t, hpdcache_req_tid_t,
hpdcache_tag_t);
`HPDCACHE_TYPEDEF_RSP_T(hpdcache_rsp_t, hpdcache_req_data_t, hpdcache_req_sid_t,
hpdcache_req_tid_t);
typedef logic [hpdcacheCfg.u.wbufTimecntWidth-1:0] hpdcache_wbuf_timecnt_t;
typedef logic [HPDcacheCfg.u.wbufTimecntWidth-1:0] hpdcache_wbuf_timecnt_t;
typedef logic [63:0] hwpf_stride_param_t;
logic dcache_read_ready;
logic dcache_read_valid;
hpdcache_mem_req_t dcache_read;
logic dcache_req_valid[HPDCACHE_NREQUESTERS-1:0];
logic dcache_req_ready[HPDCACHE_NREQUESTERS-1:0];
hpdcache_req_t dcache_req [HPDCACHE_NREQUESTERS-1:0];
logic dcache_req_abort[HPDCACHE_NREQUESTERS-1:0];
hpdcache_tag_t dcache_req_tag [HPDCACHE_NREQUESTERS-1:0];
hpdcache_pkg::hpdcache_pma_t dcache_req_pma [HPDCACHE_NREQUESTERS-1:0];
logic dcache_rsp_valid[HPDCACHE_NREQUESTERS-1:0];
hpdcache_rsp_t dcache_rsp [HPDCACHE_NREQUESTERS-1:0];
logic dcache_read_miss, dcache_write_miss;
logic dcache_read_resp_ready;
logic dcache_read_resp_valid;
hpdcache_mem_resp_r_t dcache_read_resp;
logic [ 2:0] snoop_valid;
logic [ 2:0] snoop_abort;
hpdcache_req_offset_t [ 2:0] snoop_addr_offset;
hpdcache_tag_t [ 2:0] snoop_addr_tag;
logic [ 2:0] snoop_phys_indexed;
logic dcache_write_ready;
logic dcache_write_valid;
hpdcache_mem_req_t dcache_write;
logic dcache_cmo_req_is_prefetch;
logic dcache_write_data_ready;
logic dcache_write_data_valid;
hpdcache_mem_req_w_t dcache_write_data;
logic dcache_miss_ready;
logic dcache_miss_valid;
hpdcache_mem_req_t dcache_miss;
logic dcache_write_resp_ready;
logic dcache_write_resp_valid;
hpdcache_mem_resp_w_t dcache_write_resp;
logic dcache_miss_resp_ready;
logic dcache_miss_resp_valid;
hpdcache_mem_resp_r_t dcache_miss_resp;
logic dcache_wbuf_ready;
logic dcache_wbuf_valid;
hpdcache_mem_req_t dcache_wbuf;
logic dcache_wbuf_data_ready;
logic dcache_wbuf_data_valid;
hpdcache_mem_req_w_t dcache_wbuf_data;
logic dcache_wbuf_resp_ready;
logic dcache_wbuf_resp_valid;
hpdcache_mem_resp_w_t dcache_wbuf_resp;
logic dcache_uc_read_ready;
logic dcache_uc_read_valid;
hpdcache_mem_req_t dcache_uc_read;
logic dcache_uc_read_resp_ready;
logic dcache_uc_read_resp_valid;
hpdcache_mem_resp_r_t dcache_uc_read_resp;
logic dcache_uc_write_ready;
logic dcache_uc_write_valid;
hpdcache_mem_req_t dcache_uc_write;
logic dcache_uc_write_data_ready;
logic dcache_uc_write_data_valid;
hpdcache_mem_req_w_t dcache_uc_write_data;
logic dcache_uc_write_resp_ready;
logic dcache_uc_write_resp_valid;
hpdcache_mem_resp_w_t dcache_uc_write_resp;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_in;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_out;
generate
dcache_req_i_t dcache_req_ports[HPDCACHE_NREQUESTERS-1:0];
for (genvar r = 0; r < (NumPorts - 1); r++) begin : gen_cva6_hpdcache_load_if_adapter
assign dcache_req_ports[r] = dcache_req_ports_i[r];
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.hpdcacheCfg (hpdcacheCfg),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.is_load_port (1'b1)
) i_cva6_hpdcache_load_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i(hpdcache_req_sid_t'(r)),
.cva6_req_i (dcache_req_ports[r]),
.cva6_req_o (dcache_req_ports_o[r]),
.cva6_amo_req_i ('0),
.cva6_amo_resp_o( /* unused */),
.hpdcache_req_valid_o(dcache_req_valid[r]),
.hpdcache_req_ready_i(dcache_req_ready[r]),
.hpdcache_req_o (dcache_req[r]),
.hpdcache_req_abort_o(dcache_req_abort[r]),
.hpdcache_req_tag_o (dcache_req_tag[r]),
.hpdcache_req_pma_o (dcache_req_pma[r]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[r]),
.hpdcache_rsp_i (dcache_rsp[r])
);
end
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.hpdcacheCfg (hpdcacheCfg),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.is_load_port (1'b0)
) i_cva6_hpdcache_store_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i(hpdcache_req_sid_t'(NumPorts - 1)),
.cva6_req_i (dcache_req_ports_i[NumPorts-1]),
.cva6_req_o (dcache_req_ports_o[NumPorts-1]),
.cva6_amo_req_i (dcache_amo_req_i),
.cva6_amo_resp_o(dcache_amo_resp_o),
.hpdcache_req_valid_o(dcache_req_valid[NumPorts-1]),
.hpdcache_req_ready_i(dcache_req_ready[NumPorts-1]),
.hpdcache_req_o (dcache_req[NumPorts-1]),
.hpdcache_req_abort_o(dcache_req_abort[NumPorts-1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts-1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts-1]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[NumPorts-1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts-1])
);
`ifdef HPDCACHE_ENABLE_CMO
cva6_hpdcache_cmo_if_adapter #(
.cmo_req_t(cmo_req_t),
.cmo_rsp_t(cmo_rsp_t)
) i_cva6_hpdcache_cmo_if_adapter (
.clk_i,
.rst_ni,
.dcache_req_sid_i(hpdcache_req_sid_t'(NumPorts)),
.cva6_cmo_req_i (dcache_cmo_req_i),
.cva6_cmo_resp_o(dcache_cmo_resp_o),
.dcache_req_valid_o(dcache_req_valid[NumPorts]),
.dcache_req_ready_i(dcache_req_ready[NumPorts]),
.dcache_req_o (dcache_req[NumPorts]),
.dcache_req_abort_o(dcache_req_abort[NumPorts]),
.dcache_req_tag_o (dcache_req_tag[NumPorts]),
.dcache_req_pma_o (dcache_req_pma[NumPorts]),
.dcache_rsp_valid_i(dcache_rsp_valid[NumPorts]),
.dcache_rsp_i (dcache_rsp[NumPorts])
);
`else
assign dcache_req_valid[NumPorts] = 1'b0,
dcache_req[NumPorts] = '0,
dcache_req_abort[NumPorts] = 1'b0,
dcache_req_tag[NumPorts] = '0,
dcache_req_pma[NumPorts] = '0;
`endif
endgenerate
// Snoop load port
assign snoop_valid[0] = dcache_req_valid[1] & dcache_req_ready[1],
snoop_abort[0] = dcache_req_abort[1],
snoop_addr_offset[0] = dcache_req[1].addr_offset,
snoop_addr_tag[0] = dcache_req_tag[1],
snoop_phys_indexed[0] = dcache_req[1].phys_indexed;
// Snoop Store/AMO port
assign snoop_valid[1] = dcache_req_valid[NumPorts-1] & dcache_req_ready[NumPorts-1],
snoop_abort[1] = dcache_req_abort[NumPorts-1],
snoop_addr_offset[1] = dcache_req[NumPorts-1].addr_offset,
snoop_addr_tag[1] = dcache_req_tag[NumPorts-1],
snoop_phys_indexed[1] = dcache_req[NumPorts-1].phys_indexed;
`ifdef HPDCACHE_ENABLE_CMO
// Snoop CMO port (in case of read prefetch accesses)
assign dcache_cmo_req_is_prefetch = hpdcache_pkg::is_cmo_prefetch(
dcache_req[NumPorts].op, dcache_req[NumPorts].size
);
assign snoop_valid[2] = dcache_req_valid[NumPorts]
& dcache_req_ready[NumPorts]
& dcache_cmo_req_is_prefetch,
snoop_abort[2] = dcache_req_abort[NumPorts],
snoop_addr_offset[2] = dcache_req[NumPorts].addr_offset,
snoop_addr_tag[2] = dcache_req_tag[NumPorts],
snoop_phys_indexed[2] = dcache_req[NumPorts].phys_indexed;
`else
assign snoop_valid[2] = 1'b0,
snoop_abort[2] = 1'b0,
snoop_addr_offset[2] = '0,
snoop_addr_tag[2] = '0,
snoop_phys_indexed[2] = 1'b0;
`endif
generate
for (genvar h = 0; h < NrHwPrefetchers; h++) begin : gen_hwpf_throttle
assign hwpf_throttle_in[h] = hwpf_stride_pkg::hwpf_stride_throttle_t'(hwpf_throttle_i[h]),
hwpf_throttle_o[h] = hwpf_stride_pkg::hwpf_stride_param_t'(hwpf_throttle_out[h]);
end
endgenerate
hwpf_stride_wrapper #(
.hpdcacheCfg (hpdcacheCfg),
.NUM_HW_PREFETCH (NrHwPrefetchers),
.NUM_SNOOP_PORTS (3),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_data_t (hpdcache_req_data_t),
.hpdcache_req_be_t (hpdcache_req_be_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_tid_t (hpdcache_req_tid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t)
) i_hwpf_stride_wrapper (
.clk_i,
.rst_ni,
.hwpf_stride_base_set_i (hwpf_base_set_i),
.hwpf_stride_base_i (hwpf_base_i),
.hwpf_stride_base_o (hwpf_base_o),
.hwpf_stride_param_set_i (hwpf_param_set_i),
.hwpf_stride_param_i (hwpf_param_i),
.hwpf_stride_param_o (hwpf_param_o),
.hwpf_stride_throttle_set_i(hwpf_throttle_set_i),
.hwpf_stride_throttle_i (hwpf_throttle_in),
.hwpf_stride_throttle_o (hwpf_throttle_out),
.hwpf_stride_status_o (hwpf_status_o),
.snoop_valid_i (snoop_valid),
.snoop_abort_i (snoop_abort),
.snoop_addr_offset_i (snoop_addr_offset),
.snoop_addr_tag_i (snoop_addr_tag),
.snoop_phys_indexed_i(snoop_phys_indexed),
.hpdcache_req_sid_i(hpdcache_req_sid_t'(NumPorts + 1)),
.hpdcache_req_valid_o(dcache_req_valid[NumPorts+1]),
.hpdcache_req_ready_i(dcache_req_ready[NumPorts+1]),
.hpdcache_req_o (dcache_req[NumPorts+1]),
.hpdcache_req_abort_o(dcache_req_abort[NumPorts+1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts+1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts+1]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[NumPorts+1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts+1])
);
hpdcache #(
.hpdcacheCfg (hpdcacheCfg),
.wbuf_timecnt_t (hpdcache_wbuf_timecnt_t),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_data_word_t (hpdcache_data_word_t),
.hpdcache_data_be_t (hpdcache_data_be_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_data_t (hpdcache_req_data_t),
.hpdcache_req_be_t (hpdcache_req_be_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_tid_t (hpdcache_req_tid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.hpdcache_mem_addr_t (hpdcache_mem_addr_t),
.hpdcache_mem_id_t (hpdcache_mem_id_t),
.hpdcache_mem_data_t (hpdcache_mem_data_t),
.hpdcache_mem_be_t (hpdcache_mem_be_t),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t),
cva6_hpdcache_wrapper #(
.CVA6Cfg(CVA6Cfg),
.HPDcacheCfg(HPDcacheCfg),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.NumPorts(NumPorts),
.NrHwPrefetchers(NrHwPrefetchers),
.cmo_req_t(cmo_req_t),
.cmo_rsp_t(cmo_rsp_t),
.hpdcache_mem_addr_t(hpdcache_mem_addr_t),
.hpdcache_mem_id_t(hpdcache_mem_id_t),
.hpdcache_mem_data_t(hpdcache_mem_data_t),
.hpdcache_mem_be_t(hpdcache_mem_be_t),
.hpdcache_mem_req_t(hpdcache_mem_req_t),
.hpdcache_mem_req_w_t(hpdcache_mem_req_w_t),
.hpdcache_mem_resp_r_t(hpdcache_mem_resp_r_t),
.hpdcache_mem_resp_w_t(hpdcache_mem_resp_w_t)
) i_hpdcache (
.clk_i,
.rst_ni,
.hpdcache_mem_resp_w_t(hpdcache_mem_resp_w_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_data_word_t(hpdcache_data_word_t),
.hpdcache_req_data_t(hpdcache_req_data_t),
.hpdcache_req_be_t(hpdcache_req_be_t),
.hpdcache_req_sid_t(hpdcache_req_sid_t),
.hpdcache_req_tid_t(hpdcache_req_tid_t),
.hpdcache_tag_t(hpdcache_tag_t),
.hpdcache_req_t(hpdcache_req_t),
.hpdcache_rsp_t(hpdcache_rsp_t),
.hpdcache_wbuf_timecnt_t(hpdcache_wbuf_timecnt_t),
.hpdcache_data_be_t(hpdcache_data_be_t)
) i_dcache (
.clk_i(clk_i),
.rst_ni(rst_ni),
.dcache_enable_i(dcache_enable_i),
.dcache_flush_i(dcache_flush_i),
.dcache_flush_ack_o(dcache_flush_ack_o),
.dcache_miss_o(dcache_miss_o),
.dcache_amo_req_i(dcache_amo_req_i),
.dcache_amo_resp_o(dcache_amo_resp_o),
.dcache_cmo_req_i(dcache_cmo_req_i),
.dcache_cmo_resp_o(dcache_cmo_resp_o),
.dcache_req_ports_i(dcache_req_ports_i),
.dcache_req_ports_o(dcache_req_ports_o),
.wbuffer_empty_o(wbuffer_empty_o),
.wbuffer_not_ni_o(wbuffer_not_ni_o),
.hwpf_base_set_i(hwpf_base_set_i),
.hwpf_base_i(hwpf_base_i),
.hwpf_base_o(hwpf_base_o),
.hwpf_param_set_i(hwpf_param_set_i),
.hwpf_param_i(hwpf_param_i),
.hwpf_param_o(hwpf_param_o),
.hwpf_throttle_set_i(hwpf_throttle_set_i),
.hwpf_throttle_i(hwpf_throttle_i),
.hwpf_throttle_o(hwpf_throttle_o),
.hwpf_status_o(hwpf_status_o),
.wbuf_flush_i(dcache_flush_i),
.dcache_mem_req_read_ready_i(dcache_read_ready),
.dcache_mem_req_read_valid_o(dcache_read_valid),
.dcache_mem_req_read_o(dcache_read),
.core_req_valid_i(dcache_req_valid),
.core_req_ready_o(dcache_req_ready),
.core_req_i (dcache_req),
.core_req_abort_i(dcache_req_abort),
.core_req_tag_i (dcache_req_tag),
.core_req_pma_i (dcache_req_pma),
.dcache_mem_resp_read_ready_o(dcache_read_resp_ready),
.dcache_mem_resp_read_valid_i(dcache_read_resp_valid),
.dcache_mem_resp_read_i(dcache_read_resp),
.core_rsp_valid_o(dcache_rsp_valid),
.core_rsp_o (dcache_rsp),
.dcache_mem_req_write_ready_i(dcache_write_ready),
.dcache_mem_req_write_valid_o(dcache_write_valid),
.dcache_mem_req_write_o(dcache_write),
.mem_req_miss_read_ready_i(dcache_miss_ready),
.mem_req_miss_read_valid_o(dcache_miss_valid),
.mem_req_miss_read_o (dcache_miss),
.dcache_mem_req_write_data_ready_i(dcache_write_data_ready),
.dcache_mem_req_write_data_valid_o(dcache_write_data_valid),
.dcache_mem_req_write_data_o(dcache_write_data),
.mem_resp_miss_read_ready_o(dcache_miss_resp_ready),
.mem_resp_miss_read_valid_i(dcache_miss_resp_valid),
.mem_resp_miss_read_i (dcache_miss_resp),
.mem_req_wbuf_write_ready_i(dcache_wbuf_ready),
.mem_req_wbuf_write_valid_o(dcache_wbuf_valid),
.mem_req_wbuf_write_o (dcache_wbuf),
.mem_req_wbuf_write_data_ready_i(dcache_wbuf_data_ready),
.mem_req_wbuf_write_data_valid_o(dcache_wbuf_data_valid),
.mem_req_wbuf_write_data_o (dcache_wbuf_data),
.mem_resp_wbuf_write_ready_o(dcache_wbuf_resp_ready),
.mem_resp_wbuf_write_valid_i(dcache_wbuf_resp_valid),
.mem_resp_wbuf_write_i (dcache_wbuf_resp),
.mem_req_uc_read_ready_i(dcache_uc_read_ready),
.mem_req_uc_read_valid_o(dcache_uc_read_valid),
.mem_req_uc_read_o (dcache_uc_read),
.mem_resp_uc_read_ready_o(dcache_uc_read_resp_ready),
.mem_resp_uc_read_valid_i(dcache_uc_read_resp_valid),
.mem_resp_uc_read_i (dcache_uc_read_resp),
.mem_req_uc_write_ready_i(dcache_uc_write_ready),
.mem_req_uc_write_valid_o(dcache_uc_write_valid),
.mem_req_uc_write_o (dcache_uc_write),
.mem_req_uc_write_data_ready_i(dcache_uc_write_data_ready),
.mem_req_uc_write_data_valid_o(dcache_uc_write_data_valid),
.mem_req_uc_write_data_o (dcache_uc_write_data),
.mem_resp_uc_write_ready_o(dcache_uc_write_resp_ready),
.mem_resp_uc_write_valid_i(dcache_uc_write_resp_valid),
.mem_resp_uc_write_i (dcache_uc_write_resp),
.evt_cache_write_miss_o(dcache_write_miss),
.evt_cache_read_miss_o (dcache_read_miss),
.evt_uncached_req_o ( /* unused */),
.evt_cmo_req_o ( /* unused */),
.evt_write_req_o ( /* unused */),
.evt_read_req_o ( /* unused */),
.evt_prefetch_req_o ( /* unused */),
.evt_req_on_hold_o ( /* unused */),
.evt_rtab_rollback_o ( /* unused */),
.evt_stall_refill_o ( /* unused */),
.evt_stall_o ( /* unused */),
.wbuf_empty_o(wbuffer_empty_o),
.cfg_enable_i (dcache_enable_i),
.cfg_wbuf_threshold_i (3'd2),
.cfg_wbuf_reset_timecnt_on_write_i (1'b1),
.cfg_wbuf_sequential_waw_i (1'b0),
.cfg_wbuf_inhibit_write_coalescing_i(1'b0),
.cfg_prefetch_updt_plru_i (1'b1),
.cfg_error_on_cacheable_amo_i (1'b0),
.cfg_rtab_single_entry_i (1'b0)
.dcache_mem_resp_write_ready_o(dcache_write_resp_ready),
.dcache_mem_resp_write_valid_i(dcache_write_resp_valid),
.dcache_mem_resp_write_i(dcache_write_resp)
);
assign dcache_miss_o = dcache_read_miss, wbuffer_not_ni_o = wbuffer_empty_o;
always_ff @(posedge clk_i or negedge rst_ni) begin : dcache_flush_ff
if (!rst_ni) dcache_flush_ack_o <= 1'b0;
else dcache_flush_ack_o <= ~dcache_flush_ack_o & dcache_flush_i;
end
// }}}
// AXI arbiter instantiation
// {{{
cva6_hpdcache_subsystem_axi_arbiter #(
@ -644,47 +387,25 @@ module cva6_hpdcache_subsystem
.icache_miss_resp_valid_o(icache_miss_resp_valid),
.icache_miss_resp_o (icache_miss_resp),
.dcache_miss_ready_o(dcache_miss_ready),
.dcache_miss_valid_i(dcache_miss_valid),
.dcache_miss_i (dcache_miss),
.dcache_read_ready_o(dcache_read_ready),
.dcache_read_valid_i(dcache_read_valid),
.dcache_read_i (dcache_read),
.dcache_miss_resp_ready_i(dcache_miss_resp_ready),
.dcache_miss_resp_valid_o(dcache_miss_resp_valid),
.dcache_miss_resp_o (dcache_miss_resp),
.dcache_read_resp_ready_i(dcache_read_resp_ready),
.dcache_read_resp_valid_o(dcache_read_resp_valid),
.dcache_read_resp_o (dcache_read_resp),
.dcache_wbuf_ready_o(dcache_wbuf_ready),
.dcache_wbuf_valid_i(dcache_wbuf_valid),
.dcache_wbuf_i (dcache_wbuf),
.dcache_write_ready_o(dcache_write_ready),
.dcache_write_valid_i(dcache_write_valid),
.dcache_write_i (dcache_write),
.dcache_wbuf_data_ready_o(dcache_wbuf_data_ready),
.dcache_wbuf_data_valid_i(dcache_wbuf_data_valid),
.dcache_wbuf_data_i (dcache_wbuf_data),
.dcache_write_data_ready_o(dcache_write_data_ready),
.dcache_write_data_valid_i(dcache_write_data_valid),
.dcache_write_data_i (dcache_write_data),
.dcache_wbuf_resp_ready_i(dcache_wbuf_resp_ready),
.dcache_wbuf_resp_valid_o(dcache_wbuf_resp_valid),
.dcache_wbuf_resp_o (dcache_wbuf_resp),
.dcache_uc_read_ready_o(dcache_uc_read_ready),
.dcache_uc_read_valid_i(dcache_uc_read_valid),
.dcache_uc_read_i (dcache_uc_read),
.dcache_uc_read_id_i ('1),
.dcache_uc_read_resp_ready_i(dcache_uc_read_resp_ready),
.dcache_uc_read_resp_valid_o(dcache_uc_read_resp_valid),
.dcache_uc_read_resp_o (dcache_uc_read_resp),
.dcache_uc_write_ready_o(dcache_uc_write_ready),
.dcache_uc_write_valid_i(dcache_uc_write_valid),
.dcache_uc_write_i (dcache_uc_write),
.dcache_uc_write_id_i ('1),
.dcache_uc_write_data_ready_o(dcache_uc_write_data_ready),
.dcache_uc_write_data_valid_i(dcache_uc_write_data_valid),
.dcache_uc_write_data_i (dcache_uc_write_data),
.dcache_uc_write_resp_ready_i(dcache_uc_write_resp_ready),
.dcache_uc_write_resp_valid_o(dcache_uc_write_resp_valid),
.dcache_uc_write_resp_o (dcache_uc_write_resp),
.dcache_write_resp_ready_i(dcache_write_resp_ready),
.dcache_write_resp_valid_o(dcache_write_resp_valid),
.dcache_write_resp_o (dcache_write_resp),
.axi_req_o (noc_req_o),
.axi_resp_i(noc_resp_i)
@ -695,13 +416,13 @@ module cva6_hpdcache_subsystem
// {{{
// pragma translate_off
initial begin : initial_assertions
assert (hpdcacheCfg.u.reqSrcIdWidth >= $clog2(HPDCACHE_NREQUESTERS))
assert (HPDcacheCfg.u.reqSrcIdWidth >= $clog2(HPDcacheCfg.u.nRequesters))
else $fatal(1, "HPDCACHE_REQ_SRC_ID_WIDTH is not wide enough");
assert (CVA6Cfg.MEM_TID_WIDTH <= CVA6Cfg.AxiIdWidth)
else $fatal(1, "MEM_TID_WIDTH shall be less or equal to the AxiIdWidth");
assert (CVA6Cfg.MEM_TID_WIDTH >= ($clog2(hpdcacheCfg.u.mshrSets * hpdcacheCfg.u.mshrWays) + 1))
assert (CVA6Cfg.MEM_TID_WIDTH >= ($clog2(HPDcacheCfg.u.mshrSets * HPDcacheCfg.u.mshrWays) + 1))
else $fatal(1, "MEM_TID_WIDTH shall allow to uniquely identify all D$ and I$ miss requests ");
assert (CVA6Cfg.MEM_TID_WIDTH >= ($clog2(hpdcacheCfg.u.wbufDirEntries) + 1))
assert (CVA6Cfg.MEM_TID_WIDTH >= ($clog2(HPDcacheCfg.u.wbufDirEntries) + 1))
else $fatal(1, "MEM_TID_WIDTH shall allow to uniquely identify all D$ write requests ");
end

View file

@ -58,50 +58,27 @@ module cva6_hpdcache_subsystem_axi_arbiter
// Interfaces from/to D$
// {{{
output logic dcache_miss_ready_o,
input logic dcache_miss_valid_i,
input hpdcache_mem_req_t dcache_miss_i,
// Read interface
output logic dcache_read_ready_o,
input logic dcache_read_valid_i,
input hpdcache_mem_req_t dcache_read_i,
input logic dcache_miss_resp_ready_i,
output logic dcache_miss_resp_valid_o,
output hpdcache_mem_resp_r_t dcache_miss_resp_o,
input logic dcache_read_resp_ready_i,
output logic dcache_read_resp_valid_o,
output hpdcache_mem_resp_r_t dcache_read_resp_o,
// Write-buffer write interface
output logic dcache_wbuf_ready_o,
input logic dcache_wbuf_valid_i,
input hpdcache_mem_req_t dcache_wbuf_i,
// Write interface
output logic dcache_write_ready_o,
input logic dcache_write_valid_i,
input hpdcache_mem_req_t dcache_write_i,
output logic dcache_wbuf_data_ready_o,
input logic dcache_wbuf_data_valid_i,
input hpdcache_mem_req_w_t dcache_wbuf_data_i,
output logic dcache_write_data_ready_o,
input logic dcache_write_data_valid_i,
input hpdcache_mem_req_w_t dcache_write_data_i,
input logic dcache_wbuf_resp_ready_i,
output logic dcache_wbuf_resp_valid_o,
output hpdcache_mem_resp_w_t dcache_wbuf_resp_o,
// Uncached read interface
output logic dcache_uc_read_ready_o,
input logic dcache_uc_read_valid_i,
input hpdcache_mem_req_t dcache_uc_read_i,
input hpdcache_mem_id_t dcache_uc_read_id_i,
input logic dcache_uc_read_resp_ready_i,
output logic dcache_uc_read_resp_valid_o,
output hpdcache_mem_resp_r_t dcache_uc_read_resp_o,
// Uncached write interface
output logic dcache_uc_write_ready_o,
input logic dcache_uc_write_valid_i,
input hpdcache_mem_req_t dcache_uc_write_i,
input hpdcache_mem_id_t dcache_uc_write_id_i,
output logic dcache_uc_write_data_ready_o,
input logic dcache_uc_write_data_valid_i,
input hpdcache_mem_req_w_t dcache_uc_write_data_i,
input logic dcache_uc_write_resp_ready_i,
output logic dcache_uc_write_resp_valid_o,
output hpdcache_mem_resp_w_t dcache_uc_write_resp_o,
input logic dcache_write_resp_ready_i,
output logic dcache_write_resp_valid_o,
output hpdcache_mem_resp_w_t dcache_write_resp_o,
// }}}
// AXI port to upstream memory/peripherals
@ -166,13 +143,13 @@ module cva6_hpdcache_subsystem_axi_arbiter
assign icache_miss_req_w = icache_miss_valid_i, icache_miss_ready_o = icache_miss_req_wok;
assign icache_miss_req_wdata.mem_req_addr = icache_miss_i.paddr,
icache_miss_req_wdata.mem_req_len = icache_miss_i.nc ? 0 : ICACHE_MEM_REQ_CL_LEN - 1,
icache_miss_req_wdata.mem_req_size = icache_miss_i.nc ? ICACHE_WORD_SIZE : ICACHE_MEM_REQ_CL_SIZE,
icache_miss_req_wdata.mem_req_id = icache_miss_i.tid,
icache_miss_req_wdata.mem_req_command = hpdcache_pkg::HPDCACHE_MEM_READ,
icache_miss_req_wdata.mem_req_atomic = hpdcache_pkg::hpdcache_mem_atomic_e'(0),
icache_miss_req_wdata.mem_req_cacheable = ~icache_miss_i.nc;
assign icache_miss_req_wdata.mem_req_addr = icache_miss_i.paddr;
assign icache_miss_req_wdata.mem_req_len = icache_miss_i.nc ? 0 : ICACHE_MEM_REQ_CL_LEN - 1;
assign icache_miss_req_wdata.mem_req_size = icache_miss_i.nc ? ICACHE_WORD_SIZE : ICACHE_MEM_REQ_CL_SIZE;
assign icache_miss_req_wdata.mem_req_id = icache_miss_i.tid;
assign icache_miss_req_wdata.mem_req_command = hpdcache_pkg::HPDCACHE_MEM_READ;
assign icache_miss_req_wdata.mem_req_atomic = hpdcache_pkg::hpdcache_mem_atomic_e'(0);
assign icache_miss_req_wdata.mem_req_cacheable = ~icache_miss_i.nc;
// I$ response
@ -258,12 +235,12 @@ module cva6_hpdcache_subsystem_axi_arbiter
end
endgenerate
assign icache_miss_resp_valid_o = icache_miss_resp_meta_rok,
icache_miss_resp_o.rtype = wt_cache_pkg::ICACHE_IFILL_ACK,
icache_miss_resp_o.user = '0,
icache_miss_resp_o.inv = '0,
icache_miss_resp_o.tid = icache_miss_resp_meta_id,
icache_miss_resp_o.data = icache_miss_rdata;
assign icache_miss_resp_valid_o = icache_miss_resp_meta_rok;
assign icache_miss_resp_o.rtype = wt_cache_pkg::ICACHE_IFILL_ACK;
assign icache_miss_resp_o.user = '0;
assign icache_miss_resp_o.inv = '0;
assign icache_miss_resp_o.tid = icache_miss_resp_meta_id;
assign icache_miss_resp_o.data = icache_miss_rdata;
// consume the Icache miss on the arrival of the response. The request
// metadata is decoded to forward the correct word in case of uncacheable
@ -273,27 +250,23 @@ module cva6_hpdcache_subsystem_axi_arbiter
// Read request arbiter
// {{{
logic mem_req_read_ready [2:0];
logic mem_req_read_valid [2:0];
hpdcache_mem_req_t mem_req_read [2:0];
logic [1:0] mem_req_read_ready;
logic [1:0] mem_req_read_valid;
hpdcache_mem_req_t [1:0] mem_req_read;
logic mem_req_read_ready_arb;
logic mem_req_read_valid_arb;
hpdcache_mem_req_t mem_req_read_arb;
logic mem_req_read_ready_arb;
logic mem_req_read_valid_arb;
hpdcache_mem_req_t mem_req_read_arb;
assign mem_req_read_valid[0] = icache_miss_req_rok & ~icache_miss_pending_q,
mem_req_read[0] = icache_miss_req_rdata;
assign mem_req_read_valid[0] = icache_miss_req_rok & ~icache_miss_pending_q;
assign mem_req_read[0] = icache_miss_req_rdata;
assign dcache_miss_ready_o = mem_req_read_ready[1],
mem_req_read_valid[1] = dcache_miss_valid_i,
mem_req_read[1] = dcache_miss_i;
assign dcache_uc_read_ready_o = mem_req_read_ready[2],
mem_req_read_valid[2] = dcache_uc_read_valid_i,
mem_req_read[2] = dcache_uc_read_i;
assign dcache_read_ready_o = mem_req_read_ready[1];
assign mem_req_read_valid[1] = dcache_read_valid_i;
assign mem_req_read[1] = dcache_read_i;
hpdcache_mem_req_read_arbiter #(
.N (3),
.N (2),
.hpdcache_mem_req_t(hpdcache_mem_req_t)
) i_mem_req_read_arbiter (
.clk_i,
@ -315,21 +288,20 @@ module cva6_hpdcache_subsystem_axi_arbiter
logic mem_resp_read_valid;
hpdcache_mem_resp_r_t mem_resp_read;
logic mem_resp_read_ready_arb[2:0];
logic mem_resp_read_valid_arb[2:0];
hpdcache_mem_resp_r_t mem_resp_read_arb [2:0];
logic mem_resp_read_ready_arb[1:0];
logic mem_resp_read_valid_arb[1:0];
hpdcache_mem_resp_r_t mem_resp_read_arb [1:0];
mem_resp_rt_t mem_resp_read_rt;
always_comb begin
for (int i = 0; i < MEM_RESP_RT_DEPTH; i++) begin
mem_resp_read_rt[i] = (i == int'( icache_miss_id_i)) ? 0 :
(i == int'(dcache_uc_read_id_i)) ? 2 : 1;
mem_resp_read_rt[i] = (i == int'(icache_miss_id_i)) ? 0 : 1;
end
end
hpdcache_mem_resp_demux #(
.N (3),
.N (2),
.resp_t (hpdcache_mem_resp_r_t),
.resp_id_t(hpdcache_mem_id_t)
) i_mem_resp_read_demux (
@ -348,124 +320,13 @@ module cva6_hpdcache_subsystem_axi_arbiter
.mem_resp_rt_i(mem_resp_read_rt)
);
assign icache_miss_resp_w = mem_resp_read_valid_arb[0],
icache_miss_resp_wdata = mem_resp_read_arb[0],
mem_resp_read_ready_arb[0] = icache_miss_resp_wok;
assign icache_miss_resp_w = mem_resp_read_valid_arb[0];
assign icache_miss_resp_wdata = mem_resp_read_arb[0];
assign mem_resp_read_ready_arb[0] = icache_miss_resp_wok;
assign dcache_miss_resp_valid_o = mem_resp_read_valid_arb[1],
dcache_miss_resp_o = mem_resp_read_arb[1],
mem_resp_read_ready_arb[1] = dcache_miss_resp_ready_i;
assign dcache_uc_read_resp_valid_o = mem_resp_read_valid_arb[2],
dcache_uc_read_resp_o = mem_resp_read_arb[2],
mem_resp_read_ready_arb[2] = dcache_uc_read_resp_ready_i;
// }}}
// Write request arbiter
// {{{
logic mem_req_write_ready [1:0];
logic mem_req_write_valid [1:0];
hpdcache_mem_req_t mem_req_write [1:0];
logic mem_req_write_data_ready [1:0];
logic mem_req_write_data_valid [1:0];
hpdcache_mem_req_w_t mem_req_write_data [1:0];
logic mem_req_write_ready_arb;
logic mem_req_write_valid_arb;
hpdcache_mem_req_t mem_req_write_arb;
logic mem_req_write_data_ready_arb;
logic mem_req_write_data_valid_arb;
hpdcache_mem_req_w_t mem_req_write_data_arb;
assign dcache_wbuf_ready_o = mem_req_write_ready[0],
mem_req_write_valid[0] = dcache_wbuf_valid_i,
mem_req_write[0] = dcache_wbuf_i;
assign dcache_wbuf_data_ready_o = mem_req_write_data_ready[0],
mem_req_write_data_valid[0] = dcache_wbuf_data_valid_i,
mem_req_write_data[0] = dcache_wbuf_data_i;
assign dcache_uc_write_ready_o = mem_req_write_ready[1],
mem_req_write_valid[1] = dcache_uc_write_valid_i,
mem_req_write[1] = dcache_uc_write_i;
assign dcache_uc_write_data_ready_o = mem_req_write_data_ready[1],
mem_req_write_data_valid[1] = dcache_uc_write_data_valid_i,
mem_req_write_data[1] = dcache_uc_write_data_i;
hpdcache_mem_req_write_arbiter #(
.N (2),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t(hpdcache_mem_req_w_t)
) i_mem_req_write_arbiter (
.clk_i,
.rst_ni,
.mem_req_write_ready_o(mem_req_write_ready),
.mem_req_write_valid_i(mem_req_write_valid),
.mem_req_write_i (mem_req_write),
.mem_req_write_data_ready_o(mem_req_write_data_ready),
.mem_req_write_data_valid_i(mem_req_write_data_valid),
.mem_req_write_data_i (mem_req_write_data),
.mem_req_write_ready_i(mem_req_write_ready_arb),
.mem_req_write_valid_o(mem_req_write_valid_arb),
.mem_req_write_o (mem_req_write_arb),
.mem_req_write_data_ready_i(mem_req_write_data_ready_arb),
.mem_req_write_data_valid_o(mem_req_write_data_valid_arb),
.mem_req_write_data_o (mem_req_write_data_arb)
);
// }}}
// Write response demultiplexor
// {{{
logic mem_resp_write_ready;
logic mem_resp_write_valid;
hpdcache_mem_resp_w_t mem_resp_write;
logic mem_resp_write_ready_arb[1:0];
logic mem_resp_write_valid_arb[1:0];
hpdcache_mem_resp_w_t mem_resp_write_arb [1:0];
mem_resp_rt_t mem_resp_write_rt;
always_comb begin
for (int i = 0; i < MEM_RESP_RT_DEPTH; i++) begin
mem_resp_write_rt[i] = (i == int'(dcache_uc_write_id_i)) ? 1 : 0;
end
end
hpdcache_mem_resp_demux #(
.N (2),
.resp_t (hpdcache_mem_resp_w_t),
.resp_id_t(hpdcache_mem_id_t)
) i_hpdcache_mem_resp_write_demux (
.clk_i,
.rst_ni,
.mem_resp_ready_o(mem_resp_write_ready),
.mem_resp_valid_i(mem_resp_write_valid),
.mem_resp_id_i (mem_resp_write.mem_resp_w_id),
.mem_resp_i (mem_resp_write),
.mem_resp_ready_i(mem_resp_write_ready_arb),
.mem_resp_valid_o(mem_resp_write_valid_arb),
.mem_resp_o (mem_resp_write_arb),
.mem_resp_rt_i(mem_resp_write_rt)
);
assign dcache_wbuf_resp_valid_o = mem_resp_write_valid_arb[0],
dcache_wbuf_resp_o = mem_resp_write_arb[0],
mem_resp_write_ready_arb[0] = dcache_wbuf_resp_ready_i;
assign dcache_uc_write_resp_valid_o = mem_resp_write_valid_arb[1],
dcache_uc_write_resp_o = mem_resp_write_arb[1],
mem_resp_write_ready_arb[1] = dcache_uc_write_resp_ready_i;
assign dcache_read_resp_valid_o = mem_resp_read_valid_arb[1];
assign dcache_read_resp_o = mem_resp_read_arb[1];
assign mem_resp_read_ready_arb[1] = dcache_read_resp_ready_i;
// }}}
// I$ miss pending
@ -491,17 +352,17 @@ module cva6_hpdcache_subsystem_axi_arbiter
.w_chan_t (axi_w_chan_t),
.b_chan_t (axi_b_chan_t)
) i_hpdcache_mem_to_axi_write (
.req_ready_o(mem_req_write_ready_arb),
.req_valid_i(mem_req_write_valid_arb),
.req_i (mem_req_write_arb),
.req_ready_o(dcache_write_ready_o),
.req_valid_i(dcache_write_valid_i),
.req_i (dcache_write_i),
.req_data_ready_o(mem_req_write_data_ready_arb),
.req_data_valid_i(mem_req_write_data_valid_arb),
.req_data_i (mem_req_write_data_arb),
.req_data_ready_o(dcache_write_data_ready_o),
.req_data_valid_i(dcache_write_data_valid_i),
.req_data_i (dcache_write_data_i),
.resp_ready_i(mem_resp_write_ready),
.resp_valid_o(mem_resp_write_valid),
.resp_o (mem_resp_write),
.resp_ready_i(dcache_write_resp_ready_i),
.resp_valid_o(dcache_write_resp_valid_o),
.resp_o (dcache_write_resp_o),
.axi_aw_valid_o(axi_req_o.aw_valid),
.axi_aw_o (axi_req_o.aw),
@ -546,13 +407,13 @@ module cva6_hpdcache_subsystem_axi_arbiter
// pragma translate_off
initial
assert (CVA6Cfg.MEM_TID_WIDTH <= AxiIdWidth)
else $fatal("MEM_TID_WIDTH shall be less or equal to AxiIdWidth");
else $fatal(1, "MEM_TID_WIDTH shall be less or equal to AxiIdWidth");
initial
assert (CVA6Cfg.AxiDataWidth <= CVA6Cfg.ICACHE_LINE_WIDTH)
else $fatal("AxiDataWidth shall be less or equal to the width of a Icache line");
else $fatal(1, "AxiDataWidth shall be less or equal to the width of a Icache line");
initial
assert (CVA6Cfg.AxiDataWidth <= CVA6Cfg.DCACHE_LINE_WIDTH)
else $fatal("AxiDataWidth shall be less or equal to the width of a Dcache line");
else $fatal(1, "AxiDataWidth shall be less or equal to the width of a Dcache line");
// pragma translate_on
// }}}

View file

@ -0,0 +1,426 @@
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Authors: Cesar Fuguet
// Date: February, 2023
// Description: Wrapper for the Core-V High-Performance L1 data cache (CV-HPDcache)
`include "hpdcache_typedef.svh"
module cva6_hpdcache_wrapper
// Parameters
// {{{
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter hpdcache_pkg::hpdcache_cfg_t HPDcacheCfg = '0,
parameter type dcache_req_i_t = logic,
parameter type dcache_req_o_t = logic,
parameter int NumPorts = 4,
parameter int NrHwPrefetchers = 4,
parameter type cmo_req_t = logic,
parameter type cmo_rsp_t = logic,
parameter type hpdcache_mem_addr_t = logic,
parameter type hpdcache_mem_id_t = logic,
parameter type hpdcache_mem_data_t = logic,
parameter type hpdcache_mem_be_t = logic,
parameter type hpdcache_mem_req_t = logic,
parameter type hpdcache_mem_req_w_t = logic,
parameter type hpdcache_mem_resp_r_t = logic,
parameter type hpdcache_mem_resp_w_t = logic,
parameter type hpdcache_req_offset_t = logic,
parameter type hpdcache_data_word_t = logic,
parameter type hpdcache_req_data_t = logic,
parameter type hpdcache_req_be_t = logic,
parameter type hpdcache_req_sid_t = logic,
parameter type hpdcache_req_tid_t = logic,
parameter type hpdcache_tag_t = logic,
parameter type hpdcache_req_t = logic,
parameter type hpdcache_rsp_t = logic,
parameter type hpdcache_wbuf_timecnt_t = logic,
parameter type hpdcache_data_be_t = logic
)
// }}}
// Ports
// {{{
(
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
// D$
// {{{
// Cache management
// Data cache enable - CSR_REGFILE
input logic dcache_enable_i,
// Data cache flush - CONTROLLER
input logic dcache_flush_i,
// Flush acknowledge - CONTROLLER
output logic dcache_flush_ack_o,
// Load or store miss - PERF_COUNTERS
output logic dcache_miss_o,
// AMO request/response - EX_STAGE
input ariane_pkg::amo_req_t dcache_amo_req_i,
output ariane_pkg::amo_resp_t dcache_amo_resp_o,
// CMO interface request/response
input cmo_req_t dcache_cmo_req_i,
output cmo_rsp_t dcache_cmo_resp_o,
// Data cache input request/response ports - EX_STAGE
input dcache_req_i_t [NumPorts-1:0] dcache_req_ports_i,
output dcache_req_o_t [NumPorts-1:0] dcache_req_ports_o,
// Write buffer status - EX_STAGE
output logic wbuffer_empty_o,
output logic wbuffer_not_ni_o,
// Hardware memory prefetcher configuration
input logic [NrHwPrefetchers-1:0] hwpf_base_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_base_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_base_o,
input logic [NrHwPrefetchers-1:0] hwpf_param_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_param_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_param_o,
input logic [NrHwPrefetchers-1:0] hwpf_throttle_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_throttle_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_throttle_o,
output logic [ 63:0] hwpf_status_o,
input logic dcache_mem_req_read_ready_i,
output logic dcache_mem_req_read_valid_o,
output hpdcache_mem_req_t dcache_mem_req_read_o,
output logic dcache_mem_resp_read_ready_o,
input logic dcache_mem_resp_read_valid_i,
input hpdcache_mem_resp_r_t dcache_mem_resp_read_i,
input logic dcache_mem_req_write_ready_i,
output logic dcache_mem_req_write_valid_o,
output hpdcache_mem_req_t dcache_mem_req_write_o,
input logic dcache_mem_req_write_data_ready_i,
output logic dcache_mem_req_write_data_valid_o,
output hpdcache_mem_req_w_t dcache_mem_req_write_data_o,
output logic dcache_mem_resp_write_ready_o,
input logic dcache_mem_resp_write_valid_i,
input hpdcache_mem_resp_w_t dcache_mem_resp_write_i
);
localparam int HPDCACHE_NREQUESTERS = NumPorts + 2;
typedef logic [63:0] hwpf_stride_param_t;
logic dcache_req_valid[HPDCACHE_NREQUESTERS];
logic dcache_req_ready[HPDCACHE_NREQUESTERS];
hpdcache_req_t dcache_req [HPDCACHE_NREQUESTERS];
logic dcache_req_abort[HPDCACHE_NREQUESTERS];
hpdcache_tag_t dcache_req_tag [HPDCACHE_NREQUESTERS];
hpdcache_pkg::hpdcache_pma_t dcache_req_pma [HPDCACHE_NREQUESTERS];
logic dcache_rsp_valid[HPDCACHE_NREQUESTERS];
hpdcache_rsp_t dcache_rsp [HPDCACHE_NREQUESTERS];
logic dcache_read_miss, dcache_write_miss;
logic [ 2:0] snoop_valid;
logic [ 2:0] snoop_abort;
hpdcache_req_offset_t [ 2:0] snoop_addr_offset;
hpdcache_tag_t [ 2:0] snoop_addr_tag;
logic [ 2:0] snoop_phys_indexed;
logic dcache_cmo_req_is_prefetch;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_in;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_out;
generate
dcache_req_i_t dcache_req_ports[NumPorts - 1];
for (genvar r = 0; r < (NumPorts - 1); r++) begin : gen_cva6_hpdcache_load_if_adapter
assign dcache_req_ports[r] = dcache_req_ports_i[r];
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.HPDcacheCfg (HPDcacheCfg),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.InvalidateOnFlush (1'b0),
.IsLoadPort (1'b1)
) i_cva6_hpdcache_load_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i(hpdcache_req_sid_t'(r)),
.cva6_req_i (dcache_req_ports[r]),
.cva6_req_o (dcache_req_ports_o[r]),
.cva6_amo_req_i ('0),
.cva6_amo_resp_o( /* unused */),
.cva6_dcache_flush_i (1'b0),
.cva6_dcache_flush_ack_o( /* unused */),
.hpdcache_req_valid_o(dcache_req_valid[r]),
.hpdcache_req_ready_i(dcache_req_ready[r]),
.hpdcache_req_o (dcache_req[r]),
.hpdcache_req_abort_o(dcache_req_abort[r]),
.hpdcache_req_tag_o (dcache_req_tag[r]),
.hpdcache_req_pma_o (dcache_req_pma[r]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[r]),
.hpdcache_rsp_i (dcache_rsp[r])
);
end
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.HPDcacheCfg (HPDcacheCfg),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.InvalidateOnFlush (CVA6Cfg.DcacheInvalidateOnFlush),
.IsLoadPort (1'b0)
) i_cva6_hpdcache_store_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i(hpdcache_req_sid_t'(NumPorts - 1)),
.cva6_req_i (dcache_req_ports_i[NumPorts-1]),
.cva6_req_o (dcache_req_ports_o[NumPorts-1]),
.cva6_amo_req_i (dcache_amo_req_i),
.cva6_amo_resp_o(dcache_amo_resp_o),
.cva6_dcache_flush_i (dcache_flush_i),
.cva6_dcache_flush_ack_o(dcache_flush_ack_o),
.hpdcache_req_valid_o(dcache_req_valid[NumPorts-1]),
.hpdcache_req_ready_i(dcache_req_ready[NumPorts-1]),
.hpdcache_req_o (dcache_req[NumPorts-1]),
.hpdcache_req_abort_o(dcache_req_abort[NumPorts-1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts-1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts-1]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[NumPorts-1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts-1])
);
`ifdef HPDCACHE_ENABLE_CMO
cva6_hpdcache_cmo_if_adapter #(
.cmo_req_t(cmo_req_t),
.cmo_rsp_t(cmo_rsp_t)
) i_cva6_hpdcache_cmo_if_adapter (
.clk_i,
.rst_ni,
.dcache_req_sid_i(hpdcache_req_sid_t'(NumPorts)),
.cva6_cmo_req_i (dcache_cmo_req_i),
.cva6_cmo_resp_o(dcache_cmo_resp_o),
.dcache_req_valid_o(dcache_req_valid[NumPorts]),
.dcache_req_ready_i(dcache_req_ready[NumPorts]),
.dcache_req_o (dcache_req[NumPorts]),
.dcache_req_abort_o(dcache_req_abort[NumPorts]),
.dcache_req_tag_o (dcache_req_tag[NumPorts]),
.dcache_req_pma_o (dcache_req_pma[NumPorts]),
.dcache_rsp_valid_i(dcache_rsp_valid[NumPorts]),
.dcache_rsp_i (dcache_rsp[NumPorts])
);
`else
assign dcache_req_valid[NumPorts] = 1'b0,
dcache_req[NumPorts] = '0,
dcache_req_abort[NumPorts] = 1'b0,
dcache_req_tag[NumPorts] = '0,
dcache_req_pma[NumPorts] = '0;
`endif
endgenerate
// Snoop load port
assign snoop_valid[0] = dcache_req_valid[1] & dcache_req_ready[1],
snoop_abort[0] = dcache_req_abort[1],
snoop_addr_offset[0] = dcache_req[1].addr_offset,
snoop_addr_tag[0] = dcache_req_tag[1],
snoop_phys_indexed[0] = dcache_req[1].phys_indexed;
// Snoop Store/AMO port
assign snoop_valid[1] = dcache_req_valid[NumPorts-1] & dcache_req_ready[NumPorts-1],
snoop_abort[1] = dcache_req_abort[NumPorts-1],
snoop_addr_offset[1] = dcache_req[NumPorts-1].addr_offset,
snoop_addr_tag[1] = dcache_req_tag[NumPorts-1],
snoop_phys_indexed[1] = dcache_req[NumPorts-1].phys_indexed;
`ifdef HPDCACHE_ENABLE_CMO
// Snoop CMO port (in case of read prefetch accesses)
assign dcache_cmo_req_is_prefetch = hpdcache_pkg::is_cmo_prefetch(
dcache_req[NumPorts].op, dcache_req[NumPorts].size
);
assign snoop_valid[2] = dcache_req_valid[NumPorts]
& dcache_req_ready[NumPorts]
& dcache_cmo_req_is_prefetch,
snoop_abort[2] = dcache_req_abort[NumPorts],
snoop_addr_offset[2] = dcache_req[NumPorts].addr_offset,
snoop_addr_tag[2] = dcache_req_tag[NumPorts],
snoop_phys_indexed[2] = dcache_req[NumPorts].phys_indexed;
`else
assign snoop_valid[2] = 1'b0,
snoop_abort[2] = 1'b0,
snoop_addr_offset[2] = '0,
snoop_addr_tag[2] = '0,
snoop_phys_indexed[2] = 1'b0;
`endif
generate
for (genvar h = 0; h < NrHwPrefetchers; h++) begin : gen_hwpf_throttle
assign hwpf_throttle_in[h] = hwpf_stride_pkg::hwpf_stride_throttle_t'(hwpf_throttle_i[h]);
assign hwpf_throttle_o[h] = hwpf_stride_pkg::hwpf_stride_param_t'(hwpf_throttle_out[h]);
end
endgenerate
hwpf_stride_wrapper #(
.HPDcacheCfg (HPDcacheCfg),
.NUM_HW_PREFETCH (NrHwPrefetchers),
.NUM_SNOOP_PORTS (3),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_data_t (hpdcache_req_data_t),
.hpdcache_req_be_t (hpdcache_req_be_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_tid_t (hpdcache_req_tid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t)
) i_hwpf_stride_wrapper (
.clk_i,
.rst_ni,
.hwpf_stride_base_set_i (hwpf_base_set_i),
.hwpf_stride_base_i (hwpf_base_i),
.hwpf_stride_base_o (hwpf_base_o),
.hwpf_stride_param_set_i (hwpf_param_set_i),
.hwpf_stride_param_i (hwpf_param_i),
.hwpf_stride_param_o (hwpf_param_o),
.hwpf_stride_throttle_set_i(hwpf_throttle_set_i),
.hwpf_stride_throttle_i (hwpf_throttle_in),
.hwpf_stride_throttle_o (hwpf_throttle_out),
.hwpf_stride_status_o (hwpf_status_o),
.snoop_valid_i (snoop_valid),
.snoop_abort_i (snoop_abort),
.snoop_addr_offset_i (snoop_addr_offset),
.snoop_addr_tag_i (snoop_addr_tag),
.snoop_phys_indexed_i(snoop_phys_indexed),
.hpdcache_req_sid_i(hpdcache_req_sid_t'(NumPorts + 1)),
.hpdcache_req_valid_o(dcache_req_valid[NumPorts+1]),
.hpdcache_req_ready_i(dcache_req_ready[NumPorts+1]),
.hpdcache_req_o (dcache_req[NumPorts+1]),
.hpdcache_req_abort_o(dcache_req_abort[NumPorts+1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts+1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts+1]),
.hpdcache_rsp_valid_i(dcache_rsp_valid[NumPorts+1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts+1])
);
hpdcache #(
.HPDcacheCfg (HPDcacheCfg),
.wbuf_timecnt_t (hpdcache_wbuf_timecnt_t),
.hpdcache_tag_t (hpdcache_tag_t),
.hpdcache_data_word_t (hpdcache_data_word_t),
.hpdcache_data_be_t (hpdcache_data_be_t),
.hpdcache_req_offset_t(hpdcache_req_offset_t),
.hpdcache_req_data_t (hpdcache_req_data_t),
.hpdcache_req_be_t (hpdcache_req_be_t),
.hpdcache_req_sid_t (hpdcache_req_sid_t),
.hpdcache_req_tid_t (hpdcache_req_tid_t),
.hpdcache_req_t (hpdcache_req_t),
.hpdcache_rsp_t (hpdcache_rsp_t),
.hpdcache_mem_addr_t (hpdcache_mem_addr_t),
.hpdcache_mem_id_t (hpdcache_mem_id_t),
.hpdcache_mem_data_t (hpdcache_mem_data_t),
.hpdcache_mem_be_t (hpdcache_mem_be_t),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t),
.hpdcache_mem_resp_r_t(hpdcache_mem_resp_r_t),
.hpdcache_mem_resp_w_t(hpdcache_mem_resp_w_t)
) i_hpdcache (
.clk_i,
.rst_ni,
.wbuf_flush_i(dcache_flush_i),
.core_req_valid_i(dcache_req_valid),
.core_req_ready_o(dcache_req_ready),
.core_req_i (dcache_req),
.core_req_abort_i(dcache_req_abort),
.core_req_tag_i (dcache_req_tag),
.core_req_pma_i (dcache_req_pma),
.core_rsp_valid_o(dcache_rsp_valid),
.core_rsp_o (dcache_rsp),
.mem_req_read_ready_i(dcache_mem_req_read_ready_i),
.mem_req_read_valid_o(dcache_mem_req_read_valid_o),
.mem_req_read_o (dcache_mem_req_read_o),
.mem_resp_read_ready_o(dcache_mem_resp_read_ready_o),
.mem_resp_read_valid_i(dcache_mem_resp_read_valid_i),
.mem_resp_read_i (dcache_mem_resp_read_i),
.mem_req_write_ready_i(dcache_mem_req_write_ready_i),
.mem_req_write_valid_o(dcache_mem_req_write_valid_o),
.mem_req_write_o (dcache_mem_req_write_o),
.mem_req_write_data_ready_i(dcache_mem_req_write_data_ready_i),
.mem_req_write_data_valid_o(dcache_mem_req_write_data_valid_o),
.mem_req_write_data_o (dcache_mem_req_write_data_o),
.mem_resp_write_ready_o(dcache_mem_resp_write_ready_o),
.mem_resp_write_valid_i(dcache_mem_resp_write_valid_i),
.mem_resp_write_i (dcache_mem_resp_write_i),
.evt_cache_write_miss_o(dcache_write_miss),
.evt_cache_read_miss_o (dcache_read_miss),
.evt_uncached_req_o ( /* unused */),
.evt_cmo_req_o ( /* unused */),
.evt_write_req_o ( /* unused */),
.evt_read_req_o ( /* unused */),
.evt_prefetch_req_o ( /* unused */),
.evt_req_on_hold_o ( /* unused */),
.evt_rtab_rollback_o ( /* unused */),
.evt_stall_refill_o ( /* unused */),
.evt_stall_o ( /* unused */),
.wbuf_empty_o(wbuffer_empty_o),
.cfg_enable_i (dcache_enable_i),
.cfg_wbuf_threshold_i (3'd2),
.cfg_wbuf_reset_timecnt_on_write_i (1'b1),
.cfg_wbuf_sequential_waw_i (1'b0),
.cfg_wbuf_inhibit_write_coalescing_i(1'b0),
.cfg_prefetch_updt_plru_i (1'b1),
.cfg_error_on_cacheable_amo_i (1'b0),
.cfg_rtab_single_entry_i (1'b0),
.cfg_default_wb_i (1'b0)
);
assign dcache_miss_o = dcache_read_miss, wbuffer_not_ni_o = wbuffer_empty_o;
// }}}
endmodule : cva6_hpdcache_wrapper

View file

@ -424,9 +424,9 @@ module cva6_icache
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] hit_idx;
for (genvar i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
assign cl_hit[i] = (cl_tag_rdata[i] == cl_tag_d) & vld_rdata[i];
assign cl_sel[i] = cl_rdata[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
assign cl_user[i] = cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
assign cl_hit[i] = (cl_tag_rdata[i] == cl_tag_d) & vld_rdata[i];
assign cl_sel[i] = cl_rdata[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
assign cl_user[i] = CVA6Cfg.FETCH_USER_EN ? cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH] : '0;
end
@ -441,10 +441,10 @@ module cva6_icache
always_comb begin
if (cmp_en_q) begin
dreq_o.data = cl_sel[hit_idx];
dreq_o.user = cl_user[hit_idx];
dreq_o.user = CVA6Cfg.FETCH_USER_EN ? cl_user[hit_idx] : '0;
end else begin
dreq_o.data = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
dreq_o.user = mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
dreq_o.user = CVA6Cfg.FETCH_USER_EN ? mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH] : '0;
end
end

@ -1 +1 @@
Subproject commit 32407cb8f69b71824083abd72b2d4e8bcd0c2f01
Subproject commit 04de80896981527c34fbbd35d7b1ef787a082d7c

View file

@ -135,6 +135,8 @@ module std_cache_subsystem
logic [1:0] w_select, w_select_fifo, w_select_arbiter;
logic [1:0] w_fifo_usage;
logic w_fifo_empty, w_fifo_full;
logic w_fifo_push, w_fifo_pop;
logic aw_lock_q, aw_lock_d;
// AR Channel
@ -191,17 +193,26 @@ module std_cache_subsystem
.flush_i (1'b0),
.testmode_i(1'b0),
.full_o (w_fifo_full),
.empty_o (), // leave open
.empty_o (), // leave open
.usage_o (w_fifo_usage),
.data_i (w_select),
// a new transaction was requested and granted
.push_i (axi_req_o.aw_valid & axi_resp_i.aw_ready),
.push_i (w_fifo_push),
// write ID to select the output MUX
.data_o (w_select_fifo),
// transaction has finished
.pop_i (axi_req_o.w_valid & axi_resp_i.w_ready & axi_req_o.w.last)
.pop_i (w_fifo_pop)
);
always_ff @(posedge clk_i or negedge rst_ni) begin : aw_lock_reg
if (~rst_ni) aw_lock_q <= 1'b0;
else aw_lock_q <= aw_lock_d;
end
assign w_fifo_push = ~aw_lock_q & axi_req_o.aw_valid;
assign w_fifo_pop = axi_req_o.w_valid & axi_resp_i.w_ready & axi_req_o.w.last;
assign aw_lock_d = ~axi_resp_i.aw_ready & (axi_req_o.aw_valid | aw_lock_q);
// In fall-through mode, the empty_o will be low when push_i is high (on zero usage).
// We do not want this here. Also, usage_o is missing the MSB, so on full fifo, usage_o is zero.
assign w_fifo_empty = w_fifo_usage == 0 && !w_fifo_full;

View file

@ -81,18 +81,19 @@ module tag_cmp #(
if (req_i[i]) break;
end
end
`ifndef SYNTHESIS
`ifndef VERILATOR
// assert that cache only hits on one way
// this only needs to be checked one cycle after all ways have been requested
onehot :
assert property (@(posedge clk_i) disable iff (!rst_ni) &req_i |=> $onehot0(hit_way_o))
else begin
$fatal(1, "Hit should be one-hot encoded");
end
`endif
`endif
// assert that cache only hits on one way
// this only needs to be checked one cycle after all ways have been requested
onehot :
assert property (@(posedge clk_i) disable iff (!rst_ni) &req_i |=> $onehot0(hit_way_o))
else begin
$fatal(1, "Hit should be one-hot encoded");
end
`endif
`endif
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin

View file

@ -64,6 +64,7 @@ module wt_axi_adapter
localparam MaxNumWords = $clog2(CVA6Cfg.AxiDataWidth / 8);
localparam AxiRdBlenIcache = CVA6Cfg.ICACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
localparam AxiRdBlenDcache = CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
localparam AxiBlenWidth = AxiNumWords > 1 ? $clog2(AxiNumWords) : AxiNumWords;
///////////////////////////////////////////////////////
// request path
@ -82,7 +83,7 @@ module wt_axi_adapter
logic axi_wr_valid, axi_rd_valid, axi_rd_rdy, axi_wr_rdy;
logic axi_rd_lock, axi_wr_lock, axi_rd_exokay, axi_wr_exokay, wr_exokay;
logic [CVA6Cfg.AxiAddrWidth-1:0] axi_rd_addr, axi_wr_addr;
logic [$clog2(AxiNumWords)-1:0] axi_rd_blen, axi_wr_blen;
logic [AxiBlenWidth-1:0] axi_rd_blen, axi_wr_blen;
logic [2:0] axi_rd_size, axi_wr_size;
logic [CVA6Cfg.AxiIdWidth-1:0]
axi_rd_id_in, axi_wr_id_in, axi_rd_id_out, axi_wr_id_out, wr_id_out;
@ -141,7 +142,7 @@ module wt_axi_adapter
axi_wr_data[0] = {(CVA6Cfg.AxiDataWidth/CVA6Cfg.XLEN){dcache_data.data}};
axi_wr_user[0] = dcache_data.user;
// Cast to AXI address width
axi_wr_addr = {{CVA6Cfg.AxiAddrWidth-CVA6Cfg.PLEN{1'b0}}, dcache_data.paddr};
axi_wr_addr = CVA6Cfg.AxiAddrWidth'(dcache_data.paddr);
axi_wr_size = dcache_data.size;
axi_wr_req = 1'b0;
axi_wr_blen = '0;// single word writes
@ -166,18 +167,18 @@ module wt_axi_adapter
// arbiter mux
if (arb_idx) begin
// Cast to AXI address width
axi_rd_addr = {{CVA6Cfg.AxiAddrWidth - CVA6Cfg.PLEN{1'b0}}, dcache_data.paddr};
axi_rd_addr = CVA6Cfg.AxiAddrWidth'(dcache_data.paddr);
// If dcache_data.size MSB is set, we want to read as much as possible
axi_rd_size = dcache_data.size[2] ? MaxNumWords[2:0] : dcache_data.size;
if (dcache_data.size[2]) begin
axi_rd_blen = AxiRdBlenDcache[$clog2(AxiNumWords)-1:0];
axi_rd_blen = AxiRdBlenDcache[AxiBlenWidth-1:0];
end
end else begin
// Cast to AXI address width
axi_rd_addr = {{CVA6Cfg.AxiAddrWidth - CVA6Cfg.PLEN{1'b0}}, icache_data.paddr};
axi_rd_addr = CVA6Cfg.AxiAddrWidth'(icache_data.paddr);
axi_rd_size = MaxNumWords[2:0]; // always request max number of words in case of ifill
if (!icache_data.nc) begin
axi_rd_blen = AxiRdBlenIcache[$clog2(AxiNumWords)-1:0];
axi_rd_blen = AxiRdBlenIcache[AxiBlenWidth-1:0];
end
end
@ -311,8 +312,9 @@ module wt_axi_adapter
end
cva6_fifo_v3 #(
.dtype (icache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_ALTERA(CVA6Cfg.FpgaAlteraEn),
.dtype(icache_req_t),
.DEPTH(ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FpgaEn)
) i_icache_data_fifo (
.clk_i (clk_i),
@ -329,8 +331,9 @@ module wt_axi_adapter
);
cva6_fifo_v3 #(
.dtype (dcache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_ALTERA(CVA6Cfg.FpgaAlteraEn),
.dtype(dcache_req_t),
.DEPTH(ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FpgaEn)
) i_dcache_data_fifo (
.clk_i (clk_i),

View file

@ -188,10 +188,10 @@ module wt_dcache
// read controllers (LD unit and PTW/MMU)
///////////////////////////////////////////////////////
// 0 is used by MMU, 1 by READ access requests
// 0 is used by MMU or implicit read by zcmt, 1 by READ access requests
for (genvar k = 0; k < NumPorts - 1; k++) begin : gen_rd_ports
// set these to high prio ports
if ((k == 0 && CVA6Cfg.MmuPresent) || (k == 1) || (k == 2 && CVA6Cfg.EnableAccelerator)) begin
if ((k == 0 && (CVA6Cfg.MmuPresent || CVA6Cfg.RVZCMT )) || (k == 1) || (k == 2 && CVA6Cfg.EnableAccelerator)) begin
assign rd_prio[k] = 1'b1;
wt_dcache_ctrl #(
.CVA6Cfg(CVA6Cfg),

View file

@ -199,7 +199,7 @@ module wt_dcache_missunit
// generate random cacheline index
lfsr #(
.LfsrWidth(8),
.OutWidth ($clog2(CVA6Cfg.DCACHE_SET_ASSOC))
.OutWidth (CVA6Cfg.DCACHE_SET_ASSOC_WIDTH)
) i_lfsr_inv (
.clk_i (clk_i),
.rst_ni(rst_ni),

View file

@ -594,8 +594,6 @@ module wt_dcache_wbuffer
wbuffer_d[wr_ptr].data[k*8+:8] = req_port_i.data_wdata[k*8+:8];
if (CVA6Cfg.DATA_USER_EN) begin
wbuffer_d[wr_ptr].user[k*8+:8] = req_port_i.data_wuser[k*8+:8];
end else begin
wbuffer_d[wr_ptr].user[k*8+:8] = '0;
end
end
end

View file

@ -303,8 +303,12 @@ module wt_l15_adapter
always_comb begin : p_rtrn_logic
icache_rtrn_o.rtype = ICACHE_IFILL_ACK;
dcache_rtrn_o.rtype = DCACHE_LOAD_ACK;
icache_rtrn_vld_o = 1'b0;
dcache_rtrn_vld_o = 1'b0;
icache_rtrn_vld_o = 1'b0;
dcache_rtrn_vld_o = 1'b0;
icache_rtrn_o.inv.vld = rtrn_fifo_data.l15_inval_icache_inval;
icache_rtrn_o.inv.all = rtrn_fifo_data.l15_inval_icache_all_way;
dcache_rtrn_o.inv.vld = rtrn_fifo_data.l15_inval_dcache_inval;
dcache_rtrn_o.inv.all = rtrn_fifo_data.l15_inval_dcache_all_way;
if (!rtrn_fifo_empty) begin
unique case (rtrn_fifo_data.l15_returntype)
L15_LOAD_RET: begin
@ -370,13 +374,9 @@ module wt_l15_adapter
// invalidation signal mapping
assign icache_rtrn_o.inv.idx = {rtrn_fifo_data.l15_inval_address_15_4, 4'b0000};
assign icache_rtrn_o.inv.way = rtrn_fifo_data.l15_inval_way;
assign icache_rtrn_o.inv.vld = rtrn_fifo_data.l15_inval_icache_inval;
assign icache_rtrn_o.inv.all = rtrn_fifo_data.l15_inval_icache_all_way;
assign dcache_rtrn_o.inv.idx = {rtrn_fifo_data.l15_inval_address_15_4, 4'b0000};
assign dcache_rtrn_o.inv.way = rtrn_fifo_data.l15_inval_way;
assign dcache_rtrn_o.inv.vld = rtrn_fifo_data.l15_inval_dcache_inval;
assign dcache_rtrn_o.inv.all = rtrn_fifo_data.l15_inval_dcache_all_way;
fifo_v2 #(
.dtype(l15_rtrn_t),

View file

@ -36,6 +36,8 @@ module commit_stage
input logic single_step_i,
// The instruction we want to commit - ISSUE_STAGE
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_i,
// The instruction is cancelled - ISSUE_STAGE
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_drop_i,
// Acknowledge that we are indeed committing - ISSUE_STAGE
output logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack_o,
// Acknowledge that we are indeed committing - CSR_REGFILE
@ -58,10 +60,10 @@ module commit_stage
output logic [CVA6Cfg.XLEN-1:0] csr_wdata_o,
// Data to read from CSR - CSR_REGFILE
input logic [CVA6Cfg.XLEN-1:0] csr_rdata_i,
// Exception or interrupt occurred in CSR stage (the same as commit) - CSR_REGFILE
input exception_t csr_exception_i,
// Write the fflags CSR - CSR_REGFILE
output logic csr_write_fflags_o,
// Exception or interrupt occurred in CSR stage (the same as commit) - CSR_REGFILE
input exception_t csr_exception_i,
// Commit the pending store - EX_STAGE
output logic commit_lsu_o,
// Commit buffer of LSU is ready - EX_STAGE
@ -82,7 +84,9 @@ module commit_stage
output logic flush_commit_o,
// Flush TLBs and pipeline - CONTROLLER
output logic sfence_vma_o,
// TO_BE_COMPLETED - CONTROLLER
output logic hfence_vvma_o,
// TO_BE_COMPLETED - CONTROLLER
output logic hfence_gvma_o
);
@ -101,7 +105,7 @@ module commit_stage
// );
for (genvar i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin : gen_waddr
assign waddr_o[i] = commit_instr_i[i].rd[4:0];
assign waddr_o[i] = commit_instr_i[i].rd;
end
assign pc_o = commit_instr_i[0].pc;
@ -111,9 +115,8 @@ module commit_stage
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
dirty_fp_state_o |= commit_ack_o[i] & (commit_instr_i[i].fu inside {FPU, FPU_VEC} || (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
commit_instr_i[i].op
)));
// Check if we issued a vector floating-point instruction to the accellerator
dirty_fp_state_o |= commit_instr_i[i].fu == ACCEL && commit_instr_i[i].vfp;
// Check if we issued a vector floating-point instruction to the accellerator
))) | commit_instr_i[i].fu == ACCEL && commit_instr_i[i].vfp;
end
end
@ -149,136 +152,159 @@ module commit_stage
csr_write_fflags_o = 1'b0;
flush_commit_o = 1'b0;
// we will not commit the instruction if we took an exception
// and we do not commit the instruction if we requested a halt
if (commit_instr_i[0].valid && !commit_instr_i[0].ex.valid && !halt_i) begin
if (CVA6Cfg.RVZCMP && commit_instr_i[0].is_macro_instr && commit_instr_i[0].is_last_macro_instr)
commit_macro_ack[0] = 1'b1;
else commit_macro_ack[0] = 1'b0;
// we can definitely write the register file
// if the instruction is not committing anything the destination
commit_ack_o[0] = 1'b1;
if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[0].op)) begin
we_fpr_o[0] = 1'b1;
// we do not commit the instruction yet if we requested a halt
if (commit_instr_i[0].valid && !halt_i) begin
// we will not commit the instruction if we took an exception
if (commit_instr_i[0].ex.valid) begin
// However we can drop it (with its exception)
if (commit_drop_i[0]) begin
commit_ack_o[0] = 1'b1;
end
end else begin
we_gpr_o[0] = 1'b1;
end
// check whether the instruction we retire was a store
if ((!CVA6Cfg.RVA && commit_instr_i[0].fu == STORE) || (CVA6Cfg.RVA && commit_instr_i[0].fu == STORE && !instr_0_is_amo)) begin
// check if the LSU is ready to accept another commit entry (e.g.: a non-speculative store)
if (commit_lsu_ready_i) begin
commit_ack_o[0] = 1'b1;
commit_lsu_o = 1'b1;
// stall in case the store buffer is not able to accept anymore instructions
end else begin
commit_ack_o[0] = 1'b0;
commit_ack_o[0] = 1'b1;
if (CVA6Cfg.RVZCMP && commit_instr_i[0].is_macro_instr && commit_instr_i[0].is_last_macro_instr)
commit_macro_ack[0] = 1'b1;
else commit_macro_ack[0] = 1'b0;
if (!commit_drop_i[0]) begin
// we can definitely write the register file
// if the instruction is not committing anything the destination
if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[0].op)) begin
we_fpr_o[0] = 1'b1;
end else begin
we_gpr_o[0] = 1'b1;
end
end
end
// ---------
// FPU Flags
// ---------
if (CVA6Cfg.FpPresent) begin
if (commit_instr_i[0].fu inside {FPU, FPU_VEC}) begin
// write the CSR with potential exception flags from retiring floating point instruction
csr_wdata_o = {{CVA6Cfg.XLEN - 5{1'b0}}, commit_instr_i[0].ex.cause[4:0]};
csr_write_fflags_o = 1'b1;
commit_ack_o[0] = 1'b1;
// check whether the instruction we retire was a store
if (commit_instr_i[0].fu == STORE && !(CVA6Cfg.RVA && instr_0_is_amo)) begin
// check if the LSU is ready to accept another commit entry (e.g.: a non-speculative store)
if (commit_lsu_ready_i) begin
commit_lsu_o = 1'b1;
// stall in case the store buffer is not able to accept anymore instructions
end else begin
commit_ack_o[0] = 1'b0;
end
end
end
// ---------
// CSR Logic
// ---------
// check whether the instruction we retire was a CSR instruction and it did not
// throw an exception
if (commit_instr_i[0].fu == CSR) begin
// write the CSR file
csr_op_o = commit_instr_i[0].op;
csr_wdata_o = commit_instr_i[0].result;
if (!csr_exception_i.valid) begin
commit_csr_o = 1'b1;
wdata_o[0] = csr_rdata_i;
commit_ack_o[0] = 1'b1;
end else begin
commit_ack_o[0] = 1'b0;
we_gpr_o[0] = 1'b0;
// ---------
// FPU Flags
// ---------
if (CVA6Cfg.FpPresent) begin
if (commit_instr_i[0].fu inside {FPU, FPU_VEC}) begin
if (!commit_drop_i[0]) begin
// write the CSR with potential exception flags from retiring floating point instruction
csr_wdata_o = {{CVA6Cfg.XLEN - 5{1'b0}}, commit_instr_i[0].ex.cause[4:0]};
csr_write_fflags_o = 1'b1;
end
end
end
// ---------
// CSR Logic
// ---------
// check whether the instruction we retire was a CSR instruction and it did not
// throw an exception
if (commit_instr_i[0].fu == CSR) begin
// write the CSR file
csr_op_o = commit_instr_i[0].op;
csr_wdata_o = commit_instr_i[0].result;
if (!commit_drop_i[0]) begin
if (!csr_exception_i.valid) begin
commit_csr_o = 1'b1;
wdata_o[0] = csr_rdata_i;
end else begin
commit_ack_o[0] = 1'b0;
we_gpr_o[0] = 1'b0;
end
end
end
// ------------------
// SFENCE.VMA Logic
// ------------------
// sfence.vma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a SFENCE_VMA
if (CVA6Cfg.RVS && commit_instr_i[0].op == SFENCE_VMA) begin
if (!commit_drop_i[0]) begin
// no store pending so we can flush the TLBs and pipeline
sfence_vma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
end
// ------------------
// HFENCE.VVMA Logic
// ------------------
// hfence.vvma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a HFENCE_VVMA
if (CVA6Cfg.RVH && commit_instr_i[0].op == HFENCE_VVMA) begin
if (!commit_drop_i[0]) begin
// no store pending so we can flush the TLBs and pipeline
hfence_vvma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
end
// ------------------
// HFENCE.GVMA Logic
// ------------------
// hfence.gvma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a HFENCE_GVMA
if (CVA6Cfg.RVH && commit_instr_i[0].op == HFENCE_GVMA) begin
if (!commit_drop_i[0]) begin
// no store pending so we can flush the TLBs and pipeline
hfence_gvma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
end
// ------------------
// FENCE.I Logic
// ------------------
// fence.i is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// Fence synchronizes data and instruction streams. That means that we need to flush the private icache
// and the private dcache. This is the most expensive instruction.
if (commit_instr_i[0].op == FENCE_I || (flush_dcache_i && CVA6Cfg.DCacheType == config_pkg::WB && commit_instr_i[0].fu != STORE)) begin
if (!commit_drop_i[0]) begin
commit_ack_o[0] = no_st_pending_i;
// tell the controller to flush the I$
fence_i_o = no_st_pending_i;
end
end
// ------------------
// FENCE Logic
// ------------------
// fence is idempotent so we can safely re-execute it after returning
// from interrupt service routine
if (commit_instr_i[0].op == FENCE) begin
if (!commit_drop_i[0]) begin
commit_ack_o[0] = no_st_pending_i;
// tell the controller to flush the D$
fence_o = no_st_pending_i;
end
end
// ------------------
// AMO
// ------------------
if (CVA6Cfg.RVA && instr_0_is_amo) begin
// AMO finished
commit_ack_o[0] = amo_resp_i.ack;
// flush the pipeline
flush_commit_o = amo_resp_i.ack;
amo_valid_commit_o = 1'b1;
we_gpr_o[0] = amo_resp_i.ack;
end
end
// ------------------
// SFENCE.VMA Logic
// ------------------
// sfence.vma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a SFENCE_VMA
if (CVA6Cfg.RVS && commit_instr_i[0].op == SFENCE_VMA) begin
// no store pending so we can flush the TLBs and pipeline
sfence_vma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
// ------------------
// HFENCE.VVMA Logic
// ------------------
// hfence.vvma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a HFENCE_VVMA
if (CVA6Cfg.RVH && commit_instr_i[0].op == HFENCE_VVMA) begin
// no store pending so we can flush the TLBs and pipeline
hfence_vvma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
// ------------------
// HFENCE.GVMA Logic
// ------------------
// hfence.gvma is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// check if this instruction was a HFENCE_GVMA
if (CVA6Cfg.RVH && commit_instr_i[0].op == HFENCE_GVMA) begin
// no store pending so we can flush the TLBs and pipeline
hfence_gvma_o = no_st_pending_i;
// wait for the store buffer to drain until flushing the pipeline
commit_ack_o[0] = no_st_pending_i;
end
// ------------------
// FENCE.I Logic
// ------------------
// fence.i is idempotent so we can safely re-execute it after returning
// from interrupt service routine
// Fence synchronizes data and instruction streams. That means that we need to flush the private icache
// and the private dcache. This is the most expensive instruction.
if (commit_instr_i[0].op == FENCE_I || (flush_dcache_i && CVA6Cfg.DCacheType == config_pkg::WB && commit_instr_i[0].fu != STORE)) begin
commit_ack_o[0] = no_st_pending_i;
// tell the controller to flush the I$
fence_i_o = no_st_pending_i;
end
// ------------------
// FENCE Logic
// ------------------
// fence is idempotent so we can safely re-execute it after returning
// from interrupt service routine
if (commit_instr_i[0].op == FENCE) begin
commit_ack_o[0] = no_st_pending_i;
// tell the controller to flush the D$
fence_o = no_st_pending_i;
end
// ------------------
// AMO
// ------------------
if (CVA6Cfg.RVA && instr_0_is_amo) begin
// AMO finished
commit_ack_o[0] = amo_resp_i.ack;
// flush the pipeline
flush_commit_o = amo_resp_i.ack;
amo_valid_commit_o = 1'b1;
we_gpr_o[0] = amo_resp_i.ack;
end
end
if (CVA6Cfg.NrCommitPorts > 1) begin
commit_ack_o[1] = 1'b0;
we_gpr_o[1] = 1'b0;
wdata_o[1] = commit_instr_i[1].result;
commit_macro_ack[1] = 1'b0;
commit_ack_o[1] = 1'b0;
we_gpr_o[1] = 1'b0;
wdata_o[1] = commit_instr_i[1].result;
// -----------------
// Commit Port 2
@ -289,42 +315,44 @@ module commit_stage
&& !halt_i
&& !(commit_instr_i[0].fu inside {CSR})
&& !flush_dcache_i
&& !instr_0_is_amo
&& !(CVA6Cfg.RVA && instr_0_is_amo)
&& !single_step_i) begin
// only if the first instruction didn't throw an exception and this instruction won't throw an exception
// and the functional unit is of type ALU, LOAD, CTRL_FLOW, MULT, FPU or FPU_VEC
if (!exception_o.valid && !commit_instr_i[1].ex.valid
&& (commit_instr_i[1].fu inside {ALU, LOAD, CTRL_FLOW, MULT, FPU, FPU_VEC})) begin
if (!commit_instr_i[1].ex.valid && (commit_instr_i[1].fu inside {ALU, LOAD, CTRL_FLOW, MULT, FPU, FPU_VEC})) begin
if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[1].op)) we_fpr_o[1] = 1'b1;
else we_gpr_o[1] = 1'b1;
if (commit_instr_i[1].is_macro_instr && commit_instr_i[1].is_last_macro_instr)
if (CVA6Cfg.RVZCMP && commit_instr_i[1].is_macro_instr && commit_instr_i[1].is_last_macro_instr)
commit_macro_ack[1] = 1'b1;
else commit_macro_ack[1] = 1'b0;
commit_ack_o[1] = 1'b1;
// additionally check if we are retiring an FPU instruction because we need to make sure that we write all
// exception flags
if (CVA6Cfg.FpPresent && commit_instr_i[1].fu inside {FPU, FPU_VEC}) begin
if (csr_write_fflags_o)
csr_wdata_o = {
{CVA6Cfg.XLEN - 5{1'b0}},
(commit_instr_i[0].ex.cause[4:0] | commit_instr_i[1].ex.cause[4:0])
};
else csr_wdata_o = {{CVA6Cfg.XLEN - 5{1'b0}}, commit_instr_i[1].ex.cause[4:0]};
if (!commit_drop_i[1]) begin
if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[1].op))
we_fpr_o[1] = 1'b1;
else we_gpr_o[1] = 1'b1;
csr_write_fflags_o = 1'b1;
// additionally check if we are retiring an FPU instruction because we need to make sure that we write all
// exception flags
if (CVA6Cfg.FpPresent) begin
if (commit_instr_i[1].fu inside {FPU, FPU_VEC}) begin
if (csr_write_fflags_o)
csr_wdata_o = {
{CVA6Cfg.XLEN - 5{1'b0}},
(commit_instr_i[0].ex.cause[4:0] | commit_instr_i[1].ex.cause[4:0])
};
else csr_wdata_o = {{CVA6Cfg.XLEN - 5{1'b0}}, commit_instr_i[1].ex.cause[4:0]};
csr_write_fflags_o = 1'b1;
end
end
end
end
end
end
if (CVA6Cfg.RVZCMP) begin
if (CVA6Cfg.NrCommitPorts > 1)
commit_macro_ack_o = (commit_instr_i[0].is_macro_instr || commit_instr_i[1].is_macro_instr) ? commit_macro_ack : commit_ack_o;
else
commit_macro_ack_o = (commit_instr_i[0].is_macro_instr) ? commit_macro_ack : commit_ack_o;
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
commit_macro_ack_o[i] = commit_instr_i[i].is_macro_instr ? commit_macro_ack[i] : commit_ack_o[i];
end
end else commit_macro_ack_o = commit_ack_o;
end
@ -344,7 +372,7 @@ module commit_stage
exception_o.gva = 1'b0;
// we need a valid instruction in the commit stage
if (commit_instr_i[0].valid) begin
if (commit_instr_i[0].valid && !commit_drop_i[0]) begin
// ------------------------
// check for CSR exception
// ------------------------

View file

@ -31,7 +31,9 @@ module compressed_decoder #(
// Output instruction is macro - decoder
output logic is_macro_instr_o,
// Output instruction is compressed - decoder
output logic is_compressed_o
output logic is_compressed_o,
// Output instruction is macro - decoder
output logic is_zcmt_instr_o
);
// -------------------
@ -39,10 +41,10 @@ module compressed_decoder #(
// -------------------
always_comb begin
illegal_instr_o = 1'b0;
instr_o = '0;
is_compressed_o = 1'b1;
instr_o = instr_i;
is_macro_instr_o = 0;
is_zcmt_instr_o = 1'b0;
// I: | imm[11:0] | rs1 | funct3 | rd | opcode |
// S: | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
@ -868,18 +870,13 @@ module compressed_decoder #(
3'b000,
riscv::OpcodeStoreFp
};
end else if (CVA6Cfg.RVZCMP) begin
if (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011) begin //is a push/pop instruction
is_macro_instr_o = 1;
instr_o = instr_i;
end else begin
illegal_instr_o = 1'b1;
end
end else begin
illegal_instr_o = 1'b1;
end
end else if (CVA6Cfg.RVZCMP && (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011)) begin
is_macro_instr_o = 1;
instr_o = instr_i;
end else if (CVA6Cfg.RVZCMT && (instr_i[12:10] == 3'b000)) //jt/jalt instruction
is_zcmt_instr_o = 1'b1;
else illegal_instr_o = 1'b1;
end
riscv::OpcodeC2Swsp: begin
// c.swsp -> sw rs2, imm(x2)
instr_o = {

View file

@ -45,7 +45,9 @@ module controller
input logic flush_dcache_ack_i,
// Flush TLBs - EX_STAGE
output logic flush_tlb_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED
output logic flush_tlb_vvma_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED
output logic flush_tlb_gvma_o,
// Halt request from CSR (WFI instruction) - CSR_REGFILE
input logic halt_csr_i,
@ -69,7 +71,9 @@ module controller
input logic fence_i,
// We got an instruction to flush the TLBs and pipeline - COMMIT_STAGE
input logic sfence_vma_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic hfence_vvma_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic hfence_gvma_i,
// Flush request from commit stage - COMMIT_STAGE
input logic flush_commit_i,
@ -120,7 +124,7 @@ module controller
flush_ex_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -138,7 +142,7 @@ module controller
flush_icache_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -146,7 +150,7 @@ module controller
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
// wait for the acknowledge here
if (flush_dcache_ack_i && fence_active_q) begin
fence_active_d = 1'b0;
@ -238,7 +242,7 @@ module controller
// ----------------------
always_comb begin
// halt the core if the fence is active
halt_o = halt_csr_i || halt_acc_i || (CVA6Cfg.DCacheType == config_pkg::WB && fence_active_q);
halt_o = halt_csr_i || halt_acc_i || (CVA6Cfg.DcacheFlushOnFence && fence_active_q);
end
// ----------------------

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright 2024 - PlanV Technologies for additionnal contribution.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
@ -9,9 +10,12 @@
// specific language governing permissions and limitations under the License.
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
// Additional contributions by:
// Angela Gonzalez - PlanV Technologies
module cva6_fifo_v3 #(
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
parameter bit FPGA_ALTERA = 1'b0, // FPGA Altera optimizations enabled
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
parameter type dtype = logic [DATA_WIDTH-1:0],
@ -46,6 +50,8 @@ module cva6_fifo_v3 #(
logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q;
// actual memory
dtype [FifoDepth - 1:0] mem_n, mem_q;
dtype data_ft_n, data_ft_q;
logic first_word_n, first_word_q;
// fifo ram signals for fpga target
logic fifo_ram_we;
@ -71,12 +77,18 @@ module cva6_fifo_v3 #(
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
status_cnt_n = status_cnt_q;
if (FPGA_EN && FPGA_ALTERA) data_ft_n = data_ft_q;
if (FPGA_EN && FPGA_ALTERA) first_word_n = first_word_q;
if (FPGA_EN) begin
fifo_ram_we = '0;
fifo_ram_read_address = read_pointer_q;
fifo_ram_write_address = '0;
fifo_ram_wdata = '0;
data_o = (DEPTH == 0) ? data_i : fifo_ram_rdata;
if (DEPTH == 0) begin
data_o = data_i;
end else begin
if (FPGA_ALTERA) data_o = first_word_q ? data_ft_q : fifo_ram_rdata;
else data_o = fifo_ram_rdata;
end
end else begin
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
mem_n = mem_q;
@ -89,6 +101,7 @@ module cva6_fifo_v3 #(
fifo_ram_we = 1'b1;
fifo_ram_write_address = write_pointer_q;
fifo_ram_wdata = data_i;
if (FPGA_ALTERA) first_word_n = first_word_q && pop_i;
end else begin
// push the data onto the queue
mem_n[write_pointer_q] = data_i;
@ -104,6 +117,8 @@ module cva6_fifo_v3 #(
end
if (pop_i && ~empty_o) begin
data_ft_n = data_i;
if (FPGA_EN && FPGA_ALTERA) first_word_n = first_word_q && push_i;
// read from the queue is a default assignment
// but increment the read pointer...
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1) read_pointer_n = '0;
@ -116,14 +131,23 @@ module cva6_fifo_v3 #(
if (push_i && pop_i && ~full_o && ~empty_o) status_cnt_n = status_cnt_q;
// FIFO is in pass through mode -> do not change the pointers
if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin
data_o = data_i;
if ((FALL_THROUGH || (FPGA_EN && FPGA_ALTERA)) && (status_cnt_q == 0) && push_i) begin
if (FALL_THROUGH) data_o = data_i;
if (FPGA_EN && FPGA_ALTERA) begin
data_ft_n = data_i;
first_word_n = '1;
end
if (pop_i) begin
first_word_n = '0;
status_cnt_n = status_cnt_q;
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
end
end
if (FPGA_EN) fifo_ram_read_address = (FPGA_ALTERA == 1) ? read_pointer_n : read_pointer_q;
else fifo_ram_read_address = '0;
end
// sequential process
@ -132,32 +156,53 @@ module cva6_fifo_v3 #(
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
if (FPGA_ALTERA) first_word_q <= '0;
if (FPGA_ALTERA) data_ft_q <= '0;
end else begin
if (flush_i) begin
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
if (FPGA_ALTERA) first_word_q <= '0;
if (FPGA_ALTERA) data_ft_q <= '0;
end else begin
read_pointer_q <= read_pointer_n;
write_pointer_q <= write_pointer_n;
status_cnt_q <= status_cnt_n;
if (FPGA_ALTERA) data_ft_q <= data_ft_n;
if (FPGA_ALTERA) first_word_q <= first_word_n;
end
end
end
if (FPGA_EN) begin : gen_fpga_queue
AsyncDpRam #(
.ADDR_WIDTH(ADDR_DEPTH),
.DATA_DEPTH(DEPTH),
.DATA_WIDTH($bits(dtype))
) fifo_ram (
.Clk_CI (clk_i),
.WrEn_SI (fifo_ram_we),
.RdAddr_DI(fifo_ram_read_address),
.WrAddr_DI(fifo_ram_write_address),
.WrData_DI(fifo_ram_wdata),
.RdData_DO(fifo_ram_rdata)
);
if (FPGA_ALTERA) begin
SyncDpRam_ind_r_w #(
.ADDR_WIDTH(ADDR_DEPTH),
.DATA_DEPTH(DEPTH),
.DATA_WIDTH($bits(dtype))
) fifo_ram (
.Clk_CI (clk_i),
.WrEn_SI (fifo_ram_we),
.RdAddr_DI(fifo_ram_read_address),
.WrAddr_DI(fifo_ram_write_address),
.WrData_DI(fifo_ram_wdata),
.RdData_DO(fifo_ram_rdata)
);
end else begin
AsyncDpRam #(
.ADDR_WIDTH(ADDR_DEPTH),
.DATA_DEPTH(DEPTH),
.DATA_WIDTH($bits(dtype))
) fifo_ram (
.Clk_CI (clk_i),
.WrEn_SI (fifo_ram_we),
.RdAddr_DI(fifo_ram_read_address),
.WrAddr_DI(fifo_ram_write_address),
.WrData_DI(fifo_ram_wdata),
.RdData_DO(fifo_ram_rdata)
);
end
end else begin : gen_asic_queue
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
@ -169,7 +214,6 @@ module cva6_fifo_v3 #(
end
// pragma translate_off
`ifndef VERILATOR
initial begin
assert (DEPTH > 0)
else $error("DEPTH must be greater than 0.");
@ -182,7 +226,6 @@ module cva6_fifo_v3 #(
empty_read :
assert property (@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
else $fatal(1, "Trying to pop data although the FIFO is empty.");
`endif
// pragma translate_on
endmodule // fifo_v3

View file

@ -92,14 +92,16 @@ module cva6_mmu
input logic flush_tlb_gvma_i,
// Performance counters
output logic itlb_miss_o,
output logic dtlb_miss_o,
output logic itlb_miss_o,
output logic dtlb_miss_o,
// PTW memory interface
input dcache_req_o_t req_port_i,
output dcache_req_i_t req_port_o,
input dcache_req_o_t req_port_i,
output dcache_req_i_t req_port_o,
// PMP
input riscv::pmpcfg_t [15:0] pmpcfg_i,
input logic [15:0][CVA6Cfg.PLEN-3:0] pmpaddr_i
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i
);
// memory management, pte for cva6
@ -131,6 +133,7 @@ module cva6_mmu
logic iaccess_err; // insufficient privilege to access this instruction page
logic i_g_st_access_err; // insufficient privilege at g stage to access this instruction page
logic daccess_err; // insufficient privilege to access this data page
logic canonical_addr_check; // canonical check on the virtual address for SV39
logic d_g_st_access_err; // insufficient privilege to access this data page
logic ptw_active; // PTW is currently walking a page table
logic walking_instr; // PTW is walking because of an ITLB miss
@ -192,12 +195,15 @@ module cva6_mmu
.lu_asid_i (itlb_lu_asid),
.lu_vmid_i (vmid_i),
.lu_vaddr_i (icache_areq_i.fetch_vaddr),
.lu_gpaddr_o (itlb_gpaddr),
.lu_content_o (itlb_content),
.lu_g_content_o(itlb_g_content),
.lu_gpaddr_o (itlb_gpaddr),
.asid_to_be_flushed_i,
.vmid_to_be_flushed_i,
.vaddr_to_be_flushed_i,
.gpaddr_to_be_flushed_i,
.lu_is_page_o (itlb_is_page),
.lu_hit_o (itlb_lu_hit),
.*
.lu_hit_o (itlb_lu_hit)
);
cva6_tlb #(
@ -217,15 +223,18 @@ module cva6_mmu
.v_i (ld_st_v_i),
.update_i (update_dtlb),
.lu_access_i (dtlb_lu_access),
.lu_asid_i (itlb_lu_asid),
.lu_asid_i (dtlb_lu_asid),
.lu_vmid_i (vmid_i),
.lu_vaddr_i (lsu_vaddr_i),
.lu_gpaddr_o (dtlb_gpaddr),
.lu_content_o (dtlb_content),
.lu_g_content_o(dtlb_g_content),
.lu_gpaddr_o (dtlb_gpaddr),
.asid_to_be_flushed_i,
.vmid_to_be_flushed_i,
.vaddr_to_be_flushed_i,
.gpaddr_to_be_flushed_i,
.lu_is_page_o (dtlb_is_page),
.lu_hit_o (dtlb_lu_hit),
.*
.lu_hit_o (dtlb_lu_hit)
);
@ -289,6 +298,7 @@ module cva6_mmu
) i_ptw (
.clk_i (clk_i),
.rst_ni(rst_ni),
.flush_i,
.ptw_active_o (ptw_active),
.walking_instr_o (walking_instr),
@ -296,17 +306,27 @@ module cva6_mmu
.ptw_error_at_g_st_o (ptw_error_at_g_st),
.ptw_err_at_g_int_st_o (ptw_err_at_g_int_st),
.ptw_access_exception_o(ptw_access_exception),
.enable_translation_i,
.enable_g_translation_i,
.en_ld_st_translation_i,
.en_ld_st_g_translation_i,
.v_i,
.ld_st_v_i,
.hlvx_inst_i (hlvx_inst_i),
.lsu_is_store_i(lsu_is_store_i),
// PTW memory interface
.req_port_i (req_port_i),
.req_port_o (req_port_o),
.update_vaddr_o(update_vaddr),
// to Shared TLB, update logic
.shared_tlb_update_o(update_shared_tlb),
.update_vaddr_o(update_vaddr),
.asid_i,
.vs_asid_i,
.vmid_i,
// from shared TLB
// did we miss?
@ -316,7 +336,11 @@ module cva6_mmu
.itlb_req_i(itlb_req),
.hlvx_inst_i(hlvx_inst_i),
.satp_ppn_i,
.vsatp_ppn_i,
.hgatp_ppn_i,
.mxr_i,
.vmxr_i,
// Performance counters
.shared_tlb_miss_o(shared_tlb_miss), //open for now
@ -325,16 +349,12 @@ module cva6_mmu
.pmpcfg_i (pmpcfg_i),
.pmpaddr_i (pmpaddr_i),
.bad_paddr_o(ptw_bad_paddr),
.bad_gpaddr_o(ptw_bad_gpaddr),
.*
.bad_gpaddr_o(ptw_bad_gpaddr)
);
//-----------------------
// Instruction Interface
//-----------------------
logic match_any_execute_region;
logic pmp_instr_allow;
localparam int PPNWMin = (CVA6Cfg.PPNW - 1 > 29) ? 29 : CVA6Cfg.PPNW - 1;
// The instruction interface is a simple request response interface
@ -361,7 +381,7 @@ module cva6_mmu
// we work with SV39 or SV32, so if VM is enabled, check that all bits [CVA6Cfg.VLEN-1:CVA6Cfg.SV-1] are equal
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b0)) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(icache_areq_i.fetch_vaddr);
@ -419,16 +439,6 @@ module cva6_mmu
icache_areq_o.fetch_exception.tinst = '0;
icache_areq_o.fetch_exception.gva = v_i;
end
end else if (!pmp_instr_allow) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(icache_areq_i.fetch_vaddr);
if (CVA6Cfg.RVH) begin
icache_areq_o.fetch_exception.tval2 = '0;
icache_areq_o.fetch_exception.tinst = '0;
icache_areq_o.fetch_exception.gva = v_i;
end
end
end else if (ptw_active && walking_instr) begin
// ---------//
@ -459,7 +469,7 @@ module cva6_mmu
end else begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn) //To confirm this is the right TVAL
if (CVA6Cfg.TvalEn) //To confirm this is the right TVAL
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
if (CVA6Cfg.RVH) begin
icache_areq_o.fetch_exception.tval2 = '0;
@ -469,48 +479,8 @@ module cva6_mmu
end
end
end
// if it didn't match any execute region throw an `Instruction Access Fault`
// or: if we are not translating, check PMPs immediately on the paddr
if ((!match_any_execute_region && !ptw_error) || (!(enable_translation_i || enable_g_translation_i) && !pmp_instr_allow)) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn) begin //To confirm this is the right TVAL
if (enable_translation_i || enable_g_translation_i)
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
else
icache_areq_o.fetch_exception.tval=CVA6Cfg.XLEN'(icache_areq_o.fetch_paddr[CVA6Cfg.PLEN-1:(CVA6Cfg.PLEN > CVA6Cfg.VLEN) ? (CVA6Cfg.PLEN - CVA6Cfg.VLEN) : 0]);
end
if (CVA6Cfg.RVH) begin
icache_areq_o.fetch_exception.tval2 = '0;
icache_areq_o.fetch_exception.tinst = '0;
icache_areq_o.fetch_exception.gva = v_i;
end
end
end
// check for execute flag on memory
assign match_any_execute_region = config_pkg::is_inside_execute_regions(
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, icache_areq_o.fetch_paddr}
);
// Instruction fetch
pmp #(
.CVA6Cfg (CVA6Cfg), //comment for hypervisor extension
.PLEN (CVA6Cfg.PLEN),
.PMP_LEN (CVA6Cfg.PLEN - 2),
.NR_ENTRIES(CVA6Cfg.NrPMPEntries)
// .NR_ENTRIES ( ArianeCfg.NrPMPEntries ) // configuration used in hypervisor extension
) i_pmp_if (
.addr_i (icache_areq_o.fetch_paddr),
.priv_lvl_i,
// we will always execute on the instruction fetch port
.access_type_i(riscv::ACCESS_EXEC),
// Configuration
.conf_addr_i (pmpaddr_i),
.conf_i (pmpcfg_i),
.allow_o (pmp_instr_allow)
);
//-----------------------
// Data Interface
@ -521,38 +491,37 @@ module cva6_mmu
logic hs_ld_st_inst_n, hs_ld_st_inst_q;
pte_cva6_t dtlb_pte_n, dtlb_pte_q;
pte_cva6_t dtlb_gpte_n, dtlb_gpte_q;
exception_t misaligned_ex_n, misaligned_ex_q;
logic lsu_req_n, lsu_req_q;
logic lsu_is_store_n, lsu_is_store_q;
logic dtlb_hit_n, dtlb_hit_q;
logic [CVA6Cfg.PtLevels-2:0] dtlb_is_page_n, dtlb_is_page_q;
exception_t misaligned_ex_n, misaligned_ex_q;
// check if we need to do translation or if we are always ready (e.g.: we are not translating anything)
assign lsu_dtlb_hit_o = (en_ld_st_translation_i || en_ld_st_g_translation_i) ? dtlb_lu_hit : 1'b1;
// Wires to PMP checks
riscv::pmp_access_t pmp_access_type;
logic pmp_data_allow;
// The data interface is simpler and only consists of a request/response interface
always_comb begin : data_interface
// save request and DTLB response
lsu_vaddr_n = lsu_vaddr_i;
lsu_req_n = lsu_req_i;
misaligned_ex_n = misaligned_ex_i;
dtlb_pte_n = dtlb_content;
dtlb_hit_n = dtlb_lu_hit;
lsu_is_store_n = lsu_is_store_i;
dtlb_is_page_n = dtlb_is_page;
misaligned_ex_n = misaligned_ex_i;
lsu_valid_o = lsu_req_q;
lsu_exception_o = misaligned_ex_q;
pmp_access_type = lsu_is_store_q ? riscv::ACCESS_WRITE : riscv::ACCESS_READ;
// mute misaligned exceptions if there is no request otherwise they will throw accidental exceptions
misaligned_ex_n.valid = misaligned_ex_i.valid & lsu_req_i;
// we work with SV39 or SV32, so if VM is enabled, check that all bits [CVA6Cfg.VLEN-1:CVA6Cfg.SV-1] are equal to bit [CVA6Cfg.SV]
canonical_addr_check = (lsu_req_i && en_ld_st_translation_i &&
!((&lsu_vaddr_i[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|lsu_vaddr_i[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b0));
// Check if the User flag is set, then we may only access it in supervisor mode
// if SUM is enabled
daccess_err = en_ld_st_translation_i &&
@ -619,7 +588,7 @@ module cva6_mmu
lsu_exception_o.tinst = '0;
lsu_exception_o.gva = ld_st_v_i;
end
end else if ((en_ld_st_translation_i || !CVA6Cfg.RVH) && (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d)) begin
end else if ((en_ld_st_translation_i || !CVA6Cfg.RVH) && (!dtlb_pte_q.w || daccess_err || canonical_addr_check || !dtlb_pte_q.d)) begin
lsu_exception_o.cause = riscv::STORE_PAGE_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
@ -631,19 +600,6 @@ module cva6_mmu
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
// Check if any PMPs are violated
end else if (!pmp_data_allow) begin
lsu_exception_o.cause = riscv::ST_ACCESS_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
lsu_exception_o.tval = {
{CVA6Cfg.XLEN - CVA6Cfg.VLEN{lsu_vaddr_q[CVA6Cfg.VLEN-1]}}, lsu_vaddr_q
};
if (CVA6Cfg.RVH) begin
lsu_exception_o.tval2 = '0;
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
end
// this is a load
end else begin
@ -660,7 +616,7 @@ module cva6_mmu
lsu_exception_o.gva = ld_st_v_i;
end
// check for sufficient access privileges - throw a page fault if necessary
end else if (daccess_err) begin
end else if (daccess_err || canonical_addr_check) begin
lsu_exception_o.cause = riscv::LOAD_PAGE_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
@ -672,19 +628,6 @@ module cva6_mmu
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
// Check if any PMPs are violated
end else if (!pmp_data_allow) begin
lsu_exception_o.cause = riscv::LD_ACCESS_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
lsu_exception_o.tval = {
{CVA6Cfg.XLEN - CVA6Cfg.VLEN{lsu_vaddr_q[CVA6Cfg.VLEN-1]}}, lsu_vaddr_q
};
if (CVA6Cfg.RVH) begin
lsu_exception_o.tval2 = '0;
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
end
end
end else
@ -780,50 +723,9 @@ module cva6_mmu
end
end
end
// If translation is not enabled, check the paddr immediately against PMPs
end else if (lsu_req_q && !misaligned_ex_q.valid && !pmp_data_allow) begin
if (lsu_is_store_q) begin
lsu_exception_o.cause = riscv::ST_ACCESS_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
lsu_exception_o.tval = CVA6Cfg.XLEN'(lsu_paddr_o[CVA6Cfg.PLEN-1:(CVA6Cfg.PLEN>CVA6Cfg.VLEN)?(CVA6Cfg.PLEN-CVA6Cfg.VLEN) : 0]);
if (CVA6Cfg.RVH) begin
lsu_exception_o.tval2 = '0;
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
end else begin
lsu_exception_o.cause = riscv::LD_ACCESS_FAULT;
lsu_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn)
lsu_exception_o.tval = CVA6Cfg.XLEN'(lsu_paddr_o[CVA6Cfg.PLEN-1:(CVA6Cfg.PLEN>CVA6Cfg.VLEN)?(CVA6Cfg.PLEN-CVA6Cfg.VLEN) : 0]);
if (CVA6Cfg.RVH) begin
lsu_exception_o.tval2 = '0;
lsu_exception_o.tinst = lsu_tinst_q;
lsu_exception_o.gva = ld_st_v_i;
end
end
end
end
// Load/store PMP check
pmp #(
.CVA6Cfg (CVA6Cfg),
.PLEN (CVA6Cfg.PLEN),
.PMP_LEN (CVA6Cfg.PLEN - 2),
.NR_ENTRIES(CVA6Cfg.NrPMPEntries)
) i_pmp_data (
.addr_i (lsu_paddr_o),
.priv_lvl_i (ld_st_priv_lvl_i),
.access_type_i(pmp_access_type),
// Configuration
.conf_addr_i (pmpaddr_i),
.conf_i (pmpcfg_i),
.allow_o (pmp_data_allow)
);
// ----------
// Registers
// ----------
@ -832,7 +734,6 @@ module cva6_mmu
lsu_vaddr_q <= '0;
lsu_gpaddr_q <= '0;
lsu_req_q <= '0;
misaligned_ex_q <= '0;
dtlb_pte_q <= '0;
dtlb_gpte_q <= '0;
dtlb_hit_q <= '0;
@ -840,20 +741,21 @@ module cva6_mmu
dtlb_is_page_q <= '0;
lsu_tinst_q <= '0;
hs_ld_st_inst_q <= '0;
misaligned_ex_q <= '0;
end else begin
lsu_vaddr_q <= lsu_vaddr_n;
lsu_req_q <= lsu_req_n;
misaligned_ex_q <= misaligned_ex_n;
dtlb_pte_q <= dtlb_pte_n;
dtlb_hit_q <= dtlb_hit_n;
lsu_is_store_q <= lsu_is_store_n;
dtlb_is_page_q <= dtlb_is_page_n;
lsu_vaddr_q <= lsu_vaddr_n;
lsu_req_q <= lsu_req_n;
dtlb_pte_q <= dtlb_pte_n;
dtlb_hit_q <= dtlb_hit_n;
lsu_is_store_q <= lsu_is_store_n;
dtlb_is_page_q <= dtlb_is_page_n;
if (CVA6Cfg.RVH) begin
lsu_tinst_q <= lsu_tinst_n;
hs_ld_st_inst_q <= hs_ld_st_inst_n;
dtlb_gpte_q <= dtlb_gpte_n;
lsu_gpaddr_q <= lsu_gpaddr_n;
misaligned_ex_q <= misaligned_ex_n;
end
end
end

View file

@ -16,7 +16,7 @@
// Date: 26/02/2024
// Description: Hardware-PTW (Page-Table-Walker) for CVA6 supporting sv32, sv39 and sv39x4.
// This module is an merge of the PTW Sv39 developed by Florian Zaruba,
// the PTW Sv32 developed by Sebastien Jacq and the PTW Sv39x4 by Bruno Sá.
// the PTW Sv32 developed by Sebastien Jacq and the PTW Sv39x4 by Bruno Sá.
/* verilator lint_off WIDTH */
@ -83,12 +83,10 @@ module cva6_ptw
output logic shared_tlb_miss_o,
// PMP
input riscv::pmpcfg_t [15:0] pmpcfg_i,
input logic [15:0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
output logic [CVA6Cfg.PLEN-1:0] bad_paddr_o,
output logic [CVA6Cfg.GPLEN-1:0] bad_gpaddr_o
);
// input registers
@ -218,7 +216,7 @@ module cva6_ptw
// output the correct ASIDs
shared_tlb_update_o.asid = tlb_update_asid_q;
shared_tlb_update_o.vmid = tlb_update_vmid_q;
shared_tlb_update_o.vmid = CVA6Cfg.RVH ? tlb_update_vmid_q : '0;
bad_paddr_o = ptw_access_exception_o ? ptw_pptr_q : 'b0;
if (CVA6Cfg.RVH)
@ -232,10 +230,7 @@ module cva6_ptw
pmp #(
.CVA6Cfg (CVA6Cfg),
.PLEN (CVA6Cfg.PLEN),
.PMP_LEN (CVA6Cfg.PLEN - 2),
.NR_ENTRIES(CVA6Cfg.NrPMPEntries)
.CVA6Cfg(CVA6Cfg)
) i_pmp_ptw (
.addr_i (ptw_pptr_q),
// PTW access are always checked as if in S-Mode...
@ -263,8 +258,8 @@ module cva6_ptw
// PAGESIZE=2^12 and LEVELS=3.)
// 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For
// Sv32, PTESIZE=4.)
// 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if any bits or encodings
// that are reserved for future standard use are set within pte, stop and raise
// 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if any bits or encodings
// that are reserved for future standard use are set within pte, stop and raise
// a page-fault exception corresponding to the original access type.
// 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5.
// Otherwise, this PTE is a pointer to the next level of the page table.
@ -301,7 +296,6 @@ module cva6_ptw
global_mapping_n = global_mapping_q;
// input registers
tlb_update_asid_n = tlb_update_asid_q;
tlb_update_vmid_n = tlb_update_vmid_q;
vaddr_n = vaddr_q;
pptr = ptw_pptr_q;
@ -309,6 +303,7 @@ module cva6_ptw
gpaddr_n = gpaddr_q;
gptw_pptr_n = gptw_pptr_q;
gpte_d = gpte_q;
tlb_update_vmid_n = tlb_update_vmid_q;
end
shared_tlb_miss_o = 1'b0;
@ -621,17 +616,17 @@ module cva6_ptw
ptw_lvl_q <= '0;
tag_valid_q <= 1'b0;
tlb_update_asid_q <= '0;
tlb_update_vmid_q <= '0;
vaddr_q <= '0;
ptw_pptr_q <= '0;
global_mapping_q <= 1'b0;
data_rdata_q <= '0;
data_rvalid_q <= 1'b0;
if (CVA6Cfg.RVH) begin
gpaddr_q <= '0;
gptw_pptr_q <= '0;
ptw_stage_q <= S_STAGE;
gpte_q <= '0;
gpaddr_q <= '0;
gptw_pptr_q <= '0;
ptw_stage_q <= S_STAGE;
gpte_q <= '0;
tlb_update_vmid_q <= '0;
end
end else begin
state_q <= state_d;

View file

@ -400,7 +400,6 @@ for (
//--------------
//pragma translate_off
`ifndef VERILATOR
initial begin : p_assertions
assert ((TLB_ENTRIES % 2 == 0) && (TLB_ENTRIES > 1))
@ -435,7 +434,6 @@ for (
$stop();
end
`endif
//pragma translate_on
endmodule

View file

@ -51,21 +51,23 @@ module cva6_rvfi
localparam logic [63:0] SMODE_STATUS_READ_MASK = ariane_pkg::smode_status_read_mask(CVA6Cfg);
logic flush;
logic issue_instr_ack;
logic [ariane_pkg::SUPERSCALAR:0] fetch_entry_valid;
logic [ariane_pkg::SUPERSCALAR:0][31:0] instruction;
logic [ariane_pkg::SUPERSCALAR:0] is_compressed;
logic [ariane_pkg::SUPERSCALAR:0][31:0] truncated;
logic [CVA6Cfg.NrIssuePorts-1:0] issue_instr_ack;
logic [CVA6Cfg.NrIssuePorts-1:0] fetch_entry_valid;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] truncated;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer;
logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer;
logic flush_unissued_instr;
logic decoded_instr_valid;
logic decoded_instr_ack;
logic [CVA6Cfg.NrIssuePorts-1:0] decoded_instr_valid;
logic [CVA6Cfg.NrIssuePorts-1:0] decoded_instr_ack;
logic [CVA6Cfg.XLEN-1:0] rs1_forwarding;
logic [CVA6Cfg.XLEN-1:0] rs2_forwarding;
logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs1;
logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs2;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.XLEN-1:0] rvfi_intr;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.VLEN-1:0] commit_instr_pc;
fu_op [CVA6Cfg.NrCommitPorts-1:0] commit_instr_op;
@ -73,7 +75,8 @@ module cva6_rvfi
logic [CVA6Cfg.NrCommitPorts-1:0][REG_ADDR_SIZE-1:0] commit_instr_rs2;
logic [CVA6Cfg.NrCommitPorts-1:0][REG_ADDR_SIZE-1:0] commit_instr_rd;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.XLEN-1:0] commit_instr_result;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.VLEN-1:0] commit_instr_valid;
logic [CVA6Cfg.NrCommitPorts-1:0] commit_instr_valid;
logic [CVA6Cfg.NrCommitPorts-1:0] commit_drop;
logic [CVA6Cfg.XLEN-1:0] ex_commit_cause;
logic ex_commit_valid;
@ -129,8 +132,8 @@ module cva6_rvfi
assign decoded_instr_valid = instr.decoded_instr_valid;
assign decoded_instr_ack = instr.decoded_instr_ack;
assign rs1_forwarding = instr.rs1_forwarding;
assign rs2_forwarding = instr.rs2_forwarding;
assign rs1 = instr.rs1;
assign rs2 = instr.rs2;
assign commit_instr_pc = instr.commit_instr_pc;
assign commit_instr_op = instr.commit_instr_op;
@ -139,6 +142,7 @@ module cva6_rvfi
assign commit_instr_rd = instr.commit_instr_rd;
assign commit_instr_result = instr.commit_instr_result;
assign commit_instr_valid = instr.commit_instr_valid;
assign commit_drop = instr.commit_drop;
assign ex_commit_cause = instr.ex_commit_cause;
assign ex_commit_valid = instr.ex_commit_valid;
@ -159,7 +163,7 @@ module cva6_rvfi
//ID STAGE
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
assign truncated[i] = (is_compressed[i]) ? {16'b0, instruction[i][15:0]} : instruction[i];
end
@ -167,38 +171,42 @@ module cva6_rvfi
logic valid;
logic [31:0] instr;
} issue_struct_t;
issue_struct_t [ariane_pkg::SUPERSCALAR:0] issue_n, issue_q;
issue_struct_t [CVA6Cfg.NrIssuePorts-1:0] issue_n, issue_q;
logic took0;
always_comb begin
issue_n = issue_q;
took0 = 1'b0;
if (issue_instr_ack) issue_n[0].valid = 1'b0;
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
if (issue_instr_ack[i]) begin
issue_n[i].valid = 1'b0;
end
end
if (!issue_n[ariane_pkg::SUPERSCALAR].valid) begin
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[0];
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[0];
if (!issue_n[CVA6Cfg.NrIssuePorts-1].valid) begin
issue_n[CVA6Cfg.NrIssuePorts-1].valid = fetch_entry_valid[0];
issue_n[CVA6Cfg.NrIssuePorts-1].instr = truncated[0];
took0 = 1'b1;
end
if (!issue_n[0].valid) begin
issue_n[0] = issue_n[ariane_pkg::SUPERSCALAR];
issue_n[ariane_pkg::SUPERSCALAR].valid = 1'b0;
issue_n[0] = issue_n[CVA6Cfg.NrIssuePorts-1];
issue_n[CVA6Cfg.NrIssuePorts-1].valid = 1'b0;
end
if (!issue_n[ariane_pkg::SUPERSCALAR].valid) begin
if (!issue_n[CVA6Cfg.NrIssuePorts-1].valid) begin
if (took0) begin
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[ariane_pkg::SUPERSCALAR];
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[ariane_pkg::SUPERSCALAR];
issue_n[CVA6Cfg.NrIssuePorts-1].valid = fetch_entry_valid[CVA6Cfg.NrIssuePorts-1];
issue_n[CVA6Cfg.NrIssuePorts-1].instr = truncated[CVA6Cfg.NrIssuePorts-1];
end else begin
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[0];
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[0];
issue_n[CVA6Cfg.NrIssuePorts-1].valid = fetch_entry_valid[0];
issue_n[CVA6Cfg.NrIssuePorts-1].instr = truncated[0];
end
end
if (flush) begin
for (int unsigned i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
issue_n[i].valid = 1'b0;
end
end
@ -229,16 +237,18 @@ module cva6_rvfi
always_comb begin : issue_fifo
mem_n = mem_q;
if (decoded_instr_valid && decoded_instr_ack && !flush_unissued_instr) begin
mem_n[issue_pointer] = '{
rs1_rdata: rs1_forwarding,
rs2_rdata: rs2_forwarding,
lsu_addr: '0,
lsu_rmask: '0,
lsu_wmask: '0,
lsu_wdata: '0,
instr: issue_q[0].instr
};
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
if (decoded_instr_valid[i] && decoded_instr_ack[i] && !flush_unissued_instr) begin
mem_n[issue_pointer[i]] = '{
rs1_rdata: rs1[i],
rs2_rdata: rs2[i],
lsu_addr: '0,
lsu_rmask: '0,
lsu_wmask: '0,
lsu_wdata: '0,
instr: issue_q[i].instr
};
end
end
if (lsu_rmask != 0) begin
@ -247,7 +257,7 @@ module cva6_rvfi
end else if (lsu_wmask != 0) begin
mem_n[lsu_addr_trans_id].lsu_addr = lsu_addr;
mem_n[lsu_addr_trans_id].lsu_wmask = lsu_wmask;
mem_n[lsu_addr_trans_id].lsu_wdata = wbdata[1];
mem_n[lsu_addr_trans_id].lsu_wdata = wbdata[STORE_WB];
end
end
@ -266,20 +276,34 @@ module cva6_rvfi
always_ff @(posedge clk_i) begin
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
logic exception;
exception = commit_instr_valid[i][0] && ex_commit_valid;
rvfi_instr_o[i].valid <= (commit_ack[i] && !ex_commit_valid) ||
logic valid;
exception = (i == 0) && commit_instr_valid[i] && ex_commit_valid && !commit_drop[i];
valid = (commit_ack[i] && !ex_commit_valid && !commit_drop[i]) ||
(exception && (ex_commit_cause == riscv::ENV_CALL_MMODE ||
ex_commit_cause == riscv::ENV_CALL_SMODE ||
ex_commit_cause == riscv::ENV_CALL_UMODE));
rvfi_instr_o[i].insn <= mem_q[commit_pointer[i]].instr;
// when trap, the instruction is not executed
rvfi_instr_o[i].trap <= exception;
rvfi_instr_o[i].valid <= valid;
rvfi_instr_o[i].insn <= mem_q[commit_pointer[i]].instr;
// when synchronous trap, the instruction is not executed
rvfi_instr_o[i].trap <= exception && !ex_commit_cause[31];
if (exception && ex_commit_cause[31]) begin
rvfi_intr[i] <= 'b101;
end else if (exception) begin
rvfi_intr[i] <= 'b11;
end
if (valid) begin
rvfi_intr[i] <= 0;
end
rvfi_instr_o[i].intr <= rvfi_intr[i];
rvfi_instr_o[i].cause <= ex_commit_cause;
rvfi_instr_o[i].mode <= (CVA6Cfg.DebugEn && debug_mode) ? 2'b10 : priv_lvl;
rvfi_instr_o[i].ixl <= CVA6Cfg.XLEN == 64 ? 2 : 1;
rvfi_instr_o[i].rs1_addr <= commit_instr_rs1[i][4:0];
rvfi_instr_o[i].rs2_addr <= commit_instr_rs2[i][4:0];
rvfi_instr_o[i].rd_addr <= commit_instr_rd[i][4:0];
rvfi_instr_o[i].rs1_addr <= commit_instr_rs1[i];
rvfi_instr_o[i].rs2_addr <= commit_instr_rs2[i];
rvfi_instr_o[i].rd_addr <= commit_instr_rd[i];
rvfi_instr_o[i].rd_wdata <= (CVA6Cfg.FpPresent && is_rd_fpr(
commit_instr_op[i]
)) ? commit_instr_result[i] : wdata[i];
@ -312,14 +336,12 @@ module cva6_rvfi
assign rvfi_csr_o.``CSR_NAME``.rmask = CSR_ENABLE_COND ? 1 : 0; \
assign rvfi_csr_o.``CSR_NAME``.wmask = (rvfi_csr_o.``CSR_NAME``.rdata != {{CVA6Cfg.XLEN - $bits(CSR_SOURCE_NAME)}, CSR_SOURCE_NAME}) && CSR_ENABLE_COND;
`define COMMA ,
`define CONNECT_RVFI_SAME(CSR_ENABLE_COND, CSR_NAME) \
`CONNECT_RVFI_FULL(CSR_ENABLE_COND, CSR_NAME, csr.``CSR_NAME``_q)
`CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, fflags, csr.fcsr_q.fflags)
`CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, frm, csr.fcsr_q.frm)
`CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, fcsr, { csr.fcsr_q.frm `COMMA csr.fcsr_q.fflags})
`CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, fcsr, {csr.fcsr_q.frm, csr.fcsr_q.fflags})
`CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, ftran, csr.fcsr_q.fprec)
`CONNECT_RVFI_SAME(CVA6Cfg.FpPresent, dcsr)
@ -350,7 +372,7 @@ module cva6_rvfi
`CONNECT_RVFI_FULL(1'b1, mstatus, csr.mstatus_extended)
bit [31:0] mstatush_q;
`CONNECT_RVFI_FULL(1'b1, mstatush, mstatush_q)
`CONNECT_RVFI_FULL(1'b1, mstatush, mstatush_q)
`CONNECT_RVFI_FULL(1'b1, misa, IsaCode)
@ -394,7 +416,7 @@ module cva6_rvfi
`CONNECT_RVFI_SAME(1'b1, icache)
`CONNECT_RVFI_SAME(CVA6Cfg.EnableAccelerator, acc_cons)
`CONNECT_RVFI_SAME(CVA6Cfg.RVZCMT, jvt)
`CONNECT_RVFI_FULL(1'b1, pmpcfg0, csr.pmpcfg_q[CVA6Cfg.XLEN/8-1:0])
`CONNECT_RVFI_FULL(CVA6Cfg.XLEN == 32, pmpcfg1, csr.pmpcfg_q[7:4])
@ -405,7 +427,8 @@ module cva6_rvfi
genvar i;
generate
for (i = 0; i < 16; i++) begin
`CONNECT_RVFI_FULL(1'b1, pmpaddr[i], csr.pmpaddr_q[i][CVA6Cfg.PLEN-3:0])
`CONNECT_RVFI_FULL(1'b1, pmpaddr[i], {
csr.pmpaddr_q[i][CVA6Cfg.PLEN-3:1], pmpcfg_q[i].addr_mode[1]})
end
endgenerate
;

View file

@ -22,23 +22,24 @@ module cva6_rvfi_probes
) (
input logic flush_i,
input logic [SUPERSCALAR:0] issue_instr_ack_i,
input logic [SUPERSCALAR:0] fetch_entry_valid_i,
input logic [SUPERSCALAR:0][31:0] instruction_i,
input logic [SUPERSCALAR:0] is_compressed_i,
input logic flush_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] issue_instr_ack_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] fetch_entry_valid_i,
input logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_i,
input logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer_i,
input logic [CVA6Cfg.NrIssuePorts-1 : 0][CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_i,
input logic [ CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer_i,
input logic flush_unissued_instr_i,
input logic decoded_instr_valid_i,
input logic decoded_instr_ack_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] decoded_instr_valid_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] decoded_instr_ack_i,
input logic [CVA6Cfg.XLEN-1:0] rs1_forwarding_i,
input logic [CVA6Cfg.XLEN-1:0] rs2_forwarding_i,
input logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs1_i,
input logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs2_i,
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_i,
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_drop_i,
input exception_t ex_commit_i,
input riscv::priv_lvl_t priv_lvl_i,
@ -50,6 +51,7 @@ module cva6_rvfi_probes
input logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.XLEN-1:0] wdata_i,
input rvfi_probes_csr_t csr_i,
input logic [1:0] irq_i,
output rvfi_probes_t rvfi_probes_o
);
@ -63,7 +65,7 @@ module cva6_rvfi_probes
instr = '0;
instr.flush = flush_i;
instr.issue_instr_ack = issue_instr_ack_i[0];
instr.issue_instr_ack = issue_instr_ack_i;
instr.fetch_entry_valid = fetch_entry_valid_i;
instr.instruction = instruction_i;
instr.is_compressed = is_compressed_i;
@ -74,8 +76,8 @@ module cva6_rvfi_probes
instr.decoded_instr_valid = decoded_instr_valid_i;
instr.decoded_instr_ack = decoded_instr_ack_i;
instr.rs1_forwarding = rs1_forwarding_i;
instr.rs2_forwarding = rs2_forwarding_i;
instr.rs1 = rs1_i;
instr.rs2 = rs2_i;
instr.ex_commit_cause = ex_commit_i.cause;
instr.ex_commit_valid = ex_commit_i.valid;
@ -103,10 +105,12 @@ module cva6_rvfi_probes
instr.commit_instr_valid[i] = commit_instr_i[i].valid;
end
instr.commit_drop = commit_drop_i;
instr.commit_ack = commit_ack_i;
instr.wdata = wdata_i;
csr = csr_i;
csr.mip_q = csr_i.mip_q | ({{CVA6Cfg.XLEN - 1{1'b0}}, CVA6Cfg.RVS && irq_i[1]} << riscv::IRQ_S_EXT);
end

View file

@ -0,0 +1,66 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module cvxif_compressed_if_driver #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
input logic flush_i,
// CVA6 Hart id
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
input logic is_compressed_i,
input logic is_illegal_i,
input logic [31:0] instruction_i,
output logic is_compressed_o,
output logic is_illegal_o,
output logic [31:0] instruction_o,
input logic stall_i,
output logic stall_o,
// CVXIF Compressed interface
input logic compressed_ready_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
output x_compressed_req_t compressed_req_o
);
always_comb begin
is_illegal_o = is_illegal_i;
instruction_o = instruction_i;
is_compressed_o = is_compressed_i;
compressed_valid_o = 1'b0;
compressed_req_o.instr = '0;
compressed_req_o.hartid = hart_id_i;
stall_o = stall_i;
if (is_illegal_i) begin
compressed_valid_o = is_illegal_i;
compressed_req_o.instr = instruction_i[15:0];
is_illegal_o = ~compressed_resp_i.accept;
instruction_o = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i;
is_compressed_o = compressed_resp_i.accept ? 1'b0 : is_compressed_i;
if (~stall_i) begin
// Propagate stall from macro decoder or wait for compressed ready if compressed transaction is happening.
stall_o = (compressed_valid_o && ~compressed_ready_i);
end
end
if (flush_i) begin
compressed_valid_o = 1'b0;
compressed_req_o.instr = '0;
compressed_req_o.hartid = hart_id_i;
end
end
endmodule

View file

@ -0,0 +1,49 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module compressed_instr_decoder #(
parameter type copro_compressed_resp_t = logic,
parameter int NbInstr = 1,
parameter copro_compressed_resp_t CoproInstr [NbInstr] = {0},
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic compressed_valid_i,
input x_compressed_req_t compressed_req_i,
output logic compressed_ready_o,
output x_compressed_resp_t compressed_resp_o
);
logic [NbInstr-1:0] sel;
for (genvar i = 0; i < NbInstr; i++) begin : gen_predecoder_selector
assign sel[i] = ((CoproInstr[i].mask & compressed_req_i.instr) == CoproInstr[i].instr);
end
always_comb begin
compressed_ready_o = '1;
compressed_resp_o.accept = '0;
compressed_resp_o.instr = '0;
for (int unsigned i = 0; i < NbInstr; i++) begin
if (sel[i] && compressed_valid_i) begin
compressed_resp_o.accept = CoproInstr[i].resp.accept;
compressed_resp_o.instr = CoproInstr[i].resp.instr;
// Remap rs1 and rs2
compressed_resp_o.instr[19:15] = compressed_req_i.instr[11:7];
compressed_resp_o.instr[24:20] = compressed_req_i.instr[6:2];
end
end
end
assert property (@(posedge clk_i) $onehot0(sel))
else $warning("This offloaded instruction is valid for multiple coprocessor instructions !");
endmodule

View file

@ -0,0 +1,160 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module copro_alu
import cvxif_instr_pkg::*;
#(
parameter int unsigned NrRgprPorts = 2,
parameter int unsigned XLEN = 32,
parameter type hartid_t = logic,
parameter type id_t = logic,
parameter type registers_t = logic
) (
input logic clk_i,
input logic rst_ni,
input registers_t registers_i,
input opcode_t opcode_i,
input hartid_t hartid_i,
input id_t id_i,
input logic [ 4:0] rd_i,
output logic [XLEN-1:0] result_o,
output hartid_t hartid_o,
output id_t id_o,
output logic [ 4:0] rd_o,
output logic valid_o,
output logic we_o
);
logic [XLEN-1:0] result_n, result_q;
hartid_t hartid_n, hartid_q;
id_t id_n, id_q;
logic valid_n, valid_q;
logic [4:0] rd_n, rd_q;
logic we_n, we_q;
assign result_o = result_q;
assign hartid_o = hartid_q;
assign id_o = id_q;
assign valid_o = valid_q;
assign rd_o = rd_q;
assign we_o = we_q;
always_comb begin
case (opcode_i)
cvxif_instr_pkg::NOP: begin
result_n = '0;
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = '0;
we_n = '0;
end
cvxif_instr_pkg::ADD: begin
result_n = registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::DOUBLE_RS1: begin
result_n = registers_i[0] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::DOUBLE_RS2: begin
result_n = registers_i[1] + registers_i[1];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::ADD_MULTI: begin
result_n = registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::MADD_RS3_R4: begin
result_n = NrRgprPorts == 3 ? (registers_i[0] + registers_i[1] + registers_i[2]) : (registers_i[0] + registers_i[1]);
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::MSUB_RS3_R4: begin
result_n = NrRgprPorts == 3 ? (registers_i[0] - registers_i[1] - registers_i[2]) : (registers_i[0] - registers_i[1]);
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::NMADD_RS3_R4: begin
result_n = NrRgprPorts == 3 ? ~(registers_i[0] + registers_i[1] + registers_i[2]) : ~(registers_i[0] + registers_i[1]);
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::NMSUB_RS3_R4: begin
result_n = NrRgprPorts == 3 ? ~(registers_i[0] - registers_i[1] - registers_i[2]) : ~(registers_i[0] - registers_i[1]);
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::ADD_RS3_R: begin
result_n = NrRgprPorts == 3 ? registers_i[2] + registers_i[1] + registers_i[0] : registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = 5'b01010;
we_n = 1'b1;
end
default: begin
result_n = '0;
hartid_n = '0;
id_n = '0;
valid_n = '0;
rd_n = '0;
we_n = '0;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
result_q <= '0;
hartid_q <= '0;
id_q <= '0;
valid_q <= '0;
rd_q <= '0;
we_q <= '0;
end else begin
result_q <= result_n;
hartid_q <= hartid_n;
id_q <= id_n;
valid_q <= valid_n;
rd_q <= rd_n;
we_q <= we_n;
end
end
endmodule

View file

@ -1,19 +1,32 @@
// Copyright 2021 Thales DIS design services SAS
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com)
// Example coprocessor adds rs1,rs2(,rs3) together and gives back the result to the CPU via the CoreV-X-Interface.
// Coprocessor delays the sending of the result depending on result least significant bits.
// Original Author: Guillaume Chauvon
module cvxif_example_coprocessor
import cvxif_pkg::*;
import cvxif_instr_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
// CVXIF Types
parameter int unsigned NrRgprPorts = 2,
parameter int unsigned XLEN = 32,
parameter type readregflags_t = logic,
parameter type writeregflags_t = logic,
parameter type id_t = logic,
parameter type hartid_t = logic,
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic,
parameter type x_result_t = logic,
parameter type cvxif_req_t = logic,
parameter type cvxif_resp_t = logic,
localparam type registers_t = logic [NrRgprPorts-1:0][XLEN-1:0]
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
@ -21,138 +34,119 @@ module cvxif_example_coprocessor
output cvxif_resp_t cvxif_resp_o
);
//Compressed interface
logic x_compressed_valid_i;
logic x_compressed_ready_o;
x_compressed_req_t x_compressed_req_i;
x_compressed_resp_t x_compressed_resp_o;
//Issue interface
logic x_issue_valid_i;
logic x_issue_ready_o;
x_issue_req_t x_issue_req_i;
x_issue_resp_t x_issue_resp_o;
//Commit interface
logic x_commit_valid_i;
x_commit_t x_commit_i;
//Memory interface
logic x_mem_valid_o;
logic x_mem_ready_i;
x_mem_req_t x_mem_req_o;
x_mem_resp_t x_mem_resp_i;
//Memory result interface
logic x_mem_result_valid_i;
x_mem_result_t x_mem_result_i;
//Result interface
logic x_result_valid_o;
logic x_result_ready_i;
x_result_t x_result_o;
// Compressed interface signals
x_compressed_req_t compressed_req;
x_compressed_resp_t compressed_resp;
logic compressed_valid, compressed_ready;
// Issue interface signals
x_issue_req_t issue_req;
x_issue_resp_t issue_resp;
logic issue_valid, issue_ready;
assign x_compressed_valid_i = cvxif_req_i.x_compressed_valid;
assign x_compressed_req_i = cvxif_req_i.x_compressed_req;
assign x_issue_valid_i = cvxif_req_i.x_issue_valid;
assign x_issue_req_i = cvxif_req_i.x_issue_req;
assign x_commit_valid_i = cvxif_req_i.x_commit_valid;
assign x_commit_i = cvxif_req_i.x_commit;
assign x_mem_ready_i = cvxif_req_i.x_mem_ready;
assign x_mem_resp_i = cvxif_req_i.x_mem_resp;
assign x_mem_result_valid_i = cvxif_req_i.x_mem_result_valid;
assign x_mem_result_i = cvxif_req_i.x_mem_result;
assign x_result_ready_i = cvxif_req_i.x_result_ready;
// Register interface signals
x_register_t register;
logic register_valid;
assign cvxif_resp_o.x_compressed_ready = x_compressed_ready_o;
assign cvxif_resp_o.x_compressed_resp = x_compressed_resp_o;
assign cvxif_resp_o.x_issue_ready = x_issue_ready_o;
assign cvxif_resp_o.x_issue_resp = x_issue_resp_o;
assign cvxif_resp_o.x_mem_valid = x_mem_valid_o;
assign cvxif_resp_o.x_mem_req = x_mem_req_o;
assign cvxif_resp_o.x_result_valid = x_result_valid_o;
assign cvxif_resp_o.x_result = x_result_o;
// Decoder and alu signals
registers_t registers;
opcode_t opcode;
hartid_t issue_hartid, hartid;
id_t issue_id, id;
logic [4:0] issue_rd, rd;
logic [XLEN-1:0] result;
logic we;
//Compressed interface
assign x_compressed_ready_o = '0;
assign x_compressed_resp_o.instr = '0;
assign x_compressed_resp_o.accept = '0;
// Issue and Register interface
// Mandatory when X_ISSUE_REGISTER_SPLIT = 0
assign cvxif_resp_o.compressed_ready = compressed_ready;
assign cvxif_resp_o.compressed_resp = compressed_resp;
assign cvxif_resp_o.issue_ready = issue_ready;
assign cvxif_resp_o.issue_resp = issue_resp;
assign cvxif_resp_o.register_ready = cvxif_resp_o.issue_ready;
assign compressed_req = cvxif_req_i.compressed_req;
assign compressed_valid = cvxif_req_i.compressed_valid;
assign issue_req = cvxif_req_i.issue_req;
assign issue_valid = cvxif_req_i.issue_valid;
assign register = cvxif_req_i.register;
assign register_valid = cvxif_req_i.register_valid;
compressed_instr_decoder #(
.copro_compressed_resp_t(cvxif_instr_pkg::copro_compressed_resp_t),
.NbInstr(cvxif_instr_pkg::NbCompInstr),
.CoproInstr(cvxif_instr_pkg::CoproCompInstr),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) compressed_instr_decoder_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.compressed_valid_i(compressed_valid),
.compressed_req_i (compressed_req),
.compressed_ready_o(compressed_ready),
.compressed_resp_o (compressed_resp)
);
instr_decoder #(
.copro_issue_resp_t (cvxif_instr_pkg::copro_issue_resp_t),
.opcode_t (cvxif_instr_pkg::opcode_t),
.NbInstr (cvxif_instr_pkg::NbInstr),
.CoproInstr(cvxif_instr_pkg::CoproInstr)
.CoproInstr(cvxif_instr_pkg::CoproInstr),
.NrRgprPorts(NrRgprPorts),
.hartid_t (hartid_t),
.id_t (id_t),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t (x_issue_resp_t),
.x_register_t (x_register_t),
.registers_t (registers_t)
) instr_decoder_i (
.clk_i (clk_i),
.x_issue_req_i (x_issue_req_i),
.x_issue_resp_o(x_issue_resp_o)
.clk_i (clk_i),
.rst_ni (rst_ni),
.issue_valid_i (issue_valid),
.issue_req_i (issue_req),
.issue_ready_o (issue_ready),
.issue_resp_o (issue_resp),
.register_valid_i(register_valid),
.register_i (register),
.registers_o (registers),
.opcode_o (opcode),
.hartid_o (issue_hartid),
.id_o (issue_id),
.rd_o (issue_rd)
);
typedef struct packed {
x_issue_req_t req;
x_issue_resp_t resp;
} x_issue_t;
logic fifo_full, fifo_empty;
logic x_issue_ready_q;
logic instr_push, instr_pop;
x_issue_t req_i;
x_issue_t req_o;
assign instr_push = x_issue_resp_o.accept ? 1 : 0;
assign instr_pop = (x_commit_i.x_commit_kill && x_commit_valid_i) || x_result_valid_o;
assign x_issue_ready_q = ~fifo_full; // if something is in the fifo, the instruction is being processed
// so we can't receive anything else
assign req_i.req = x_issue_req_i;
assign req_i.resp = x_issue_resp_o;
always_ff @(posedge clk_i or negedge rst_ni) begin : regs
if (!rst_ni) begin
x_issue_ready_o <= 1;
end else begin
x_issue_ready_o <= x_issue_ready_q;
end
end
cva6_fifo_v3 #(
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
.DATA_WIDTH (64),
.DEPTH (8),
.dtype (x_issue_t),
.FPGA_EN (CVA6Cfg.FpgaEn)
) fifo_commit_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (1'b0),
.testmode_i(1'b0),
.full_o (fifo_full),
.empty_o (fifo_empty),
.usage_o (),
.data_i (req_i),
.push_i (instr_push),
.data_o (req_o),
.pop_i (instr_pop)
);
logic [3:0] c;
counter #(
.WIDTH(4)
) counter_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (~x_commit_i.x_commit_kill && x_commit_valid_i),
.en_i (1'b1),
.load_i (),
.down_i (),
.d_i (),
.q_o (c),
.overflow_o()
logic alu_valid;
// Result interface
copro_alu #(
.NrRgprPorts(NrRgprPorts),
.XLEN(XLEN),
.hartid_t(hartid_t),
.id_t(id_t),
.registers_t(registers_t)
) i_copro_alu (
.clk_i (clk_i),
.rst_ni (rst_ni),
.registers_i(registers),
.opcode_i (opcode),
.hartid_i (issue_hartid),
.id_i (issue_id),
.rd_i (issue_rd),
.hartid_o (hartid),
.id_o (id),
.result_o (result),
.valid_o (alu_valid),
.rd_o (rd),
.we_o (we)
);
always_comb begin
x_result_o.data = req_o.req.rs[0] + req_o.req.rs[1] + (X_NUM_RS == 3 ? req_o.req.rs[2] : 0);
x_result_valid_o = (c == x_result_o.data[3:0]) && ~fifo_empty ? 1 : 0;
x_result_o.id = req_o.req.id;
x_result_o.rd = req_o.req.instr[11:7];
x_result_o.we = req_o.resp.writeback & x_result_valid_o;
x_result_o.exc = 0;
x_result_o.exccode = 0;
cvxif_resp_o.result_valid = alu_valid; //TODO Should wait for ready from CPU
cvxif_resp_o.result.hartid = hartid;
cvxif_resp_o.result.id = id;
cvxif_resp_o.result.data = result;
cvxif_resp_o.result.rd = rd;
cvxif_resp_o.result.we = we;
end
endmodule

View file

@ -7,40 +7,147 @@
//
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com)
package cvxif_instr_pkg;
typedef enum logic [3:0] {
ILLEGAL = 4'b0000,
NOP = 4'b0001,
ADD = 4'b0010,
DOUBLE_RS1 = 4'b0011,
DOUBLE_RS2 = 4'b0100,
ADD_MULTI = 4'b0101,
MADD_RS3_R4 = 4'b0110,
MSUB_RS3_R4 = 4'b0111,
NMADD_RS3_R4 = 4'b1000,
NMSUB_RS3_R4 = 4'b1001,
ADD_RS3_R = 4'b1111
} opcode_t;
typedef struct packed {
logic [31:0] instr;
logic [31:0] mask;
cvxif_pkg::x_issue_resp_t resp;
logic accept;
logic writeback; // TODO depends on dualwrite
logic [2:0] register_read; // TODO Nr read ports
} issue_resp_t;
typedef struct packed {
logic accept;
logic [31:0] instr;
} compressed_resp_t;
typedef struct packed {
logic [31:0] instr;
logic [31:0] mask;
issue_resp_t resp;
opcode_t opcode;
} copro_issue_resp_t;
// 2 Possible RISCV instructions for Coprocessor
parameter int unsigned NbInstr = 2;
typedef struct packed {
logic [15:0] instr;
logic [15:0] mask;
compressed_resp_t resp;
} copro_compressed_resp_t;
// 4 Possible RISCV instructions for Coprocessor
parameter int unsigned NbInstr = 10;
parameter copro_issue_resp_t CoproInstr[NbInstr] = '{
'{
instr: 32'b00000_00_00000_00000_0_00_00000_0101011, // custom1 opcode
mask: 32'b00000_00_00000_00000_0_00_00000_1111111,
resp : '{
accept : 1'b1,
writeback : 1'b0,
dualwrite : 1'b0,
dualread : 1'b0,
loadstore : 1'b0,
exc : 1'b0
}
// Custom Nop
instr:
32'b00000_00_00000_00000_0_00_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b0, register_read : {1'b0, 1'b0, 1'b0}},
opcode : NOP
},
'{
instr: 32'b00000_00_00000_00000_0_00_00000_1011011, // custom2 opcode
mask: 32'b00000_00_00000_00000_0_00_00000_1111111,
resp : '{
accept : 1'b1,
writeback : 1'b1,
dualwrite : 1'b0,
dualread : 1'b0,
loadstore : 1'b0,
exc : 1'b0
}
// Custom Add : cus_add rd, rs1, rs2
instr:
32'b00000_00_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b1}},
opcode : ADD
},
'{
// Custom Add rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_01_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b0, 1'b1}},
opcode : DOUBLE_RS1
},
'{
// Custom Add rs2 : cus_add rd, rs2, rs2
instr:
32'b00000_10_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b0}},
opcode : DOUBLE_RS2
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_11_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b1}},
opcode : ADD_MULTI
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00001_00_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1000011, // MADD opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : MADD_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1000111, // MSUB opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : MSUB_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1001011, // NMSUB opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : NMSUB_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1001111, // NMADD opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : NMADD_RS3_R4
}
};
parameter int unsigned NbCompInstr = 2;
parameter copro_compressed_resp_t CoproCompInstr[NbCompInstr] = '{
// C_NOP
'{
instr : 16'b111_0_00000_00000_00,
mask : 16'b111_1_00000_00000_11,
resp : '{accept : 1'b1, instr : 32'b00000_00_00000_00000_0_00_00000_1111011}
},
'{
instr : 16'b111_1_00000_00000_00,
mask : 16'b111_1_00000_00000_11,
resp : '{accept : 1'b1, instr : 32'b00000_00_00000_00000_0_01_01010_1111011}
}
};

View file

@ -1,46 +1,86 @@
// Copyright 2021 Thales DIS design services SAS
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com)
// Original Author: Guillaume Chauvon
module instr_decoder
import cvxif_pkg::*;
#(
parameter int NbInstr = 1,
parameter cvxif_instr_pkg::copro_issue_resp_t CoproInstr[NbInstr] = {0}
module instr_decoder #(
parameter type copro_issue_resp_t = logic,
parameter type opcode_t = logic,
parameter int NbInstr = 1,
parameter copro_issue_resp_t CoproInstr [NbInstr] = {0},
parameter int unsigned NrRgprPorts = 2,
parameter type hartid_t = logic,
parameter type id_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type registers_t = logic
) (
input logic clk_i,
input x_issue_req_t x_issue_req_i,
output x_issue_resp_t x_issue_resp_o
input logic clk_i,
input logic rst_ni,
input logic issue_valid_i,
input x_issue_req_t issue_req_i,
output logic issue_ready_o,
output x_issue_resp_t issue_resp_o,
input logic register_valid_i,
input x_register_t register_i,
output registers_t registers_o,
output opcode_t opcode_o,
output hartid_t hartid_o,
output id_t id_o,
output logic [4:0] rd_o
);
logic [NbInstr-1:0] sel;
logic rs1_ready;
logic rs2_ready;
logic rs3_ready;
for (genvar i = 0; i < NbInstr; i++) begin : gen_predecoder_selector
assign sel[i] = ((CoproInstr[i].mask & x_issue_req_i.instr) == CoproInstr[i].instr);
assign sel[i] = ((CoproInstr[i].mask & issue_req_i.instr) == CoproInstr[i].instr);
end
always_comb begin
x_issue_resp_o.accept = '0;
x_issue_resp_o.writeback = '0;
x_issue_resp_o.dualwrite = '0;
x_issue_resp_o.dualread = '0;
x_issue_resp_o.loadstore = '0;
x_issue_resp_o.exc = '0;
rs1_ready = '0;
rs2_ready = '0;
rs3_ready = '0;
issue_ready_o = '0;
issue_resp_o.accept = '0;
issue_resp_o.writeback = '0;
issue_resp_o.register_read = '0;
registers_o = '0;
opcode_o = opcode_t'(0); // == ILLEGAL see cvxif_instr_pkg.sv
hartid_o = '0;
id_o = '0;
rd_o = '0;
for (int unsigned i = 0; i < NbInstr; i++) begin
if (sel[i]) begin
x_issue_resp_o.accept = CoproInstr[i].resp.accept;
x_issue_resp_o.writeback = CoproInstr[i].resp.writeback;
x_issue_resp_o.dualwrite = CoproInstr[i].resp.dualwrite;
x_issue_resp_o.dualread = CoproInstr[i].resp.dualread;
x_issue_resp_o.loadstore = CoproInstr[i].resp.loadstore;
x_issue_resp_o.exc = CoproInstr[i].resp.exc;
if (sel[i] && issue_valid_i) begin
issue_resp_o.accept = CoproInstr[i].resp.accept;
issue_resp_o.writeback = CoproInstr[i].resp.writeback;
issue_resp_o.register_read = CoproInstr[i].resp.register_read; // Warning : potential 3 bits vector into 2 bits one
if (issue_resp_o.accept) begin
rs1_ready = (~CoproInstr[i].resp.register_read[0] || register_i.rs_valid[0]);
rs2_ready = (~CoproInstr[i].resp.register_read[1] || register_i.rs_valid[1]);
rs3_ready = NrRgprPorts == 3 ? (~CoproInstr[i].resp.register_read[2] || register_i.rs_valid[2]) : 1'b1;
issue_ready_o = rs1_ready && rs2_ready && rs3_ready;
end
opcode_o = CoproInstr[i].opcode;
id_o = issue_req_i.id;
hartid_o = issue_req_i.hartid;
rd_o = issue_req_i.instr[11:7];
for (int unsigned j = 0; j < NrRgprPorts; j++) begin
registers_o[j] = issue_resp_o.register_read[j] ? register_i.rs[j] : '0;
end
end
end
// Coprocessor could not decode offloaded instruction -> instruction is not accepted
if (issue_valid_i && ~(|sel)) begin
issue_ready_o = 1'b1;
end
end
assert property (@(posedge clk_i) $onehot0(sel))

View file

@ -1,13 +1,14 @@
// Copyright 2021 Thales DIS design services SAS
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume CHAUVON (guillaume.chauvon@thalesgroup.com)
// Original Author: Guillaume Chauvon
// Functional Unit for the logic of the CoreV-X-Interface
// Functional Unit for the CoreV-X-Interface
// Handles Result interface and exception forwarding to next stages.
module cvxif_fu
@ -15,117 +16,64 @@ module cvxif_fu
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type exception_t = logic,
parameter type fu_data_t = logic
parameter type x_result_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
// FU data needed to execute instruction - ISSUE_STAGE
input fu_data_t fu_data_i,
// Current privilege mode - CSR_REGFILE
input riscv::priv_lvl_t priv_lvl_i,
input logic rst_ni,
// Virtualization mode state - CSR_REGFILE
input logic v_i,
// CVXIF instruction is valid - ISSUE_STAGE
input logic x_valid_i,
// CVXIF is ready - ISSUE_STAGE
output logic x_ready_o,
input logic x_valid_i,
// Transaction ID - ISSUE_STAGE
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_i,
// Instruction is illegal, determined during CVXIF issue transaction - ISSUE_STAGE
input logic x_illegal_i,
// Offloaded instruction - ISSUE_STAGE
input logic [ 31:0] x_off_instr_i,
// CVXIF transaction ID - ISSUE_STAGE
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
input logic [ 31:0] x_off_instr_i,
// CVXIF is ready - ISSUE_STAGE
output logic x_ready_o,
// CVXIF result transaction ID - ISSUE_STAGE
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
// CVXIF exception - ISSUE_STAGE
output exception_t x_exception_o,
output exception_t x_exception_o,
// CVXIF FU result - ISSUE_STAGE
output logic [ CVA6Cfg.XLEN-1:0] x_result_o,
output logic [ CVA6Cfg.XLEN-1:0] x_result_o,
// CVXIF result valid - ISSUE_STAGE
output logic x_valid_o,
output logic x_valid_o,
// CVXIF write enable - ISSUE_STAGE
output logic x_we_o,
// CVXIF request - SUBSYSTEM
output cvxif_pkg::cvxif_req_t cvxif_req_o,
// CVXIF response - SUBSYSTEM
input cvxif_pkg::cvxif_resp_t cvxif_resp_i
output logic x_we_o,
// CVXIF destination register - ISSUE_STAGE
output logic [ 4:0] x_rd_o,
// CVXIF result interface
input logic result_valid_i,
input x_result_t result_i,
output logic result_ready_o
);
localparam X_NUM_RS = ariane_pkg::NR_RGPR_PORTS;
logic illegal_n, illegal_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] illegal_id_n, illegal_id_q;
logic [31:0] illegal_instr_n, illegal_instr_q;
logic [X_NUM_RS-1:0] rs_valid;
if (cvxif_pkg::X_NUM_RS == 3) begin : gen_third_operand
assign rs_valid = 3'b111;
end else begin : gen_no_third_operand
assign rs_valid = 2'b11;
end
assign result_ready_o = 1'b1;
assign x_ready_o = 1'b1; // Readyness of cvxif_fu is determined in issue stage by CVXIF issue interface
// Result signals
assign x_valid_o = x_illegal_i || result_valid_i;
assign x_result_o = result_i.data;
assign x_trans_id_o = x_illegal_i ? x_trans_id_i : result_i.id;
assign x_we_o = result_i.we;
assign x_rd_o = result_i.rd;
// Handling of illegal instruction exception
always_comb begin
cvxif_req_o = '0;
cvxif_req_o.x_result_ready = 1'b1;
x_ready_o = cvxif_resp_i.x_issue_ready;
if (x_valid_i) begin
cvxif_req_o.x_issue_valid = x_valid_i;
cvxif_req_o.x_issue_req.instr = x_off_instr_i;
cvxif_req_o.x_issue_req.mode = priv_lvl_i;
cvxif_req_o.x_issue_req.id = fu_data_i.trans_id;
cvxif_req_o.x_issue_req.rs[0] = fu_data_i.operand_a;
cvxif_req_o.x_issue_req.rs[1] = fu_data_i.operand_b;
if (cvxif_pkg::X_NUM_RS == 3) begin
cvxif_req_o.x_issue_req.rs[2] = fu_data_i.imm;
end
cvxif_req_o.x_issue_req.rs_valid = rs_valid;
cvxif_req_o.x_commit_valid = x_valid_i;
cvxif_req_o.x_commit.id = fu_data_i.trans_id;
cvxif_req_o.x_commit.x_commit_kill = 1'b0;
end
end
always_comb begin
illegal_n = illegal_q;
illegal_id_n = illegal_id_q;
illegal_instr_n = illegal_instr_q;
if (~cvxif_resp_i.x_issue_resp.accept && cvxif_req_o.x_issue_valid && cvxif_resp_i.x_issue_ready && ~illegal_n) begin
illegal_n = 1'b1;
illegal_id_n = cvxif_req_o.x_issue_req.id;
illegal_instr_n = cvxif_req_o.x_issue_req.instr;
end
x_valid_o = cvxif_resp_i.x_result_valid; //Read result only when CVXIF is enabled
x_trans_id_o = x_valid_o ? cvxif_resp_i.x_result.id : '0;
x_result_o = x_valid_o ? cvxif_resp_i.x_result.data : '0;
x_exception_o.cause = x_valid_o ? {{(CVA6Cfg.XLEN-6){1'b0}}, cvxif_resp_i.x_result.exccode} : '0;
x_exception_o.valid = x_valid_o ? cvxif_resp_i.x_result.exc : '0;
x_exception_o.tval = '0;
x_exception_o.valid = x_illegal_i;
x_exception_o.cause = x_illegal_i ? riscv::ILLEGAL_INSTR : '0;
if (CVA6Cfg.TvalEn)
x_exception_o.tval = x_off_instr_i; // TODO Optimization : Set exception in IRO.
// Hypervisor exception fields
x_exception_o.tval2 = {CVA6Cfg.GPLEN{1'b0}};
x_exception_o.tinst = '0;
x_exception_o.tval2 = '0;
x_exception_o.gva = '0;
x_we_o = x_valid_o ? cvxif_resp_i.x_result.we : '0;
if (illegal_n) begin
if (~x_valid_o) begin
x_trans_id_o = illegal_id_n;
x_result_o = '0;
x_valid_o = 1'b1;
x_exception_o.cause = riscv::ILLEGAL_INSTR;
x_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn) x_exception_o.tval = illegal_instr_n;
x_exception_o.tinst = '0;
x_exception_o.tval2 = '0;
x_exception_o.gva = '0;
x_we_o = '0;
illegal_n = '0; // Reset flag for illegal instr. illegal_id and illegal instr values are a don't care, no need to reset it.
end
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
illegal_q <= 1'b0;
illegal_id_q <= '0;
illegal_instr_q <= '0;
end else begin
illegal_q <= illegal_n;
illegal_id_q <= illegal_id_n;
illegal_instr_q <= illegal_instr_n;
end
x_exception_o.gva = CVA6Cfg.RVH ? v_i : 1'b0;
end
endmodule

View file

@ -0,0 +1,66 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module cvxif_issue_register_commit_if_driver #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic
) (
// CVA6 inputs
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
// CVXIF Issue interface
input logic issue_ready_i,
input x_issue_resp_t issue_resp_i,
output logic issue_valid_o,
output x_issue_req_t issue_req_o,
// CVXIF Register interface
input logic register_ready_i,
output logic register_valid_o,
output x_register_t register_o,
// CVXIF Commit interface
output logic commit_valid_o,
output x_commit_t commit_o,
// IRO in/out
input logic valid_i,
input logic [31:0] x_off_instr_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_i,
input [(CVA6Cfg.NrRgprPorts/CVA6Cfg.NrIssuePorts)-1:0][CVA6Cfg.XLEN-1:0] register_i,
input logic [(CVA6Cfg.NrRgprPorts/CVA6Cfg.NrIssuePorts)-1:0] rs_valid_i
);
// X_ISSUE_REGISTER_SPLIT = 0 : Issue and register transactions are synchrone
// Mandatory assignement
assign register_valid_o = issue_valid_o;
assign register_o.hartid = issue_req_o.hartid;
assign register_o.id = issue_req_o.id;
always_comb begin
issue_valid_o = valid_i && ~flush_i;
issue_req_o.instr = x_off_instr_i;
issue_req_o.hartid = hart_id_i;
issue_req_o.id = x_trans_id_i;
register_o.rs = register_i;
register_o.rs_valid = rs_valid_i;
end
/* WARNING */
// Always commit since speculation in execute in not possible : TODO to be verified
// Always do commit transaction with issue
// If instruction goes to execute then it is not speculative
assign commit_valid_o = issue_valid_o && issue_ready_i;
assign commit_o.hartid = issue_req_o.hartid;
assign commit_o.id = issue_req_o.id;
assign commit_o.commit_kill = 1'b0;
endmodule

View file

@ -48,6 +48,10 @@ module decoder
input logic is_last_macro_instr_i,
// Is mvsa01/mva01s macro instruction - macro_decoder
input logic is_double_rd_macro_instr_i,
// Zcmt instruction - FRONTEND
input logic is_zcmt_i,
// Jump address - zcmt_decoder
input logic [CVA6Cfg.XLEN-1:0] jump_address_i,
// Is a branch predict instruction - FRONTEND
input branchpredict_sbe_t branch_predict_i,
// If an exception occured in fetch stage - FRONTEND
@ -112,7 +116,8 @@ module decoder
SBIMM,
UIMM,
JIMM,
RS3
RS3,
MUX_RD_RS3
} imm_select;
logic [CVA6Cfg.XLEN-1:0] imm_i_type;
@ -120,7 +125,6 @@ module decoder
logic [CVA6Cfg.XLEN-1:0] imm_sb_type;
logic [CVA6Cfg.XLEN-1:0] imm_u_type;
logic [CVA6Cfg.XLEN-1:0] imm_uj_type;
logic [CVA6Cfg.XLEN-1:0] imm_bi_type;
// ---------------------------------------
// Accelerator instructions' first-pass decoder
@ -178,18 +182,19 @@ module decoder
instruction_o.use_zimm = 1'b0;
instruction_o.bp = branch_predict_i;
instruction_o.vfp = 1'b0;
tinst = '0;
instruction_o.is_zcmt = is_zcmt_i;
ecall = 1'b0;
ebreak = 1'b0;
check_fprm = 1'b0;
tinst = 32'h0;
if (~ex_i.valid) begin
case (instr.rtype.opcode)
riscv::OpcodeSystem: begin
instruction_o.fu = CSR;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2; //TODO: needs to be checked if better way is available
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rs2 = instr.rtype.rs2; //TODO: needs to be checked if better way is available
instruction_o.rd = instr.itype.rd;
unique case (instr.itype.funct3)
3'b000: begin
@ -328,13 +333,13 @@ module decoder
if (instr.instr[25] != 1'b0) begin
instruction_o.fu = STORE;
imm_select = NOIMM;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
instruction_o.rs1 = instr.stype.rs1;
instruction_o.rs2 = instr.stype.rs2;
end else begin
instruction_o.fu = LOAD;
imm_select = NOIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
end
// Hypervisor load/store instructions when V=1 cause virtual instruction
@ -401,25 +406,25 @@ module decoder
3'b010: begin // CSRRS
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
if (instr.itype.rs1 == '0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_SET;
end
// atomically clear values in the CSR and write back to rd
3'b011: begin // CSRRC
imm_select = IIMM;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
if (instr.itype.rs1 == '0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_CLEAR;
end
// use zimm and iimm
3'b101: begin // CSRRWI
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs1 = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
instruction_o.op = ariane_pkg::CSR_WRITE;
end
3'b110: begin // CSRRSI
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs1 = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
@ -427,11 +432,11 @@ module decoder
else instruction_o.op = ariane_pkg::CSR_SET;
end
3'b111: begin // CSRRCI
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs1 = instr.itype.rs1;
imm_select = IIMM;
instruction_o.use_zimm = 1'b1;
// this is just a read
if (instr.itype.rs1 == 5'b0) instruction_o.op = ariane_pkg::CSR_READ;
if (instr.itype.rs1 == '0) instruction_o.op = ariane_pkg::CSR_READ;
else instruction_o.op = ariane_pkg::CSR_CLEAR;
end
default: illegal_instr = 1'b1;
@ -467,24 +472,24 @@ module decoder
if (CVA6Cfg.FpPresent && CVA6Cfg.XFVec && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin
automatic logic allow_replication; // control honoring of replication flag
instruction_o.fu = FPU_VEC; // Same unit, but sets 'vectorial' signal
instruction_o.rs1[4:0] = instr.rvftype.rs1;
instruction_o.rs2[4:0] = instr.rvftype.rs2;
instruction_o.rd[4:0] = instr.rvftype.rd;
check_fprm = 1'b1;
allow_replication = 1'b1;
instruction_o.fu = FPU_VEC; // Same unit, but sets 'vectorial' signal
instruction_o.rs1 = instr.rvftype.rs1;
instruction_o.rs2 = instr.rvftype.rs2;
instruction_o.rd = instr.rvftype.rd;
check_fprm = 1'b1;
allow_replication = 1'b1;
// decode vectorial FP instruction
unique case (instr.rvftype.vecfltop)
5'b00001: begin
instruction_o.op = ariane_pkg::FADD; // vfadd.vfmt - Vectorial FP Addition
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rvftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
instruction_o.op = ariane_pkg::FADD; // vfadd.vfmt - Vectorial FP Addition
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2 = instr.rvftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00010: begin
instruction_o.op = ariane_pkg::FSUB; // vfsub.vfmt - Vectorial FP Subtraction
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rvftype.rs1; // Operand B is set to rs1
instruction_o.rs2 = instr.rvftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00011:
@ -515,7 +520,7 @@ module decoder
5'b01100: begin
unique case (instr.rvftype.rs2) inside // operation encoded in rs2, `inside` for matching ?
5'b00000: begin
instruction_o.rs2[4:0] = instr.rvftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
instruction_o.rs2 = instr.rvftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
if (instr.rvftype.repl)
instruction_o.op = ariane_pkg::FMV_X2F; // vfmv.vfmt.x - GPR to FPR Move
else instruction_o.op = ariane_pkg::FMV_F2X; // vfmv.x.vfmt - FPR to GPR Move
@ -532,7 +537,7 @@ module decoder
instruction_o.op = ariane_pkg::FCVT_I2F; // vfcvt.vfmt.x - Vectorial Int to FP Conversion
5'b001??: begin
instruction_o.op = ariane_pkg::FCVT_F2F; // vfcvt.vfmt.vfmt - Vectorial FP to FP Conversion
instruction_o.rs2[4:0] = instr.rvftype.rd; // set rs2 = rd as target vector for conversion
instruction_o.rs2 = instr.rvftype.rd; // set rs2 = rd as target vector for conversion
imm_select = IIMM; // rs2 holds part of the intruction
// TODO CHECK R bit for valid fmt combinations
// determine source format
@ -715,9 +720,9 @@ module decoder
end else begin
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
end
instruction_o.rs1[4:0] = instr.rtype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2;
instruction_o.rd[4:0] = instr.rtype.rd;
instruction_o.rs1 = instr.rtype.rs1;
instruction_o.rs2 = instr.rtype.rs2;
instruction_o.rd = instr.rtype.rd;
unique case ({
instr.rtype.funct7, instr.rtype.funct3
@ -777,12 +782,19 @@ module decoder
// Bitwise Shifting
{7'b011_0000, 3'b001} : instruction_o.op = ariane_pkg::ROL; // rol
{7'b011_0000, 3'b101} : instruction_o.op = ariane_pkg::ROR; // ror
{
7'b000_0100, 3'b111
} : begin
if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::PACK_H; //packh
else illegal_instr_bm = 1'b1;
end
// Zero Extend Op RV32 encoding
{
7'b000_0100, 3'b100
} : begin
if (!CVA6Cfg.IS_XLEN64 && instr.instr[24:20] == 5'b00000)
instruction_o.op = ariane_pkg::ZEXTH;
instruction_o.op = ariane_pkg::ZEXTH; // Zero Extend Op RV32 encoding
else if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::PACK; // pack
else illegal_instr_bm = 1'b1;
end
default: begin
@ -806,10 +818,11 @@ module decoder
unique case ({
CVA6Cfg.RVB, CVA6Cfg.RVZiCond
})
2'b00: illegal_instr = illegal_instr_non_bm;
2'b01: illegal_instr = illegal_instr_non_bm & illegal_instr_zic;
2'b10: illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
2'b11: illegal_instr = illegal_instr_non_bm & illegal_instr_bm & illegal_instr_zic;
2'b00: illegal_instr = illegal_instr_non_bm;
2'b01: illegal_instr = illegal_instr_non_bm & illegal_instr_zic;
2'b10: illegal_instr = illegal_instr_non_bm & illegal_instr_bm;
2'b11: illegal_instr = illegal_instr_non_bm & illegal_instr_bm & illegal_instr_zic;
default: ; // TODO: Check that default case is not synthesized.
endcase
end
end
@ -818,10 +831,10 @@ module decoder
// 32bit Reg-Reg Operations
// --------------------------
riscv::OpcodeOp32: begin
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
instruction_o.rs1[4:0] = instr.rtype.rs1;
instruction_o.rs2[4:0] = instr.rtype.rs2;
instruction_o.rd[4:0] = instr.rtype.rd;
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
instruction_o.rs1 = instr.rtype.rs1;
instruction_o.rs2 = instr.rtype.rs2;
instruction_o.rd = instr.rtype.rd;
if (CVA6Cfg.IS_XLEN64) begin
unique case ({
instr.rtype.funct7, instr.rtype.funct3
@ -844,21 +857,21 @@ module decoder
instr.rtype.funct7, instr.rtype.funct3
})
// Shift with Add (Unsigned Word)
{7'b001_0000, 3'b010}: instruction_o.op = ariane_pkg::SH1ADDUW; // sh1add.uw
{7'b001_0000, 3'b100}: instruction_o.op = ariane_pkg::SH2ADDUW; // sh2add.uw
{7'b001_0000, 3'b110}: instruction_o.op = ariane_pkg::SH3ADDUW; // sh3add.uw
{7'b001_0000, 3'b010} : instruction_o.op = ariane_pkg::SH1ADDUW; // sh1add.uw
{7'b001_0000, 3'b100} : instruction_o.op = ariane_pkg::SH2ADDUW; // sh2add.uw
{7'b001_0000, 3'b110} : instruction_o.op = ariane_pkg::SH3ADDUW; // sh3add.uw
// Unsigned word Op's
{7'b000_0100, 3'b000}: instruction_o.op = ariane_pkg::ADDUW; // add.uw
{7'b000_0100, 3'b000} : instruction_o.op = ariane_pkg::ADDUW; // add.uw
// Bitwise Shifting
{7'b011_0000, 3'b001}: instruction_o.op = ariane_pkg::ROLW; // rolw
{7'b011_0000, 3'b101}: instruction_o.op = ariane_pkg::RORW; // rorw
// Zero Extend Op RV64 encoding
{7'b000_0100, 3'b100}:
begin
{7'b011_0000, 3'b001} : instruction_o.op = ariane_pkg::ROLW; // rolw
{7'b011_0000, 3'b101} : instruction_o.op = ariane_pkg::RORW; // rorw
{
7'b000_0100, 3'b100
} : begin
if (instr.instr[24:20] == 5'b00000)
instruction_o.op = ariane_pkg::ZEXTH;
else
illegal_instr_bm = 1'b1;
instruction_o.op = ariane_pkg::ZEXTH; // Zero Extend Op RV64 encoding
else if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::PACK_W; // packw
else illegal_instr_bm = 1'b1;
end
default: illegal_instr_bm = 1'b1;
endcase
@ -874,8 +887,8 @@ module decoder
riscv::OpcodeOpImm: begin
instruction_o.fu = ALU;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
unique case (instr.itype.funct3)
3'b000: instruction_o.op = ariane_pkg::ADD; // Add Immediate
3'b010: instruction_o.op = ariane_pkg::SLTS; // Set to one if Lower Than Immediate
@ -904,14 +917,26 @@ module decoder
unique case (instr.itype.funct3)
3'b001: begin
if (instr.instr[31:25] == 7'b0110000) begin
if (instr.instr[22:20] == 3'b100) instruction_o.op = ariane_pkg::SEXTB;
else if (instr.instr[22:20] == 3'b101) instruction_o.op = ariane_pkg::SEXTH;
else if (instr.instr[22:20] == 3'b010) instruction_o.op = ariane_pkg::CPOP;
else if (instr.instr[22:20] == 3'b000) instruction_o.op = ariane_pkg::CLZ;
else if (instr.instr[22:20] == 3'b001) instruction_o.op = ariane_pkg::CTZ;
end else if (instr.instr[31:26] == 6'b010010) instruction_o.op = ariane_pkg::BCLRI;
else if (instr.instr[31:26] == 6'b011010) instruction_o.op = ariane_pkg::BINVI;
else if (instr.instr[31:26] == 6'b001010) instruction_o.op = ariane_pkg::BSETI;
if (instr.instr[24:20] == 5'b00100) instruction_o.op = ariane_pkg::SEXTB;
else if (instr.instr[24:20] == 5'b00101) instruction_o.op = ariane_pkg::SEXTH;
else if (instr.instr[24:20] == 5'b00010) instruction_o.op = ariane_pkg::CPOP;
else if (instr.instr[24:20] == 5'b00000) instruction_o.op = ariane_pkg::CLZ;
else if (instr.instr[24:20] == 5'b00001) instruction_o.op = ariane_pkg::CTZ;
else illegal_instr_bm = 1'b1;
end else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:26] == 6'b010010)
instruction_o.op = ariane_pkg::BCLRI;
else if (CVA6Cfg.IS_XLEN32 && instr.instr[31:25] == 7'b0100100)
instruction_o.op = ariane_pkg::BCLRI;
else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:26] == 6'b011010)
instruction_o.op = ariane_pkg::BINVI;
else if (CVA6Cfg.IS_XLEN32 && instr.instr[31:25] == 7'b0110100)
instruction_o.op = ariane_pkg::BINVI;
else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:26] == 6'b001010)
instruction_o.op = ariane_pkg::BSETI;
else if (CVA6Cfg.IS_XLEN32 && instr.instr[31:25] == 7'b0010100)
instruction_o.op = ariane_pkg::BSETI;
else if (CVA6Cfg.ZKN && instr.instr[31:20] == 12'b000010001111)
instruction_o.op = ariane_pkg::ZIP;
else illegal_instr_bm = 1'b1;
end
3'b101: begin
@ -920,8 +945,18 @@ module decoder
instruction_o.op = ariane_pkg::REV8;
else if (instr.instr[31:20] == 12'b011010011000)
instruction_o.op = ariane_pkg::REV8;
else if (instr.instr[31:26] == 6'b010_010) instruction_o.op = ariane_pkg::BEXTI;
else if (instr.instr[31:26] == 6'b011_000) instruction_o.op = ariane_pkg::RORI;
else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:26] == 6'b010_010)
instruction_o.op = ariane_pkg::BEXTI;
else if (CVA6Cfg.IS_XLEN32 && instr.instr[31:25] == 7'b010_0100)
instruction_o.op = ariane_pkg::BEXTI;
else if (CVA6Cfg.IS_XLEN64 && instr.instr[31:26] == 6'b011_000)
instruction_o.op = ariane_pkg::RORI;
else if (CVA6Cfg.IS_XLEN32 && instr.instr[31:25] == 7'b011_0000)
instruction_o.op = ariane_pkg::RORI;
else if (CVA6Cfg.ZKN && instr.instr[31:20] == 12'b011010000111)
instruction_o.op = ariane_pkg::BREV8;
else if (CVA6Cfg.ZKN && instr.instr[31:20] == 12'b000010001111)
instruction_o.op = ariane_pkg::UNZIP;
else illegal_instr_bm = 1'b1;
end
default: illegal_instr_bm = 1'b1;
@ -938,8 +973,8 @@ module decoder
riscv::OpcodeOpImm32: begin
instruction_o.fu = ALU;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
if (CVA6Cfg.IS_XLEN64) begin
unique case (instr.itype.funct3)
3'b000: instruction_o.op = ariane_pkg::ADDW; // Add Immediate
@ -987,8 +1022,8 @@ module decoder
riscv::OpcodeStore: begin
instruction_o.fu = STORE;
imm_select = SIMM;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
instruction_o.rs1 = instr.stype.rs1;
instruction_o.rs2 = instr.stype.rs2;
// determine store size
unique case (instr.stype.funct3)
3'b000: instruction_o.op = ariane_pkg::SB;
@ -1008,8 +1043,8 @@ module decoder
riscv::OpcodeLoad: begin
instruction_o.fu = LOAD;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
// determine load size and signed type
unique case (instr.itype.funct3)
3'b000: instruction_o.op = ariane_pkg::LB;
@ -1038,8 +1073,8 @@ module decoder
if (CVA6Cfg.FpPresent && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin // only generate decoder if FP extensions are enabled (static)
instruction_o.fu = STORE;
imm_select = SIMM;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
instruction_o.rs1 = instr.stype.rs1;
instruction_o.rs2 = instr.stype.rs2;
// determine store size
unique case (instr.stype.funct3)
// Only process instruction if corresponding extension is active (static)
@ -1068,8 +1103,8 @@ module decoder
if (CVA6Cfg.FpPresent && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin // only generate decoder if FP extensions are enabled (static)
instruction_o.fu = LOAD;
imm_select = IIMM;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rs1 = instr.itype.rs1;
instruction_o.rd = instr.itype.rd;
// determine load size
unique case (instr.itype.funct3)
// Only process instruction if corresponding extension is active (static)
@ -1099,12 +1134,12 @@ module decoder
// ----------------------------------
riscv::OpcodeMadd, riscv::OpcodeMsub, riscv::OpcodeNmsub, riscv::OpcodeNmadd: begin
if (CVA6Cfg.FpPresent && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin // only generate decoder if FP extensions are enabled (static)
instruction_o.fu = FPU;
instruction_o.rs1[4:0] = instr.r4type.rs1;
instruction_o.rs2[4:0] = instr.r4type.rs2;
instruction_o.rd[4:0] = instr.r4type.rd;
imm_select = RS3; // rs3 into result field
check_fprm = 1'b1;
instruction_o.fu = FPU;
instruction_o.rs1 = instr.r4type.rs1;
instruction_o.rs2 = instr.r4type.rs2;
instruction_o.rd = instr.r4type.rd;
imm_select = RS3; // rs3 into result field
check_fprm = 1'b1;
// select the correct fused operation
unique case (instr.r4type.opcode)
default: instruction_o.op = ariane_pkg::FMADD; // fmadd.fmt - FP Fused multiply-add
@ -1154,24 +1189,24 @@ module decoder
riscv::OpcodeOpFp: begin
if (CVA6Cfg.FpPresent && fs_i != riscv::Off && ((CVA6Cfg.RVH && (!v_i || vfs_i != riscv::Off)) || !CVA6Cfg.RVH)) begin // only generate decoder if FP extensions are enabled (static)
instruction_o.fu = FPU;
instruction_o.rs1[4:0] = instr.rftype.rs1;
instruction_o.rs2[4:0] = instr.rftype.rs2;
instruction_o.rd[4:0] = instr.rftype.rd;
check_fprm = 1'b1;
instruction_o.fu = FPU;
instruction_o.rs1 = instr.rftype.rs1;
instruction_o.rs2 = instr.rftype.rs2;
instruction_o.rd = instr.rftype.rd;
check_fprm = 1'b1;
// decode FP instruction
unique case (instr.rftype.funct5)
5'b00000: begin
instruction_o.op = ariane_pkg::FADD; // fadd.fmt - FP Addition
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
instruction_o.op = ariane_pkg::FADD; // fadd.fmt - FP Addition
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2 = instr.rftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00001: begin
instruction_o.op = ariane_pkg::FSUB; // fsub.fmt - FP Subtraction
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2[4:0] = instr.rftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
instruction_o.op = ariane_pkg::FSUB; // fsub.fmt - FP Subtraction
instruction_o.rs1 = '0; // Operand A is set to 0
instruction_o.rs2 = instr.rftype.rs1; // Operand B is set to rs1
imm_select = IIMM; // Operand C is set to rs2
end
5'b00010: instruction_o.op = ariane_pkg::FMUL; // fmul.fmt - FP Multiplication
5'b00011: instruction_o.op = ariane_pkg::FDIV; // fdiv.fmt - FP Division
@ -1202,7 +1237,7 @@ module decoder
end
5'b01000: begin
instruction_o.op = ariane_pkg::FCVT_F2F; // fcvt.fmt.fmt - FP to FP Conversion
instruction_o.rs2[4:0] = instr.rvftype.rs1; // tie rs2 to rs1 to be safe (vectors use rs2)
instruction_o.rs2 = instr.rvftype.rs1; // tie rs2 to rs1 to be safe (vectors use rs2)
imm_select = IIMM; // rs2 holds part of the intruction
if (|instr.rftype.rs2[24:23])
illegal_instr = 1'b1; // bits [22:20] used, other bits must be 0
@ -1240,7 +1275,7 @@ module decoder
illegal_instr = 1'b1; // bits [21:20] used, other bits must be 0
end
5'b11100: begin
instruction_o.rs2[4:0] = instr.rftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
instruction_o.rs2 = instr.rftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
check_fprm = 1'b0; // instruction encoded in rm, do the check here
if (instr.rftype.rm == 3'b000 || (CVA6Cfg.XF16ALT && instr.rftype.rm == 3'b100)) // FP16ALT has separate encoding
instruction_o.op = ariane_pkg::FMV_F2X; // fmv.ifmt.fmt - FPR to GPR Move
@ -1252,7 +1287,7 @@ module decoder
end
5'b11110: begin
instruction_o.op = ariane_pkg::FMV_X2F; // fmv.fmt.ifmt - GPR to FPR Move
instruction_o.rs2[4:0] = instr.rftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
instruction_o.rs2 = instr.rftype.rs1; // set rs2 = rs1 so we can map FMV to SGNJ in the unit
check_fprm = 1'b0; // instruction encoded in rm, do the check here
if (!(instr.rftype.rm == 3'b000 || (CVA6Cfg.XF16ALT && instr.rftype.rm == 3'b100)))
illegal_instr = 1'b1;
@ -1303,10 +1338,10 @@ module decoder
// ----------------------------------
riscv::OpcodeAmo: begin
// we are going to use the load unit for AMOs
instruction_o.fu = STORE;
instruction_o.rs1[4:0] = instr.atype.rs1;
instruction_o.rs2[4:0] = instr.atype.rs2;
instruction_o.rd[4:0] = instr.atype.rd;
instruction_o.fu = STORE;
instruction_o.rs1 = instr.atype.rs1;
instruction_o.rs2 = instr.atype.rs2;
instruction_o.rd = instr.atype.rd;
// TODO(zarubaf): Ordering
// words
if (CVA6Cfg.RVA && instr.stype.funct3 == 3'h2) begin
@ -1349,16 +1384,18 @@ module decoder
end else begin
illegal_instr = 1'b1;
end
tinst = {
instr.atype.funct5,
instr.atype.aq,
instr.atype.rl,
instr.atype.rs2,
5'b0,
instr.atype.funct3,
instr.atype.rd,
instr.atype.opcode
};
if (CVA6Cfg.RVH) begin
tinst = {
instr.atype.funct5,
instr.atype.aq,
instr.atype.rl,
instr.atype.rs2,
5'b0,
instr.atype.funct3,
instr.atype.rd,
instr.atype.opcode
};
end
end
// --------------------------------
@ -1367,8 +1404,8 @@ module decoder
riscv::OpcodeBranch: begin
imm_select = SBIMM;
instruction_o.fu = CTRL_FLOW;
instruction_o.rs1[4:0] = instr.stype.rs1;
instruction_o.rs2[4:0] = instr.stype.rs2;
instruction_o.rs1 = instr.stype.rs1;
instruction_o.rs2 = instr.stype.rs2;
is_control_flow_instr_o = 1'b1;
@ -1389,9 +1426,9 @@ module decoder
riscv::OpcodeJalr: begin
instruction_o.fu = CTRL_FLOW;
instruction_o.op = ariane_pkg::JALR;
instruction_o.rs1[4:0] = instr.itype.rs1;
instruction_o.rs1 = instr.itype.rs1;
imm_select = IIMM;
instruction_o.rd[4:0] = instr.itype.rd;
instruction_o.rd = instr.itype.rd;
is_control_flow_instr_o = 1'b1;
// invalid jump and link register -> reserved for vector encoding
if (instr.itype.funct3 != 3'b0) illegal_instr = 1'b1;
@ -1400,34 +1437,37 @@ module decoder
riscv::OpcodeJal: begin
instruction_o.fu = CTRL_FLOW;
imm_select = JIMM;
instruction_o.rd[4:0] = instr.utype.rd;
instruction_o.rd = instr.utype.rd;
is_control_flow_instr_o = 1'b1;
end
riscv::OpcodeAuipc: begin
instruction_o.fu = ALU;
imm_select = UIMM;
instruction_o.use_pc = 1'b1;
instruction_o.rd[4:0] = instr.utype.rd;
instruction_o.fu = ALU;
imm_select = UIMM;
instruction_o.use_pc = 1'b1;
instruction_o.rd = instr.utype.rd;
end
riscv::OpcodeLui: begin
imm_select = UIMM;
instruction_o.fu = ALU;
instruction_o.rd[4:0] = instr.utype.rd;
imm_select = UIMM;
instruction_o.fu = ALU;
instruction_o.rd = instr.utype.rd;
end
default: illegal_instr = 1'b1;
endcase
end
if (CVA6Cfg.CvxifEn) begin
if (is_illegal_i || illegal_instr) begin
instruction_o.fu = CVXIF;
instruction_o.rs1[4:0] = instr.r4type.rs1;
instruction_o.rs2[4:0] = instr.r4type.rs2;
instruction_o.rd[4:0] = instr.r4type.rd;
instruction_o.op = ariane_pkg::OFFLOAD;
imm_select = RS3;
if (~ex_i.valid && (is_illegal_i || illegal_instr)) begin
instruction_o.fu = CVXIF;
instruction_o.rs1 = instr.r4type.rs1;
instruction_o.rs2 = instr.r4type.rs2;
instruction_o.rd = instr.r4type.rd;
instruction_o.op = ariane_pkg::OFFLOAD;
imm_select = instr.rtype.opcode == riscv::OpcodeMadd ||
instr.rtype.opcode == riscv::OpcodeMsub ||
instr.rtype.opcode == riscv::OpcodeNmadd ||
instr.rtype.opcode == riscv::OpcodeNmsub ? RS3 : MUX_RD_RS3;
end
end
@ -1466,16 +1506,20 @@ module decoder
imm_u_type = {
{CVA6Cfg.XLEN - 32{instruction_i[31]}}, instruction_i[31:12], 12'b0
}; // JAL, AUIPC, sign extended to 64 bit
imm_uj_type = {
{CVA6Cfg.XLEN - 20{instruction_i[31]}},
instruction_i[19:12],
instruction_i[20],
instruction_i[30:21],
1'b0
};
imm_bi_type = {{CVA6Cfg.XLEN - 5{instruction_i[24]}}, instruction_i[24:20]};
// if zcmt then xlen jump address assign to immidiate
if (CVA6Cfg.RVZCMT && is_zcmt_i) begin
imm_uj_type = {{CVA6Cfg.XLEN - 32{jump_address_i[31]}}, jump_address_i[31:0]};
end else begin
imm_uj_type = {
{CVA6Cfg.XLEN - 20{instruction_i[31]}},
instruction_i[19:12],
instruction_i[20],
instruction_i[30:21],
1'b0
};
end
// NOIMM, IIMM, SIMM, BIMM, UIMM, JIMM, RS3
// NOIMM, IIMM, SIMM, SBIMM, UIMM, JIMM, RS3
// select immediate
case (imm_select)
IIMM: begin
@ -1503,6 +1547,11 @@ module decoder
instruction_o.result = {{CVA6Cfg.XLEN - 5{1'b0}}, instr.r4type.rs3};
instruction_o.use_imm = 1'b0;
end
MUX_RD_RS3: begin
// result holds address of operand rs3 which is in rd field
instruction_o.result = {{CVA6Cfg.XLEN - 5{1'b0}}, instr.rtype.rd};
instruction_o.use_imm = 1'b0;
end
default: begin
instruction_o.result = {CVA6Cfg.XLEN{1'b0}};
instruction_o.use_imm = 1'b0;
@ -1619,9 +1668,11 @@ module decoder
if (irq_ctrl_i.mip[riscv::IRQ_M_TIMER] && irq_ctrl_i.mie[riscv::IRQ_M_TIMER]) begin
interrupt_cause = INTERRUPTS.M_TIMER;
end
// Machine Mode Software Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_SOFT] && irq_ctrl_i.mie[riscv::IRQ_M_SOFT]) begin
interrupt_cause = INTERRUPTS.M_SW;
if (CVA6Cfg.SoftwareInterruptEn) begin
// Machine Mode Software Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_SOFT] && irq_ctrl_i.mie[riscv::IRQ_M_SOFT]) begin
interrupt_cause = INTERRUPTS.M_SW;
end
end
// Machine Mode External Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_EXT] && irq_ctrl_i.mie[riscv::IRQ_M_EXT]) begin

Some files were not shown because too many files have changed in this diff Show more