Skip to content

Explicit writes to minstret lose to the automatic retirement update #260

Description

@jf-cc727

Bug Description

NutShell does not make an explicit write to minstret visible to the immediately following CSR read.

The minimal sequence is:

csrw minstret, zero
csrr s0, minstret

In the supplied differential trace, Spike returns s0 = 0, while NutShell returns s0 = 3. The failing value is the running retired-instruction count, indicating that the automatic retire-count update wins over, or is not correctly arbitrated with, the architectural CSR write.

RISC-V Specification Requirement

The key rule for this case is that an explicit CSR write must be the value observed by following instructions. For this sequence, csrw minstret, zero must leave minstret holding zero, even though the csrw instruction itself also retires. The next csrr s0, minstret therefore must read zero.

The ratified Zicsr specification, Section CSR Access Ordering, provides the underlying rule:

  • when a CSR modified implicitly by instruction execution is explicitly written, the explicit write is performed instead of the implicit update;
  • a value written to instret by one instruction is the value read by the following instruction;
  • explicit CSR accesses and their consequences are observed in program order.

Reference: https://docs.riscv.org/reference/isa/v20260120/unpriv/zicsr.html#_csr_access_ordering

Because minstret is the machine-level writable instructions-retired counter, this instret ordering rule applies here.

Steps to Reproduce

  1. Use the supplied poc/program.elf artifact for the NutShell test environment.
  2. Run it with NutShell as DUT and Spike as the differential reference.
  3. Observe the first five committed instructions, especially the write at 0x8000000c and read at 0x80000010.

Essential source:

la   t0, trap_entry
csrw mtvec, t0
csrw minstret, zero
csrr s0, minstret
bnez s0, fail_minstret_not_cleared

Expected Result

The write instruction sets minstret to zero and suppresses its own implicit retirement increment. The following csrr reads zero, matching Spike.

Actual Result

NutShell reads 3:

[03] ... csrw minstret, zero
[04] ... csrr s0, minstret ... data 0000000000000003
...
s0 different ... right = 0x0, wrong = 0x3
Image

NS-1.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions