Skip to content

Add mcounteren register#2403

Merged
SamuelRiedel merged 13 commits into
lowRISC:masterfrom
SamuelRiedel:mcounteren
Jun 11, 2026
Merged

Add mcounteren register#2403
SamuelRiedel merged 13 commits into
lowRISC:masterfrom
SamuelRiedel:mcounteren

Conversation

@SamuelRiedel

@SamuelRiedel SamuelRiedel commented May 11, 2026

Copy link
Copy Markdown
Contributor

This PR adds the mcounteren register, which has so far been tied to zero and implements the U-mode performance counter aliases. The mcounteren register can be locked with an external MUBI signal (mcounteren_writable_i).

DV:
This PR adds two directed tests:

  • mcounteren_test goes through multiple configurations of the mcounteren register and validates that u-mode can only access the ones enabled.
  • mcounteren_lock_test verifies that the mcounteren CSR cannot be modified without the mcounteren_writable_i signal being set.

To Dos:

  • For the directed tests and the cosim to pass, we have to update riscv-isa-sim to also support those performance counters: Enable ZIHPM unpriviledged performance counters riscv-isa-sim#29
  • Currently, u-mode counter reads will lead to illegal instruction exceptions. However, we are not gating the value at the CSR module's interface for simplicity. The signal will not leave the core, but we should double-check that this is no security issue.
  • The dv/uvm/core_ibex/directed_tests/directed_testlist.yaml changes a lot everytime I regenerate it after even small modifications. This polluted the diff quite a bit. Is this expected?

resolves #1973
fixes #2312

@gautschimi gautschimi 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.

The changes look all good to me! Just a few minor comments. (I did not look at the two WIP commits about formal)

Comment thread rtl/ibex_cs_registers.sv
Comment thread rtl/ibex_top.sv
Comment thread dv/uvm/core_ibex/directed_tests/mcounteren_test/mcounteren_test.S
Comment thread dv/uvm/core_ibex/directed_tests/directed_testlist.yaml
@SamuelRiedel

Copy link
Copy Markdown
Contributor Author

I disabled the check of the mcounteren CSR in the formal verification for now. Another reason for the failure of the formal verification was that we ran out of memory on the runner that has twice as many cores but half as much memory available. I'll address this in a separate PR and rebase once merged.

@gautschimi gautschimi 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.

Looks good to me!

I mostly looked at RTL, but the changes in python, C, yaml, etc. look also good to me!

@SamuelRiedel SamuelRiedel force-pushed the mcounteren branch 2 times, most recently from c799da7 to 49bffac Compare June 3, 2026 10:11

@marnovandermaas marnovandermaas 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.

Since we're adding an extension do we need to do an update of ISA strings that are passed to compilers?

Comment thread rtl/ibex_cs_registers.sv Outdated
Comment thread rtl/ibex_pkg.sv
Comment thread dv/formal/check/top.sv

// CPU Control Signals
input ibex_mubi_t fetch_enable_i,
input ibex_mubi_t mcounteren_writable_i,

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.

What's the point of making this an input as opposed to a parameter? Is there a use-case to be able to switch this dynamically during runtime?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. This allows locking the mcounteren in a certain configuration. For example, the boot code could enable only the instret counter to be accessible to the user mode and then lock it to prevent the software from switching it later and use other counters to profile the core. This option, gives us the most flexibility and security.

Comment thread ci/vars.env

@marnovandermaas marnovandermaas 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.

I realised there are some more commits so here are some more comments. Very good work on this and please disregard my previous mention that the docs needed updating.

Comment thread dv/uvm/core_ibex/directed_tests/gen_testlist.py Outdated
Comment thread dv/uvm/core_ibex/directed_tests/mcounteren_test/mcounteren_test.S
Comment thread dv/cosim/cosim.h Outdated
Comment thread dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
@rswarbrick rswarbrick removed their request for review June 9, 2026 09:32
The `wb_count_q` signal can become stale. It tracks whether the current
or previous retired instruction increments the `instret` count. If there
is a bubble before an `minstret` read, the counter will be updated, but
`wb_count_q` and therefore `perf_instr_ret_wb_spec_o` will incorrectly
suggest speculatively incrementing the counter further. This led to the
`instret` counter being one instruction ahead every time we read it
after a stall cycle.

We fix this by validating `wb_count_q` and only incrementing
speculatively if we actually have to. That is, when we are executing instructions back-to-back and the counter hasn't updated yet.
According to the Specification Section 6.1 CSR Instructions:

Some CSRs, such as the instructions-retired counter, instret, may be
modified as side effects of instruction execution. In these cases, if a
CSR access instruction reads a CSR, it reads the value prior to the
execution of the instruction. If a CSR access instruction writes such a
CSR, the explicit write is done instead of the update from the side
effect. In particular, a value written to instret by one instruction
will be the value read by the following instruction.
@SamuelRiedel

Copy link
Copy Markdown
Contributor Author

@marnovandermaas thank you for your review. Now that the CI works again, this PR would be ready to merge from my side. I included a check for the minstret value in the test to directly verify that instructions are counted correctly. This PR now also includes the commits from #2446 because we rely on them to pass the tests. We can either directly merge this one and close #2446 or merge the other one first and then rebase and merge this one.

@marnovandermaas marnovandermaas 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.

These changes look good to me now. Thanks for including the instret fixes as well. And for checking everything in CI.

@SamuelRiedel SamuelRiedel added this pull request to the merge queue Jun 11, 2026
Merged via the queue into lowRISC:master with commit aae4809 Jun 11, 2026
12 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.

[Bug,TestFW] Zicntr in CoSim not compliant with the standard [rtl] Implement cycle/instret/time/hmpcountern CSRs

3 participants