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
172 lines
6.4 KiB
Python
172 lines
6.4 KiB
Python
################################################################################
|
|
#
|
|
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cop-
|
|
# ies of the Software, and to permit persons to whom the Software is furnished
|
|
# to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
# copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM-
|
|
# PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNE-
|
|
# CTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
################################################################################
|
|
|
|
"""Tests for the StinkyTofu pass plugin mechanism exposed through rocisa."""
|
|
|
|
import pytest
|
|
import rocisa
|
|
from rocisa.code import Module, SignatureBase
|
|
|
|
_ISA = (12, 5, 0)
|
|
|
|
pytestmark = pytest.mark.skipif(
|
|
not rocisa.isSupportedByStinkyTofu(_ISA),
|
|
reason=f"gfx{''.join(str(v) for v in _ISA)} not registered in StinkyTofu BackendRegistry",
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
|
def _isa_context():
|
|
import os
|
|
import shutil
|
|
|
|
rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm")
|
|
search_path = os.pathsep.join([
|
|
os.path.join(rocm_path, "bin"),
|
|
os.path.join(rocm_path, "lib", "llvm", "bin"),
|
|
])
|
|
assembler = shutil.which("amdclang++", path=search_path) or "amdclang++"
|
|
rocisa.rocIsa.getInstance().init(_ISA, assembler, False)
|
|
|
|
|
|
def _make_stinky_module(name="test_kernel"):
|
|
mod = Module(name)
|
|
sig = SignatureBase(
|
|
kernelName=name,
|
|
kernArgsVersion=0,
|
|
codeObjectVersion="default",
|
|
groupSegmentSize=0,
|
|
sgprWorkGroup=[0, 1, 2],
|
|
vgprWorkItem=0,
|
|
flatWorkGroupSize=32,
|
|
)
|
|
opts = {"OptLevel": 0, "wavefrontSize": 32}
|
|
return rocisa.toStinkyTofuModule(mod, _ISA, name, sig, opts)
|
|
|
|
|
|
class TestExtensionPointEnum:
|
|
def test_enum_exists(self):
|
|
assert hasattr(rocisa, "PipelineExtensionPoint")
|
|
|
|
def test_values_exist(self):
|
|
EP = rocisa.PipelineExtensionPoint
|
|
assert hasattr(EP, "BeforeRegionPasses")
|
|
assert hasattr(EP, "InnerRegionBegin")
|
|
assert hasattr(EP, "InnerRegionEnd")
|
|
assert hasattr(EP, "AfterRegionPasses")
|
|
|
|
def test_values_are_distinct(self):
|
|
EP = rocisa.PipelineExtensionPoint
|
|
eps = {
|
|
EP.BeforeRegionPasses,
|
|
EP.InnerRegionBegin,
|
|
EP.InnerRegionEnd,
|
|
EP.AfterRegionPasses,
|
|
}
|
|
assert len(eps) == 4
|
|
|
|
|
|
class TestPluginData:
|
|
def test_set_and_get_i64(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataI64("enableTDMA", 1)
|
|
assert st.getPluginDataI64("enableTDMA") == 1
|
|
|
|
def test_get_i64_default(self):
|
|
st = _make_stinky_module()
|
|
assert st.getPluginDataI64("nonexistent", -1) == -1
|
|
|
|
def test_set_and_get_str(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataStr("kernelName", "my_kernel")
|
|
assert st.getPluginDataStr("kernelName") == "my_kernel"
|
|
|
|
def test_get_str_default(self):
|
|
st = _make_stinky_module()
|
|
assert st.getPluginDataStr("nonexistent", "fallback") == "fallback"
|
|
|
|
def test_overwrite_i64(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataI64("key", 42)
|
|
assert st.getPluginDataI64("key") == 42
|
|
st.setPluginDataI64("key", 99)
|
|
assert st.getPluginDataI64("key") == 99
|
|
|
|
def test_multiple_keys(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataI64("a", 1)
|
|
st.setPluginDataI64("b", 2)
|
|
st.setPluginDataStr("c", "three")
|
|
assert st.getPluginDataI64("a") == 1
|
|
assert st.getPluginDataI64("b") == 2
|
|
assert st.getPluginDataStr("c") == "three"
|
|
|
|
|
|
class TestRegisterPassAtExtensionPoint:
|
|
def test_register_unknown_pass_does_not_crash_until_run(self):
|
|
st = _make_stinky_module()
|
|
st.registerPassAtExtensionPoint(rocisa.PipelineExtensionPoint.InnerRegionEnd, "UnknownPass")
|
|
|
|
def test_pipeline_runs_with_no_plugins(self):
|
|
st = _make_stinky_module()
|
|
st.runOptimizationPipeline()
|
|
|
|
def test_plugin_data_survives_pipeline_run(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataI64("testKey", 123)
|
|
st.runOptimizationPipeline()
|
|
assert st.getPluginDataI64("testKey") == 123
|
|
|
|
|
|
class TestHelloWorldPassIntegration:
|
|
"""End-to-end test: dynamically load HelloWorldPass plugin, set
|
|
plugin data, run pipeline, verify the pass executed."""
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _load_plugin(self):
|
|
# Ask stinkytofu where its own example plugin is; it resolves the path
|
|
# relative to the loaded libstinkytofu. Empty means it was built with
|
|
# STINKYTOFU_BUILD_EXAMPLES=OFF (e.g. a production ROCm package).
|
|
path = rocisa.stinkytofuExamplePluginPath()
|
|
if not path:
|
|
pytest.skip("StinkyTofu example plugin not built (STINKYTOFU_BUILD_EXAMPLES=OFF)")
|
|
rocisa.loadPlugin(path)
|
|
|
|
def test_hello_world_pass_executes(self):
|
|
st = _make_stinky_module()
|
|
st.setPluginDataStr("greeting", "Hello from rocisa test!")
|
|
st.registerPassAtExtensionPoint(
|
|
rocisa.PipelineExtensionPoint.AfterRegionPasses, "HelloWorldPass"
|
|
)
|
|
st.runOptimizationPipeline()
|
|
assert st.getPluginDataI64("pass_executed") == 1
|
|
assert st.getPluginDataStr("greeting_result") == "executed: Hello from rocisa test!"
|
|
|
|
def test_hello_world_pass_default_greeting(self):
|
|
st = _make_stinky_module()
|
|
st.registerPassAtExtensionPoint(
|
|
rocisa.PipelineExtensionPoint.AfterRegionPasses, "HelloWorldPass"
|
|
)
|
|
st.runOptimizationPipeline()
|
|
assert st.getPluginDataI64("pass_executed") == 1
|
|
assert st.getPluginDataStr("greeting_result") == "executed: Hello from plugin!"
|