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
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,8 @@ class RJ_API_TYPE_EXPORT ComputeUnitCore : public simdojo::CompositeComponent {
/// `UnimplementedInst::what()` when that legacy exception is translated.
/// Otherwise the pointed-to string is unchanged.
/// @returns Failure for an unimplemented instruction stub or a reported operand
/// failure. The wavefront retains the reason for caller-owned diagnostics.
/// or register-access failure. The wavefront retains the reason for caller-owned
/// diagnostics.
/// Each call clears the previous error; a failed call does not halt the wavefront.
/// Other host failures inside implemented instructions still raise exceptions.
util::Result execute_instruction(Instruction *inst, Wavefront &wf,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,9 @@ class RegisterAccess {
});
}

/// @brief Return raw lane words for one register in the region.
/// @returns Failure for a partial-byte region, reporting InvalidRegisterAccess
/// through the wavefront's instruction-execution error channel.
FailureOr<std::span<const uint32_t>> lanes(uint32_t relative_reg = 0) const {
assert(relative_reg < reg_count_ && "relative VGPR outside read region");
if (byte_mask_ != rocjitsu::ExecutionPlugin::kFullByteMask)
Expand Down
23 changes: 23 additions & 0 deletions emulation/rocjitsu/tests/register_access_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1883,6 +1883,29 @@ TEST(RegisterAccessTest, PartialByteRawRegionOperationsRejectBeforeSideEffects)
expect_failure([&] { return region.copy_dwords_lane_major(bytes, 1); });
}

TEST(RegisterAccessTest, OversizedRawRegionCopyRejectsBeforeSideEffects) {
Fixture fx(ROCJITSU_CODE_ARCH_CDNA4, kSgprsPerWave, /*wavefront_slots=*/1, kVgprsPerWave,
/*wave_size=*/64);
ASSERT_NE(fx.wf, nullptr);
ASSERT_EQ(fx.wf->wf_size(), 64u);
for (uint32_t lane = 0; lane < fx.wf->wf_size(); ++lane)
fx.cu->write_vgpr(fx.vgpr_base(), lane, 0x12340000u + lane);
auto region = RegisterAccess(*fx.wf).read_vgpr_region(
fx.vgpr_base(), /*reg_count=*/1, /*lane_mask=*/~uint64_t{0}, ExecutionPlugin::kFullByteMask);
ASSERT_TRUE(region.valid());
std::array<uint32_t, 65> words;
words.fill(0xAABBCCDDu);
const auto original_words = words;

fx.wf->clear_instruction_execution_error();
ASSERT_EQ(fx.wf->instruction_execution_error(), InstructionExecutionError::None);
ASSERT_EQ(fx.wf->instruction_execution_error_detail(), nullptr);
EXPECT_TRUE(region.copy_to(words).failed());
EXPECT_EQ(fx.wf->instruction_execution_error(), InstructionExecutionError::InvalidRegisterAccess);
EXPECT_STREQ(fx.wf->instruction_execution_error_detail(), "destination exceeds read region");
EXPECT_EQ(words, original_words);
}

TEST(RegisterAccessTest, ScalarBackedPartialByteStoresRejectBeforeObservation) {
Fixture fx;
ASSERT_NE(fx.wf, nullptr);
Expand Down
Loading