Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions emulation/rocjitsu/docs/vm-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,13 @@ SC0/GLC is set. The L1 line is invalidated after the atomic to prevent
stale reads. Supported integer atomics: swap, cmpswap, add, sub,
smin/umin, smax/umax, and, or, xor, inc, dec.

**Scalar atomics** (`s_atomic_*` and `s_atomic_*_x2`, CDNA1–4) bypass the
L1 scalar cache and perform read-modify-write at L2; the atomic boundary's
coherence epoch makes stale K$ lines refetch. The old value is returned to
SDATA when GLC is set. Supported: swap, add, sub, smin/umin, smax/umax,
and, or, xor, inc, dec. `s_atomic_cmpswap[_x2]` and `s_buffer_atomic_*` are
not yet implemented.

**Cache management instructions:**

- `s_dcache_inv` / `s_dcache_inv_vol` — invalidate the L1 scalar cache
Expand Down
23 changes: 21 additions & 2 deletions emulation/rocjitsu/lib/python/amdisa/semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,25 @@ def _derive_vop3p(name: str) -> InstructionSemantics | None:
'U16': (2, False),
}

# S_ATOMIC_* operations the CDNA ISAs define and the scalar pipeline supports.
# Other flat atomic operations stay 'nop' even when the flat tables know them.
_SMEM_ATOMIC_OPS = frozenset(
{
'swap',
'add',
'sub',
'smin',
'umin',
'smax',
'umax',
'and',
'or',
'xor',
'inc',
'dec',
}
)


def _derive_smem(name: str) -> InstructionSemantics | None:
"""Derive semantics for an SMEM (Scalar Memory) instruction."""
Expand Down Expand Up @@ -1836,7 +1855,7 @@ def _derive_smem(name: str) -> InstructionSemantics | None:
if is_x2:
suffix = suffix[:-3]
info = _derive_flat_atomic_info(suffix, is_x2)
if info and upper in ('S_ATOMIC_DEC', 'S_ATOMIC_DEC_X2'):
if info and info[0] in _SMEM_ATOMIC_OPS:
op, elem_size, data_dw_actual = info
return InstructionSemantics(
name,
Expand All @@ -1845,7 +1864,7 @@ def _derive_smem(name: str) -> InstructionSemantics | None:
elem_size=elem_size,
num_elems=data_dw_actual,
)
# Other scalar atomics are not currently simulated.
# Scalar buffer atomics and compare-swap are not currently simulated.
return InstructionSemantics(name, 'nop')

is_store = '_STORE_' in upper or '_SCRATCH_STORE_' in upper
Expand Down
23 changes: 21 additions & 2 deletions emulation/rocjitsu/lib/python/amdisa/tests/test_sema_derive.py
Original file line number Diff line number Diff line change
Expand Up @@ -2273,8 +2273,10 @@ def test_gfx1250_prefetch_hints_are_true_nop(self, name):


_IMPLEMENTED_SCALAR_ATOMICS = {
'S_ATOMIC_DEC': ('dec', 4, 1),
'S_ATOMIC_DEC_X2': ('dec', 8, 2),
f'S_ATOMIC_{op}{width}': (op.lower(), elem_size, num_elems)
for op in _SCALAR_ATOMIC_OPS
if op != 'CMPSWAP'
for width, elem_size, num_elems in (('', 4, 1), ('_X2', 8, 2))
}


Expand Down Expand Up @@ -2304,6 +2306,23 @@ def test_unimplemented_scalar_atomics_stay_nop(self, name):
assert sem is not None
assert sem.semantic_class == 'nop'

# No CDNA ISA defines these. The flat atomic tables know their operations,
# so they pin that scalar support comes from the allowlist, not that table.
@pytest.mark.parametrize(
'name',
[
'S_ATOMIC_ADD_F32',
'S_ATOMIC_FMIN',
'S_ATOMIC_PK_ADD_F16',
'S_ATOMIC_CSUB',
'S_ATOMIC_COND_SUB_U32',
],
)
def test_scalar_atomic_operations_outside_allowlist_stay_nop(self, name):
sem = derive_semantics(name, 'ENC_SMEM')
assert sem is not None
assert sem.semantic_class == 'nop'


class TestDeriveBufferLoad:
def test_buffer_load(self):
Expand Down
Loading
Loading