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
287 lines
14 KiB
CMake
287 lines
14 KiB
CMake
# Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
# Support both standalone (scikit-build-core / tox) and subdirectory
|
|
# (hipblaslt CMake) builds.
|
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|
cmake_minimum_required(VERSION 3.25)
|
|
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../../../../cmake/modules/default_amdclang.cmake)
|
|
|
|
project(rocisa LANGUAGES CXX)
|
|
set(ROCISA_STANDALONE ON)
|
|
else()
|
|
set(ROCISA_STANDALONE OFF)
|
|
endif()
|
|
|
|
option(ROCISA_USE_STABLE_ABI
|
|
"Build rocisa as a Python stable ABI extension (requires Python >= 3.12 and CMake >= 3.26)."
|
|
OFF)
|
|
|
|
option(ROCISA_ENABLE_COVERAGE "Enable code coverage instrumentation for rocisa" OFF)
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
add_library(rocisa-cpp INTERFACE)
|
|
add_library(rocisa::rocisa-cpp ALIAS rocisa-cpp)
|
|
target_sources(rocisa-cpp
|
|
INTERFACE
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/rocisa/include/enum.hpp>
|
|
)
|
|
target_include_directories(rocisa-cpp
|
|
INTERFACE
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
)
|
|
|
|
# Build the Python extension when bundling deps (hipblaslt subdir build)
|
|
# or when building standalone.
|
|
if(HIPBLASLT_BUNDLE_PYTHON_DEPS OR ROCISA_STANDALONE)
|
|
if(ROCISA_STANDALONE)
|
|
# scikit-build-core pre-installs nanobind (from build-system.requires)
|
|
# and injects its CMake path, so find_package works without FetchContent.
|
|
# nanobind requires Python to be found first.
|
|
if(ROCISA_USE_STABLE_ABI)
|
|
find_package(Python 3.12 COMPONENTS Interpreter Development.Module Development.SABIModule REQUIRED)
|
|
else()
|
|
find_package(Python 3.10 COMPONENTS Interpreter Development.Module REQUIRED)
|
|
endif()
|
|
find_package(nanobind REQUIRED CONFIG)
|
|
else()
|
|
include(FetchContent)
|
|
FetchContent_Declare(
|
|
nanobind
|
|
GIT_REPOSITORY https://github.com/wjakob/nanobind.git
|
|
GIT_TAG 9b3afa9dbdc23641daf26fadef7743e7127ff92f # v2.6.1
|
|
)
|
|
FetchContent_MakeAvailable(nanobind)
|
|
if(ROCISA_USE_STABLE_ABI)
|
|
find_package(Python 3.12 COMPONENTS Interpreter Development.Module Development.SABIModule REQUIRED)
|
|
endif()
|
|
endif()
|
|
|
|
# HIP is required to build _rocisa (via hip::host). Set the search prefix
|
|
# so find_package works both in developer environments and in the temporary
|
|
# build sandbox created by scikit-build-core / uv.
|
|
if(ROCM_PATH)
|
|
list(APPEND CMAKE_PREFIX_PATH "${ROCM_PATH}")
|
|
endif()
|
|
list(APPEND CMAKE_PREFIX_PATH /opt/rocm/hip /opt/rocm)
|
|
find_package(hip REQUIRED)
|
|
|
|
# Locate origami: prefer the monorepo sibling, fall back to installed package.
|
|
if(NOT TARGET roc::origami)
|
|
set(_origami_sibling "${CMAKE_CURRENT_SOURCE_DIR}/../../../../shared/origami")
|
|
if(IS_DIRECTORY "${_origami_sibling}")
|
|
add_subdirectory("${_origami_sibling}" origami EXCLUDE_FROM_ALL)
|
|
else()
|
|
find_package(origami REQUIRED)
|
|
endif()
|
|
endif()
|
|
|
|
set(ROCISAINST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/instruction.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/common.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/branch.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/cmp.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/cvt.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/mem.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/mfma.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/instruction/extension.cpp")
|
|
set(ROCISAFUNC_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/functions/functions.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/functions/argument.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/functions/f_math.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/functions/f_branch.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/functions/f_cast.cpp")
|
|
set(ROCISAPASS_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/pass.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/graph.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/composite.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/cycle.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/remove.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/insert_delay_alu.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/pass/macro_inline.cpp")
|
|
|
|
set(_rocisa_nb_flags NOMINSIZE NB_SUPPRESS_WARNINGS)
|
|
if(ROCISA_USE_STABLE_ABI)
|
|
list(APPEND _rocisa_nb_flags STABLE_ABI)
|
|
endif()
|
|
|
|
nanobind_add_module(_rocisa ${_rocisa_nb_flags}
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/main.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/base.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/code.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/container.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/count.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/enum.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/helper.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/label.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/macro.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/src/register.cpp"
|
|
${ROCISAINST_SOURCE}
|
|
${ROCISAPASS_SOURCE}
|
|
${ROCISAFUNC_SOURCE})
|
|
target_include_directories(_rocisa PRIVATE
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/include"
|
|
)
|
|
|
|
if(ROCISA_ENABLE_COVERAGE)
|
|
target_compile_options(_rocisa PRIVATE -fprofile-instr-generate -fcoverage-mapping)
|
|
target_link_options(_rocisa PRIVATE -fprofile-instr-generate)
|
|
endif()
|
|
|
|
# Locate stinkytofu: prefer installed package, fall back to monorepo sibling.
|
|
if(NOT TARGET stinkytofu::stinkytofu)
|
|
find_package(stinkytofu QUIET)
|
|
if(NOT stinkytofu_FOUND)
|
|
set(_stinkytofu_sibling "${CMAKE_CURRENT_SOURCE_DIR}/../../../../shared/stinkytofu")
|
|
if(IS_DIRECTORY "${_stinkytofu_sibling}")
|
|
set(STINKYTOFU_ENABLE_WERROR ON)
|
|
add_subdirectory("${_stinkytofu_sibling}" stinkytofu EXCLUDE_FROM_ALL)
|
|
set(_stinkytofu_from_subdirectory TRUE)
|
|
else()
|
|
message(FATAL_ERROR "stinkytofu not found via find_package or sibling directory")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT DEFINED _stinkytofu_from_subdirectory)
|
|
get_target_property(_st_imported stinkytofu::stinkytofu IMPORTED)
|
|
if(_st_imported)
|
|
set(_stinkytofu_from_subdirectory FALSE)
|
|
else()
|
|
set(_stinkytofu_from_subdirectory TRUE)
|
|
endif()
|
|
endif()
|
|
|
|
target_link_libraries(_rocisa PUBLIC roc::origami)
|
|
target_link_libraries(_rocisa PRIVATE hip::host stinkytofu::stinkytofu)
|
|
|
|
# rocisa<->stinkytofu conversion glue. These sources live in the stinkytofu
|
|
# source tree but are rocisa-side bindings (they include rocisa headers and
|
|
# define init_stinkytofu), so they compile into _rocisa, not libstinkytofu.
|
|
# rocisa owns them directly here rather than relying on stinkytofu to inject
|
|
# them, so the de-bundled (find_package) build links them too.
|
|
set(_stinkytofu_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/../../../../shared/stinkytofu")
|
|
target_sources(_rocisa PRIVATE
|
|
"${_stinkytofu_src_dir}/src/conversion/rocisa/AllHwMappings.cpp"
|
|
"${_stinkytofu_src_dir}/src/conversion/rocisa/ToStinkyTofuUtils.cpp"
|
|
)
|
|
|
|
if(_stinkytofu_from_subdirectory)
|
|
# Source-built stinkytofu via add_subdirectory: generated headers are in
|
|
# the stinkytofu/ subdirectory of the binary dir.
|
|
target_include_directories(_rocisa PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/stinkytofu")
|
|
endif()
|
|
# _build_info.py is intentionally NOT in install() rules for production
|
|
# wheels/packages, acting as the source-build sentinel. Dev/editable installs
|
|
# pass -DROCISA_INCLUDE_BUILD_INFO=ON to include it; that flag also marks a
|
|
# dev build, where libstinkytofu lives in a temp install prefix off the
|
|
# loader's default search path.
|
|
option(ROCISA_INCLUDE_BUILD_INFO "Install _build_info.py for staleness detection" OFF)
|
|
|
|
# Directory containing libstinkytofu, resolved by CMake for the active
|
|
# config. $<TARGET_FILE_DIR:...> handles both the add_subdirectory target
|
|
# (build output dir) and the imported package target (IMPORTED_LOCATION_<CONFIG>)
|
|
# without hand-matching configs.
|
|
set(_st_lib_dir "$<TARGET_FILE_DIR:stinkytofu::stinkytofu>")
|
|
set_target_properties(_rocisa PROPERTIES
|
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/rocisa"
|
|
BUILD_RPATH "${_st_lib_dir}"
|
|
)
|
|
if(_stinkytofu_from_subdirectory)
|
|
# Source-built sibling: no installed libstinkytofu exists, so the wheel carries
|
|
# its own copy next to _rocisa and loads it from there.
|
|
set_target_properties(_rocisa PROPERTIES INSTALL_RPATH "$ORIGIN")
|
|
# Windows has no RPATH; copy stinkytofu.dll next to _rocisa.pyd so the loader
|
|
# finds it at runtime.
|
|
if(WIN32)
|
|
add_custom_command(TARGET _rocisa POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
$<TARGET_FILE:stinkytofu::stinkytofu>
|
|
$<TARGET_FILE_DIR:_rocisa>
|
|
)
|
|
endif()
|
|
elseif(ROCISA_INCLUDE_BUILD_INFO)
|
|
# Dev/editable find_package build: libstinkytofu is installed to a temp
|
|
# prefix off the loader's default search path, so bake its dir into the
|
|
# install RPATH from the link line. Gated on the dev-build signal so
|
|
# released ROCm builds stay RPATH-free and rely on libstinkytofu being
|
|
# resident in rocm/lib.
|
|
set_target_properties(_rocisa PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON)
|
|
endif()
|
|
# In a released build, installed stinkytofu is a standard ROCm library on the
|
|
# loader's search path (like libyaml behind PyYAML); _rocisa's DT_NEEDED
|
|
# resolves it from there, so no wheel-local copy or RPATH is needed.
|
|
configure_file(
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/__init__.py"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/rocisa/__init__.py"
|
|
COPYONLY
|
|
)
|
|
# STINKYTOFU_ROOT_DIR feeds @STINKYTOFU_ROOT_DIR@ in _build_info.py (the
|
|
# staleness check scans stinkytofu sources too, since the conversion glue is
|
|
# compiled into _rocisa). It is set via PARENT_SCOPE only in the
|
|
# add_subdirectory build; in the de-bundled find_package build it is unset,
|
|
# which would leave the path empty and make the check scan the CWD. Point it
|
|
# at the real stinkytofu source tree.
|
|
if(NOT STINKYTOFU_ROOT_DIR)
|
|
cmake_path(ABSOLUTE_PATH _stinkytofu_src_dir NORMALIZE OUTPUT_VARIABLE STINKYTOFU_ROOT_DIR)
|
|
endif()
|
|
configure_file(
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/rocisa/_build_info.py.in"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/rocisa/_build_info.py"
|
|
@ONLY
|
|
)
|
|
if(ROCISA_INCLUDE_BUILD_INFO)
|
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/rocisa/_build_info.py" DESTINATION rocisa)
|
|
endif()
|
|
|
|
# Windows: emit the resolved runtime DLL dependencies so __init__.py can
|
|
# register their directories via os.add_dll_directory(). Since Python 3.8 the
|
|
# extension loader ignores PATH, and in a source/integrated build _rocisa's
|
|
# deps (origami, hip, comgr, stinkytofu) live in scattered per-subproject
|
|
# directories. TARGET_RUNTIME_DLLS resolves the full set (direct + transitive)
|
|
# from the linked/imported targets. Build-tree only, like _build_info.py; not
|
|
# installed -- packaged builds resolve deps via the merged install layout.
|
|
if(WIN32)
|
|
file(GENERATE
|
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rocisa/_dll_dirs.py"
|
|
CONTENT "DEP_DLLS = [p for p in r'''$<TARGET_RUNTIME_DLLS:_rocisa>'''.split(';') if p]\n"
|
|
)
|
|
endif()
|
|
|
|
if(ROCISA_STANDALONE)
|
|
# scikit-build-core wheel install rules: place _rocisa and __init__.py into the
|
|
# rocisa/ package directory in the wheel.
|
|
install(TARGETS _rocisa DESTINATION rocisa)
|
|
if(_stinkytofu_from_subdirectory)
|
|
# Source-built: vendor libstinkytofu into the wheel — no installed copy exists.
|
|
install(FILES $<TARGET_FILE:stinkytofu::stinkytofu> DESTINATION rocisa)
|
|
if(NOT WIN32)
|
|
install(FILES $<TARGET_SONAME_FILE:stinkytofu::stinkytofu> DESTINATION rocisa)
|
|
endif()
|
|
endif()
|
|
# Installed stinkytofu ships in its own ROCm package; it is not bundled here.
|
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/rocisa/__init__.py" DESTINATION rocisa)
|
|
endif()
|
|
|
|
# Example plugin — the target only exists when stinkytofu is configured with
|
|
# -DSTINKYTOFU_BUILD_EXAMPLES=ON (default OFF; opted in by the source-built standalone
|
|
# wheel via tasks.py). Integrated/ROCm builds leave it OFF, so the target is absent and
|
|
# this block is skipped — the example never lands in a production ROCm package; there,
|
|
# the installed stinkytofu package ships and locates its own plugin.
|
|
#
|
|
# In the source-built wheel, libstinkytofu is vendored into rocisa/, so the plugin must
|
|
# sit at rocisa/${STINKYTOFU_PLUGIN_INSTALL_RELDIR} to match PassBuilder::examplePluginPath()'s
|
|
# lookup relative to libstinkytofu. Consuming stinkytofu's exported reldir keeps the install
|
|
# path in lockstep with the runtime lookup — no hardcoded duplicate.
|
|
# No INSTALL_RPATH is needed: on Linux the plugin has no DT_NEEDED on libstinkytofu (it
|
|
# is headers-only) and the host is already resident when loadPlugin() dlopens it.
|
|
# Only installable for shared builds (MODULE target); static builds use OBJECT.
|
|
if(TARGET stinkytofu-plugin-helloworld AND BUILD_SHARED_LIBS AND _stinkytofu_from_subdirectory)
|
|
set_target_properties(stinkytofu-plugin-helloworld PROPERTIES EXCLUDE_FROM_ALL FALSE)
|
|
add_dependencies(_rocisa stinkytofu-plugin-helloworld)
|
|
install(TARGETS stinkytofu-plugin-helloworld
|
|
DESTINATION "rocisa/${STINKYTOFU_PLUGIN_INSTALL_RELDIR}")
|
|
endif()
|
|
endif()
|