Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

308 lines
11 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#include <rocRoller/Context.hpp>
#include <rocRoller/Expression.hpp>
#include <rocRoller/KernelOptions.hpp>
#include <rocRoller/Operations/Command.hpp>
#include <rocRoller/Operations/Operations.hpp>
#include <rocRoller/Operations/Scratch.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators.hpp>
#include <catch2/generators/catch_generators_range.hpp>
#include "TestContext.hpp"
#include <set>
#include <sstream>
using namespace rocRoller;
using namespace rocRoller::Operations;
namespace ScratchOperationTest
{
TEST_CASE("ScratchPolicy enum", "[scratch][serialization]")
{
SECTION("toString for all values")
{
CHECK(toString(ScratchPolicy::None) == "None");
CHECK(toString(ScratchPolicy::ZeroedBeforeAndAfter) == "ZeroedBeforeAndAfter");
}
SECTION("operator<< for ScratchPolicy")
{
std::ostringstream oss;
oss << ScratchPolicy::None;
CHECK(oss.str() == "None");
oss.str("");
oss << ScratchPolicy::ZeroedBeforeAndAfter;
CHECK(oss.str() == "ZeroedBeforeAndAfter");
}
SECTION("toString for None policy")
{
Scratch scratch(OperationTag(), ScratchPolicy::None);
CHECK(scratch.toString() == "Scratch(None)");
}
SECTION("toString for ZeroedBeforeAndAfter policy")
{
Scratch scratch(OperationTag(), ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(scratch.toString() == "Scratch(ZeroedBeforeAndAfter)");
}
SECTION("Verify format is Scratch(PolicyName)")
{
Scratch scratch(OperationTag(), ScratchPolicy::None);
std::string str = scratch.toString();
CHECK(str.substr(0, 8) == "Scratch(");
CHECK(str.back() == ')');
}
}
TEST_CASE("Scratch construction", "[operation][scratch]")
{
SECTION("Count value for range checking")
{
// Verify Count is at the end for range-based operations
CHECK(static_cast<int>(ScratchPolicy::Count) == 2);
}
SECTION("Invalid policy returns Invalid")
{
auto invalidPolicy = static_cast<ScratchPolicy>(99);
CHECK(toString(invalidPolicy) == "Invalid");
}
SECTION("Create Scratch with None policy")
{
Scratch scratch(OperationTag(), ScratchPolicy::None);
CHECK(scratch.policy() == ScratchPolicy::None);
}
SECTION("Create Scratch with ZeroedBeforeAndAfter policy")
{
Scratch scratch(OperationTag(), ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(scratch.policy() == ScratchPolicy::ZeroedBeforeAndAfter);
}
SECTION("Constructor with only tag defaults policy to None")
{
auto tag = OperationTag();
Scratch scratch(tag);
CHECK(scratch.policy() == ScratchPolicy::None);
CHECK(scratch.getTag() == tag);
}
SECTION("Create Scratch with None policy and tag")
{
auto tag = OperationTag();
Scratch scratch(tag, ScratchPolicy::None);
CHECK(scratch.policy() == ScratchPolicy::None);
CHECK(scratch.getTag() == tag);
}
SECTION("policy() accessor returns correct value")
{
Scratch scratch1(OperationTag(), ScratchPolicy::None);
Scratch scratch2(OperationTag(), ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(scratch1.policy() == ScratchPolicy::None);
CHECK(scratch2.policy() == ScratchPolicy::ZeroedBeforeAndAfter);
}
SECTION("Same policy should be equal")
{
auto tag1 = OperationTag();
auto tag2 = OperationTag();
Scratch scratch1(tag1, ScratchPolicy::None);
Scratch scratch2(tag2, ScratchPolicy::None);
CHECK(tag1 == tag2);
CHECK(scratch1 == scratch2);
auto tag3 = OperationTag();
auto tag4 = OperationTag();
Scratch scratch3(tag3, ScratchPolicy::ZeroedBeforeAndAfter);
Scratch scratch4(tag4, ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(tag3 == tag4);
CHECK(scratch3 == scratch4);
}
SECTION("Different policies should not be equal")
{
Scratch scratch1(OperationTag(), ScratchPolicy::None);
Scratch scratch2(OperationTag(), ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(!(scratch1 == scratch2));
}
SECTION("operator== is reflexive")
{
Scratch scratch(OperationTag(), ScratchPolicy::None);
CHECK(scratch == scratch);
}
SECTION("ToString visitor")
{
Scratch scratch(OperationTag(), ScratchPolicy::ZeroedBeforeAndAfter);
ToStringVisitor toStringVisitor;
std::string str = toStringVisitor(scratch);
CHECK(str == "Scratch(ZeroedBeforeAndAfter)");
}
SECTION("VariableTypeVisitor returns DataType::None")
{
Scratch scratch(OperationTag(), ScratchPolicy::None);
VariableTypeVisitor typeVisitor;
auto varType = typeVisitor(scratch);
CHECK(varType.dataType == DataType::None);
}
SECTION("SetCommand visitor")
{
auto command = std::make_shared<Command>();
auto tag = command->allocateTag();
Scratch scratch(tag, ScratchPolicy::None);
SetCommand setCommandVisitor(command);
setCommandVisitor(scratch);
// Verify command was set (indirectly by checking tag can be assigned)
auto scratchTag = command->addOperation(scratch);
CHECK(!scratchTag.uninitialized());
}
}
TEST_CASE("Scratch in Command", "[scratch][command]")
{
SECTION("Add Scratch operation to Command")
{
auto command = std::make_shared<Command>();
auto tag = command->allocateTag();
auto scratchTag
= command->addOperation(Scratch(tag, ScratchPolicy::ZeroedBeforeAndAfter));
CHECK(tag.uninitialized() == false);
CHECK(scratchTag.uninitialized() == false);
}
SECTION("Tag assignment works correctly")
{
auto command = std::make_shared<Command>();
auto scratchTag1 = command->allocateTag();
auto scratchTag2 = command->allocateTag();
Scratch scratch1(scratchTag1, ScratchPolicy::None);
Scratch scratch2(scratchTag2, ScratchPolicy::ZeroedBeforeAndAfter);
auto scratchOpTag1 = command->addOperation(scratch1);
auto scratchOpTag2 = command->addOperation(scratch2);
CHECK(scratch1.getTag() == scratchTag1);
CHECK(scratch2.getTag() == scratchTag2);
CHECK(scratch1 != scratch2);
CHECK(scratchOpTag1.uninitialized() == false);
CHECK(scratchOpTag2.uninitialized() == false);
}
}
TEST_CASE("Scratch allocator per policy", "[scratch][context]")
{
auto context = TestContext::ForDefaultTarget();
SECTION("Context initializes all policies to zero")
{
for(size_t i = 0; i < static_cast<size_t>(ScratchPolicy::Count); ++i)
{
auto policy = static_cast<ScratchPolicy>(i);
auto amount = context->getScratchAmount(policy);
auto value = rocRoller::Expression::evaluate(amount);
CHECK(rocRoller::getUnsignedInt(value) == 0);
}
}
SECTION("allocateScratch returns offset before allocation and accumulates size")
{
auto size1 = rocRoller::Expression::literal(100u);
auto size2 = rocRoller::Expression::literal(200u);
auto offset1 = context->allocateScratch(ScratchPolicy::None, size1);
auto offset2 = context->allocateScratch(ScratchPolicy::None, size2);
// First allocation should return offset 0
CHECK(rocRoller::getUnsignedInt(rocRoller::Expression::evaluate(offset1)) == 0);
// Second allocation should return offset 100 (after first allocation)
CHECK(rocRoller::getUnsignedInt(rocRoller::Expression::evaluate(offset2)) == 100);
// Total should now be 300
auto amount = context->getScratchAmount(ScratchPolicy::None);
auto value = rocRoller::Expression::evaluate(amount);
CHECK(rocRoller::getUnsignedInt(value) == 300);
}
SECTION("allocateScratch returns correct offset per policy")
{
auto size = rocRoller::Expression::literal(500u);
auto offset = context->allocateScratch(ScratchPolicy::ZeroedBeforeAndAfter, size);
// First allocation should return offset 0
CHECK(rocRoller::getUnsignedInt(rocRoller::Expression::evaluate(offset)) == 0);
// Query total should now be 500
auto amount = context->getScratchAmount(ScratchPolicy::ZeroedBeforeAndAfter);
auto value = rocRoller::Expression::evaluate(amount);
CHECK(rocRoller::getUnsignedInt(value) == 500);
}
SECTION("Different policies have independent allocations")
{
auto sizeNone = rocRoller::Expression::literal(100u);
auto sizeZeroed = rocRoller::Expression::literal(200u);
context->allocateScratch(ScratchPolicy::None, sizeNone);
context->allocateScratch(ScratchPolicy::ZeroedBeforeAndAfter, sizeZeroed);
auto amountNone = context->getScratchAmount(ScratchPolicy::None);
auto amountZeroed = context->getScratchAmount(ScratchPolicy::ZeroedBeforeAndAfter);
auto valueNone = rocRoller::Expression::evaluate(amountNone);
auto valueZeroed = rocRoller::Expression::evaluate(amountZeroed);
CHECK(rocRoller::getUnsignedInt(valueNone) == 100);
CHECK(rocRoller::getUnsignedInt(valueZeroed) == 200);
}
}
TEST_CASE("Utilities to get scratch policy name", "[scratch][utils]")
{
SECTION("Returns correct name for None policy")
{
auto name = rocRoller::getScratchName(ScratchPolicy::None);
CHECK(name == "SCRATCH_None");
}
SECTION("Returns correct name for ZeroedBeforeAndAfter policy")
{
auto name = rocRoller::getScratchName(ScratchPolicy::ZeroedBeforeAndAfter);
CHECK(name == "SCRATCH_ZeroedBeforeAndAfter");
}
SECTION("All policies have unique names")
{
std::set<std::string> names;
for(size_t i = 0; i < static_cast<size_t>(ScratchPolicy::Count); ++i)
{
auto policy = static_cast<ScratchPolicy>(i);
auto name = rocRoller::getScratchName(policy);
CHECK(names.find(name) == names.end());
names.insert(name);
}
CHECK(names.size() == static_cast<size_t>(ScratchPolicy::Count));
}
}
}