|
| 1 | +# SPDX-License-Identifier: BSD-3-Clause |
| 2 | +# Copyright (c) 2026, The OpenROAD Authors |
| 3 | + |
| 4 | +# Kokkos GPU backend wiring for OpenROAD. Included from the root |
| 5 | +# CMakeLists.txt only when ENABLE_GPU=ON; not loaded otherwise. |
| 6 | +# |
| 7 | +# Discovers the user's Kokkos install, inherits its compute backend, turns |
| 8 | +# on the matching CMake language so downstream targets can mark kernel |
| 9 | +# sources with set_source_files_properties(... LANGUAGE CUDA|HIP), and |
| 10 | +# applies the small set of nvcc / fmt / host-compiler workarounds that the |
| 11 | +# CUDA backend currently needs in modern Linux toolchains. Per-module |
| 12 | +# CMakeLists (e.g. src/gpl) key off ENABLE_GPU and Kokkos_ENABLE_*; they |
| 13 | +# do not need to call find_package(Kokkos) or enable_language() themselves. |
| 14 | + |
| 15 | +find_package(Kokkos QUIET) |
| 16 | +if(NOT Kokkos_FOUND) |
| 17 | + message(FATAL_ERROR |
| 18 | + "OpenROAD: ENABLE_GPU=ON requires the Kokkos package to be " |
| 19 | + "installed and discoverable by CMake, but Kokkos was not found.\n" |
| 20 | + " - If Kokkos is already installed: pass " |
| 21 | + "-DKokkos_ROOT=/path/to/kokkos (or extend CMAKE_PREFIX_PATH).\n" |
| 22 | + " - If not: build and install Kokkos from " |
| 23 | + "https://github.com/kokkos/kokkos with the desired backend " |
| 24 | + "(CUDA / HIP / SYCL / OpenMP) and a target architecture that " |
| 25 | + "matches the host GPU.\n" |
| 26 | + " - A future etc/DependencyInstaller.sh -gpu option will " |
| 27 | + "automate this step.") |
| 28 | +endif() |
| 29 | + |
| 30 | +# KokkosFFT — required by the gpl GPU FFT backend (src/gpl/src/gpu/dct.cpp). |
| 31 | +# A separate package from Kokkos core. |
| 32 | +find_package(KokkosFFT QUIET) |
| 33 | +if(NOT KokkosFFT_FOUND) |
| 34 | + message(FATAL_ERROR |
| 35 | + "ENABLE_GPU=ON requires KokkosFFT, which was not found.\n" |
| 36 | + " - Install KokkosFFT (https://github.com/kokkos/kokkos-fft) against\n" |
| 37 | + " your Kokkos build, then re-configure with -DKokkosFFT_ROOT=<prefix>.\n" |
| 38 | + " - A future etc/DependencyInstaller.sh -gpu will install Kokkos and\n" |
| 39 | + " KokkosFFT together.") |
| 40 | +endif() |
| 41 | + |
| 42 | +message(STATUS "OpenROAD: GPU acceleration enabled (Kokkos ${Kokkos_VERSION})") |
| 43 | + |
| 44 | +if(Kokkos_ENABLE_CUDA) |
| 45 | + # Auto-discover nvcc when the user has CUDA installed at a standard |
| 46 | + # location but their environment does not expose it on PATH (common |
| 47 | + # with IDE-launched configures: the bundled CMake does not inherit |
| 48 | + # the shell PATH). enable_language(CUDA) below would otherwise abort |
| 49 | + # with "No CMAKE_CUDA_COMPILER could be found" even though Kokkos's |
| 50 | + # find_package already located the toolkit. |
| 51 | + if(NOT DEFINED CMAKE_CUDA_COMPILER AND NOT DEFINED ENV{CUDACXX}) |
| 52 | + find_program(_OPENROAD_NVCC nvcc |
| 53 | + HINTS ENV CUDA_HOME ENV CUDA_PATH ENV CUDA_ROOT |
| 54 | + /usr/local/cuda/bin |
| 55 | + /usr/local/cuda-13.0/bin |
| 56 | + /usr/local/cuda-12.8/bin /usr/local/cuda-12.0/bin |
| 57 | + /opt/cuda/bin |
| 58 | + ) |
| 59 | + if(_OPENROAD_NVCC) |
| 60 | + set(CMAKE_CUDA_COMPILER "${_OPENROAD_NVCC}" CACHE FILEPATH "") |
| 61 | + message(STATUS "OpenROAD: auto-discovered nvcc at ${_OPENROAD_NVCC}") |
| 62 | + endif() |
| 63 | + endif() |
| 64 | + # nvcc < 13 cannot parse glibc 2.38+'s _Float128 type that ships with |
| 65 | + # gcc 13+'s C++ standard library headers (math.h template specialization |
| 66 | + # for __iseqsig_type<_Float128>). When a known-broken pairing is detected, |
| 67 | + # pin a compatible older g++ as the CUDA host compiler (the system C++ |
| 68 | + # compiler stays unchanged for non-CUDA TUs). Override is always |
| 69 | + # available via -DCMAKE_CUDA_HOST_COMPILER or CUDAHOSTCXX. |
| 70 | + if(NOT DEFINED CMAKE_CUDA_HOST_COMPILER AND NOT DEFINED ENV{CUDAHOSTCXX} |
| 71 | + AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" |
| 72 | + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "13.0" |
| 73 | + AND _OPENROAD_NVCC) |
| 74 | + execute_process( |
| 75 | + COMMAND "${_OPENROAD_NVCC}" --version |
| 76 | + OUTPUT_VARIABLE _OPENROAD_NVCC_VERSION_OUTPUT |
| 77 | + ERROR_QUIET |
| 78 | + OUTPUT_STRIP_TRAILING_WHITESPACE) |
| 79 | + if(_OPENROAD_NVCC_VERSION_OUTPUT MATCHES "release ([0-9]+)") |
| 80 | + set(_OPENROAD_NVCC_MAJOR "${CMAKE_MATCH_1}") |
| 81 | + if(_OPENROAD_NVCC_MAJOR LESS 13) |
| 82 | + foreach(_OPENROAD_GXX_VER 12 11) |
| 83 | + find_program(_OPENROAD_CUDAHOST g++-${_OPENROAD_GXX_VER} |
| 84 | + HINTS /usr/bin /usr/local/bin) |
| 85 | + if(_OPENROAD_CUDAHOST) |
| 86 | + set(CMAKE_CUDA_HOST_COMPILER "${_OPENROAD_CUDAHOST}" |
| 87 | + CACHE FILEPATH "") |
| 88 | + message(STATUS |
| 89 | + "OpenROAD: pinning CUDA host compiler to " |
| 90 | + "${_OPENROAD_CUDAHOST} (nvcc ${_OPENROAD_NVCC_MAJOR}.x + " |
| 91 | + "glibc/gcc 13+ _Float128 compat)") |
| 92 | + break() |
| 93 | + endif() |
| 94 | + unset(_OPENROAD_CUDAHOST CACHE) |
| 95 | + endforeach() |
| 96 | + if(NOT DEFINED CMAKE_CUDA_HOST_COMPILER) |
| 97 | + message(FATAL_ERROR |
| 98 | + "OpenROAD: nvcc ${_OPENROAD_NVCC_MAJOR}.x cannot parse " |
| 99 | + "_Float128 declarations in glibc 2.38+ system headers used " |
| 100 | + "by gcc ${CMAKE_CXX_COMPILER_VERSION}, and no compatible " |
| 101 | + "g++-12 / g++-11 was found in /usr/bin or /usr/local/bin. " |
| 102 | + "Install one (e.g. apt install g++-12) or set " |
| 103 | + "-DCMAKE_CUDA_HOST_COMPILER=/path/to/older-g++ explicitly.") |
| 104 | + endif() |
| 105 | + endif() |
| 106 | + endif() |
| 107 | + endif() |
| 108 | + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES OR "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") |
| 109 | + if(DEFINED Kokkos_CUDA_ARCHITECTURES |
| 110 | + AND NOT "${Kokkos_CUDA_ARCHITECTURES}" STREQUAL "") |
| 111 | + set(CMAKE_CUDA_ARCHITECTURES "${Kokkos_CUDA_ARCHITECTURES}") |
| 112 | + else() |
| 113 | + message(FATAL_ERROR |
| 114 | + "OpenROAD: ENABLE_GPU=ON with Kokkos CUDA backend, but the " |
| 115 | + "Kokkos package does not advertise Kokkos_CUDA_ARCHITECTURES " |
| 116 | + "and CMAKE_CUDA_ARCHITECTURES was not provided. Set " |
| 117 | + "-DCMAKE_CUDA_ARCHITECTURES=<arch> explicitly (e.g. 89 for " |
| 118 | + "RTX 4070, 120 for RTX 5090) or rebuild Kokkos with the " |
| 119 | + "target architecture baked in.") |
| 120 | + endif() |
| 121 | + endif() |
| 122 | + enable_language(CUDA) |
| 123 | + find_package(CUDAToolkit REQUIRED) |
| 124 | + message(STATUS "OpenROAD: CUDA backend (arch=${CMAKE_CUDA_ARCHITECTURES})") |
| 125 | + # A GPU driver (the kernel module exposing libcuda.so.1) is needed only to |
| 126 | + # *run* CUDA code, never to build it -- nvcc cross-compiles device code on a |
| 127 | + # host with no GPU. Note its absence so the resulting libcuda.so.1 load |
| 128 | + # errors on this host (e.g. ctest, or running openroad) read as expected |
| 129 | + # rather than as a misconfiguration. This is informational only: a GPU build |
| 130 | + # on a driverless host is a supported cross-compile workflow, not an error. |
| 131 | + if(NOT EXISTS "/proc/driver/nvidia") |
| 132 | + message(STATUS |
| 133 | + "OpenROAD: no NVIDIA driver on this host -- GPU code is being " |
| 134 | + "cross-compiled. Run the GPU binaries and tests on a GPU machine.") |
| 135 | + endif() |
| 136 | + # nvcc 12.8 cannot parse fmt 11's nontype-template-parameter user-defined |
| 137 | + # literals (fmt/bundled/format.h: operator""_a with fixed_string). The |
| 138 | + # legacy literal fallback is still available; opt into it for CUDA TUs |
| 139 | + # only. Project-wide CXX compilation is unaffected. |
| 140 | + add_compile_definitions( |
| 141 | + $<$<COMPILE_LANGUAGE:CUDA>:FMT_USE_NONTYPE_TEMPLATE_ARGS=0>) |
| 142 | + # On aarch64, Boost's unordered_flat_map detects __ARM_NEON and includes |
| 143 | + # <arm_neon.h> for SIMD-accelerated hashing. nvcc cannot parse gcc's |
| 144 | + # arm_neon.h (it contains gcc-specific intrinsics), so disable the NEON |
| 145 | + # path for CUDA TUs. The CPU TUs (compiled by g++) are unaffected. |
| 146 | + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64") |
| 147 | + add_compile_definitions( |
| 148 | + $<$<COMPILE_LANGUAGE:CUDA>:BOOST_UNORDERED_DISABLE_NEON>) |
| 149 | + endif() |
| 150 | +elseif(Kokkos_ENABLE_HIP) |
| 151 | + enable_language(HIP) |
| 152 | + message(STATUS "OpenROAD: HIP backend") |
| 153 | +elseif(Kokkos_ENABLE_SYCL) |
| 154 | + message(STATUS "OpenROAD: SYCL backend (driven by Kokkos host compiler)") |
| 155 | +else() |
| 156 | + message(STATUS |
| 157 | + "OpenROAD: host-only Kokkos backend (Serial / OpenMP / Threads)") |
| 158 | +endif() |
0 commit comments