Skip to content

Commit ed58324

Browse files
authored
✨ add time[h] CSRs (#556)
2 parents 68dd2f2 + a89d14c commit ed58324

File tree

8 files changed

+173
-160
lines changed

8 files changed

+173
-160
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12
3131

3232
| Date (*dd.mm.yyyy*) | Version | Comment |
3333
|:-------------------:|:-------:|:--------|
34+
| 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) |
3435
| 17.03.2023 | 1.8.2.4 | re-add VHDL process names; [#555](https://github.com/stnolting/neorv32/pull/555) |
3536
| 15.03.2023 | 1.8.2.3 | rtl reworks, cleanups and optimizations; [#550](https://github.com/stnolting/neorv32/pull/550) |
3637
| 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) |

docs/datasheet/cpu.adoc

+10-4
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,16 @@ code (see `sw/example/floating_point_test`).
459459

460460
==== `Zicntr` ISA Extension
461461

462-
The `Zicntr` ISA extension adds the basic cycle <<_cycleh>>, <<_mcycleh>> and instruction-retired
463-
<<_instreth>>, <<_minstreth>> counters. This extensions is stated as _mandatory_ by the RISC-V spec.
464-
However, area-constrained setups may remove support for these counters. Section <<_machine_counter_and_timer_csrs>>
465-
shows a list of all `Zicntr`-related CSRs.
462+
The `Zicntr` ISA extension adds the basic <<_cycleh>>, <<_mcycleh>>, <<_timeh>> and <<_instreth>>, <<_minstreth>>
463+
counter CSRs. Section <<_machine_counter_and_timer_csrs>> shows a list of all `Zicntr`-related CSRs.
464+
465+
[NOTE]
466+
Note that the <<_timeh>> CSRs are implemented as just another user-level shadow copy of the machine-mode cycle
467+
counters <<_mcycleh>> (just like <<_cycleh>>).
468+
469+
[NOTE]
470+
This extensions is stated as _mandatory_ by the RISC-V spec. However, area-constrained setups may remove
471+
support for these counters.
466472

467473

468474
==== `Zicond` ISA Extension

docs/datasheet/cpu_csr.adoc

+74-55
Large diffs are not rendered by default.

rtl/core/neorv32_cpu_control.vhd

+47-43
Large diffs are not rendered by default.

rtl/core/neorv32_package.vhd

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ package neorv32_package is
5353

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

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

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

7171
-- Check if we're inside the Matrix -------------------------------------------------------

sim/neorv32_tb.vhd

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ begin
180180
if ci_mode then
181181
-- No need to send the full expectation in one big chunk
182182
check_uart(net, uart1_rx_handle, nul & nul);
183-
check_uart(net, uart1_rx_handle, "0/47" & cr & lf);
183+
check_uart(net, uart1_rx_handle, "0/46" & cr & lf);
184184
end if;
185185

186186
-- Wait until all expected data has been received

sw/example/processor_check/main.c

+26-43
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ uint32_t pmp_num_regions;
125125
**************************************************************************/
126126
int main() {
127127

128-
uint32_t tmp_a, tmp_b;
128+
uint32_t tmp_a, tmp_b, tmp_c;
129129
uint8_t id;
130130

131131
// disable machine-mode interrupts
@@ -313,58 +313,41 @@ int main() {
313313

314314

315315
// ----------------------------------------------------------
316-
// Test standard RISC-V performance counter [m]cycle[h]
316+
// Test standard RISC-V counters
317317
// ----------------------------------------------------------
318318
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
319-
PRINT_STANDARD("[%i] cycle counter ", cnt_test);
319+
PRINT_STANDARD("[%i] Zicntr counters ", cnt_test);
320320

321-
cnt_test++;
322-
323-
// make sure counter is enabled
324-
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));
325-
326-
// prepare overflow
327-
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
328-
329-
asm volatile ("nop"); // counter LOW should overflow here
330-
331-
// get current cycle counter HIGH
332-
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);
333-
334-
// make sure cycle counter high has incremented and there was no exception during access
335-
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) {
336-
test_ok();
337-
}
338-
else {
339-
test_fail();
340-
}
341-
342-
343-
// ----------------------------------------------------------
344-
// Test standard RISC-V performance counter [m]instret[h]
345-
// ----------------------------------------------------------
346-
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
347-
PRINT_STANDARD("[%i] instret counter ", cnt_test);
348-
349-
cnt_test++;
321+
if (neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_ZICNTR)) {
322+
cnt_test++;
350323

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

354-
// prepare overflow
355-
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
327+
// prepare overflow
328+
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
329+
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
356330

357-
asm volatile ("nop"); // counter LOW should overflow here
331+
asm volatile ("nop");
358332

359-
// get instruction counter HIGH
360-
tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
333+
// get current counter HIGH words
334+
asm volatile ("rdcycleh %[rd]" : [rd] "=r" (tmp_a) : );
335+
asm volatile ("rdtimeh %[rd]" : [rd] "=r" (tmp_b) : );
336+
asm volatile ("rdinstreth %[rd]" : [rd] "=r" (tmp_c) : );
361337

362-
// make sure instruction counter high has incremented and there was no exception during access
363-
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) {
364-
test_ok();
338+
// make sure cycle counter high has incremented and there was no exception during access
339+
if ((tmp_a == 1) && // cycle overflow
340+
(tmp_a == tmp_b) && // cycle = time
341+
(tmp_c == 1) && // instret overflow
342+
(neorv32_cpu_csr_read(CSR_MCAUSE) == mcause_never_c)) { // no exception
343+
test_ok();
344+
}
345+
else {
346+
test_fail();
347+
}
365348
}
366349
else {
367-
test_fail();
350+
PRINT_STANDARD("[skipped, n.a.]\n");
368351
}
369352

370353

sw/lib/include/neorv32_cpu_csr.h

+12-12
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ enum NEORV32_CSR_enum {
146146
CSR_DSCRATCH0 = 0x7b2, /**< 0x7b2 - dscratch0 (-/-): Debug scratch register */
147147

148148
/* machine counters and timers */
149-
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
150-
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
151-
149+
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
150+
//CSR_MTIME = 0xb01, /**< 0xb01 - mtime (r/w): MAchine time counter low word */
151+
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
152152
CSR_MHPMCOUNTER3 = 0xb03, /**< 0xb03 - mhpmcounter3 (r/w): Machine hardware performance monitor 3 counter low word */
153153
CSR_MHPMCOUNTER4 = 0xb04, /**< 0xb04 - mhpmcounter4 (r/w): Machine hardware performance monitor 4 counter low word */
154154
CSR_MHPMCOUNTER5 = 0xb05, /**< 0xb05 - mhpmcounter5 (r/w): Machine hardware performance monitor 5 counter low word */
@@ -179,9 +179,9 @@ enum NEORV32_CSR_enum {
179179
CSR_MHPMCOUNTER30 = 0xb1e, /**< 0xb1e - mhpmcounter30 (r/w): Machine hardware performance monitor 30 counter low word */
180180
CSR_MHPMCOUNTER31 = 0xb1f, /**< 0xb1f - mhpmcounter31 (r/w): Machine hardware performance monitor 31 counter low word */
181181

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

215215
/* user counters and timers */
216-
CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
217-
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
218-
216+
CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
217+
CSR_TIME = 0xc01, /**< 0xc01 - time (r/-): Time counter low word */
218+
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
219219
CSR_HPMCOUNTER3 = 0xc03, /**< 0xc03 - hpmcounter3 (r/-): User hardware performance monitor 3 counter low word */
220220
CSR_HPMCOUNTER4 = 0xc04, /**< 0xc04 - hpmcounter4 (r/-): User hardware performance monitor 4 counter low word */
221221
CSR_HPMCOUNTER5 = 0xc05, /**< 0xc05 - hpmcounter5 (r/-): User hardware performance monitor 5 counter low word */
@@ -246,9 +246,9 @@ enum NEORV32_CSR_enum {
246246
CSR_HPMCOUNTER30 = 0xc1e, /**< 0xc1e - hpmcounter30 (r/-): User hardware performance monitor 30 counter low word */
247247
CSR_HPMCOUNTER31 = 0xc1f, /**< 0xc1f - hpmcounter31 (r/-): User hardware performance monitor 31 counter low word */
248248

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

0 commit comments

Comments
 (0)