Skip to content

Implement Zama16b misaligned atomicity - #1893

Open
davidharrishmc wants to merge 5 commits into
openhwfoundation:rva23from
davidharrishmc:dh/zama16b
Open

davidharrishmc wants to merge 5 commits into
openhwfoundation:rva23from
davidharrishmc:dh/zama16b

Conversation

@davidharrishmc

Copy link
Copy Markdown
Contributor

Implements Zama16b, which makes a misaligned load, store or AMO that lies within one naturally aligned 16-byte granule atomic. RVA23 requires it.

Misaligned loads and stores already run through the Zicclsm hardware path. What was missing was the AMO case: mmu.sv faulted every misaligned atomic to cacheable memory, on the grounds that atomics are "never handled in hardware".

The change

One term in the MMU's misaligned access fault:

assign MisalignedCausesAccessFaultM = DataMisalignedM & P.ZICCLSM_SUPPORTED &
                                      ((AtomicAccessM & Cacheable & ~(P.ZAMA16B_SUPPORTED & ~CrossesLineM)) | ~Idempotent);

CrossesLineM comes out of the decoder that already computes DataMisalignedM, so it is three gate terms beside an existing check, nothing on the address path, and it folds away entirely when the parameter is 0.

Why the granule is the cache line, not 16 bytes

align.sv splits an access into two cache accesses exactly when it runs off the end of a cache line (OFFSET_BIT_POS = $clog2(DCACHE_LINELENINBITS/8), align.sv:61). Anything within a line is one cache access and is therefore already atomic. So CrossesLineM mirrors PotentialSpillM, and Wally's atomicity granule is the whole 64-byte line on rv64gc — a superset of the 16 bytes Zama16b guarantees, which the architecture permits.

Configuration and assertions

ZAMA16B_SUPPORTED is added to cvw.sv, parameter-defs.vh and all six configs, set on rv64gc, which is also the only config with Zicclsm.

  • riscvassertions_wally.sv: the cache line must be at least 128 bits, so a line always covers the 16 bytes the extension guarantees.
  • riscvassertions.sv: Zama16b requires Zicclsm, without which there is no hardware path for the misaligned access and the parameter would silently do nothing.

Testing

tests/coverage/zama16b.S (using WALLY-selfcheck.h) checks all three cases on a 64-byte-aligned buffer: a doubleword AMO at offset 4 completes and updates memory; one at offset 12, which crosses a 16-byte boundary but stays in the line, also completes; one at offset 60 runs off the line and still takes a store/AMO access fault, which the handler skips, leaving memory untouched.

check with ZAMA16B_SUPPORTED without
tests/coverage/zama16b.S passes fails at check 1
ACT Zama16b suite on cvw-rv64gc 1/1 passes 1/1 fails

Also Verilator lint clean on all six configs, and arch64a_amo, arch64d, arch64i, arch32a_amo unchanged.

Companion ACT change needed. config/cores/cvw/cvw-rv64gc currently declares "Zama16b": {"supported": false}, so the suite does not run against Wally in CI. Enabling it also requires misaligned_atomicity_granule_size_exp on the 0x80000000 main memory region to move from 0 to 6 (the 64-byte line), or Sail rejects the config. I ran the suite above with those two edits applied locally; they should land as a riscv-arch-test PR alongside this one.

🤖 Generated with Claude Code

davidharrishmc and others added 5 commits September 18, 2026 07:21
Zama16b makes a misaligned load, store or AMO that lies within one
naturally aligned 16 byte granule atomic.  Misaligned loads and stores
already run through the Zicclsm hardware path; this adds the AMO case,
which previously took a store/AMO access fault along with the granule
crossing ones.

The whole implementation is one term in the MMU's misaligned access
fault: a misaligned atomic to cacheable memory no longer faults when it
stays inside its granule.  CrossesGranuleM comes out of the decoder that
already computes DataMisalignedM, so it costs a few gates beside the
existing check and nothing on the address path, and it folds away in
configs without the extension.

riscvassertions_wally requires a cache line of at least 128 bits so a
granule never spans two lines, and riscvassertions requires Zicclsm,
without which the misaligned access has no hardware path.

tests/coverage/zama16b.S checks both halves: a doubleword AMO at offset 4
completes and updates memory, while one at offset 12 still faults and is
skipped, leaving memory untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
align.sv splits an access only when it runs off the end of a cache line,
so everything within a line is a single cache access and already atomic.
Fault only on the line crossing rather than on a 16 byte granule, which
gives a wider guarantee than Zama16b asks for and matches what the LSU
actually does.  The condition mirrors PotentialSpillM in align.sv.

Extend the test with an AMO at offset 12, which crosses a 16 byte
boundary inside the line and must now complete, and move the faulting
case to offset 60, which runs off the end of a 64 byte line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The signal declaration and the fault assignment already say it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hardware

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant