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
223 lines
6.0 KiB
Markdown
223 lines
6.0 KiB
Markdown
# StinkyTofu Python Module
|
|
|
|
A Python interface for generating GPU assembly code for AMD GPUs using the StinkyTofu IR.
|
|
|
|
## Features
|
|
|
|
- **Instance-based design** - No global state, each builder is independent
|
|
- **Explicit module management** - Create named IR modules and add instructions explicitly
|
|
- **Architecture-specific** - Target different GPU architectures (e.g., gfx1250)
|
|
- **Thread-safe** - Multiple instances can be used concurrently
|
|
|
|
## Building
|
|
|
|
### Prerequisites
|
|
|
|
- CMake 3.16+
|
|
- Python 3.6+
|
|
- nanobind: `pip install nanobind`
|
|
|
|
### Build Instructions
|
|
|
|
From the repository root:
|
|
|
|
```bash
|
|
cd shared/stinkytofu
|
|
mkdir -p build && cd build
|
|
cmake .. -DSTINKYTOFU_BUILD_PYTHON=ON
|
|
cmake --build . --target stinkytofu_python -j12
|
|
```
|
|
|
|
The Python module will be built to `build/lib/stinkytofu.*.so`.
|
|
|
|
### Add to Python Path
|
|
|
|
```bash
|
|
export PYTHONPATH=/path/to/build/lib:$PYTHONPATH
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Basic Usage
|
|
|
|
```python
|
|
from stinkytofu import StinkyAsmIR, vgpr, sgpr
|
|
|
|
# Create builder for gfx1250
|
|
st = StinkyAsmIR([12, 5, 0])
|
|
|
|
# Create a module to hold instructions
|
|
module = st.createIRList("my_kernel")
|
|
|
|
# Create instructions and add to module
|
|
module.add(st.VAddU32(vgpr(0), vgpr(1), vgpr(2), "add"))
|
|
module.add(st.VMulF32(vgpr(3), vgpr(0), vgpr(4), "multiply"))
|
|
module.add(st.SBarrier("sync"))
|
|
|
|
# Emit assembly
|
|
print(module.emitAssembly())
|
|
```
|
|
|
|
### Register Ranges
|
|
|
|
```python
|
|
from stinkytofu import StinkyAsmIR, vgpr, acc
|
|
|
|
st = StinkyAsmIR([12, 5, 0])
|
|
module = st.createIRList("mfma_kernel")
|
|
|
|
# Use count parameter for register ranges
|
|
# createMFMA for Matrix-FMA instructions
|
|
module.add(st.createMFMA(
|
|
instType="f32", # input type
|
|
accType="f32", # accumulator type
|
|
m=16, n=16, k=4, # dimensions
|
|
blocks=1, # number of blocks
|
|
mfma1k=False, # not 1k variant
|
|
acc=acc(0, 4), # dst: a[0:3] - 4 registers
|
|
a=vgpr(0, 4), # matrix A: v[0:3] - 4 registers
|
|
b=vgpr(4, 4), # matrix B: v[4:7] - 4 registers
|
|
acc2=acc(0, 4), # input acc: a[0:3] - 4 registers
|
|
comment="MFMA"
|
|
))
|
|
|
|
print(module.emitAssembly())
|
|
```
|
|
|
|
### Composite Instructions (Architecture-Aware Lowering)
|
|
|
|
Some instructions may not be supported on all architectures. StinkyTofu automatically handles this by lowering unsupported instructions into equivalent sequences:
|
|
|
|
```python
|
|
from stinkytofu import StinkyAsmIR, vgpr
|
|
|
|
st = StinkyAsmIR([12, 5, 0]) # gfx1250 supports v_pk_add_f32
|
|
module = st.createIRList("composite_example")
|
|
|
|
# VAddPKF32 demonstrates the composite instruction pattern:
|
|
# - On architectures with v_pk_add_f32: returns 1 instruction
|
|
# - On older architectures: returns 2 v_add_f32 instructions (lowered)
|
|
insts = st.VAddPKF32(vgpr(0, 2), vgpr(2, 2), vgpr(4, 2), "packed add")
|
|
print(f"Generated {len(insts)} instruction(s)") # Prints "1" on gfx1250
|
|
|
|
# module.add() accepts lists of instructions
|
|
module.add(insts)
|
|
|
|
print(module.emitAssembly())
|
|
# Output on gfx1250: v_pk_add_f32 v[0:1], v[2:3], v[4:5] // packed add
|
|
```
|
|
|
|
**Note:** All instruction creation methods return a list of instructions. Most of the time this list contains a single instruction, but for composite/lowered instructions, it may contain multiple instructions depending on the target architecture. The `module.add()` method accepts these lists directly.
|
|
|
|
### Multiple Modules
|
|
|
|
```python
|
|
from stinkytofu import StinkyAsmIR, vgpr
|
|
|
|
st = StinkyAsmIR([12, 5, 0])
|
|
|
|
# Create multiple kernels
|
|
kernel_a = st.createIRList("kernel_a")
|
|
kernel_b = st.createIRList("kernel_b")
|
|
|
|
# Add different instructions to each
|
|
kernel_a.add(st.VAddU32(vgpr(0), vgpr(1), vgpr(2)))
|
|
kernel_b.add(st.VMulF32(vgpr(0), vgpr(1), vgpr(2)))
|
|
|
|
# Emit separately
|
|
print("Kernel A:")
|
|
print(kernel_a.emitAssembly())
|
|
|
|
print("\nKernel B:")
|
|
print(kernel_b.emitAssembly())
|
|
```
|
|
|
|
### Conditional Assembly
|
|
|
|
```python
|
|
from stinkytofu import StinkyAsmIR, vgpr
|
|
|
|
st = StinkyAsmIR([12, 5, 0])
|
|
module = st.createIRList("conditional_kernel")
|
|
|
|
# Create instruction but don't add yet
|
|
inst = st.VAddU32(vgpr(0), vgpr(1), vgpr(2), "conditional add")
|
|
|
|
# Add conditionally
|
|
use_optimization = True
|
|
if use_optimization:
|
|
module.add(inst)
|
|
|
|
module.add(st.SBarrier("sync"))
|
|
print(module.emitAssembly())
|
|
```
|
|
|
|
More examples in `examples/basic_usage.py`.
|
|
|
|
## Testing
|
|
|
|
The test suite uses **pytest** for better test organization and reporting.
|
|
|
|
### Quick Start
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pip install -r python_module/tests/requirements.txt
|
|
|
|
# Run all tests
|
|
PYTHONPATH=build/lib:$PYTHONPATH pytest python_module/tests/ -v
|
|
```
|
|
|
|
### Detailed Testing Guide
|
|
|
|
For comprehensive testing documentation including:
|
|
- Running specific tests and test categories
|
|
- Using fixtures and parametrized tests
|
|
- Coverage reports and parallel execution
|
|
- Debugging and CI/CD integration
|
|
|
|
See **[tests/testing.md](tests/testing.md)** for the complete testing guide.
|
|
|
|
## API Reference
|
|
|
|
### Main Classes
|
|
|
|
- **`StinkyAsmIR(arch)`** - Create builder for target architecture
|
|
- `arch`: List `[major, minor, stepping]`, e.g., `[12, 5, 0]` for gfx1250
|
|
|
|
- **`IRListModule`** - Container for instructions
|
|
- `add(inst)` - Add instruction to module (returns inst for chaining)
|
|
- `emitAssembly(emit_cycle_info=False, emit_user_comments=True)` - Emit assembly code
|
|
- `getName()` - Get module name
|
|
|
|
### Register Helpers
|
|
|
|
- **`vgpr(idx, count=1)`** - Vector general purpose register
|
|
- **`sgpr(idx, count=1)`** - Scalar general purpose register
|
|
- **`acc(idx, count=1)`** - Accumulator register
|
|
|
|
### Instruction Methods (on StinkyAsmIR)
|
|
|
|
Vector ALU:
|
|
- `VAddU32(dst, src0, src1, comment="")`
|
|
- `VMulF32(dst, src0, src1, comment="")`
|
|
|
|
Scalar:
|
|
- `SAbsI32(dst, src, comment="")`
|
|
- `SBarrier(comment="")`
|
|
|
|
Matrix (Generic Creation):
|
|
- `createMFMA(output_type, input_type, M, N, K, dst, src0, src1, src2, comment="")`
|
|
- `createMXMFMA(output_type, input_type, M, N, K, dst, src0, src1, src2, comment="")`
|
|
- `createSMFMA(output_type, input_type, M, N, K, dst, src0, src1, src2, index, comment="")`
|
|
|
|
See [docs/mfma-instructions.md](docs/mfma-instructions.md) for detailed MFMA documentation.
|
|
|
|
*All instruction methods return a list of `StinkyInstruction*` pointers.*
|
|
|
|
## License
|
|
|
|
MIT License - See LICENSE file for details.
|
|
|
|
Copyright (C) 2025 Advanced Micro Devices, Inc.
|