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
280 lines
8.0 KiB
Python
280 lines
8.0 KiB
Python
"""
|
|
Basic tests for stinkytofu high-level IR Python bindings with shared_ptr
|
|
"""
|
|
|
|
import pytest
|
|
import sys
|
|
import os
|
|
|
|
# Add the build directory to path
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../build/lib"))
|
|
|
|
import stinkytofu
|
|
|
|
|
|
class TestRegisterCreation:
|
|
"""Test register creation helper functions"""
|
|
|
|
def test_vgpr(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
assert v0.reg_type == stinkytofu.RegType.V
|
|
assert v0.index == 0
|
|
assert v0.count == 1
|
|
assert not v0.is_literal
|
|
|
|
def test_sgpr(self):
|
|
s0 = stinkytofu.sgpr(10, 2)
|
|
assert s0.reg_type == stinkytofu.RegType.S
|
|
assert s0.index == 10
|
|
assert s0.count == 2
|
|
|
|
def test_accvgpr(self):
|
|
acc = stinkytofu.accvgpr(0, 4)
|
|
assert acc.reg_type == stinkytofu.RegType.A # AccVGPR uses RegType.A
|
|
assert acc.index == 0
|
|
assert acc.count == 4
|
|
|
|
|
|
class TestIRModule:
|
|
"""Test LogicalModule creation and management"""
|
|
|
|
def test_create_module(self):
|
|
module = stinkytofu.LogicalModule("test_kernel")
|
|
assert module.getName() == "test_kernel"
|
|
|
|
def test_add_instructions(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
module = stinkytofu.LogicalModule("test_kernel")
|
|
|
|
# Add instructions
|
|
module.add(stinkytofu.VAddF32(v0, v1, v2))
|
|
module.add(stinkytofu.VMulF32(v0, v1, v2))
|
|
module.add(stinkytofu.VFmaF32(v0, v1, v2, v0))
|
|
|
|
# Check module dump
|
|
dump = module.dump()
|
|
assert "test_kernel" in dump
|
|
assert "Instructions: 3" in dump
|
|
assert "VAddF32" in dump
|
|
assert "VMulF32" in dump
|
|
assert "VFmaF32" in dump
|
|
|
|
def test_instruction_with_comment(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
module = stinkytofu.LogicalModule("test")
|
|
module.add(stinkytofu.VAddU32(v0, v1, v2, comment="This is a test comment"))
|
|
|
|
dump = module.dump()
|
|
assert "This is a test comment" in dump
|
|
|
|
|
|
class TestInstructionTypes:
|
|
"""Test different instruction types"""
|
|
|
|
def test_vector_alu_instructions(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
module = stinkytofu.LogicalModule("alu_test")
|
|
|
|
# Integer operations
|
|
module.add(stinkytofu.VAddU32(v0, v1, v2))
|
|
module.add(stinkytofu.VSubU32(v0, v1, v2))
|
|
module.add(stinkytofu.VMulLOU32(v0, v1, v2))
|
|
|
|
# Float operations
|
|
module.add(stinkytofu.VAddF32(v0, v1, v2))
|
|
module.add(stinkytofu.VMulF32(v0, v1, v2))
|
|
module.add(stinkytofu.VFmaF32(v0, v1, v2, v0))
|
|
|
|
# FP16 operations
|
|
module.add(stinkytofu.VAddF16(v0, v1, v2))
|
|
module.add(stinkytofu.VMulF16(v0, v1, v2))
|
|
|
|
dump = module.dump()
|
|
assert "Instructions: 8" in dump
|
|
|
|
def test_ds_instructions(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
module = stinkytofu.LogicalModule("ds_test")
|
|
|
|
# DS load/store instructions
|
|
module.add(stinkytofu.DSLoadB32(v0, v1, comment="Load 32-bit"))
|
|
module.add(stinkytofu.DSLoadB64(v0, v1, comment="Load 64-bit"))
|
|
module.add(stinkytofu.DSStoreB32(v1, v2, comment="Store 32-bit"))
|
|
|
|
dump = module.dump()
|
|
assert "DSLoadB32" in dump
|
|
assert "Load 32-bit" in dump
|
|
|
|
def test_scalar_instructions(self):
|
|
s0 = stinkytofu.sgpr(0)
|
|
s1 = stinkytofu.sgpr(1)
|
|
s2 = stinkytofu.sgpr(2)
|
|
|
|
module = stinkytofu.LogicalModule("scalar_test")
|
|
|
|
module.add(stinkytofu.SAddU32(s0, s1, s2))
|
|
module.add(stinkytofu.SSubU32(s0, s1, s2))
|
|
module.add(stinkytofu.SMulI32(s0, s1, s2))
|
|
|
|
dump = module.dump()
|
|
assert "SAddU32" in dump
|
|
|
|
|
|
class TestSpecialInstructions:
|
|
"""Test special instruction classes (MFMA, Label, etc.)"""
|
|
|
|
def test_mfma(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
acc = stinkytofu.accvgpr(0, 4)
|
|
|
|
module = stinkytofu.LogicalModule("mfma_test")
|
|
|
|
mfma = stinkytofu.MFMA(
|
|
instType="f32",
|
|
accType="f32",
|
|
m=16,
|
|
n=16,
|
|
k=16,
|
|
blocks=1,
|
|
mfma1k=False,
|
|
acc=acc,
|
|
a=v0,
|
|
b=v1,
|
|
comment="16x16x16 MFMA",
|
|
)
|
|
module.add(mfma)
|
|
|
|
dump = module.dump()
|
|
assert "MFMA" in dump
|
|
assert "16x16x16 MFMA" in dump
|
|
|
|
def test_label(self):
|
|
module = stinkytofu.LogicalModule("label_test")
|
|
|
|
label = stinkytofu.Label("loop_start")
|
|
module.add(label)
|
|
|
|
dump = module.dump()
|
|
assert "loop_start:" in dump
|
|
|
|
def test_tensor_load_to_lds(self):
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
|
|
module = stinkytofu.LogicalModule("tensor_test")
|
|
|
|
tensor_load = stinkytofu.TensorLoadToLds(v0, v1, comment="Load tensor")
|
|
module.add(tensor_load)
|
|
|
|
dump = module.dump()
|
|
assert "TensorLoadToLds" in dump
|
|
assert "Load tensor" in dump
|
|
|
|
|
|
class TestMemoryManagement:
|
|
"""Test that shared_ptr memory management works correctly"""
|
|
|
|
def test_module_destruction(self):
|
|
"""Test that modules can be created and destroyed without memory leaks"""
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
# Create and destroy multiple modules
|
|
for i in range(10):
|
|
module = stinkytofu.LogicalModule(f"test_{i}")
|
|
for j in range(10):
|
|
module.add(stinkytofu.VAddF32(v0, v1, v2))
|
|
del module
|
|
|
|
# If we get here without segfault, memory management works!
|
|
assert True
|
|
|
|
def test_instruction_reuse(self):
|
|
"""Test that instructions can be shared across modules"""
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
|
|
# Create instruction
|
|
inst = stinkytofu.VAddF32(v0, v1, v2, comment="shared instruction")
|
|
|
|
# Add to multiple modules
|
|
module1 = stinkytofu.LogicalModule("module1")
|
|
module2 = stinkytofu.LogicalModule("module2")
|
|
|
|
module1.add(inst)
|
|
module2.add(inst)
|
|
|
|
# Both should contain the instruction
|
|
assert "shared instruction" in module1.dump()
|
|
assert "shared instruction" in module2.dump()
|
|
|
|
|
|
class TestComplexKernel:
|
|
"""Test building a more complex kernel"""
|
|
|
|
def test_gemm_like_kernel(self):
|
|
"""Build a simple GEMM-like kernel structure"""
|
|
v0 = stinkytofu.vgpr(0)
|
|
v1 = stinkytofu.vgpr(1)
|
|
v2 = stinkytofu.vgpr(2)
|
|
v3 = stinkytofu.vgpr(3)
|
|
acc = stinkytofu.accvgpr(0, 4)
|
|
|
|
module = stinkytofu.LogicalModule("simple_gemm")
|
|
|
|
# Load data
|
|
module.add(stinkytofu.Label("load_data"))
|
|
module.add(stinkytofu.DSLoadB32(v0, v1, comment="Load A"))
|
|
module.add(stinkytofu.DSLoadB32(v2, v3, comment="Load B"))
|
|
|
|
# Compute loop
|
|
module.add(stinkytofu.Label("compute_loop"))
|
|
module.add(
|
|
stinkytofu.MFMA(
|
|
"f32",
|
|
"f32",
|
|
16,
|
|
16,
|
|
16,
|
|
1,
|
|
False,
|
|
acc,
|
|
v0,
|
|
v2,
|
|
comment="Matrix multiply",
|
|
)
|
|
)
|
|
module.add(stinkytofu.VAddF32(v0, v0, v1, comment="Update A ptr"))
|
|
module.add(stinkytofu.VAddF32(v2, v2, v3, comment="Update B ptr"))
|
|
|
|
# Store result
|
|
module.add(stinkytofu.Label("store_result"))
|
|
module.add(stinkytofu.VMovB32(v0, acc, comment="Move result"))
|
|
module.add(stinkytofu.DSStoreB32(v1, v0, comment="Store C"))
|
|
|
|
dump = module.dump()
|
|
assert "simple_gemm" in dump
|
|
assert "load_data:" in dump
|
|
assert "compute_loop:" in dump
|
|
assert "store_result:" in dump
|
|
assert "Instructions: 10" in dump
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|