Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ add time[h] CSRs #556

Merged
merged 6 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 17.03.2023 | 1.8.2.5 | add RISC-V `time[h]` CSRs (part of the `Zicntr` ISA extension); [#556](https://github.com/stnolting/neorv32/pull/556) |
| 17.03.2023 | 1.8.2.4 | re-add VHDL process names; [#555](https://github.com/stnolting/neorv32/pull/555) |
| 15.03.2023 | 1.8.2.3 | rtl reworks, cleanups and optimizations; [#550](https://github.com/stnolting/neorv32/pull/550) |
| 11.03.2023 | 1.8.2.2 | :sparkles: add support for RISC-V `Zicond` ISA extension (conditional operations); [#546](https://github.com/stnolting/neorv32/pull/546) |
Expand Down
14 changes: 10 additions & 4 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,16 @@ code (see `sw/example/floating_point_test`).

==== `Zicntr` ISA Extension

The `Zicntr` ISA extension adds the basic cycle <<_cycleh>>, <<_mcycleh>> and instruction-retired
<<_instreth>>, <<_minstreth>> counters. This extensions is stated as _mandatory_ by the RISC-V spec.
However, area-constrained setups may remove support for these counters. Section <<_machine_counter_and_timer_csrs>>
shows a list of all `Zicntr`-related CSRs.
The `Zicntr` ISA extension adds the basic <<_cycleh>>, <<_mcycleh>>, <<_timeh>> and <<_instreth>>, <<_minstreth>>
counter CSRs. Section <<_machine_counter_and_timer_csrs>> shows a list of all `Zicntr`-related CSRs.

[NOTE]
Note that the <<_timeh>> CSRs are implemented as just another user-level shadow copy of the machine-mode cycle
counters <<_mcycleh>> (just like <<_cycleh>>).

[NOTE]
This extensions is stated as _mandatory_ by the RISC-V spec. However, area-constrained setups may remove
support for these counters.


==== `Zicond` ISA Extension
Expand Down
129 changes: 74 additions & 55 deletions docs/datasheet/cpu_csr.adoc

Large diffs are not rendered by default.

90 changes: 47 additions & 43 deletions rtl/core/neorv32_cpu_control.vhd

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ package neorv32_package is

-- "response time window" for processor-internal modules --
-- = cycles after which an *unacknowledged* internal bus access will timeout and trigger a bus fault exception
constant max_proc_int_response_time_c : natural := 15; -- min 2
constant max_proc_int_response_time_c : natural := 15; -- default = 15 (min 2)

-- log2 of co-processor timeout cycles --
constant cp_timeout_c : natural := 7; -- default = 7 (= 128 cycles)
Expand All @@ -65,7 +65,7 @@ package neorv32_package is

-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080204"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080205"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID

-- Check if we're inside the Matrix -------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion sim/neorv32_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,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/47" & cr & lf);
check_uart(net, uart1_rx_handle, "0/46" & cr & lf);
end if;

-- Wait until all expected data has been received
Expand Down
69 changes: 26 additions & 43 deletions sw/example/processor_check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ uint32_t pmp_num_regions;
**************************************************************************/
int main() {

uint32_t tmp_a, tmp_b;
uint32_t tmp_a, tmp_b, tmp_c;
uint8_t id;

// disable machine-mode interrupts
Expand Down Expand Up @@ -313,58 +313,41 @@ int main() {


// ----------------------------------------------------------
// Test standard RISC-V performance counter [m]cycle[h]
// Test standard RISC-V counters
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
PRINT_STANDARD("[%i] cycle counter ", cnt_test);
PRINT_STANDARD("[%i] Zicntr counters ", cnt_test);

cnt_test++;

// make sure counter is enabled
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));

// prepare overflow
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);

asm volatile ("nop"); // counter LOW should overflow here

// get current cycle counter HIGH
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);

// make sure cycle counter high has incremented and there was no exception during access
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) {
test_ok();
}
else {
test_fail();
}


// ----------------------------------------------------------
// Test standard RISC-V performance counter [m]instret[h]
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
PRINT_STANDARD("[%i] instret counter ", cnt_test);

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

// make sure counter is enabled
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR));
// make sure counters are enabled
neorv32_cpu_csr_clr(CSR_MCOUNTINHIBIT, (1<<CSR_MCOUNTINHIBIT_CY) | (1<<CSR_MCOUNTINHIBIT_IR));

// prepare overflow
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
// prepare overflow
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);

asm volatile ("nop"); // counter LOW should overflow here
asm volatile ("nop");

// get instruction counter HIGH
tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
// get current counter HIGH words
asm volatile ("rdcycleh %[rd]" : [rd] "=r" (tmp_a) : );
asm volatile ("rdtimeh %[rd]" : [rd] "=r" (tmp_b) : );
asm volatile ("rdinstreth %[rd]" : [rd] "=r" (tmp_c) : );

// make sure instruction counter high has incremented and there was no exception during access
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) {
test_ok();
// make sure cycle counter high has incremented and there was no exception during access
if ((tmp_a == 1) && // cycle overflow
(tmp_a == tmp_b) && // cycle = time
(tmp_c == 1) && // instret overflow
(neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) { // no exception
test_ok();
}
else {
test_fail();
}
}
else {
test_fail();
PRINT_STANDARD("[skipped, n.a.]\n");
}


Expand Down
24 changes: 12 additions & 12 deletions sw/lib/include/neorv32_cpu_csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ enum NEORV32_CSR_enum {
CSR_DSCRATCH0 = 0x7b2, /**< 0x7b2 - dscratch0 (-/-): Debug scratch register */

/* machine counters and timers */
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */

CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
//CSR_MTIME = 0xb01, /**< 0xb01 - mtime (r/w): MAchine time counter low word */
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
CSR_MHPMCOUNTER3 = 0xb03, /**< 0xb03 - mhpmcounter3 (r/w): Machine hardware performance monitor 3 counter low word */
CSR_MHPMCOUNTER4 = 0xb04, /**< 0xb04 - mhpmcounter4 (r/w): Machine hardware performance monitor 4 counter low word */
CSR_MHPMCOUNTER5 = 0xb05, /**< 0xb05 - mhpmcounter5 (r/w): Machine hardware performance monitor 5 counter low word */
Expand Down Expand Up @@ -179,9 +179,9 @@ enum NEORV32_CSR_enum {
CSR_MHPMCOUNTER30 = 0xb1e, /**< 0xb1e - mhpmcounter30 (r/w): Machine hardware performance monitor 30 counter low word */
CSR_MHPMCOUNTER31 = 0xb1f, /**< 0xb1f - mhpmcounter31 (r/w): Machine hardware performance monitor 31 counter low word */

CSR_MCYCLEH = 0xb80, /**< 0xb80 - mcycleh (r/w): Machine cycle counter high word */
CSR_MINSTRETH = 0xb82, /**< 0xb82 - minstreth (r/w): Machine instructions-retired counter high word */

CSR_MCYCLEH = 0xb80, /**< 0xb80 - mcycleh (r/w): Machine cycle counter high word */
//CSR_MTIMEH = 0xb81, /**< 0xb81 - mtimeh (r/w): Machine time counter high word */
CSR_MINSTRETH = 0xb82, /**< 0xb82 - minstreth (r/w): Machine instructions-retired counter high word */
CSR_MHPMCOUNTER3H = 0xb83, /**< 0xb83 - mhpmcounter3h (r/w): Machine hardware performance monitor 3 counter high word */
CSR_MHPMCOUNTER4H = 0xb84, /**< 0xb84 - mhpmcounter4h (r/w): Machine hardware performance monitor 4 counter high word */
CSR_MHPMCOUNTER5H = 0xb85, /**< 0xb85 - mhpmcounter5h (r/w): Machine hardware performance monitor 5 counter high word */
Expand Down Expand Up @@ -213,9 +213,9 @@ enum NEORV32_CSR_enum {
CSR_MHPMCOUNTER31H = 0xb9f, /**< 0xb9f - mhpmcounter31h (r/w): Machine hardware performance monitor 31 counter high word */

/* user counters and timers */
CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */

CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
CSR_TIME = 0xc01, /**< 0xc01 - time (r/-): Time counter low word */
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
CSR_HPMCOUNTER3 = 0xc03, /**< 0xc03 - hpmcounter3 (r/-): User hardware performance monitor 3 counter low word */
CSR_HPMCOUNTER4 = 0xc04, /**< 0xc04 - hpmcounter4 (r/-): User hardware performance monitor 4 counter low word */
CSR_HPMCOUNTER5 = 0xc05, /**< 0xc05 - hpmcounter5 (r/-): User hardware performance monitor 5 counter low word */
Expand Down Expand Up @@ -246,9 +246,9 @@ enum NEORV32_CSR_enum {
CSR_HPMCOUNTER30 = 0xc1e, /**< 0xc1e - hpmcounter30 (r/-): User hardware performance monitor 30 counter low word */
CSR_HPMCOUNTER31 = 0xc1f, /**< 0xc1f - hpmcounter31 (r/-): User hardware performance monitor 31 counter low word */

CSR_CYCLEH = 0xc80, /**< 0xc80 - cycleh (r/-): Cycle counter high word (from MCYCLEH) */
CSR_INSTRETH = 0xc82, /**< 0xc82 - instreth (r/-): Instructions-retired counter high word (from MINSTRETH) */

CSR_CYCLEH = 0xc80, /**< 0xc80 - cycleh (r/-): Cycle counter high word (from MCYCLEH) */
CSR_TIMEH = 0xc81, /**< 0xc81 - timeh (r/-): Time counter high word */
CSR_INSTRETH = 0xc82, /**< 0xc82 - instreth (r/-): Instructions-retired counter high word (from MINSTRETH) */
CSR_HPMCOUNTER3H = 0xc83, /**< 0xc83 - hpmcounter3h (r/-): User hardware performance monitor 3 counter high word */
CSR_HPMCOUNTER4H = 0xc84, /**< 0xc84 - hpmcounter4h (r/-): User hardware performance monitor 4 counter high word */
CSR_HPMCOUNTER5H = 0xc85, /**< 0xc85 - hpmcounter5h (r/-): User hardware performance monitor 5 counter high word */
Expand Down