Re: Requirements on implementing cycle/instret/hpmcountern

Greg Chadwick

> While CSR ops must be atomic, that's pretty easy to do when the CSR is read-only, and the time CSR is in that category.

Agreed, I had forgotten time was read-only so time accesses becoming a memory access doesn't result in a need to support atomics in your memory system. That eases the difficulties but I still think a direct conversion to a memory access is fraught with issues (in particular how you deal with exceptions, say a software PMP mis-configuration causes mtime to be un-readable, what do you get when 'csrr time' is executed?).

> It is inconsistent, but pretty easy to understand, and Mcode really has no need to use it if it can just do the load to the MMIO address.

I agree there's no reason from M-mode to execute 'csrr time' but it's still something that can happen so I'd like to understand the architecturally permissible behaviours when it does.


On Thu, Jan 26, 2023 at 1:30 AM Allen Baum <allen.baum@...> wrote:
1. Divide is an optional instruction, not a required one, contingent on misa.M==1.
2. While CSR ops must be atomic, that's pretty easy to do when the CSR is read-only, and the time CSR is in that category.
3. Why "Time' is explicitly called out to 
 "Implementations can convert reads of the time ... CSRs into loads...or emulate this functionality in M-mode software."
as opposed to defining a RdTime op I can only explain as a historical accident (there used to be an mtime CSR...)
It is inconsistent, but pretty easy to understand, and Mcode really has no need to use it if it can just do the load to the MMIO address. 

On Wed, Jan 25, 2023 at 5:42 AM Greg Chadwick <gac@...> wrote:
I can see your point.

Though whilst I've got nothing concrete to point to in the spec I'd say there is a difference between the 'div' and 'csrr time' instructions in that taking a trap from U-mode to implement the CSR read seems reasonable and something the spec suggests as an implementation option whilst trapping on 'div' in U-mode to implement in a M-mode handler given the 'div' instruction must be implemented seems nonsensical.

I'd also say that mandating a 'csrr time' from M-mode must turn into a memory read doesn't feel like sane architecture given it's only for that specific CSR. For one you need some mechanism to tell the hart what address 'mtime' lives at and for another a 'csrr' instruction actually having memory semantics i.e. generates a architecturally visible memory access, which could generate memory related exceptions or interrupts, could cause some surprising action if the 'mtime' address has been mis-configured, are CSR instructions even allowed to produce memory related traps? There's this 'The CSRs defined so far do not have any architectural side effects on reads beyond raising illegal instruction exceptions on disallowed accesses' indicating they're not. Overall it does not seem sensible (were there some general declaration that an implementation may choose to use a memory backed CSR implementation so all csr instructions should be considered potential memory accesses that would be different). Indeed choosing it as an implementation choice regardless of if it's mandated seems to conflict with other architecture, the spec states:

'Standard CSRs do not have side effects on reads but may have side effects on writes'

I'd say a read to an effectively arbitrary address is a side effect (or could cause side effects), the hart would need to somehow guarantee that the address it has for 'mtime' would not generate any architecturally visible side-effects.

There's also this:

'All CSR instructions atomically read-modify-write a single CSR'

So if you have to do an mtime read/write you have to guarantee atomicity of this operation. Implementations are then forced to potentially have a significant/costly addition to their memory system to enable atomics (which it otherwise wouldn't have implemented) purely for the odd side case of an M-mode 'csrr time' execution.

From a micro-architecture point of view having a special case to turn this specific CSR read into a  memory access is also awkward.

There's also the point of what the spec is actually saying vs what you believe it should be saying. My core point is if we decide the spec in fact demands a m-mode 'csrr time' turns into a memory access to some platform defined mtime address that should be considered a specification bug and the 'csrr time' always traps should be specifically allowed.


On Tue, Jan 24, 2023 at 10:45 PM Paul Donahue <pdonahue@...> wrote:
How is "csrr time" different than "div" in this regard?  There was a lot of discussion at some point about whether you could claim M extension compatibility if you trapped and emulated divides in M-mode.  My understanding of the outcome is that if an instruction is not supported by the execution environment visible to M-mode then you can't claim to implement that extension.  (Of course, the SEE can claim to support emulated instructions but I'm talking about what hardware can claim to support.)  The Zmmul extension was created specifically for that case.

Why is there a non-normative comment that says that reads of time can be emulated in M-mode?  I agree that the CSR read can be converted into a load of mtime but I don't think that "or emulate this functionality in M-mode software" complies with what I said above.  Just like emulation of divides, emulation of the time CSR would be seen by the execution environment visible to M-mode.  (Emulating in an implementation-defined mode that's at a higher privilege level than M would be OK.)



On Mon, Jan 23, 2023 at 7:33 PM Allen Baum via <> wrote:
From an implementers point of view, that means an CSRR of the time CSR  could read the Mtime MMIO location (or a local copy if implemented that way_),
or it could trap and have Mmode firmware do the read and return a value. Any other type of access (CSRRW, CSRS*, CSRC*, etc) will trap

Form the ACT point of view we do not test firmware (e.g. the Mmode handler that would do that), 
so we only care whether it traps or returns some value that is monotonically increasing 
(at some rate that we need to define in terms of the only deterministically increasing counter we have which  is instret),
and whether other variations of the op cause a trap.

So, vendors need to supply a parameter (number of instret counts guaranteed to be longer than a time tick) and the tests will do the rest.

On Mon, Jan 23, 2023 at 1:19 AM Greg Chadwick <gac@...> wrote:
Thanks Greg and Jeff, useful to have my interpretation confirmed by a couple of people. I might put a PR together for the spec to add some clarification around these points.


On Fri, Jan 20, 2023 at 5:15 PM Greg Favor <gfavor@...> wrote:
On Fri, Jan 20, 2023 at 1:38 AM Greg Chadwick <gac@...> wrote:
On a related note I think it's permissible to not implement the 'time' CSR? It's an actual CSR that mirrors the memory mapped 'mtime' and the specification states 'Implementations can convert reads of the time and timeh CSRs into loads to the memory-mapped mtime register, or emulate this functionality in M-mode software' which presumably means M-mode accesses to 'time' can still be emulated by M-mode software (i.e. architecturally it's an illegal instruction exception and you're expecting the software to deal with it which is functionally identical to just not implementing it in hardware).

This is correct.  The overarching idea is that the 'time' CSR must appear to be present, i.e.  one can execute a CSR instruction accessing the 'time' CRS and the instruction - one way or another - will successfully be completed and will return a correct value.  Put differently, from an architectural and software perspective, the 'time' CSR must appear to be implemented - even if it isn't actually implemented in hardware as a physically distinct register.


Join { to automatically receive all group messages.