P38 cleaned up the arch-test plumbing without touching the ISA. P39
is the first rung past that plateau where the chip actually grows: it
adds read-only cycle, time, and instret counters at the Zicntr
CSR addresses (0xC00/0xC01/0xC02 and their h halves).
The RTL diff is tiny:
- Two 64-bit counters in the FSM datapath.
cycleticks every clock.instretticks once perS_WBcycle. In our multi-cycle FSM, trapping instructions skipS_WB(they jump straight into the handler fromS_FETCH), and the halt loop never re-entersS_WB- so the count matches what the architecture actually wants.timealiasescycle. The spec is fine with aliasing as long astimeis monotonically non-decreasing, and a separate 64-bitmtimeis a future rung. Documented, not hidden.
Two new things confirmed by running it:
- The directed test (
zicntr_probe()) reads cycles/instret before and after a 50-iteration loop and checks(cycles_advanced) > (instret_advanced). PASS - the first concrete CPI > 1 assertion on the chip. Runtime now halts at4002clocks (P37 was1620); the extra is exactly the new probe’s busy loop. - The arch-test sweep (
make arch_test) now has a fifth batch (rv32i/Zicntr) with 2 tests at upstream reva7c9930:Zicntr-csrrc-00andZicntr-csrrs-00. Both pass in 1120 clocks. The framework doesn’t include a CSRRW Zicntr test because writes to the user-mode counter aliases are illegal in M-mode anyway.
Aggregate sweep result: PASS=56 FAIL=0 NOT RUN=0 across all five
batches. P38’s PASS=54 plus P39’s two new Zicntr tests, with no
regression on the inherited 54.
The plumbing diff is also small - the DUT plugin is verbatim P38 content, just copied. That is exactly the inheritance pattern P38 set up: each rung copies the plugin into its own directory rather than sharing one across projects, so individual rungs can deviate later without disturbing each other.
Honest framing: P39 is small, but it is the right next step toward
FreeRTOS. The port will want cycle and instret as real CSRs when
it eventually computes idle-task stats. Stubbing them as zero would
make the FreeRTOS port misbehave silently rather than fail loudly,
and that is the worst kind of bug.