882 lines
30 KiB
CMake
882 lines
30 KiB
CMake
######################################################################
|
|
#
|
|
# 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 <your-c-sources>)
|
|
# verilate(simulator SOURCES <your-hdl-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()
|
|
|
|
function(_verilator_check_cxx_compiler_flag FLAG RESVAR)
|
|
# Check whether the compiler understands the flag FLAG
|
|
set(_VERILATOR_CHECK_CXX_COMPILER_FLAG_SRC
|
|
"
|
|
#warning warning
|
|
int main() { return 0; }
|
|
"
|
|
)
|
|
set(CMAKE_REQUIRED_FLAGS ${FLAG})
|
|
# Make sure the compiler warning is not turned into an error
|
|
string(APPEND CMAKE_REQUIRED_FLAGS " -Wno-error=cpp")
|
|
set(CMAKE_REQUIRED_DEFINITIONS)
|
|
set(CMAKE_REQUIRED_INCLUDES)
|
|
set(CMAKE_REQUIRED_LINK_OPTIONS)
|
|
set(CMAKE_REQUIRED_LIBRARIES)
|
|
set(CMAKE_REQUIRED_QUIET)
|
|
|
|
check_compiler_flag_common_patterns(_common_patterns)
|
|
check_cxx_source_compiles(
|
|
"${_VERILATOR_CHECK_CXX_COMPILER_FLAG_SRC}"
|
|
"${RESVAR}"
|
|
FAIL_REGEX
|
|
"command[ -]line option .* is valid for .* but not for C[+][+]"
|
|
FAIL_REGEX
|
|
"-Werror=.* argument .* is not valid for C[+][+]"
|
|
${_common_patterns}
|
|
)
|
|
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)
|
|
_verilator_check_cxx_compiler_flag(${FLAG} ${FLAGNAME})
|
|
if(${FLAGNAME})
|
|
list(APPEND VERILATOR_CFLAGS $<$<COMPILE_LANGUAGE:CXX>:${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=$<BOOL:$<TARGET_PROPERTY:VERILATOR_COVERAGE>>
|
|
VM_SC=$<BOOL:$<TARGET_PROPERTY:VERILATOR_SYSTEMC>>
|
|
VM_TRACE=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE>>
|
|
VM_TRACE_VCD=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_VCD>>
|
|
VM_TRACE_FST=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_FST>>
|
|
VM_TRACE_SAIF=$<BOOL:$<TARGET_PROPERTY:VERILATOR_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
|
|
$<IF:$<BOOL:${COROUTINES_TS_FLAG}>,-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()
|