1212#include "test_macros.h"
1313
1414# Register Allocation:
15+ # s0: mcounteren WARL readback used by check_counter_aliases
1516# s1: Expected instruction execution state(1 = should succeed, 0 = should trap)
1617# s2: Readback snapshot of valid mcounteren bits
1718# s3: Subroutine return address backup tracking register(ra)
@@ -110,6 +111,37 @@ next_test_\idx:
110111 RUN_CSR_TEST 63 , 0xC9F # hpmcounter31h
111112.endm
112113
114+ # Freeze one HPM counter, write it, drop to U-mode to read the user-mode alias,
115+ # then verify the values match.
116+ # s0 is the mcounteren readback on entry
117+ # s1 carries the M-mode read.
118+ # s2 carries the U-mode read.
119+ .macro CHECK_HPM_ALIAS_ONE idx, mhpmcsr, hpmcsr
120+ li t0, (1 << \idx)
121+ and t1, t0, s0
122+ beqz t1, skip_hpm_alias_\hpmcsr
123+
124+ csrs mcountinhibit, t0
125+ li t0, (0x12345678 ^ \idx)
126+ csrw \mhpmcsr, t0
127+ csrr s1, \mhpmcsr
128+
129+ la s5, after_hpm_alias_\hpmcsr
130+ SWITCH_TO_U_MODE_LABEL(hpm_alias_u_\hpmcsr)
131+
132+ .balign 4
133+ hpm_alias_u_\hpmcsr:
134+ csrr s2, \hpmcsr
135+ ecall
136+
137+ after_hpm_alias_\hpmcsr:
138+ bne s2, s1, fail
139+ li t0, (1 << \idx)
140+ csrc mcountinhibit, t0
141+
142+ skip_hpm_alias_\hpmcsr:
143+ .endm
144+
113145# -----------------------------------------------------------------------
114146# Main Verification Blocks
115147# -----------------------------------------------------------------------
@@ -160,6 +192,12 @@ RVTEST_CODE_BEGIN
160192 csrr s2, mcounteren
161193 jal ra, run_all_csr_tests
162194
195+ # Re-enable all counters and verify U-mode CSRs alias their M-mode counterparts.
196+ li t0, 0xFFFFFFFF
197+ csrw mcounteren, t0
198+ csrr s0, mcounteren
199+ jal ra, check_counter_aliases
200+
163201 # If execution hits this line, all pattern sweeps successfully completed
164202 csrwi mcounteren, 0
165203 j pass
@@ -186,6 +224,97 @@ post_all_tests:
186224 mv ra, s3
187225 ret
188226
227+ # -----------------------------------------------------------------------
228+ # Counter Alias Verification Subroutine
229+ # -----------------------------------------------------------------------
230+ # Verifies that the user-mode counter CSRs alias their M-mode counterparts.
231+ # cycle is checked by the cosim.
232+ check_counter_aliases:
233+ mv s3, ra
234+
235+ # Custom minstret test
236+ # instret should be exactly 2 more than minstret.
237+ csrr t0, minstret
238+ nop
239+ csrr t1, instret
240+ addi t2, t0, 2
241+ bne t1, t2, fail
242+
243+ # Reset minstret to zero. The write should suppress the automatic retirement
244+ # increment, so the immediate read-back will be 0. Reading instret next counts
245+ # the one csr read.
246+ csrwi minstret, 0
247+ csrr t0, minstret
248+ csrr t1, instret
249+ bnez t0, fail
250+ li t2, 1
251+ bne t1, t2, fail
252+
253+ # HPM alias: iterate over each HPM counter (bits 3-31) that mcounteren
254+ # reports as implemented. Each counter is frozen with mcountinhibit, set to a
255+ # value through the m-mode counter, and read back via the U-mode alias CSR.
256+ CHECK_HPM_ALIAS_ONE 3 , mhpmcounter3, hpmcounter3
257+ CHECK_HPM_ALIAS_ONE 4 , mhpmcounter4, hpmcounter4
258+ CHECK_HPM_ALIAS_ONE 5 , mhpmcounter5, hpmcounter5
259+ CHECK_HPM_ALIAS_ONE 6 , mhpmcounter6, hpmcounter6
260+ CHECK_HPM_ALIAS_ONE 7 , mhpmcounter7, hpmcounter7
261+ CHECK_HPM_ALIAS_ONE 8 , mhpmcounter8, hpmcounter8
262+ CHECK_HPM_ALIAS_ONE 9 , mhpmcounter9, hpmcounter9
263+ CHECK_HPM_ALIAS_ONE 10 , mhpmcounter10, hpmcounter10
264+ CHECK_HPM_ALIAS_ONE 11 , mhpmcounter11, hpmcounter11
265+ CHECK_HPM_ALIAS_ONE 12 , mhpmcounter12, hpmcounter12
266+ CHECK_HPM_ALIAS_ONE 13 , mhpmcounter13, hpmcounter13
267+ CHECK_HPM_ALIAS_ONE 14 , mhpmcounter14, hpmcounter14
268+ CHECK_HPM_ALIAS_ONE 15 , mhpmcounter15, hpmcounter15
269+ CHECK_HPM_ALIAS_ONE 16 , mhpmcounter16, hpmcounter16
270+ CHECK_HPM_ALIAS_ONE 17 , mhpmcounter17, hpmcounter17
271+ CHECK_HPM_ALIAS_ONE 18 , mhpmcounter18, hpmcounter18
272+ CHECK_HPM_ALIAS_ONE 19 , mhpmcounter19, hpmcounter19
273+ CHECK_HPM_ALIAS_ONE 20 , mhpmcounter20, hpmcounter20
274+ CHECK_HPM_ALIAS_ONE 21 , mhpmcounter21, hpmcounter21
275+ CHECK_HPM_ALIAS_ONE 22 , mhpmcounter22, hpmcounter22
276+ CHECK_HPM_ALIAS_ONE 23 , mhpmcounter23, hpmcounter23
277+ CHECK_HPM_ALIAS_ONE 24 , mhpmcounter24, hpmcounter24
278+ CHECK_HPM_ALIAS_ONE 25 , mhpmcounter25, hpmcounter25
279+ CHECK_HPM_ALIAS_ONE 26 , mhpmcounter26, hpmcounter26
280+ CHECK_HPM_ALIAS_ONE 27 , mhpmcounter27, hpmcounter27
281+ CHECK_HPM_ALIAS_ONE 28 , mhpmcounter28, hpmcounter28
282+ CHECK_HPM_ALIAS_ONE 29 , mhpmcounter29, hpmcounter29
283+ CHECK_HPM_ALIAS_ONE 30 , mhpmcounter30, hpmcounter30
284+ CHECK_HPM_ALIAS_ONE 31 , mhpmcounter31, hpmcounter31
285+ CHECK_HPM_ALIAS_ONE 3 , mhpmcounter3h, hpmcounter3h
286+ CHECK_HPM_ALIAS_ONE 4 , mhpmcounter4h, hpmcounter4h
287+ CHECK_HPM_ALIAS_ONE 5 , mhpmcounter5h, hpmcounter5h
288+ CHECK_HPM_ALIAS_ONE 6 , mhpmcounter6h, hpmcounter6h
289+ CHECK_HPM_ALIAS_ONE 7 , mhpmcounter7h, hpmcounter7h
290+ CHECK_HPM_ALIAS_ONE 8 , mhpmcounter8h, hpmcounter8h
291+ CHECK_HPM_ALIAS_ONE 9 , mhpmcounter9h, hpmcounter9h
292+ CHECK_HPM_ALIAS_ONE 10 , mhpmcounter10h, hpmcounter10h
293+ CHECK_HPM_ALIAS_ONE 11 , mhpmcounter11h, hpmcounter11h
294+ CHECK_HPM_ALIAS_ONE 12 , mhpmcounter12h, hpmcounter12h
295+ CHECK_HPM_ALIAS_ONE 13 , mhpmcounter13h, hpmcounter13h
296+ CHECK_HPM_ALIAS_ONE 14 , mhpmcounter14h, hpmcounter14h
297+ CHECK_HPM_ALIAS_ONE 15 , mhpmcounter15h, hpmcounter15h
298+ CHECK_HPM_ALIAS_ONE 16 , mhpmcounter16h, hpmcounter16h
299+ CHECK_HPM_ALIAS_ONE 17 , mhpmcounter17h, hpmcounter17h
300+ CHECK_HPM_ALIAS_ONE 18 , mhpmcounter18h, hpmcounter18h
301+ CHECK_HPM_ALIAS_ONE 19 , mhpmcounter19h, hpmcounter19h
302+ CHECK_HPM_ALIAS_ONE 20 , mhpmcounter20h, hpmcounter20h
303+ CHECK_HPM_ALIAS_ONE 21 , mhpmcounter21h, hpmcounter21h
304+ CHECK_HPM_ALIAS_ONE 22 , mhpmcounter22h, hpmcounter22h
305+ CHECK_HPM_ALIAS_ONE 23 , mhpmcounter23h, hpmcounter23h
306+ CHECK_HPM_ALIAS_ONE 24 , mhpmcounter24h, hpmcounter24h
307+ CHECK_HPM_ALIAS_ONE 25 , mhpmcounter25h, hpmcounter25h
308+ CHECK_HPM_ALIAS_ONE 26 , mhpmcounter26h, hpmcounter26h
309+ CHECK_HPM_ALIAS_ONE 27 , mhpmcounter27h, hpmcounter27h
310+ CHECK_HPM_ALIAS_ONE 28 , mhpmcounter28h, hpmcounter28h
311+ CHECK_HPM_ALIAS_ONE 29 , mhpmcounter29h, hpmcounter29h
312+ CHECK_HPM_ALIAS_ONE 30 , mhpmcounter30h, hpmcounter30h
313+ CHECK_HPM_ALIAS_ONE 31 , mhpmcounter31h, hpmcounter31h
314+
315+ mv ra, s3
316+ ret
317+
189318# -----------------------------------------------------------------------
190319# Exception Trap Handler
191320# -----------------------------------------------------------------------
0 commit comments