Skip to content

Commit

Permalink
Add Smcntrpmf ISA extension (#676)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting authored Aug 24, 2023
2 parents e9c6e68 + 6cce552 commit aeaf116
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 216 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 23.08.2023 | 1.8.8.3 | :test_tube: add experimental `Smcntrpmf` ISA extension (counter privilege mode filtering; spec. is frozen but not yet ratified); remove unused `menvcfg` CSRs; [#676](https://github.com/stnolting/neorv32/pull/676) |
| 19.08.2023 | 1.8.8.2 | :warning: constrain `mtval` CSR; add support for `mtinst` CSR (trap instruction); [#674](https://github.com/stnolting/neorv32/pull/674) |
| 19.08.2023 | 1.8.8.1 | :test_tube: update RTE to support easy emulation of instructions; add example program to showcase how to emulate unaligned memory accesses; [#673](https://github.com/stnolting/neorv32/pull/673) |
| 18.08.2023 | [**:rocket:1.8.8**](https://github.com/stnolting/neorv32/releases/tag/v1.8.8) | **New release** |
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ see the [_open-source architecture ID list_](https://github.com/riscv/riscv-isa-
[[`Zmmul`](https://stnolting.github.io/neorv32/#_zmmul_isa_extension)]
[[`Zxcfu`](https://stnolting.github.io/neorv32/#_zxcfu_isa_extension)]
[[`PMP`](https://stnolting.github.io/neorv32/#_pmp_isa_extension)]
[[`Smcntrpmf`](https://stnolting.github.io/neorv32/#_smcntrpmf_isa_extension)]
[[`Sdext`](https://stnolting.github.io/neorv32/#_sdext_isa_extension)]
[[`Sdtrig`](https://stnolting.github.io/neorv32/#_sdtrig_isa_extension)]
* compatible to subsets of the RISC-V
Expand Down
27 changes: 22 additions & 5 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -693,11 +693,11 @@ behave like regular C functions but that evaluate to a single custom instruction

==== `PMP` ISA Extension

The NEORV32 physical memory protection (PMP) provides an elementary memory protection mechanism that can be used
to constrain read, write and execute rights of arbitrary memory regions. The NEORV32 PMP is partly compatible
to the RISC-V Privileged Architecture Specifications. In general, the PMP can **grant permissions to user mode**,
which by default has none, and can **revoke permissions from M-mode**, which by default has full permissions.
The PMP is configured via the <<_machine_physical_memory_protection_csrs>>.
The NEORV32 physical memory protection (PMP, also known as `Smpmp` ISA extension) provides an elementary memory
protection mechanism that can be used to constrain read, write and execute rights of arbitrary memory regions.
The NEORV32 PMP is fully compatible to the RISC-V Privileged Architecture Specifications. In general, the PMP can
**grant permissions to user mode**, which by default has none, and can **revoke permissions from M-mode**, which
by default has full permissions. The PMP is configured via the <<_machine_physical_memory_protection_csrs>>.

.PMP Rules when in Debug Mode
[NOTE]
Expand All @@ -708,6 +708,23 @@ Instruction fetches are also triggered when denied by a certain PMP rule. Howeve
will not be executed and will not change CPU core state to preserve memory access protection.


==== `Smcntrpmf` - ISA Extension

[IMPORTANT]
The `Smcntrpmf` ISA extension is frozen but not ratified yet.

The _counter privilege mode filtering_ `Smcntrpmf` ISA extension allows to halt the standard cycle ([m]cycle[h])
and instructions-retired (`[m]instret[h]`) counters if the CPU is in a specific privilege mode (machine oder user).
This ISA extension is automatically enabled if the <<_u_isa_extension>> is enabled.

Four additional CSRs are provided by this extensions:

* <<_mcyclecfgh, `mcyclecfg`>>
* <<_mcyclecfgh, `mcyclecfgh`>>
* <<_minstretcfgh, `minstretcfg`>>
* <<_minstretcfgh, `minstretcfgh`>>


==== `Sdext` ISA Extension

This ISA extension enables the RISC-V-compatible "external debug support" by implementing
Expand Down
200 changes: 105 additions & 95 deletions docs/datasheet/cpu_csr.adoc

Large diffs are not rendered by default.

Binary file modified docs/figures/neorv32_processor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
230 changes: 137 additions & 93 deletions rtl/core/neorv32_cpu_control.vhd

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ package neorv32_package is

-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080802"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080803"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width, do not change!

Expand Down Expand Up @@ -342,13 +342,11 @@ package neorv32_package is
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304";
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305";
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306";
--
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310";
-- machine configuration --
constant csr_menvcfg_c : std_ulogic_vector(11 downto 0) := x"30a";
constant csr_menvcfgh_c : std_ulogic_vector(11 downto 0) := x"31a";
-- machine counter setup --
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320";
constant csr_mcyclecfg_c : std_ulogic_vector(11 downto 0) := x"321";
constant csr_minstretcfg_c : std_ulogic_vector(11 downto 0) := x"322";
constant csr_mhpmevent3_c : std_ulogic_vector(11 downto 0) := x"323";
constant csr_mhpmevent4_c : std_ulogic_vector(11 downto 0) := x"324";
constant csr_mhpmevent5_c : std_ulogic_vector(11 downto 0) := x"325";
Expand Down Expand Up @@ -391,6 +389,9 @@ package neorv32_package is
constant csr_pmpaddr13_c : std_ulogic_vector(11 downto 0) := x"3bd";
constant csr_pmpaddr14_c : std_ulogic_vector(11 downto 0) := x"3be";
constant csr_pmpaddr15_c : std_ulogic_vector(11 downto 0) := x"3bf";
-- machine counter setup - continued --
constant csr_mcyclecfgh_c : std_ulogic_vector(11 downto 0) := x"721";
constant csr_minstretcfgh_c : std_ulogic_vector(11 downto 0) := x"722";
-- trigger module registers --
constant csr_tselect_c : std_ulogic_vector(11 downto 0) := x"7a0";
constant csr_tdata1_c : std_ulogic_vector(11 downto 0) := x"7a1";
Expand Down
2 changes: 1 addition & 1 deletion sim/neorv32_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ begin
if ci_mode then
-- No need to send the full expectation in one big chunk
check_uart(net, uart1_rx_handle, nul & nul);
check_uart(net, uart1_rx_handle, "0/54" & cr & lf);
check_uart(net, uart1_rx_handle, "0/55" & cr & lf);
end if;

-- Wait until all expected data has been received
Expand Down
47 changes: 45 additions & 2 deletions sw/example/processor_check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ int main() {
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch

// prepare (performance) counters
// prepare counters
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable counter auto increment (ALL counters)
neorv32_cpu_csr_write(CSR_MCOUNTEREN, -1); // allow counter access from user-mode code
if (neorv32_cpu_csr_read(CSR_MISA) & (1 << CSR_MISA_U)) {
neorv32_cpu_csr_write(CSR_MCOUNTEREN, -1); // allow counter access from user-mode code
}

// set CMP of machine system timer MTIME to max to prevent an IRQ
neorv32_mtime_set_timecmp(-1);
Expand Down Expand Up @@ -397,6 +399,47 @@ int main() {
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0);


// ----------------------------------------------------------
// Test mcyclecfg: counter privilege mode filtering
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
PRINT_STANDARD("[%i] mcyclecfg CSR ", cnt_test);

if (neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_SMCNTRPMF)) {
cnt_test++;

neorv32_cpu_csr_write(CSR_MCYCLECFGH, 1<<CSR_MCYCLECFGH_UINH); // inhibit when in user-mode

tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
asm volatile ("nop");
asm volatile ("nop");
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a; // delta machine-mode

// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
tmp_b = neorv32_cpu_csr_read(CSR_CYCLE);
asm volatile ("nop");
asm volatile ("nop");
tmp_b = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_b; // delta user-mode
asm volatile ("ecall"); // leave user-mode
}

if ((tmp_a != 0) && (tmp_b == 0)) {
test_ok();
}
else {
test_fail();
}

// re-enable base counters for all privilege modes
neorv32_cpu_csr_write(CSR_MCYCLECFGH, 0);
}
else {
PRINT_STANDARD("[n.a.]\n");
}


// ----------------------------------------------------------
// Execute MRET in U-mode (has to trap!)
// ----------------------------------------------------------
Expand Down
32 changes: 27 additions & 5 deletions sw/lib/include/neorv32_cpu_csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ enum NEORV32_CSR_enum {
CSR_MIE = 0x304, /**< 0x304 - mie: Machine interrupt-enable register */
CSR_MTVEC = 0x305, /**< 0x305 - mtvec: Machine trap-handler base address */
CSR_MCOUNTEREN = 0x306, /**< 0x305 - mcounteren: Machine counter enable register */
CSR_MENVCFG = 0x30a, /**< 0x30a - menvcfg: Machine environment configuration register */
CSR_MSTATUSH = 0x310, /**< 0x310 - mstatush: Machine status register - high word */
CSR_MENVCFGH = 0x31a, /**< 0x31a - menvcfgh: Machine environment configuration register - high word */
CSR_MCOUNTINHIBIT = 0x320, /**< 0x320 - mcountinhibit: Machine counter-inhibit register */
CSR_MCYCLECFG = 0x321, /**< 0x321 - mcyclecfg: Machine cycle counter privilege mode filtering - low word */
CSR_MINSTRETCFG = 0x322, /**< 0x322 - minstretcfg: Machine instret counter privilege mode filtering - low word */

/* hardware performance monitors - event configuration */
CSR_MHPMEVENT3 = 0x323, /**< 0x323 - mhpmevent3: Machine hardware performance monitor event selector 3 */
Expand Down Expand Up @@ -108,6 +108,10 @@ enum NEORV32_CSR_enum {
CSR_PMPADDR14 = 0x3be, /**< 0x3be - pmpaddr14: Physical memory protection address register 14 */
CSR_PMPADDR15 = 0x3bf, /**< 0x3bf - pmpaddr15: Physical memory protection address register 15 */

/* machine control and status - continued */
CSR_MCYCLECFGH = 0x721, /**< 0x721 - mcyclecfgh: Machine cycle counter privilege mode filtering - high word */
CSR_MINSTRETCFGH = 0x722, /**< 0x722 - minstretcfgh: Machine instret counter privilege mode filtering - high word */

/* on-chip debugger - hardware trigger module */
CSR_TSELECT = 0x7a0, /**< 0x7a0 - tselect: Trigger select */
CSR_TDATA1 = 0x7a1, /**< 0x7a1 - tdata1: Trigger data register 0 */
Expand Down Expand Up @@ -263,6 +267,24 @@ enum NEORV32_CSR_MCOUNTINHIBIT_enum {
};


/**********************************************************************//**
* CPU <b>mcyclecfgh</b> CSR (r/w): Machine cycle counter privilege mode filtering
**************************************************************************/
enum NEORV32_CSR_MCYCLECFGH_enum {
CSR_MCYCLECFGH_UINH = 28, /**< CPU mcyclecfgh CSR (28): UINH - Inhibit cycle counter when in user-mode when set (r/w) */
CSR_MCYCLECFGH_MINH = 30 /**< CPU mcyclecfgh CSR (30): MINH - Inhibit cycle counter when in machine-mode when set (r/w) */
};


/**********************************************************************//**
* CPU <b>minstretcfgh</b> CSR (r/w): Machine instret counter privilege mode filtering
**************************************************************************/
enum NEORV32_CSR_MINSTRETCFGH_enum {
CSR_MINSTRETCFGH_UINH = 28, /**< CPU minstretcfgh CSR (28): UINH - Inhibit instret counter when in user-mode when set (r/w) */
CSR_MINSTRETCFGH_MINH = 30 /**< CPU minstretcfgh CSR (30): MINH - Inhibit instret counter when in machine-mode when set (r/w) */
};


/**********************************************************************//**
* CPU <b>mie</b> CSR (r/w): Machine interrupt enable
**************************************************************************/
Expand Down Expand Up @@ -347,11 +369,11 @@ enum NEORV32_CSR_XISA_enum {
CSR_MXISA_ZIFENCEI = 1, /**< CPU mxisa CSR (1): instruction stream sync (r/-)*/
CSR_MXISA_ZMMUL = 2, /**< CPU mxisa CSR (2): hardware mul/div (r/-)*/
CSR_MXISA_ZXCFU = 3, /**< CPU mxisa CSR (3): custom RISC-V instructions (r/-)*/

CSR_MXISA_ZFINX = 5, /**< CPU mxisa CSR (5): FPU using x registers, "F-alternative" (r/-)*/
CSR_MXISA_SMCNTRPMF = 4, /**< CPU mxisa CSR (4): counter privilege mode filtering (r/-)*/
CSR_MXISA_ZFINX = 5, /**< CPU mxisa CSR (5): FPU using x registers (r/-)*/

CSR_MXISA_ZICNTR = 7, /**< CPU mxisa CSR (7): standard instruction, cycle and time counter CSRs (r/-)*/
CSR_MXISA_PMP = 8, /**< CPU mxisa CSR (8): physical memory protection (also "Smpmp") (r/-)*/
CSR_MXISA_PMP = 8, /**< CPU mxisa CSR (8): physical memory protection ("Smpmp") (r/-)*/
CSR_MXISA_ZIHPM = 9, /**< CPU mxisa CSR (9): hardware performance monitors (r/-)*/
CSR_MXISA_SDEXT = 10, /**< CPU mxisa CSR (10): RISC-V debug mode (r/-)*/
CSR_MXISA_SDTRIG = 11, /**< CPU mxisa CSR (11): RISC-V trigger module (r/-)*/
Expand Down
21 changes: 11 additions & 10 deletions sw/lib/source/neorv32_rte.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,16 +467,17 @@ void neorv32_rte_print_hw_config(void) {

// CPU sub-extensions
tmp = neorv32_cpu_csr_read(CSR_MXISA);
if (tmp & (1<<CSR_MXISA_ZICSR)) { neorv32_uart0_printf("Zicsr "); }
if (tmp & (1<<CSR_MXISA_ZICNTR)) { neorv32_uart0_printf("Zicntr "); }
if (tmp & (1<<CSR_MXISA_ZIFENCEI)) { neorv32_uart0_printf("Zifencei "); }
if (tmp & (1<<CSR_MXISA_ZFINX)) { neorv32_uart0_printf("Zfinx "); }
if (tmp & (1<<CSR_MXISA_ZIHPM)) { neorv32_uart0_printf("Zihpm "); }
if (tmp & (1<<CSR_MXISA_ZMMUL)) { neorv32_uart0_printf("Zmmul "); }
if (tmp & (1<<CSR_MXISA_ZXCFU)) { neorv32_uart0_printf("Zxcfu "); }
if (tmp & (1<<CSR_MXISA_SDEXT)) { neorv32_uart0_printf("Sdext "); }
if (tmp & (1<<CSR_MXISA_SDTRIG)) { neorv32_uart0_printf("Sdtrig "); }
if (tmp & (1<<CSR_MXISA_PMP)) { neorv32_uart0_printf("Smpmp "); }
if (tmp & (1<<CSR_MXISA_ZICSR)) { neorv32_uart0_printf("Zicsr "); }
if (tmp & (1<<CSR_MXISA_ZICNTR)) { neorv32_uart0_printf("Zicntr "); }
if (tmp & (1<<CSR_MXISA_ZIFENCEI)) { neorv32_uart0_printf("Zifencei "); }
if (tmp & (1<<CSR_MXISA_ZFINX)) { neorv32_uart0_printf("Zfinx "); }
if (tmp & (1<<CSR_MXISA_ZIHPM)) { neorv32_uart0_printf("Zihpm "); }
if (tmp & (1<<CSR_MXISA_ZMMUL)) { neorv32_uart0_printf("Zmmul "); }
if (tmp & (1<<CSR_MXISA_ZXCFU)) { neorv32_uart0_printf("Zxcfu "); }
if (tmp & (1<<CSR_MXISA_SDEXT)) { neorv32_uart0_printf("Sdext "); }
if (tmp & (1<<CSR_MXISA_SDTRIG)) { neorv32_uart0_printf("Sdtrig "); }
if (tmp & (1<<CSR_MXISA_PMP)) { neorv32_uart0_printf("Smpmp "); }
if (tmp & (1<<CSR_MXISA_SMCNTRPMF)) { neorv32_uart0_printf("Smcntrpmf "); }

// CPU tuning options
neorv32_uart0_printf("\nTuning options: ");
Expand Down

0 comments on commit aeaf116

Please sign in to comment.