Skip to content

Cover the last rv64gc coverage rows and make the coverage tests check themselves - #1920

Merged
rosethompson merged 11 commits into
openhwfoundation:mainfrom
davidharrishmc:dh/coverage-remaining
Oct 16, 2026
Merged

rosethompson merged 11 commits into
openhwfoundation:mainfrom
davidharrishmc:dh/coverage-remaining

Conversation

@davidharrishmc

@davidharrishmc davidharrishmc commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Three self-checking directed tests (fetchperiph, icachebusbusy, cbofaulthit) close the last rv64gc code-coverage rows. The coverage tests also now check their own results: 17 that added no coverage are dropped, and the 18 older ones that passed by running to completion, plus gshare (kept as a branch-predictor example), now compare their results, traps and CSR values with expected values. The exceptions are six tests written against specific bugs (amoAccessFault, floatmisc, misalignedInstrSpill, misalignedStoreSpill, nonleafpbmtfault, tlbMisaligned), which lockstep still checks. It also includes #1989, which follows the exclusions to main's later RTL (the ITLBMissOrUpdateRawF rename that stopped --ccov at the exclusion step, the ITLB TLBMiss row, and an unreachable TWTimeoutM row) and adds wfiSnoTW and tlbOverlap for the rows #1941 and #1927 left uncovered; with it, rv64gc code coverage is 100%.

🤖 Generated with Claude Code

davidharrishmc and others added 6 commits October 9, 2026 16:36
fetchperiph fetches from the CLINT, PLIC, PWM, SPI and GPIO, which match
their decoders in the instruction PMA checker but take an instruction
access fault.  The UART row is excluded instead: it only accepts bytes,
and the IFU always checks a word.

icachebusbusy misses on the second half of a spilled instruction in the
cycle after a CLINT load starts on the bus, so the I$ asks for the bus
while the APB bridge holds HREADY low.

cbofaulthit fills all four ways of a D$ set, then runs cbo.inval in
supervisor mode on each line under a PMP region with no read or write
permission, so the hit's valid-bit clear and the squash of the faulting
access (SelfFaultM, part of LSUFlushW) coincide.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
fetchperiph checks that each peripheral fetch takes an instruction access
fault with mtval at that peripheral, five in all.  icachebusbusy checks the
spilled addi's result and that the CLINT load returned the running mtime.
cbofaulthit stores a value into each of the four lines before the faulting
cbo.invals, checks each fault's cause, mepc and mtval, and reads the four
values back, which fails if the fault did not cancel the valid-bit clear.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
With the riscv-arch-test suites and the other coverage tests, rv64gc code
coverage stays at 100% without btbthrash, dcache2, ebu, ebuArb,
ebuIcacheDTLBMiss, gshare, hptwAccessFault, ifuCamlineWrite, lsu, pmpTOR7,
pmpcfg1, pmpcfg2, pmppriority, tlbASID, tlbGLB, tlbGP, tlbMP and tlbTP.  None
checked its own results.  The tests written against a specific bug stay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
They passed by reaching done.  Each now logs every trap and checks the log
against the traps it expects (cause, mepc and mtval), and checks the CSR values
it writes: PMP configuration and address WARL and lock behavior, including the
TOR lock of the previous pmpaddr; PMP access faults and the fetches a locked
region allows; envcfg legalization; stimecmp and mstatus after privileged
instructions; and the wfi timeout.  pmpadrdecs aligns its scratch word so that
the supervisor AMO it expects to fault really does, and wfitimeout adds a
supervisor wfi that must time out.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
…ck results

They passed by reaching done.  Each page they map now holds code or data that
identifies it, so every fetch and load through a TLB entry checks that it
reached the right physical page: tlbASIDMISS gives the second ASID its own
pages, so a hit under the wrong ASID is caught; tlbGLBASID repoints the global
PTEs before each full sfence.vma, so a global entry that survives it is caught;
tlbNAPOT checks each NAPOT translation and the page faults on ill-formed NAPOT
PTEs.  tlbmisc checks its traps and the values of its loads, AMO, cbo.zero and
A-bit update, and vm64check, now on WALLY-init-lib.h, checks that each
non-canonical jump takes an instruction access fault.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
They passed by reaching done.  Each now checks its results: cacheInval checks
that the timer interrupt lands in the fence.i burst and adds a self-modifying
code check after it; dcache1 stores distinct values and reads them back after
the flushes and through evictions; fpu checks every legal result and fflags
and that each reserved encoding raises illegal instruction at its own address;
fpuReservedRM checks that a dynamic-rounding add with frm 5 or 6 traps and
changes nothing; ieu and ifu check their integer, bit-manipulation and
compressed results and every expected trap.  None of the timed sequences
changed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
@davidharrishmc davidharrishmc changed the title Cover the last rv64gc code coverage rows Cover the last rv64gc coverage rows and make the coverage tests check themselves Oct 10, 2026

@rosethompson rosethompson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR removes many coverage regression tests. Some of these may be useful in other context besides coverage. For example, gshare.S is useful for demonstrating how gshare and other BP function. Should we create a separate directory for tests we wish to preserve?

Comment thread tests/coverage/gshare.S
@davidharrishmc

Copy link
Copy Markdown
Contributor Author

Review notes: the tests are sound and all check themselves, but a few things need attention before merging.

🤖 Generated with Claude Code

davidharrishmc and others added 2 commits October 16, 2026 03:27
Rose uses gshare.S to show how the global history and gshare predictors
behave, so keep it in tests/coverage, where it is built and run with the
other coverage tests.  It now checks each loop's results and fails on an
unexpected trap.  The comments describe what each loop shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: David Harris <David_Harris@hmc.edu>
@davidharrishmc

Copy link
Copy Markdown
Contributor Author

@rosethompson I kept gshare.S in tests/coverage instead of making a separate directory. Tests there are built by make and run in every nightly and --ccov regression, and now they check themselves too. A directory of tests that nothing runs would drift out of step with the RTL and the harness. Tell me which other dropped tests you want back and I'll restore them the same way. None of the other 17 was written against a specific bug. They remain in git history at 644ebb4^.

Also updated:

🤖 Generated with Claude Code

regression-wally --ccov stopped at the exclusion step: two GetLineNum patterns
still named ~ITLBMissF, which ifu.sv now spells ~ITLBMissOrUpdateRawF.  The ITLB
TLBMiss exclusion named row 3, but with UpperBitsUnequal added Questa lists
TLBAccess_0 as row 5.

The wfi rework left two rows of TWTimeoutM uncovered: wfiM_0 can't occur with the
wait counter saturated, since the counter clears whenever M advances, so it is
excluded; STATUS_TW_0 in S mode is reached by the new wfiSnoTW test, an S-mode
wfi with mstatus.TW = 0 that waits past the counter limit for a timer interrupt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
davidharrishmc and others added 2 commits October 16, 2026 04:46
The Overlap check that invalidates TLB lines overlapping a new entry had rows
no test reached on any ITLB or DTLB line: a NAPOT leaf in the line's 64 KiB
region or in another region of its megapage, a global leaf under another ASID,
and an Sv57 petapage leaf that differs from the line only in VPN[3].
tlbOverlap fills all 32 lines of each TLB with 4 KiB pages before each case,
sized to the replacement policy, and checks every access's translation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-remaining

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rosethompson
rosethompson merged commit 6e10f7e into openhwfoundation:main Oct 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants