Files
TheRock/rocm-libraries/shared/stinkytofu/docs/developer/adding-architecture.md
T
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

8.0 KiB

Adding a New GPU Architecture to StinkyTofu

This guide walks through all the steps required to add support for a new GPU architecture to the StinkyTofu framework.

Note: This guide uses Gfx1250 as a concrete example. When adding your own architecture, follow the same pattern using Gfx1250 as your template.

Overview

Adding a new architecture involves:

  1. Updating the architecture list (Step 1 and 2)
  2. Creating the architecture folder with arch.cmake, .def files, and .cpp (Step 3)
  3. Updating generated-file lists: Config.h.in, tablegen CMakeLists, RocisaArchInfo (Step 4)
  4. Implementing Rocisa-related header (Step 5)

Instruction definitions and costs are in .def files; tablegen generates *_init.inc, *_costs.inc. The defineGfxXXXInsts and cost application are auto-generated from GfxArchDefines_block.inc.in and arch.cmake. You only provide the maps in GfxXXX.cpp.

Architecture Type arch.cmake defaults Notes
Gfx1250 RDNA4 cycle=1, latency=1, VGPR=256, SGPR=102, AGPR=0 Currently the only supported architecture

Step-by-Step Guide

Step 1: Update Architecture List

Add the new architecture to cmake/StinkytofuArchList.cmake:

set(STINKYTOFU_ALL_ARCHS
    Gfx1250
    GfxYourArch    # <-- Add here
)

Step 2: Update Config.h.in

Add a #cmakedefine entry in include/stinkytofu/Config.h.in:

#cmakedefine STINKYTOFU_ARCH_GFX1250
#cmakedefine STINKYTOFU_ARCH_GFXYOURARCH    // <-- Add here

Step 3: Create Architecture Definitions

Best approach: Copy an existing architecture folder and modify it.

cp -r hardware/src/gfx/Gfx1250 hardware/src/gfx/GfxYourArch
cd hardware/src/gfx/GfxYourArch
mv Gfx1250.cpp GfxYourArch.cpp
mv Gfx1250Formats.def GfxYourArchFormats.def
mv Gfx1250Instructions.def GfxYourArchInstructions.def

3a. Create arch.cmake

This file defines architecture metadata. All values are required. ARCH_MAX_AGPR may be 0 for RDNA.

# GfxYourArch arch properties
set(ARCH_MAJOR X)
set(ARCH_MINOR Y)
set(ARCH_STEPPING Z)
set(ARCH_WAVEFRONT 64)        # 64 for CDNA, 32 for RDNA
set(ARCH_DEFAULT_CYCLE 4)     # 4 for CDNA, 1 for RDNA
set(ARCH_DEFAULT_LATENCY 4)   # 4 for CDNA, 1 for RDNA
set(ARCH_MAX_VGPR 256)        # Must be > 0
set(ARCH_MAX_SGPR 102)        # Must be > 0
set(ARCH_MAX_AGPR 256)        # May be 0 for RDNA

3b. Create GfxYourArchInstructions.def and GfxYourArchFormats.def

  • Instructions: Add DEF_T(ClassName, "mnemonic", .format = X, .flags = {...}, .cost = {cycle, latency}) for each instruction. Tablegen generates *_init.inc and *_costs.inc.
  • Formats: Copy from a similar arch and adjust. See Adding Instructions for DEF_T syntax details.

3c. Create GfxYourArch.cpp

The .cpp file only contains the three map functions. No instruction definitions, no cost tables--those are generated.

#include "gfx/InstDefDSL.hpp"

namespace stinkytofu
{
    void setGfxYourArchLogicalToArchMap(GpuArch& registry)
    {
        std::unordered_map<std::string, std::string> logicalToHwInstMap = {
            {"SBranch", "s_branch"},
            // ... add Logical IR name -> assembly mnemonic mappings
        };
        registry.setLogicalToArchMap(std::move(logicalToHwInstMap));
    }

    void setGfxYourArchRocisaToArchMap(GpuArch& registry)
    {
        std::unordered_map<std::string, std::string> rocisaToArchMap = {
            // ... Rocisa type name -> mnemonic
        };
        registry.setRocisaToArchMap(std::move(rocisaToArchMap));
    }

    void setGfxYourArchConversionMap(GpuArch& registry)
    {
        std::unordered_map<std::string, std::string> rocisaConversionMap = {
            // ... Rocisa conversion mappings
        };
        registry.setRocisaConversionMap(std::move(rocisaConversionMap));
    }
}

What is auto-generated (no manual code):

  • defineGfxYourArchInsts() -- from GfxArchDefines_block.inc.in, configured per arch
  • Instruction definitions -- from GfxYourArchInstructions.def via tablegen
  • Cost tables -- from .cost in DEF_T, tablegen emits *_costs.inc
  • Wavefront size, register limits, default costs -- from arch.cmake

Step 4: Update Tablegen and Generated Headers

4a. Update tools/tablegen/CMakeLists.txt

Add your arch to the INSTRUCTION_GEN_FILES and INSTRUCTION_DEF_FILES lists:

foreach(arch Gfx1250 GfxYourArch)   # Add GfxYourArch
    ...
endforeach()
set(INSTRUCTION_DEF_FILES
    ...
    "${INSTRUCTION_DEF_BASE_DIR}/GfxYourArch/GfxYourArchFormats.def"
    "${INSTRUCTION_DEF_BASE_DIR}/GfxYourArch/GfxYourArchInstructions.def"
)

4b. GfxXXX.hpp and ArchHelper

GfxXXX.hpp is auto-generated from hardware/GfxArch.hpp.in by CMake. No manual file needed. ArchHelper_includes.inc is also generated from the arch list. As long as your arch is in StinkytofuArchList.cmake, it will be included.

5a. Create src/conversion/rocisa/GfxYourArchRocisaArchInfo.hpp

Copy from Gfx1250RocisaArchInfo.hpp and replace 1250 with your arch number.

5b. Update src/conversion/rocisa/RocisaArchInfo.hpp

Add:

#ifdef STINKYTOFU_ARCH_GFXYOURARCH
#include "GfxYourArchRocisaArchInfo.hpp"
#endif

Step 6: Create Backend Pipeline and Register Anchor

Each architecture needs an optimization pipeline registered with BackendRegistry. Create src/pipeline/backend/GfxYourArchBackend.cpp (copy from Gfx1250Backend.cpp) containing:

  1. A buildGfxYourArchPipeline() function that populates a PassManager
  2. A static registrar struct that calls BackendRegistry::setArchPipeline()
  3. An anchor function to prevent dead-stripping in static builds
namespace stinkytofu {
namespace {
bool buildGfxYourArchPipeline(PassManager& pm, StinkyAsmModule& module) {
    // Add passes here...
    return true;
}

struct GfxYourArchRegistrar {
    GfxYourArchRegistrar() {
        BackendRegistry::setArchPipeline(
            GFXYOURARCH_ARCH, {buildGfxYourArchPipeline, {"group0", "group1"}});
    }
};
static GfxYourArchRegistrar s_gfxYourArchRegistrar;
}  // namespace

// Anchor: prevents linker from dead-stripping this TU in static builds.
void anchorGfxYourArchBackend() {}

}  // namespace stinkytofu

Then register the anchor in BackendRegistry.cpp:

// In BackendRegistry::registerAllBackends():
void anchorGfxYourArchBackend();  // Add declaration

void BackendRegistry::registerAllBackends() {
    anchorGfx1250Backend();
    anchorGfxYourArchBackend();   // Add call
}

Finally, add the source file to src/pipeline/backend/CMakeLists.txt.


Summary Checklist

  • Add to cmake/StinkytofuArchList.cmake
  • Add #cmakedefine STINKYTOFU_ARCH_GFXYOURARCH in include/stinkytofu/Config.h.in
  • Create hardware/src/gfx/GfxYourArch/:
    • arch.cmake -- ARCH_MAJOR, ARCH_MINOR, ARCH_STEPPING, ARCH_WAVEFRONT, ARCH_DEFAULT_CYCLE, ARCH_DEFAULT_LATENCY, ARCH_MAX_VGPR, ARCH_MAX_SGPR, ARCH_MAX_AGPR
    • GfxYourArchFormats.def
    • GfxYourArchInstructions.def -- DEF_T for all instructions
    • GfxYourArch.cpp -- only setGfxYourArchLogicalToArchMap, setGfxYourArchRocisaToArchMap, setGfxYourArchConversionMap
  • Update tools/tablegen/CMakeLists.txt -- add arch to INSTRUCTION_GEN_FILES and INSTRUCTION_DEF_FILES
  • Create src/conversion/rocisa/GfxYourArchRocisaArchInfo.hpp
  • Update src/conversion/rocisa/RocisaArchInfo.hpp -- add #include for new arch
  • Create src/pipeline/backend/GfxYourArchBackend.cpp with pipeline, registrar, and anchor function
  • Add anchor call to BackendRegistry::registerAllBackends() in BackendRegistry.cpp
  • Add source to src/pipeline/backend/CMakeLists.txt
  • Rebuild and test:
    cd build && cmake .. && cmake --build . -j && ctest -j
    

Pro tip: Use search-and-replace on copied files:

sed -i 's/1250/YourArch/g' hardware/src/gfx/GfxYourArch/GfxYourArch.cpp
sed -i 's/12, 5, 0/X, Y, Z/g' hardware/src/gfx/GfxYourArch/arch.cmake