Verilator
/
verilator-config.cmake.in
431 строка · 15.2 Кб
1######################################################################
2#
3# DESCRIPTION: CMake configuration file for Verilator
4#
5# Include it in your CMakeLists.txt using:
6#
7# find_package(verilate)
8#
9# This script adds a verilate function.
10#
11# add_executable(simulator <your-c-sources>)
12# verilate(simulator SOURCES <your-hdl-sources>)
13#
14# Copyright 2003-2024 by Wilson Snyder. This program is free software; you
15# can redistribute it and/or modify it under the terms of either the GNU
16# Lesser General Public License Version 3 or the Perl Artistic License
17# Version 2.0.
18# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
19#
20######################################################################
21
22cmake_minimum_required(VERSION 3.13)
23
24# Prefer VERILATOR_ROOT from environment
25if (DEFINED ENV{VERILATOR_ROOT})
26set(VERILATOR_ROOT "$ENV{VERILATOR_ROOT}" CACHE PATH "VERILATOR_ROOT")
27endif()
28
29set(VERILATOR_ROOT "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "VERILATOR_ROOT")
30
31find_program(VERILATOR_BIN NAMES verilator_bin verilator_bin.exe
32HINTS ${VERILATOR_ROOT}/bin ENV VERILATOR_ROOT
33NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
34
35if (NOT VERILATOR_ROOT)
36message(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.")
37endif()
38
39if (NOT VERILATOR_BIN)
40message(FATAL_ERROR "Cannot find verilator_bin excecutable.")
41endif()
42
43set(verilator_FOUND 1)
44
45include(CheckCXXSourceCompiles)
46function(_verilator_check_cxx_libraries LIBRARIES RESVAR)
47# Check whether a particular link option creates a valid executable
48set(_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC "int main() {return 0;}\n")
49set(CMAKE_REQUIRED_FLAGS)
50set(CMAKE_REQUIRED_DEFINITIONS)
51set(CMAKE_REQUIRED_INCLUDES)
52set(CMAKE_REQUIRED_LINK_OPTIONS)
53set(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
54set(CMAKE_REQUIRED_QUIET)
55check_cxx_source_compiles("${_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC}" "${RESVAR}")
56set("${RESVAR}" "${${RESVAR}}" PARENT_SCOPE)
57endfunction()
58
59# Check compiler flag support. Skip on MSVC, these are all GCC flags.
60if (NOT CMAKE_CXX_COMPILER_ID MATCHES MSVC)
61if (NOT DEFINED VERILATOR_CFLAGS OR NOT DEFINED VERILATOR_MT_CFLAGS)
62include(CheckCXXCompilerFlag)
63foreach (FLAG @CFG_CXX_FLAGS_CMAKE@)
64string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME)
65check_cxx_compiler_flag(${FLAG} ${FLAGNAME})
66if (${FLAGNAME})
67list(APPEND VERILATOR_CFLAGS ${FLAG})
68endif()
69endforeach()
70foreach (FLAG @CFG_LDFLAGS_THREADS_CMAKE@)
71string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME)
72_verilator_check_cxx_libraries("${FLAG}" ${FLAGNAME})
73if (${FLAGNAME})
74list(APPEND VERILATOR_MT_CFLAGS ${FLAG})
75endif()
76endforeach()
77endif()
78endif()
79
80if (${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang")
81add_link_options(-Wl,-U,__Z15vl_time_stamp64v,-U,__Z13sc_time_stampv)
82endif()
83
84define_property(TARGET
85PROPERTY VERILATOR_THREADED
86BRIEF_DOCS "Deprecated and has no effect (ignored)"
87FULL_DOCS "Deprecated and has no effect (ignored)"
88)
89
90define_property(TARGET
91PROPERTY VERILATOR_TRACE_THREADED
92BRIEF_DOCS "Verilator multithread tracing enabled"
93FULL_DOCS "Verilator multithread tracing enabled"
94)
95
96define_property(TARGET
97PROPERTY VERILATOR_TIMING
98BRIEF_DOCS "Verilator timing enabled"
99FULL_DOCS "Verilator timing enabled"
100)
101
102define_property(TARGET
103PROPERTY VERILATOR_COVERAGE
104BRIEF_DOCS "Verilator coverage enabled"
105FULL_DOCS "Verilator coverage enabled"
106)
107
108define_property(TARGET
109PROPERTY VERILATOR_TRACE
110BRIEF_DOCS "Verilator trace enabled"
111FULL_DOCS "Verilator trace enabled"
112)
113
114define_property(TARGET
115PROPERTY VERILATOR_TRACE_VCD
116BRIEF_DOCS "Verilator VCD trace enabled"
117FULL_DOCS "Verilator VCD trace enabled"
118)
119
120define_property(TARGET
121PROPERTY VERILATOR_TRACE_FST
122BRIEF_DOCS "Verilator FST trace enabled"
123FULL_DOCS "Verilator FST trace enabled"
124)
125
126define_property(TARGET
127PROPERTY VERILATOR_SYSTEMC
128BRIEF_DOCS "Verilator SystemC enabled"
129FULL_DOCS "Verilator SystemC enabled"
130)
131
132define_property(TARGET
133PROPERTY VERILATOR_TRACE_STRUCTS
134BRIEF_DOCS "Verilator trace structs enabled"
135FULL_DOCS "Verilator trace structs enabled"
136)
137
138
139function(verilate TARGET)
140cmake_parse_arguments(VERILATE "COVERAGE;TRACE;TRACE_FST;SYSTEMC;TRACE_STRUCTS"
141"PREFIX;TOP_MODULE;THREADS;TRACE_THREADS;DIRECTORY"
142"SOURCES;VERILATOR_ARGS;INCLUDE_DIRS;OPT_SLOW;OPT_FAST;OPT_GLOBAL"
143${ARGN})
144if (NOT VERILATE_SOURCES)
145message(FATAL_ERROR "Need at least one source")
146endif()
147
148if (NOT VERILATE_PREFIX)
149list(LENGTH VERILATE_SOURCES NUM_SOURCES)
150if (${NUM_SOURCES} GREATER 1)
151message(WARNING "Specify PREFIX if there are multiple SOURCES")
152endif()
153list(GET VERILATE_SOURCES 0 TOPSRC)
154get_filename_component(_SRC_NAME ${TOPSRC} NAME_WE)
155string(MAKE_C_IDENTIFIER V${_SRC_NAME} VERILATE_PREFIX)
156endif()
157
158if (VERILATE_TOP_MODULE)
159list(APPEND VERILATOR_ARGS --top ${VERILATE_TOP_MODULE})
160endif()
161
162if (VERILATE_THREADS)
163list(APPEND VERILATOR_ARGS --threads ${VERILATE_THREADS})
164endif()
165
166if (VERILATE_TRACE_THREADS)
167list(APPEND VERILATOR_ARGS --trace-threads ${VERILATE_TRACE_THREADS})
168endif()
169
170if (VERILATE_COVERAGE)
171list(APPEND VERILATOR_ARGS --coverage)
172endif()
173
174if (VERILATE_TRACE AND VERILATE_TRACE_FST)
175message(FATAL_ERROR "Cannot have both TRACE and TRACE_FST")
176endif()
177
178if (VERILATE_TRACE)
179list(APPEND VERILATOR_ARGS --trace)
180endif()
181
182if (VERILATE_TRACE_FST)
183list(APPEND VERILATOR_ARGS --trace-fst)
184endif()
185
186if (VERILATE_SYSTEMC)
187list(APPEND VERILATOR_ARGS --sc)
188else()
189list(APPEND VERILATOR_ARGS --cc)
190endif()
191
192if (VERILATE_TRACE_STRUCTS)
193list(APPEND VERILATOR_ARGS --trace-structs)
194endif()
195
196foreach(INC ${VERILATE_INCLUDE_DIRS})
197list(APPEND VERILATOR_ARGS -y "${INC}")
198endforeach()
199
200string(TOLOWER ${CMAKE_CXX_COMPILER_ID} COMPILER)
201if (COMPILER STREQUAL "appleclang")
202set(COMPILER clang)
203elseif (NOT COMPILER MATCHES "^msvc$|^clang$")
204set(COMPILER gcc)
205endif()
206
207get_target_property(BINARY_DIR "${TARGET}" BINARY_DIR)
208get_target_property(TARGET_NAME "${TARGET}" NAME)
209set(VDIR "${BINARY_DIR}/CMakeFiles/${TARGET_NAME}.dir/${VERILATE_PREFIX}.dir")
210
211if (VERILATE_DIRECTORY)
212set(VDIR "${VERILATE_DIRECTORY}")
213endif()
214
215file(MAKE_DIRECTORY ${VDIR})
216
217set(VERILATOR_COMMAND "${CMAKE_COMMAND}" -E env "VERILATOR_ROOT=${VERILATOR_ROOT}"
218"${VERILATOR_BIN}" --compiler ${COMPILER}
219--prefix ${VERILATE_PREFIX} --Mdir ${VDIR} --make cmake
220${VERILATOR_ARGS} ${VERILATE_VERILATOR_ARGS}
221${VERILATE_SOURCES})
222
223set(VARGS_FILE "${VDIR}/verilator_args.txt")
224set(VCMAKE "${VDIR}/${VERILATE_PREFIX}.cmake")
225set(VCMAKE_COPY "${VDIR}/${VERILATE_PREFIX}_copy.cmake")
226
227if (NOT EXISTS "${VARGS_FILE}" OR NOT EXISTS "${VCMAKE_COPY}")
228set(VERILATOR_OUTDATED ON)
229else()
230file(READ "${VARGS_FILE}" PREVIOUS_VERILATOR_COMMAND)
231if(NOT VERILATOR_COMMAND STREQUAL PREVIOUS_VERILATOR_COMMAND)
232set(VERILATOR_OUTDATED ON)
233endif()
234endif()
235
236if (VERILATOR_OUTDATED)
237message(STATUS "Executing Verilator...")
238execute_process(
239COMMAND ${VERILATOR_COMMAND}
240WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
241RESULT_VARIABLE _VERILATOR_RC
242OUTPUT_VARIABLE _VERILATOR_OUTPUT
243ERROR_VARIABLE _VERILATOR_OUTPUT)
244if (_VERILATOR_RC)
245string(REPLACE ";" " " VERILATOR_COMMAND_READABLE "${VERILATOR_COMMAND}")
246message("Verilator command: \"${VERILATOR_COMMAND_READABLE}\"")
247message("Output:\n${_VERILATOR_OUTPUT}")
248message(FATAL_ERROR "Verilator command failed (return code=${_VERILATOR_RC})")
249endif()
250execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${VCMAKE}" "${VCMAKE_COPY}")
251endif()
252file(WRITE "${VARGS_FILE}" "${VERILATOR_COMMAND}")
253
254include("${VCMAKE_COPY}")
255
256set(GENERATED_C_SOURCES ${${VERILATE_PREFIX}_CLASSES_FAST}
257${${VERILATE_PREFIX}_CLASSES_SLOW}
258${${VERILATE_PREFIX}_SUPPORT_FAST}
259${${VERILATE_PREFIX}_SUPPORT_SLOW})
260# No need for .h's as the .cpp will get written same time
261set(GENERATED_SOURCES ${GENERATED_C_SOURCES})
262
263add_custom_command(OUTPUT ${GENERATED_SOURCES} "${VCMAKE}"
264COMMAND ${VERILATOR_COMMAND}
265WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
266DEPENDS "${VERILATOR_BIN}" ${${VERILATE_PREFIX}_DEPS} VERBATIM)
267# Reconfigure if file list has changed
268# (check contents rather than modified time to avoid unnecessary reconfiguration)
269add_custom_command(OUTPUT "${VCMAKE_COPY}"
270COMMAND "${CMAKE_COMMAND}" -E copy_if_different
271"${VCMAKE}" "${VCMAKE_COPY}"
272DEPENDS "${VCMAKE}" VERBATIM)
273
274if (${VERILATE_PREFIX}_COVERAGE)
275# If any verilate() call specifies COVERAGE, define VM_COVERAGE in the final build
276set_property(TARGET ${TARGET} PROPERTY VERILATOR_COVERAGE ON)
277endif()
278
279if (${VERILATE_PREFIX}_TRACE_VCD)
280# If any verilate() call specifies TRACE, define VM_TRACE in the final build
281set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON)
282set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_VCD ON)
283endif()
284
285if (${VERILATE_PREFIX}_TRACE_FST)
286# If any verilate() call specifies TRACE_FST, define VM_TRACE_FST in the final build
287set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON)
288set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_FST ON)
289endif()
290
291if (${VERILATE_PREFIX}_SC)
292# If any verilate() call specifies SYSTEMC, define VM_SC in the final build
293set_property(TARGET ${TARGET} PROPERTY VERILATOR_SYSTEMC ON)
294endif()
295
296if (${VERILATE_PREFIX}_TRACE_STRUCTS)
297set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_STRUCTS ON)
298endif()
299
300# Add the compile flags only on Verilated sources
301target_include_directories(${TARGET} PUBLIC ${VDIR})
302target_sources(${TARGET} PRIVATE ${GENERATED_SOURCES} "${VCMAKE_COPY}"
303${${VERILATE_PREFIX}_GLOBAL}
304${${VERILATE_PREFIX}_USER_CLASSES})
305foreach(_VSOURCE ${VERILATE_SOURCES} ${${VERILATE_PREFIX}_DEPS})
306get_filename_component(_VSOURCE "${_VSOURCE}" ABSOLUTE BASE_DIR)
307list(APPEND VHD_SOURCES "${_VSOURCE}")
308endforeach()
309target_sources(${TARGET} PRIVATE ${VHD_SOURCES})
310
311# Add the compile flags only on Verilated sources
312foreach(VSLOW ${${VERILATE_PREFIX}_CLASSES_SLOW} ${${VERILATE_PREFIX}_SUPPORT_SLOW})
313foreach(OPT_SLOW ${VERILATE_OPT_SLOW} ${${VERILATE_PREFIX}_USER_CFLAGS})
314set_property(SOURCE "${VSLOW}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_SLOW}")
315endforeach()
316endforeach()
317foreach(VFAST ${${VERILATE_PREFIX}_CLASSES_FAST} ${${VERILATE_PREFIX}_SUPPORT_FAST})
318foreach(OPT_FAST ${VERILATE_OPT_FAST} ${${VERILATE_PREFIX}_USER_CFLAGS})
319set_property(SOURCE "${VFAST}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_FAST}")
320endforeach()
321endforeach()
322foreach(VGLOBAL ${${VERILATE_PREFIX}_GLOBAL})
323foreach(OPT_GLOBAL ${VERILATE_OPT_GLOBAL} ${${VERILATE_PREFIX}_USER_CFLAGS})
324set_property(SOURCE "${VGLOBAL}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_GLOBAL}")
325endforeach()
326endforeach()
327
328target_include_directories(${TARGET} PUBLIC "${VERILATOR_ROOT}/include"
329"${VERILATOR_ROOT}/include/vltstd")
330target_compile_definitions(${TARGET} PRIVATE
331VM_COVERAGE=$<BOOL:$<TARGET_PROPERTY:VERILATOR_COVERAGE>>
332VM_SC=$<BOOL:$<TARGET_PROPERTY:VERILATOR_SYSTEMC>>
333VM_TRACE=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE>>
334VM_TRACE_VCD=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_VCD>>
335VM_TRACE_FST=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_FST>>
336)
337
338target_link_libraries(${TARGET} PUBLIC
339${${VERILATE_PREFIX}_USER_LDLIBS}
340)
341
342target_link_libraries(${TARGET} PUBLIC
343${VERILATOR_MT_CFLAGS}
344)
345
346target_compile_features(${TARGET} PRIVATE cxx_std_11)
347
348if (${VERILATE_PREFIX}_TIMING)
349check_cxx_compiler_flag(-fcoroutines-ts COROUTINES_TS_FLAG)
350target_compile_options(${TARGET} PRIVATE $<IF:$<BOOL:${COROUTINES_TS_FLAG}>,-fcoroutines-ts,-fcoroutines>)
351endif()
352endfunction()
353
354function(_verilator_find_systemc)
355if (NOT TARGET Verilator::systemc)
356# Find SystemC include file "systemc.h" in the following order:
357# 1. SYSTEMC_INCLUDE (environment) variable
358# 2. SYSTEMC_ROOT (environment) variable
359# 3. SYSTEMC (environment) variable
360# 4. Use CMake module provided by SystemC installation
361# (eventually requires CMAKE_PREFIX_PATH set)
362
363find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
364HINTS "${SYSTEMC_INCLUDE} " ENV SYSTEMC_INCLUDE)
365find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
366HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT
367PATH_SUFFIXES include)
368find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
369HINTS "${SYSTEMC}" ENV SYSTEMC
370PATH_SUFFIXES include)
371
372# Find SystemC library in the following order:
373# 1. SYSTEMC_LIBDIR (environment) variable
374# 2. SYSTEMC_ROOT (environment) variable
375# 3. SYSTEMC (environment) variable
376# 4. Use CMake module provided by SystemC installation
377# (eventually requires CMAKE_PREFIX_PATH set)
378
379# Find SystemC using include and library paths
380find_library(SYSTEMC_LIBRARY NAMES systemc
381HINTS "${SYSTEMC_LIBDIR}" ENV SYSTEMC_LIBDIR)
382find_library(SYSTEMC_LIBRARY NAMES systemc
383HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT
384PATH_SUFFIXES lib)
385find_library(SYSTEMC_LIBRARY NAMES systemc
386HINTS "${SYSTEMC}" ENV SYSTEMC
387PATH_SUFFIXES lib)
388
389if (SYSTEMC_INCLUDEDIR AND SYSTEMC_LIBRARY)
390add_library(Verilator::systemc INTERFACE IMPORTED)
391set_target_properties(Verilator::systemc
392PROPERTIES
393INTERFACE_INCLUDE_DIRECTORIES "${SYSTEMC_INCLUDEDIR}"
394INTERFACE_LINK_LIBRARIES "${SYSTEMC_LIBRARY}")
395return()
396endif()
397
398find_package(SystemCLanguage QUIET)
399if (SystemCLanguage_FOUND)
400add_library(Verilator::systemc INTERFACE IMPORTED)
401set_target_properties(Verilator::systemc
402PROPERTIES
403INTERFACE_LINK_LIBRARIES "SystemC::systemc")
404return()
405endif()
406
407message("SystemC not found. This can be fixed by doing either of the following steps:")
408message("- set the SYSTEMC_INCLUDE and SYSTEMC_LIBDIR (environment) variables; or")
409message("- set SYSTEMC_ROOT (environment) variable; or")
410message("- set SYSTEMC (environment) variable; or")
411message("- use the CMake module of your SystemC installation (may require CMAKE_PREFIX_PATH)")
412message(FATAL_ERROR "SystemC not found")
413endif()
414endfunction()
415
416function(verilator_link_systemc TARGET)
417_verilator_find_systemc()
418target_link_libraries("${TARGET}" PUBLIC Verilator::systemc)
419target_compile_options(${TARGET} PRIVATE $ENV{SYSTEMC_CXX_FLAGS} ${SYSTEMC_CXX_FLAGS})
420endfunction()
421
422function(verilator_generate_key OUTPUT_VARIABLE)
423execute_process(COMMAND ${VERILATOR_BIN} --generate-key
424OUTPUT_VARIABLE KEY_VAL
425RESULT_VARIABLE KEY_RET)
426if (KEY_RET)
427message(FATAL_ERROR "verilator --generate-key failed")
428endif()
429string(STRIP ${KEY_VAL} KEY_VAL)
430set(${OUTPUT_VARIABLE} ${KEY_VAL} PARENT_SCOPE)
431endfunction()
432