| cmake_minimum_required(VERSION 3.20) | |
| project(sov_rtx LANGUAGES C) | |
| option(SOV_BUILD_CUDA "Enable PTX validation targets" ON) | |
| if(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") | |
| set(SOV_ZERO_LIBC_DEFAULT ON) | |
| else() | |
| set(SOV_ZERO_LIBC_DEFAULT OFF) | |
| endif() | |
| option(SOV_ZERO_LIBC | |
| "Build the supported GNU/Clang zero-CRT Windows entry point" | |
| ${SOV_ZERO_LIBC_DEFAULT}) | |
| option(SOV_BUILD_FORTRAN_REFERENCE | |
| "Build the optional Fortran 2018 transformer reference" OFF) | |
| set(CMAKE_C_STANDARD 11) | |
| set(CMAKE_C_STANDARD_REQUIRED ON) | |
| set(CMAKE_C_EXTENSIONS OFF) | |
| set(SOV_PTX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/cuda") | |
| set(SOV_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") | |
| set(SOV_PTX_BLOB_SOURCE "${SOV_GENERATED_DIR}/sov_ptx_blobs.c") | |
| file(MAKE_DIRECTORY "${SOV_GENERATED_DIR}") | |
| # Convert PTX bytes to a C array at configure time. The final zero byte is | |
| # included in both the array and *_len so every loader can validate the | |
| # complete bounded text-image contract before calling cuModuleLoadData. | |
| function(sov_ptx_to_c_source input_path symbol output_variable) | |
| if(NOT EXISTS "${input_path}") | |
| message(FATAL_ERROR "Required PTX source is missing: ${input_path}") | |
| endif() | |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${input_path}") | |
| file(READ "${input_path}" ptx_text) | |
| if(ARGC GREATER 3) | |
| string(REGEX REPLACE "\\.target[ \t]+sm_[0-9]+" | |
| ".target ${ARGV3}" ptx_text "${ptx_text}") | |
| endif() | |
| string(HEX "${ptx_text}" ptx_hex) | |
| string(LENGTH "${ptx_hex}" ptx_hex_length) | |
| if(ptx_hex_length EQUAL 0) | |
| message(FATAL_ERROR "PTX source is empty: ${input_path}") | |
| endif() | |
| math(EXPR ptx_byte_count "${ptx_hex_length} / 2") | |
| math(EXPR ptx_buffer_size "${ptx_byte_count} + 1") | |
| math(EXPR ptx_last_offset "${ptx_hex_length} - 2") | |
| set(generated_text "const unsigned char ${symbol}[] = {\n ") | |
| set(bytes_on_line 0) | |
| foreach(offset RANGE 0 ${ptx_last_offset} 2) | |
| string(SUBSTRING "${ptx_hex}" ${offset} 2 byte_hex) | |
| string(APPEND generated_text "0x${byte_hex},") | |
| math(EXPR bytes_on_line "${bytes_on_line} + 1") | |
| if(bytes_on_line EQUAL 16) | |
| string(APPEND generated_text "\n ") | |
| set(bytes_on_line 0) | |
| endif() | |
| endforeach() | |
| string(APPEND generated_text | |
| "0x00\n};\n" | |
| "const unsigned int ${symbol}_len = ${ptx_buffer_size}u;\n") | |
| set(${output_variable} "${generated_text}" PARENT_SCOPE) | |
| endfunction() | |
| sov_ptx_to_c_source("${SOV_PTX_DIR}/flash_attention.ptx" | |
| flash_attention_ptx flash_ptx_source) | |
| sov_ptx_to_c_source("${SOV_PTX_DIR}/gemm.ptx" | |
| gemm_ptx gemm_ptx_source) | |
| file(WRITE "${SOV_PTX_BLOB_SOURCE}" | |
| "/* Generated by CMake. Do not edit. */\n" | |
| "${flash_ptx_source}\n" | |
| "${gemm_ptx_source}\n") | |
| add_library(sov_rtx STATIC | |
| src/loader/gguf.c | |
| src/kv_allocator.c | |
| src/sampler.c | |
| src/cuda_validation_chain.c | |
| src/rowm_cuda_validation.c | |
| src/cuda_gemm_dispatch.c | |
| src/cuda_kernels.c | |
| windows_rtx/cuda_driver_loader.c | |
| windows_rtx/power_handler.c | |
| "${SOV_PTX_BLOB_SOURCE}" | |
| ) | |
| target_include_directories(sov_rtx PUBLIC include PRIVATE src) | |
| if(SOV_BUILD_FORTRAN_REFERENCE) | |
| enable_language(Fortran) | |
| add_library(sov_rtx_fortran_reference STATIC | |
| src/fortran/transformer_kernel.f90) | |
| set_property(TARGET sov_rtx_fortran_reference PROPERTY Fortran_STANDARD 2018) | |
| set_property(TARGET sov_rtx_fortran_reference PROPERTY Fortran_STANDARD_REQUIRED ON) | |
| endif() | |
| if(SOV_ZERO_LIBC) | |
| if(NOT WIN32) | |
| message(FATAL_ERROR "SOV_ZERO_LIBC is supported only on Windows") | |
| endif() | |
| if(MSVC OR NOT CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") | |
| message(FATAL_ERROR | |
| "SOV_ZERO_LIBC currently requires GNU or Clang because main.c " | |
| "uses that compiler family's x86-64 inline assembly") | |
| endif() | |
| target_compile_options(sov_rtx PRIVATE | |
| -ffreestanding -fno-builtin -fno-stack-protector) | |
| add_executable(sov_main windows_rtx/main.c) | |
| target_link_libraries(sov_main PRIVATE sov_rtx) | |
| target_compile_options(sov_main PRIVATE | |
| -ffreestanding -fno-builtin -fno-stack-protector) | |
| target_link_options(sov_main PRIVATE -nostdlib -Wl,--entry=sov_main) | |
| add_executable(sov_gguf_zero_crt_link_smoke tests/gguf_zero_crt_link_smoke.c) | |
| target_link_libraries(sov_gguf_zero_crt_link_smoke PRIVATE sov_rtx kernel32) | |
| target_compile_options(sov_gguf_zero_crt_link_smoke PRIVATE | |
| -ffreestanding -fno-builtin -fno-stack-protector) | |
| target_link_options(sov_gguf_zero_crt_link_smoke PRIVATE | |
| -nostdlib -Wl,--entry=sov_main) | |
| endif() | |
| if(SOV_BUILD_CUDA) | |
| find_program(PTXAS_EXECUTABLE NAMES ptxas) | |
| if(PTXAS_EXECUTABLE) | |
| set(flash_cubin "${SOV_GENERATED_DIR}/flash_attention.cubin") | |
| set(gemm_cubin "${SOV_GENERATED_DIR}/gemm.cubin") | |
| add_custom_command(OUTPUT "${flash_cubin}" | |
| COMMAND "${PTXAS_EXECUTABLE}" -arch=sm_89 | |
| "${SOV_PTX_DIR}/flash_attention.ptx" -o "${flash_cubin}" | |
| DEPENDS "${SOV_PTX_DIR}/flash_attention.ptx" | |
| VERBATIM COMMENT "Validating flash_attention.ptx for sm_89") | |
| add_custom_command(OUTPUT "${gemm_cubin}" | |
| COMMAND "${PTXAS_EXECUTABLE}" -arch=sm_89 | |
| "${SOV_PTX_DIR}/gemm.ptx" -o "${gemm_cubin}" | |
| DEPENDS "${SOV_PTX_DIR}/gemm.ptx" | |
| VERBATIM COMMENT "Validating gemm.ptx for sm_89") | |
| add_custom_target(validate_ptx DEPENDS "${flash_cubin}" "${gemm_cubin}") | |
| else() | |
| add_custom_target(validate_ptx | |
| COMMAND "${CMAKE_COMMAND}" -E echo | |
| "ptxas not found; cuModuleLoadData will validate PTX at runtime" | |
| VERBATIM) | |
| endif() | |
| endif() | |
| include(CTest) | |
| if(BUILD_TESTING) | |
| add_executable(sov_rtx_host_tests | |
| tests/test_kv_sampler_host.c | |
| src/kv_allocator.c | |
| src/sampler.c) | |
| target_include_directories(sov_rtx_host_tests BEFORE PRIVATE tests/host_include) | |
| target_include_directories(sov_rtx_host_tests PRIVATE include src) | |
| add_test(NAME sov_rtx_host_tests COMMAND sov_rtx_host_tests) | |
| add_executable(sov_gguf_host_tests | |
| tests/test_gguf_host.c | |
| src/loader/gguf.c) | |
| target_include_directories(sov_gguf_host_tests PRIVATE include) | |
| add_test(NAME sov_gguf_host_tests COMMAND sov_gguf_host_tests) | |
| add_executable(sov_cuda_validation_chain_host_tests | |
| tests/test_cuda_validation_chain_host.c | |
| src/cuda_validation_chain.c) | |
| target_include_directories(sov_cuda_validation_chain_host_tests PRIVATE include) | |
| add_test(NAME sov_cuda_validation_chain_host_tests | |
| COMMAND sov_cuda_validation_chain_host_tests) | |
| add_executable(sov_cuda_kernels_host_tests | |
| tests/test_cuda_kernels_host.c | |
| src/cuda_validation_chain.c | |
| src/cuda_kernels.c) | |
| target_include_directories(sov_cuda_kernels_host_tests BEFORE PRIVATE tests/host_include) | |
| target_include_directories(sov_cuda_kernels_host_tests PRIVATE include src) | |
| add_test(NAME sov_cuda_kernels_host_tests COMMAND sov_cuda_kernels_host_tests) | |
| if(WIN32) | |
| set(SOV_CUDA_SM86_SOURCE "${SOV_GENERATED_DIR}/sov_cuda_sm86.c") | |
| sov_ptx_to_c_source("${SOV_PTX_DIR}/flash_attention.ptx" | |
| flash_attention_ptx flash_sm86 sm_86) | |
| sov_ptx_to_c_source("${SOV_PTX_DIR}/gemm.ptx" | |
| gemm_ptx gemm_sm86 sm_86) | |
| file(WRITE "${SOV_CUDA_SM86_SOURCE}" | |
| "/* Generated test-only sm_86 PTX blobs. */\n" | |
| "${flash_sm86}\n" "${gemm_sm86}\n") | |
| add_executable(sov_cuda_reference_gpu_test | |
| tests/test_cuda_reference_gpu.c | |
| src/kv_allocator.c | |
| src/cuda_validation_chain.c | |
| src/rowm_cuda_validation.c | |
| src/cuda_gemm_dispatch.c | |
| src/cuda_kernels.c | |
| windows_rtx/cuda_driver_loader.c | |
| "${SOV_CUDA_SM86_SOURCE}") | |
| target_include_directories(sov_cuda_reference_gpu_test PRIVATE include src) | |
| target_compile_definitions(sov_cuda_reference_gpu_test | |
| PRIVATE SOV_CUDA_COMPILED_PTX_TARGET=86) | |
| if(NOT MSVC) | |
| target_link_libraries(sov_cuda_reference_gpu_test PRIVATE m) | |
| endif() | |
| add_test(NAME sov_cuda_reference_gpu_test | |
| COMMAND sov_cuda_reference_gpu_test) | |
| set_tests_properties(sov_cuda_reference_gpu_test | |
| PROPERTIES LABELS gpu SKIP_RETURN_CODE 77) | |
| endif() | |
| endif() | |
| add_custom_target(cmm_info | |
| COMMAND "${CMAKE_COMMAND}" -E echo | |
| "C-- scheduler: src/c--/scheduler.cmm (GHC C-- backend)" | |
| VERBATIM) | |