###################################################################### # # DESCRIPTION: CMake configuration file for Verilator # # Include it in your CMakeLists.txt using: # # find_package(verilator) # # This script adds a verilate function. # # add_executable(simulator ) # verilate(simulator SOURCES ) # # Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 # ###################################################################### cmake_minimum_required(VERSION 3.19) # Prefer VERILATOR_ROOT from environment if(DEFINED ENV{VERILATOR_ROOT}) set(VERILATOR_ROOT "$ENV{VERILATOR_ROOT}" CACHE PATH "VERILATOR_ROOT") endif() set(VERILATOR_ROOT "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "VERILATOR_ROOT") find_program( VERILATOR_BIN NAMES verilator_bin verilator_bin.exe HINTS ${VERILATOR_ROOT}/bin ENV VERILATOR_ROOT NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH ) if(NOT VERILATOR_ROOT) message( FATAL_ERROR "VERILATOR_ROOT cannot be detected. Set it to the appropriate directory (e.g. /usr/share/verilator) as an environment variable or CMake define." ) endif() if(NOT VERILATOR_BIN) message(FATAL_ERROR "Cannot find verilator_bin excecutable.") endif() set(verilator_FOUND 1) include(CheckCXXSourceCompiles) function(_verilator_check_cxx_libraries LIBRARIES RESVAR) # Check whether a particular link option creates a valid executable set(_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC "int main() {return 0;}\n") set(CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_DEFINITIONS) set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LINK_OPTIONS) set(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) set(CMAKE_REQUIRED_QUIET) check_cxx_source_compiles( "${_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC}" "${RESVAR}" ) set("${RESVAR}" "${${RESVAR}}" PARENT_SCOPE) endfunction() # Check compiler flag support. Skip on MSVC, these are all GCC flags. if(NOT CMAKE_CXX_COMPILER_ID MATCHES MSVC) if(NOT DEFINED VERILATOR_CFLAGS OR NOT DEFINED VERILATOR_MT_CFLAGS) include(CheckCXXCompilerFlag) foreach(FLAG @CFG_CXX_FLAGS_CMAKE@) string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME) check_cxx_compiler_flag(${FLAG} ${FLAGNAME}) if(${FLAGNAME}) list(APPEND VERILATOR_CFLAGS ${FLAG}) endif() endforeach() foreach(FLAG @CFG_LDFLAGS_THREADS_CMAKE@) string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME) _verilator_check_cxx_libraries("${FLAG}" ${FLAGNAME}) if(${FLAGNAME}) list(APPEND VERILATOR_MT_CFLAGS ${FLAG}) endif() endforeach() endif() endif() if(${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") add_link_options(-Wl,-U,__Z15vl_time_stamp64v,-U,__Z13sc_time_stampv) endif() define_property( TARGET PROPERTY VERILATOR_THREADED BRIEF_DOCS "Deprecated and has no effect (ignored)" FULL_DOCS "Deprecated and has no effect (ignored)" ) define_property( TARGET PROPERTY VERILATOR_TRACE_THREADED BRIEF_DOCS "Verilator multithread tracing enabled" FULL_DOCS "Verilator multithread tracing enabled" ) define_property( TARGET PROPERTY VERILATOR_TIMING BRIEF_DOCS "Verilator timing enabled" FULL_DOCS "Verilator timing enabled" ) define_property( TARGET PROPERTY VERILATOR_COVERAGE BRIEF_DOCS "Verilator coverage enabled" FULL_DOCS "Verilator coverage enabled" ) define_property( TARGET PROPERTY VERILATOR_TRACE BRIEF_DOCS "Verilator trace enabled" FULL_DOCS "Verilator trace enabled" ) define_property( TARGET PROPERTY VERILATOR_TRACE_FST BRIEF_DOCS "Verilator FST trace enabled" FULL_DOCS "Verilator FST trace enabled" ) define_property( TARGET PROPERTY VERILATOR_TRACE_SAIF BRIEF_DOCS "Verilator SAIF trace enabled" FULL_DOCS "Verilator SAIF trace enabled" ) define_property( TARGET PROPERTY VERILATOR_TRACE_VCD BRIEF_DOCS "Verilator VCD trace enabled" FULL_DOCS "Verilator VCD trace enabled" ) define_property( TARGET PROPERTY VERILATOR_SYSTEMC BRIEF_DOCS "Verilator SystemC enabled" FULL_DOCS "Verilator SystemC enabled" ) define_property( TARGET PROPERTY VERILATOR_TRACE_STRUCTS BRIEF_DOCS "Verilator trace structs enabled" FULL_DOCS "Verilator trace structs enabled" ) function(json_get_string RET JSON SECTION VARIABLE) string(JSON JV ERROR_VARIABLE STATUS GET "${JSON}" ${SECTION} ${VARIABLE}) if(NOT ${STATUS} STREQUAL "NOTFOUND") set(JV "") endif() set(${RET} ${JV} PARENT_SCOPE) endfunction() function(json_get_bool RET JSON SECTION VARIABLE) string(JSON JV GET "${JSON}" ${SECTION} ${VARIABLE}) if(JV) set(${RET} 1 PARENT_SCOPE) else() set(${RET} 0 PARENT_SCOPE) endif() endfunction() function(json_get_int RET JSON SECTION VARIABLE) string(JSON JV GET "${JSON}" ${SECTION} ${VARIABLE}) set(${RET} ${JV} PARENT_SCOPE) endfunction() function(json_get_submodules SUBMODULES NSUBMODULES JSON) string(JSON JV ERROR_VARIABLE STATUS GET "${JSON}" submodules) if(NOT ${STATUS} STREQUAL "NOTFOUND") set(${SUBMODULES} "" PARENT_SCOPE) set(${NSUBMODULES} 0 PARENT_SCOPE) return() endif() string(JSON L ERROR_VARIABLE STATUS LENGTH "${JSON}" submodules) math(EXPR L "${L}-1") set(${SUBMODULES} ${JV} PARENT_SCOPE) set(${NSUBMODULES} ${L} PARENT_SCOPE) endfunction() function(json_get_list RET JSON SECTION VARIABLE) string(JSON L ERROR_VARIABLE STATUS LENGTH "${JSON}" ${SECTION} ${VARIABLE}) if(NOT ${STATUS} STREQUAL "NOTFOUND" OR NOT ${L}) set(${RET} "" PARENT_SCOPE) return() endif() math(EXPR L "${L}-1") foreach(I RANGE ${L}) string(JSON JV GET "${JSON}" ${SECTION} ${VARIABLE} ${I}) if(NOT JL) string(APPEND JL "${JV}") else() string(APPEND JL " ${JV}") endif() endforeach() set(${RET} ${JL} PARENT_SCOPE) endfunction() function(verilate TARGET) cmake_parse_arguments( VERILATE "COVERAGE;SYSTEMC;TRACE_FST;TRACE_SAIF;TRACE_VCD;TRACE;TRACE_STRUCTS" "PREFIX;TOP_MODULE;THREADS;TRACE_THREADS;DIRECTORY" "SOURCES;VERILATOR_ARGS;INCLUDE_DIRS;OPT_SLOW;OPT_FAST;OPT_GLOBAL" ${ARGN} ) if(VERILATE_TRACE) if(NOT VERILATE_TRACE_VCD) set(VERILATE_TRACE_VCD TRUE) endif() message( DEPRECATION "The `TRACE` argument is deprecated. Please use `TRACE_VCD` instead." ) endif() if(NOT VERILATE_SOURCES) message(FATAL_ERROR "Need at least one source") endif() if(NOT VERILATE_PREFIX) list(LENGTH VERILATE_SOURCES NUM_SOURCES) if(${NUM_SOURCES} GREATER 1) message(WARNING "Specify PREFIX if there are multiple SOURCES") endif() list(GET VERILATE_SOURCES 0 TOPSRC) get_filename_component(_SRC_NAME ${TOPSRC} NAME_WE) string(MAKE_C_IDENTIFIER V${_SRC_NAME} VERILATE_PREFIX) endif() if(VERILATE_TOP_MODULE) list(APPEND VERILATOR_ARGS --top ${VERILATE_TOP_MODULE}) endif() if(VERILATE_THREADS) list(APPEND VERILATOR_ARGS --threads ${VERILATE_THREADS}) endif() if(VERILATE_TRACE_THREADS) list(APPEND VERILATOR_ARGS --trace-threads ${VERILATE_TRACE_THREADS}) endif() if(VERILATE_COVERAGE) list(APPEND VERILATOR_ARGS --coverage) endif() if(VERILATE_SYSTEMC) list(APPEND VERILATOR_ARGS --sc) else() list(APPEND VERILATOR_ARGS --cc) endif() if(VERILATE_TRACE AND VERILATE_TRACE_FST) message(FATAL_ERROR "Cannot have both TRACE and TRACE_FST") endif() if(VERILATE_TRACE_FST AND VERILATE_TRACE_VCD) message(FATAL_ERROR "Cannot have both TRACE_FST and TRACE_VCD") endif() if(VERILATE_TRACE_SAIF AND VERILATE_TRACE_VCD) message(FATAL_ERROR "Cannot have both TRACE_SAIF and TRACE_VCD") endif() if(VERILATE_TRACE) list(APPEND VERILATOR_ARGS --trace-vcd) endif() if(VERILATE_TRACE_FST) list(APPEND VERILATOR_ARGS --trace-fst) endif() if(VERILATE_TRACE_SAIF) list(APPEND VERILATOR_ARGS --trace-saif) endif() if(VERILATE_TRACE_VCD) list(APPEND VERILATOR_ARGS --trace-vcd) endif() if(VERILATE_TRACE_STRUCTS) list(APPEND VERILATOR_ARGS --trace-structs) endif() foreach(INC ${VERILATE_INCLUDE_DIRS}) list(APPEND VERILATOR_ARGS -y "${INC}") endforeach() string(TOLOWER ${CMAKE_CXX_COMPILER_ID} COMPILER) if(COMPILER STREQUAL "appleclang") set(COMPILER clang) elseif(NOT COMPILER MATCHES "^msvc$|^clang$") set(COMPILER gcc) endif() set(OBJCACHE "" CACHE STRING "Path for ccache, auto-detected if empty") option(OBJCACHE_ENABLED "Compile Verilator with ccache" ON) if(OBJCACHE_ENABLED) if(OBJCACHE STREQUAL "") find_program(OBJCACHE_PATH ccache) if(OBJCACHE_PATH STREQUAL "OBJCACHE_PATH-NOTFOUND") set(OBJCACHE_PATH "") endif() else() set(OBJCACHE_PATH "${OBJCACHE}") endif() if(NOT OBJCACHE_PATH STREQUAL "") execute_process( COMMAND "${OBJCACHE_PATH}" --version OUTPUT_VARIABLE objcache_version ) string( REGEX MATCH "[^\n\r]+" objcache_version "${objcache_version}" ) message( STATUS "Found ccache: ${OBJCACHE_PATH} (\"${objcache_version}\")" ) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${OBJCACHE_PATH}") endif() endif() get_target_property(BINARY_DIR "${TARGET}" BINARY_DIR) get_target_property(TARGET_NAME "${TARGET}" NAME) set(VDIR "${BINARY_DIR}/CMakeFiles/${TARGET_NAME}.dir/${VERILATE_PREFIX}.dir" ) if(VERILATE_DIRECTORY) set(VDIR "${VERILATE_DIRECTORY}") endif() file(MAKE_DIRECTORY ${VDIR}) set(VERILATOR_COMMAND "${CMAKE_COMMAND}" -E env "VERILATOR_ROOT=${VERILATOR_ROOT}" "${VERILATOR_BIN}" --compiler ${COMPILER} --prefix ${VERILATE_PREFIX} --Mdir ${VDIR} --make json ${VERILATOR_ARGS} ${VERILATE_VERILATOR_ARGS} ${VERILATE_SOURCES} ) set(VARGS_FILE "${VDIR}/verilator_args.txt") set(VCMAKE "${VDIR}/${VERILATE_PREFIX}.cmake") set(VCMAKE_COPY "${VDIR}/${VERILATE_PREFIX}_copy.cmake") if(NOT EXISTS "${VARGS_FILE}" OR NOT EXISTS "${VCMAKE_COPY}") set(VERILATOR_OUTDATED ON) else() file(READ "${VARGS_FILE}" PREVIOUS_VERILATOR_COMMAND) if(NOT VERILATOR_COMMAND STREQUAL PREVIOUS_VERILATOR_COMMAND) set(VERILATOR_OUTDATED ON) endif() endif() if(VERILATOR_OUTDATED) message(STATUS "Executing Verilator...") execute_process( COMMAND ${VERILATOR_COMMAND} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" RESULT_VARIABLE _VERILATOR_RC OUTPUT_VARIABLE _VERILATOR_OUTPUT ERROR_VARIABLE _VERILATOR_OUTPUT ) if(_VERILATOR_RC) string( REPLACE ";" " " VERILATOR_COMMAND_READABLE "${VERILATOR_COMMAND}" ) message("Verilator command: \"${VERILATOR_COMMAND_READABLE}\"") message("Output:\n${_VERILATOR_OUTPUT}") message( FATAL_ERROR "Verilator command failed (return code=${_VERILATOR_RC})" ) endif() file(READ ${VDIR}/${VERILATE_PREFIX}.json MANIFEST) json_get_string(JSYSTEM_PERL "${MANIFEST}" system perl) json_get_string(JSYSTEM_PYTHON3 "${MANIFEST}" system python3) json_get_string(JSYSTEM_VERILATOR_ROOT "${MANIFEST}" system verilator_root) json_get_string(JSYSTEM_VERILATOR_SOLVER "${MANIFEST}" system verilator_solver) json_get_list(JOPTIONS_CFLAGS "${MANIFEST}" options cflags) json_get_list(JOPTIONS_LDFLAGS "${MANIFEST}" options ldflags) json_get_bool(JOPTIONS_SYSTEM_C "${MANIFEST}" options system_c) json_get_bool(JOPTIONS_COVERAGE "${MANIFEST}" options coverage) json_get_bool(JOPTIONS_USE_TIMING "${MANIFEST}" options use_timing) json_get_int(JOPTIONS_THREADS "${MANIFEST}" options threads) json_get_bool(JOPTIONS_TRACE_FST "${MANIFEST}" options trace_fst) json_get_bool(JOPTIONS_TRACE_SAIF "${MANIFEST}" options trace_saif) json_get_bool(JOPTIONS_TRACE_VCD "${MANIFEST}" options trace_vcd) json_get_list(JSOURCES_GLOBAL "${MANIFEST}" sources global) json_get_list(JSOURCES_CLASSES_SLOW "${MANIFEST}" sources classes_slow) json_get_list(JSOURCES_CLASSES_FAST "${MANIFEST}" sources classes_fast) json_get_list(JSOURCES_SUPPORT_SLOW "${MANIFEST}" sources support_slow) json_get_list(JSOURCES_SUPPORT_FAST "${MANIFEST}" sources support_fast) json_get_list(JSOURCES_USER_CLASSES "${MANIFEST}" sources user_classes) json_get_list(JSOURCES_DEPS "${MANIFEST}" sources deps) file( WRITE ${VDIR}/${VERILATE_PREFIX}.cmake "# Verilated -*- CMake -*-\n" "# DESCRIPTION: Verilator output: CMake include script with class lists\n" "#\n" "# This CMake script lists generated Verilated files, for including in higher level CMake scripts.\n" "# This file is meant to be consumed by the verilate() function,\n" "# which becomes available after executing `find_package(verilator).\n\n" "### Constants...\n" "set(PERL \"${JSYSTEM_PERL}\" CACHE FILEPATH \"Perl executable (from \$PERL, defaults to 'perl' if not set)\")\n" "set(PYTHON3 \"${JSYSTEM_PYTHON3}\" CACHE FILEPATH \"Python3 executable (from \$PYTHON3, defaults to 'python3' if not set)\")\n" "set(VERILATOR_ROOT \"${JSYSTEM_VERILATOR_ROOT}\" CACHE PATH \"Path to Verilator kit (from $VERILATOR_ROOT)\")\n" "set(VERILATOR_SOLVER \"${JSYSTEM_VERILATOR_SOLVER}\" CACHE STRING \"Default SMT solver for constrained randomization (from \$VERILATOR_SOLVER)\")\n\n" "### Compiler flags...\n" "# User CFLAGS (from -CFLAGS on Verilator command line)\n" "set(${VERILATE_PREFIX}_USER_CFLAGS ${JOPTIONS_CFLAGS})\n" "# User LDLIBS (from -LDFLAGS on Verilator command line)\n" "set(${VERILATE_PREFIX}_USER_LDLIBS ${JOPTIONS_LDFLAGS})\n\n" "### Switches...\n" "# SystemC output mode? 0/1 (from --sc)\n" "set(${VERILATE_PREFIX}_SC ${JOPTIONS_SYSTEM_C})\n" "# Coverage output mode? 0/1 (from --coverage)\n" "set(${VERILATE_PREFIX}_COVERAGE ${JOPTIONS_COVERAGE})\n" "# Timing mode? 0/1\n" "set(${VERILATE_PREFIX}_TIMING ${JOPTIONS_USE_TIMING})\n" "# Threaded output mode? 1/N threads (from --threads)\n" "set(${VERILATE_PREFIX}_THREADS ${JOPTIONS_THREADS})\n" "# FST Tracing output mode? 0/1 (from --trace-fst)\n" "set(${VERILATE_PREFIX}_TRACE_FST ${JOPTIONS_TRACE_FST})\n\n" "# SAIF Tracing output mode? 0/1 (from --trace-saif)\n" "set(${VERILATE_PREFIX}_TRACE_SAIF ${JOPTIONS_TRACE_SAIF})\n\n" "# VCD Tracing output mode? 0/1 (from --trace-vcd)\n" "set(${VERILATE_PREFIX}_TRACE_VCD ${JOPTIONS_TRACE_VCD})\n" "### Sources...\n" "# Global classes, need linked once per executable\n" "set(${VERILATE_PREFIX}_GLOBAL ${JSOURCES_GLOBAL})\n" "# Generated module classes, non-fast-path, compile with low/medium optimization\n" "set(${VERILATE_PREFIX}_CLASSES_SLOW ${JSOURCES_CLASSES_SLOW})\n" "# Generated module classes, fast-path, compile with highest optimization\n" "set(${VERILATE_PREFIX}_CLASSES_FAST ${JSOURCES_CLASSES_FAST})\n" "# Generated support classes, non-fast-path, compile with low/medium optimization\n" "set(${VERILATE_PREFIX}_SUPPORT_SLOW ${JSOURCES_SUPPORT_SLOW})\n" "# Generated support classes, fast-path, compile with highest optimization\n" "set(${VERILATE_PREFIX}_SUPPORT_FAST ${JSOURCES_SUPPORT_FAST})\n" "# All dependencies\n" "set(${VERILATE_PREFIX}_DEPS ${JSOURCES_DEPS})\n" "# User .cpp files (from .cpp's on Verilator command line)\n" "set(${VERILATE_PREFIX}_USER_CLASSES ${JSOURCES_USER_CLASSES})\n" ) json_get_submodules(JSUBMODULES JNSUBMODULES "${MANIFEST}") if(JNSUBMODULES) file( APPEND ${VDIR}/${VERILATE_PREFIX}.cmake "# Verilate hierarchical blocks\n" "get_target_property(TOP_TARGET_NAME \"\${TARGET}\" NAME)\n" ) foreach(I RANGE ${JNSUBMODULES}) json_get_string(JSUBMODULE_PREFIX "${JSUBMODULES}" ${I} prefix) json_get_string(JSUBMODULE_TOP "${JSUBMODULES}" ${I} top) json_get_list(JSUBMODULE_DEPS "${JSUBMODULES}" ${I} deps) json_get_string(JSUBMODULE_DIRECTORY "${JSUBMODULES}" ${I} directory) json_get_list(JSUBMODULE_SOURCES "${JSUBMODULES}" ${I} sources) json_get_list(JSUBMODULE_CFLAGS "${JSUBMODULES}" ${I} cflags) json_get_string(JSUBMODILE_VERILATOR_ARGS "${JSUBMODULES}" ${I} verilator_args) set(SUBMODULE_CMAKE "") set(SUBMODULE_VERILATE_ARGS "") if(NOT ${I} STREQUAL ${JNSUBMODULES}) string( APPEND SUBMODULE_CMAKE "add_library(${JSUBMODULE_PREFIX} STATIC)\n" "target_link_libraries(\${TOP_TARGET_NAME} PRIVATE ${JSUBMODULE_PREFIX})\n" ) if(JSUBMODULE_DEPS) string( APPEND SUBMODULE_CMAKE "target_link_libraries(${JSUBMODULE_PREFIX} INTERFACE ${JSUBMODULE_DEPS})\n" ) endif() string( APPEND SUBMODULE_VERILATE_ARGS "${JSUBMODULE_PREFIX} PREFIX ${JSUBMODULE_PREFIX} TOP_MODULE ${JSUBMODULE_TOP} DIRECTORY ${JSUBMODULE_DIRECTORY} SOURCES ${JSUBMODULE_SOURCES}" ) else() string( APPEND SUBMODULE_CMAKE "# Verilate the top module that refers to lib-create wrappers of above\n" ) string( APPEND SUBMODULE_VERILATE_ARGS "\${TOP_TARGET_NAME} PREFIX ${JSUBMODULE_PREFIX} TOP_MODULE ${JSUBMODULE_TOP} DIRECTORY ${JSUBMODULE_DIRECTORY} SOURCES ${JSUBMODULE_SOURCES}" ) endif() if(JSUBMODILE_VERILATOR_ARGS) string( APPEND SUBMODULE_VERILATE_ARGS " VERILATOR_ARGS -f ${JSUBMODILE_VERILATOR_ARGS}" ) endif() if(JSUBMODULE_CFLAGS) string( APPEND SUBMODULE_VERILATE_ARGS " -CFLAGS ${JSUBMODULE_CFLAGS}" ) endif() file( APPEND ${VDIR}/${VERILATE_PREFIX}.cmake "${SUBMODULE_CMAKE}" "verilate(${SUBMODULE_VERILATE_ARGS})\n" ) endforeach() endif() execute_process( COMMAND "${CMAKE_COMMAND}" -E copy "${VCMAKE}" "${VCMAKE_COPY}" ) endif() file(WRITE "${VARGS_FILE}" "${VERILATOR_COMMAND}") include("${VCMAKE_COPY}") set(GENERATED_C_SOURCES ${${VERILATE_PREFIX}_CLASSES_FAST} ${${VERILATE_PREFIX}_CLASSES_SLOW} ${${VERILATE_PREFIX}_SUPPORT_FAST} ${${VERILATE_PREFIX}_SUPPORT_SLOW} ) # No need for .h's as the .cpp will get written same time set(GENERATED_SOURCES ${GENERATED_C_SOURCES}) add_custom_command( OUTPUT ${GENERATED_SOURCES} "${VCMAKE}" COMMAND ${VERILATOR_COMMAND} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DEPENDS "${VERILATOR_BIN}" ${${VERILATE_PREFIX}_DEPS} VERBATIM ) # Reconfigure if file list has changed # (check contents rather than modified time to avoid unnecessary reconfiguration) add_custom_command( OUTPUT "${VCMAKE_COPY}" COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${VCMAKE}" "${VCMAKE_COPY}" DEPENDS "${VCMAKE}" VERBATIM ) if(${VERILATE_PREFIX}_COVERAGE) # If any verilate() call specifies COVERAGE, define VM_COVERAGE in the final build set_property(TARGET ${TARGET} PROPERTY VERILATOR_COVERAGE ON) endif() if(${VERILATE_PREFIX}_SC) # If any verilate() call specifies SYSTEMC, define VM_SC in the final build set_property(TARGET ${TARGET} PROPERTY VERILATOR_SYSTEMC ON) endif() if(${VERILATE_PREFIX}_TRACE_FST) # If any verilate() call specifies TRACE_FST, define VM_TRACE_FST in the final build set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON) set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_FST ON) endif() if(${VERILATE_PREFIX}_TRACE_SAIF) # If any verilate() call specifies TRACE_SAIF, define VM_TRACE_SAIF in the final build set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON) set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_SAIF ON) endif() if(${VERILATE_PREFIX}_TRACE_VCD) # If any verilate() call specifies TRACE, define VM_TRACE_VCD in the final build set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON) set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_VCD ON) endif() if(${VERILATE_PREFIX}_TRACE_STRUCTS) set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_STRUCTS ON) endif() # Add the compile flags only on Verilated sources target_include_directories(${TARGET} PUBLIC ${VDIR}) target_sources( ${TARGET} PRIVATE ${GENERATED_SOURCES} "${VCMAKE_COPY}" ${${VERILATE_PREFIX}_GLOBAL} ${${VERILATE_PREFIX}_USER_CLASSES} ) foreach(_VSOURCE ${VERILATE_SOURCES} ${${VERILATE_PREFIX}_DEPS}) get_filename_component(_VSOURCE "${_VSOURCE}" ABSOLUTE BASE_DIR) list(APPEND VHD_SOURCES "${_VSOURCE}") endforeach() target_sources(${TARGET} PRIVATE ${VHD_SOURCES}) # Add the compile flags only on Verilated sources foreach( VSLOW ${${VERILATE_PREFIX}_CLASSES_SLOW} ${${VERILATE_PREFIX}_SUPPORT_SLOW} ) foreach(OPT_SLOW ${VERILATE_OPT_SLOW} ${${VERILATE_PREFIX}_USER_CFLAGS}) set_property( SOURCE "${VSLOW}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_SLOW}" ) endforeach() endforeach() foreach( VFAST ${${VERILATE_PREFIX}_CLASSES_FAST} ${${VERILATE_PREFIX}_SUPPORT_FAST} ) foreach(OPT_FAST ${VERILATE_OPT_FAST} ${${VERILATE_PREFIX}_USER_CFLAGS}) set_property( SOURCE "${VFAST}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_FAST}" ) endforeach() endforeach() foreach(VGLOBAL ${${VERILATE_PREFIX}_GLOBAL}) foreach( OPT_GLOBAL ${VERILATE_OPT_GLOBAL} ${${VERILATE_PREFIX}_USER_CFLAGS} ) set_property( SOURCE "${VGLOBAL}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_GLOBAL}" ) endforeach() endforeach() target_include_directories( ${TARGET} PUBLIC "${VERILATOR_ROOT}/include" "${VERILATOR_ROOT}/include/vltstd" ) target_compile_definitions( ${TARGET} PRIVATE VM_COVERAGE=$> VM_SC=$> VM_TRACE=$> VM_TRACE_VCD=$> VM_TRACE_FST=$> VM_TRACE_SAIF=$> ) target_link_libraries(${TARGET} PUBLIC ${${VERILATE_PREFIX}_USER_LDLIBS}) target_link_libraries(${TARGET} PUBLIC ${VERILATOR_MT_CFLAGS}) target_compile_features(${TARGET} PRIVATE cxx_std_11) if(${VERILATE_PREFIX}_TIMING) check_cxx_compiler_flag(-fcoroutines-ts COROUTINES_TS_FLAG) target_compile_options( ${TARGET} PRIVATE $,-fcoroutines-ts,-fcoroutines> ) endif() endfunction() function(_verilator_find_systemc) if(NOT TARGET Verilator::systemc) # Find SystemC include file "systemc.h" in the following order: # 1. SYSTEMC_INCLUDE (environment) variable # 2. SYSTEMC_ROOT (environment) variable # 3. SYSTEMC (environment) variable # 4. Use CMake module provided by SystemC installation # (eventually requires CMAKE_PREFIX_PATH set) find_path( SYSTEMC_INCLUDEDIR NAMES systemc.h HINTS "${SYSTEMC_INCLUDE} " ENV SYSTEMC_INCLUDE ) find_path( SYSTEMC_INCLUDEDIR NAMES systemc.h HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT PATH_SUFFIXES include ) find_path( SYSTEMC_INCLUDEDIR NAMES systemc.h HINTS "${SYSTEMC}" ENV SYSTEMC PATH_SUFFIXES include ) # Find SystemC library in the following order: # 1. SYSTEMC_LIBDIR (environment) variable # 2. SYSTEMC_ROOT (environment) variable # 3. SYSTEMC (environment) variable # 4. Use CMake module provided by SystemC installation # (eventually requires CMAKE_PREFIX_PATH set) # Find SystemC using include and library paths find_library( SYSTEMC_LIBRARY NAMES systemc HINTS "${SYSTEMC_LIBDIR}" ENV SYSTEMC_LIBDIR ) find_library( SYSTEMC_LIBRARY NAMES systemc HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT PATH_SUFFIXES lib ) find_library( SYSTEMC_LIBRARY NAMES systemc HINTS "${SYSTEMC}" ENV SYSTEMC PATH_SUFFIXES lib ) if(SYSTEMC_INCLUDEDIR AND SYSTEMC_LIBRARY) add_library(Verilator::systemc INTERFACE IMPORTED) set_target_properties( Verilator::systemc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${SYSTEMC_INCLUDEDIR}" INTERFACE_LINK_LIBRARIES "${SYSTEMC_LIBRARY}" ) return() endif() find_package(SystemCLanguage QUIET) if(SystemCLanguage_FOUND) add_library(Verilator::systemc INTERFACE IMPORTED) set_target_properties( Verilator::systemc PROPERTIES INTERFACE_LINK_LIBRARIES "SystemC::systemc" ) return() endif() message( "SystemC not found. This can be fixed by doing either of the following steps:" ) message( "- set the SYSTEMC_INCLUDE and SYSTEMC_LIBDIR (environment) variables; or" ) message("- set SYSTEMC_ROOT (environment) variable; or") message("- set SYSTEMC (environment) variable; or") message( "- use the CMake module of your SystemC installation (may require CMAKE_PREFIX_PATH)" ) message(FATAL_ERROR "SystemC not found") endif() endfunction() function(verilator_link_systemc TARGET) _verilator_find_systemc() target_link_libraries("${TARGET}" PUBLIC Verilator::systemc) target_compile_options( ${TARGET} PRIVATE $ENV{SYSTEMC_CXX_FLAGS} ${SYSTEMC_CXX_FLAGS} ) endfunction() function(verilator_generate_key OUTPUT_VARIABLE) execute_process( COMMAND ${VERILATOR_BIN} --generate-key OUTPUT_VARIABLE KEY_VAL RESULT_VARIABLE KEY_RET ) if(KEY_RET) message(FATAL_ERROR "verilator --generate-key failed") endif() string(STRIP ${KEY_VAL} KEY_VAL) set(${OUTPUT_VARIABLE} ${KEY_VAL} PARENT_SCOPE) endfunction()