Add mcounteren register#2403
Conversation
fcb3067 to
bb40866
Compare
gautschimi
left a comment
There was a problem hiding this comment.
The changes look all good to me! Just a few minor comments. (I did not look at the two WIP commits about formal)
|
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
left a comment
There was a problem hiding this comment.
Looks good to me!
I mostly looked at RTL, but the changes in python, C, yaml, etc. look also good to me!
The set created a random order of the tests. So small modifications or additions to the testlist polluted the diff. Fixing the order in a list makes the output deterministic. I swapped the order of the tests to match the current output order of the testlist to avoid a diff.
|
|
||
| // mcounteren: machine counter enable (controls U-mode counter access) | ||
| logic [31:0] mcounteren; | ||
| logic [MHPMCounterNum+3-1:0] mcounteren_d, mcounteren_q; |
There was a problem hiding this comment.
It probably makes sense to have at least a local parameter with the 3 offset since this is shared with the mcountinhibit above.
There was a problem hiding this comment.
I double checked this mapping and I think they are right.
|
|
||
| // CPU Control Signals | ||
| input ibex_mubi_t fetch_enable_i, | ||
| input ibex_mubi_t mcounteren_writable_i, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
| # end up as float otherwise). | ||
| VERILATOR_VERSION=v4.210 | ||
| IBEX_COSIM_VERSION=6d5b660 | ||
| IBEX_COSIM_VERSION=aadf648 |
There was a problem hiding this comment.
This bump adds ZIHPM extension to Spike but it also pulls in the Zc* extensions. Is there any risk in that inclusion?
There was a problem hiding this comment.
You're right. But that will be fine, because we anyway already have the Zc* extension in the RTL. Only the DV is not fully merged yet, but already having Spike support those extensions will not hurt.
marnovandermaas
left a comment
There was a problem hiding this comment.
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.
|
|
||
| if 'riscv-arch-tests' in test_suite_list or test_suite == 'all': | ||
| arch_tests = {'rv32i_m/B/src', 'rv32i_m/C/src', 'rv32i_m/I/src', 'rv32i_m/M/src', 'rv32i_m/Zifencei/src'} | ||
| arch_tests = ['rv32i_m/M/src', 'rv32i_m/C/src', 'rv32i_m/Zifencei/src', 'rv32i_m/I/src', 'rv32i_m/B/src'] |
There was a problem hiding this comment.
Nit extra space here.
There was a problem hiding this comment.
Thanks for adding this test, very useful!
|
|
||
| // Set the value of minstret. | ||
| // | ||
| // The co-simulation model doesn't alter the value of minstret itself (other |
There was a problem hiding this comment.
How come this is true? Spike should have all the information it needs to calculate minstret right?
There was a problem hiding this comment.
You're right. And it does, the Spike counter is just lagging one instruction behind Ibex. It should match though, so I'll investigate a bit more...
| li s1, 0x0 | ||
| csrw mcounteren, s1 | ||
| csrr t1, mcounteren | ||
| bne t1, s0, fail |
There was a problem hiding this comment.
No, because in this instance, the register should be locked. So the csrw mcounteren, s1 must have no effect. So the read should return the previous write value.
| li s1, 0x0 | ||
| csrw mcounteren, s1 | ||
| csrr t1, mcounteren | ||
| bne t1, s0, fail |
There was a problem hiding this comment.
Also shouldn't this one fail if it is equal?
There was a problem hiding this comment.
Wait, they are both the same lines you commented. So here we either fail if:
- The current value is not equal to the previous value (
s0=0x5) from before we locked it and tried to change it tos1=0 - The current value is equal to
s1=0, because this means that the write was successful despite the locking.
I decided to do the first to also catch behaviour where the overwrite had some sort of effect, like changing just a few bits to zero.
|
|
||
| endclass | ||
|
|
||
| class core_ibex_mcounteren_lock_test extends core_ibex_base_test; |
There was a problem hiding this comment.
Thanks for adding this test, this is great!
This PR adds the
mcounterenregister, which has so far been tied to zero and implements the U-mode performance counter aliases. Themcounterenregister can be locked with an external MUBI signal (mcounteren_writable_i).DV:
This PR adds two directed tests:
mcounteren_testgoes through multiple configurations of the mcounteren register and validates that u-mode can only access the ones enabled.mcounteren_lock_testverifies that the mcounteren CSR cannot be modified without themcounteren_writable_isignal being set.To Dos:
dv/uvm/core_ibex/directed_tests/directed_testlist.yamlchanges a lot everytime I regenerate it after even small modifications. This polluted the diff quite a bit. Is this expected?resolves #1973
fixes #2312