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
- Use the supplied
poc/program.elf artifact for the NutShell test environment.
- Run it with NutShell as DUT and Spike as the differential reference.
- 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
NS-1.zip
Bug Description
NutShell does not make an explicit write to
minstretvisible to the immediately following CSR read.The minimal sequence is:
In the supplied differential trace, Spike returns
s0 = 0, while NutShell returnss0 = 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, zeromust leaveminstretholding zero, even though thecsrwinstruction itself also retires. The nextcsrr s0, minstrettherefore must read zero.The ratified Zicsr specification, Section CSR Access Ordering, provides the underlying rule:
instretby one instruction is the value read by the following instruction;Reference: https://docs.riscv.org/reference/isa/v20260120/unpriv/zicsr.html#_csr_access_ordering
Because
minstretis the machine-level writable instructions-retired counter, thisinstretordering rule applies here.Steps to Reproduce
poc/program.elfartifact for the NutShell test environment.0x8000000cand read at0x80000010.Essential source:
Expected Result
The write instruction sets
minstretto zero and suppresses its own implicit retirement increment. The followingcsrrreads zero, matching Spike.Actual Result
NutShell reads
3:NS-1.zip