Skip to content
Open
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
2 changes: 2 additions & 0 deletions emulation/rocjitsu/lib/python/amdisa/codegen/_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9051,6 +9051,8 @@ def _append_flat_lds_destination(
lines.append(
f'{indent}const int32_t offset = static_cast<int32_t>({raw} << {32-width}) >> {32-width};'
)
# GLOBAL LDS X3 uses the 16-byte lane stride specified for MUBUF X3 in CDNA4 ISA §9.1.9.
# This is only an inference; the GLOBAL LDS addressing rules in §10.3 do not specify an X3 stride.
lines.append(
f'{indent}amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),'
f' static_cast<int64_t>(wf.m0() & {mask}) + offset,'
Expand Down
17 changes: 17 additions & 0 deletions emulation/rocjitsu/lib/python/amdisa/semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2166,6 +2166,23 @@ def _derive_flat(name: str) -> InstructionSemantics | None:
num_elems=1,
sign_extend=signed,
)
if upper.startswith('GLOBAL_LOAD_LDS_'):
suffix = upper.removeprefix('GLOBAL_LOAD_LDS_')
if suffix in (
'UBYTE',
'SBYTE',
'USHORT',
'SSHORT',
'DWORD',
):
size, count, signed = _FLAT_DATA_MAP[suffix]
return InstructionSemantics(
name,
'global_load_lds',
elem_size=size,
num_elems=count,
sign_extend=signed,
)
if upper == 'GLOBAL_INV':
return InstructionSemantics(name, 'gl1_inv')
if upper == 'GLOBAL_WB':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9877,7 +9877,13 @@ def test_scratch_lds_and_global_lds_share_opcode_dispatch(arch, profile_type):
instructions = [inst for inst in flat.insts if inst.opcode == opcode]
assert {inst.required_flat_segment for inst in instructions} == {1, 2}
scratch = next(inst for inst in instructions if inst.required_flat_segment == 1)
global_lds = next(
inst for inst in instructions if inst.required_flat_segment == 2
)
assert semantics.instructions[scratch.name].semantic_class == 'scratch_load_lds'
assert (
semantics.instructions[global_lds.name].semantic_class == 'global_load_lds'
)
assert any(
entry and f'decodeFlatSegment{opcode}' in (entry.sub_decode_funcs or [])
for entry in spec.primary_decode_table
Expand All @@ -9903,3 +9909,25 @@ def test_opted_in_fixed_wave_matrix_layout_is_rejected(name):
)
with pytest.raises(ValueError, match=message):
_gen_mfma(Instruction(name, 'ENC_VOP3P', 0, []), 'fixed_wave', profile)


@pytest.mark.parametrize('count,opcode', [(3, 126), (4, 125)])
def test_cdna4_wide_global_lds_load_semantics(count, opcode):
spec = Parser(str(_mrisa_dir() / 'amdgpu_isa_cdna4.xml'), Cdna4Profile()).parse()
name = f'GLOBAL_LOAD_LDS_DWORDX{count}'
inst = next(
inst for inst in spec.encoding_map['ENC_FLAT'].insts if inst.name == name
)
assert inst.opcode == opcode
assert inst.required_flat_segment == 2
sem = derive_all_semantics(spec).instructions[name]
assert sem.semantic_class == 'global_load_lds'
assert sem.elem_size == 4
assert sem.num_elems == count
assert not sem.sign_extend
generator = CodeGenerator(spec, '', derive_all_semantics(spec))
body = generator._gen_flat_load([], [], sem)
assert f'd->num_elems = {count};' in body
assert f'+ offset, {count * 4}, 16);' in body
assert 'd->lds_dst = true;' in body
assert 'dst_reg_base' not in body
Original file line number Diff line number Diff line change
Expand Up @@ -3804,11 +3804,10 @@ GlobalLoadLdsUbyteFlat::GlobalLoadLdsUbyteFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3831,6 +3830,8 @@ GlobalLoadLdsUbyteFlat::GlobalLoadLdsUbyteFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3858,11 +3859,10 @@ GlobalLoadLdsSbyteFlat::GlobalLoadLdsSbyteFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3885,6 +3885,8 @@ GlobalLoadLdsSbyteFlat::GlobalLoadLdsSbyteFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3912,11 +3914,10 @@ GlobalLoadLdsUshortFlat::GlobalLoadLdsUshortFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3939,6 +3940,8 @@ GlobalLoadLdsUshortFlat::GlobalLoadLdsUshortFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3966,11 +3969,10 @@ GlobalLoadLdsSshortFlat::GlobalLoadLdsSshortFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3993,6 +3995,8 @@ GlobalLoadLdsSshortFlat::GlobalLoadLdsSshortFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -4020,11 +4024,10 @@ GlobalLoadLdsDwordFlat::GlobalLoadLdsDwordFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -4047,6 +4050,8 @@ GlobalLoadLdsDwordFlat::GlobalLoadLdsDwordFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1199,28 +1199,90 @@ void FlatAtomicDecX2Flat::execute_impl(amdgpu::Wavefront &wf) {
}

void GlobalLoadLdsUbyteFlat::execute_impl(amdgpu::Wavefront &wf) {
wf.report_instruction_execution_error(
amdgpu::InstructionExecutionError::UnimplementedInstruction);
auto d = std::make_unique<amdgpu::VectorMemState>(amdgpu::GLOBAL_MEM);
d->elem_size = 1;
d->num_elems = 1;
d->is_load = true;
d->wait_counter_type = amdgpu::WaitCounterType::VMCNT;
d->mtype = amdgpu::mtype_from_flags_gfx940(inst_.sc0, inst_.sc1, inst_.nt);
d->non_temporal = inst_.nt;
flat_calculate_addresses(inst_, wf, *d);
d->lds_dst = true;
d->lds_dword_extend = true;
const int32_t offset = static_cast<int32_t>((inst_.offset | (inst_.pad_12 << 12)) << 19) >> 19;
amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),
static_cast<int64_t>(wf.m0() & 0x3fffcu) + offset, 4, 4);
set_data(std::move(d));
}

void GlobalLoadLdsSbyteFlat::execute_impl(amdgpu::Wavefront &wf) {
wf.report_instruction_execution_error(
amdgpu::InstructionExecutionError::UnimplementedInstruction);
auto d = std::make_unique<amdgpu::VectorMemState>(amdgpu::GLOBAL_MEM);
d->elem_size = 1;
d->num_elems = 1;
d->is_load = true;
d->wait_counter_type = amdgpu::WaitCounterType::VMCNT;
d->sign_extend = true;
d->mtype = amdgpu::mtype_from_flags_gfx940(inst_.sc0, inst_.sc1, inst_.nt);
d->non_temporal = inst_.nt;
flat_calculate_addresses(inst_, wf, *d);
d->lds_dst = true;
d->lds_dword_extend = true;
const int32_t offset = static_cast<int32_t>((inst_.offset | (inst_.pad_12 << 12)) << 19) >> 19;
amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),
static_cast<int64_t>(wf.m0() & 0x3fffcu) + offset, 4, 4);
set_data(std::move(d));
}

void GlobalLoadLdsUshortFlat::execute_impl(amdgpu::Wavefront &wf) {
wf.report_instruction_execution_error(
amdgpu::InstructionExecutionError::UnimplementedInstruction);
auto d = std::make_unique<amdgpu::VectorMemState>(amdgpu::GLOBAL_MEM);
d->elem_size = 2;
d->num_elems = 1;
d->is_load = true;
d->wait_counter_type = amdgpu::WaitCounterType::VMCNT;
d->mtype = amdgpu::mtype_from_flags_gfx940(inst_.sc0, inst_.sc1, inst_.nt);
d->non_temporal = inst_.nt;
flat_calculate_addresses(inst_, wf, *d);
d->lds_dst = true;
d->lds_dword_extend = true;
const int32_t offset = static_cast<int32_t>((inst_.offset | (inst_.pad_12 << 12)) << 19) >> 19;
amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),
static_cast<int64_t>(wf.m0() & 0x3fffcu) + offset, 4, 4);
set_data(std::move(d));
}

void GlobalLoadLdsSshortFlat::execute_impl(amdgpu::Wavefront &wf) {
wf.report_instruction_execution_error(
amdgpu::InstructionExecutionError::UnimplementedInstruction);
auto d = std::make_unique<amdgpu::VectorMemState>(amdgpu::GLOBAL_MEM);
d->elem_size = 2;
d->num_elems = 1;
d->is_load = true;
d->wait_counter_type = amdgpu::WaitCounterType::VMCNT;
d->sign_extend = true;
d->mtype = amdgpu::mtype_from_flags_gfx940(inst_.sc0, inst_.sc1, inst_.nt);
d->non_temporal = inst_.nt;
flat_calculate_addresses(inst_, wf, *d);
d->lds_dst = true;
d->lds_dword_extend = true;
const int32_t offset = static_cast<int32_t>((inst_.offset | (inst_.pad_12 << 12)) << 19) >> 19;
amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),
static_cast<int64_t>(wf.m0() & 0x3fffcu) + offset, 4, 4);
set_data(std::move(d));
}

void GlobalLoadLdsDwordFlat::execute_impl(amdgpu::Wavefront &wf) {
wf.report_instruction_execution_error(
amdgpu::InstructionExecutionError::UnimplementedInstruction);
auto d = std::make_unique<amdgpu::VectorMemState>(amdgpu::GLOBAL_MEM);
d->elem_size = 4;
d->num_elems = 1;
d->is_load = true;
d->wait_counter_type = amdgpu::WaitCounterType::VMCNT;
d->mtype = amdgpu::mtype_from_flags_gfx940(inst_.sc0, inst_.sc1, inst_.nt);
d->non_temporal = inst_.nt;
flat_calculate_addresses(inst_, wf, *d);
d->lds_dst = true;
d->lds_dword_extend = true;
const int32_t offset = static_cast<int32_t>((inst_.offset | (inst_.pad_12 << 12)) << 19) >> 19;
amdgpu::prepare_lds_destination(*d, wf.lds_base(), wf.lds_size(),
static_cast<int64_t>(wf.m0() & 0x3fffcu) + offset, 4, 4);
set_data(std::move(d));
}

void ScratchLoadLdsUbyteFlat::execute_impl(amdgpu::Wavefront &wf) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3804,11 +3804,10 @@ GlobalLoadLdsUbyteFlat::GlobalLoadLdsUbyteFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3831,6 +3830,8 @@ GlobalLoadLdsUbyteFlat::GlobalLoadLdsUbyteFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3858,11 +3859,10 @@ GlobalLoadLdsSbyteFlat::GlobalLoadLdsSbyteFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3885,6 +3885,8 @@ GlobalLoadLdsSbyteFlat::GlobalLoadLdsSbyteFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3912,11 +3914,10 @@ GlobalLoadLdsUshortFlat::GlobalLoadLdsUshortFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3939,6 +3940,8 @@ GlobalLoadLdsUshortFlat::GlobalLoadLdsUshortFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -3966,11 +3969,10 @@ GlobalLoadLdsSshortFlat::GlobalLoadLdsSshortFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -3993,6 +3995,8 @@ GlobalLoadLdsSshortFlat::GlobalLoadLdsSshortFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down Expand Up @@ -4020,11 +4024,10 @@ GlobalLoadLdsDwordFlat::GlobalLoadLdsDwordFlat(const MachineInst *inst)
: 0))),
addr(64, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(inst)->addr),
m0(32, OperandType::OPR_SDST_M0, 124), saddr(0, OperandType::OPR_SREG, 0) {
dst_operands_[0] = &vdst;
src_operands_[0] = &addr;
src_operands_[1] = &m0;
num_src_ = 2;
num_dst_ = 1;
num_dst_ = 0;
if (inst_.seg == 1) {
addr = Operand(32, OperandType::OPR_VGPR, reinterpret_cast<const OpEncoding *>(&inst_)->addr);
if (!(inst_.lds != 0)) {
Expand All @@ -4047,6 +4050,8 @@ GlobalLoadLdsDwordFlat::GlobalLoadLdsDwordFlat(const MachineInst *inst)
src_operands_[num_src_++] = &saddr;
}
m0.apply_fieldless_caps(false, false, false);
set_memory_issue_info({amdgpu::MemoryCounterObligation{amdgpu::WaitCounterType::VMCNT,
amdgpu::MemoryCompletionClass::VMEM}});
flags_ |= MEMORY_WAIT_PRODUCER;
}

Expand Down
Loading
Loading