diff --git a/SoCMakeConfig.cmake b/SoCMakeConfig.cmake index 8484c45d..adcf0377 100644 --- a/SoCMakeConfig.cmake +++ b/SoCMakeConfig.cmake @@ -20,9 +20,8 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/uniquify_files_by_basename.cmake" # ==================================== # ======== Additional utilities ====== # ==================================== -include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/copy_rtl_files/copy_rtl_files.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/copy_rtl_files/read_rtl_sources.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/copy_rtl_files/vhier.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/generate_sources_list/generate_sources_list.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/generate_sources_list/read_rtl_sources.cmake") # ==================================== # ======== Simulation ================ diff --git a/cmake/utils/copy_rtl_files/copy_rtl_files.cmake b/cmake/utils/copy_rtl_files/copy_rtl_files.cmake deleted file mode 100644 index f631d6fd..00000000 --- a/cmake/utils/copy_rtl_files/copy_rtl_files.cmake +++ /dev/null @@ -1,91 +0,0 @@ -#[[[ -# This function copies the RTL sources of an IP to a given location. -# -# This function gets an IP_LIB target and get its RTL source files (exluding SIM/TB/FPGA files) and include directories and copy -# them to a default or given location. The output location contains a file listing all the sources, an include directory containing -# all the include files and the source files with a preserved hierarchy folder. It uses the vhier tool to parse and build the library -# hierachy and copy only the files instantiated in the hierarchy. -# vhier is part of a set of tools: -# https://github.com/gitpan/Verilog-Perl -# https://metacpan.org/pod/vhier -# -# :param IP_LIB: IP library to get RTL sources from. -# :type IP_LIB: string -# -# **Keyword Arguments** -# -# :keyword SYNTHESIS: Define SYNTHESIS, and ignore text between "ambit", "pragma", "synopsys" or "synthesis" translate_off and translate_on meta comments. -# :type SYNTHESIS: string -# :keyword OUTDIR: Change the default copy location ${CMAKE_BINARY_DIR}/ip_sources to OUTDIR. -# :type OUTDIR: string -# :keyword TOP_MODULE: Start the report at the specified module name, ignoring all modules that are not the one specified with --top-module or below, and report an error if the --top-module specified does not exist. -# :type TOP_MODULE: string -# :keyword SKIPLIST_FILE: Given file contains a list of regular expressions, one per line. If a module name in the design hierarchy matches one of these expressions, skip showing that module and any sub-hierarchy. -# :type SKIPLIST_FILE: string -#]] -function(copy_rtl_files IP_LIB) - cmake_parse_arguments(ARG "SYNTHESIS" "OUTDIR;TOP_MODULE;SKIPLIST_FILE" "" ${ARGN}) - if(ARG_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") - endif() - - include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../hwip.cmake") - - alias_dereference(IP_LIB ${IP_LIB}) - - if(NOT ARG_OUTDIR) - set(OUTDIR ${CMAKE_BINARY_DIR}/ip_sources) - else() - set(OUTDIR ${ARG_OUTDIR}) - endif() - - # Check if a top module is provided. In this case only the modules in its hierarchy are kept - if(ARG_TOP_MODULE) - set(TOP_MODULE_ARG --top-module ${ARG_TOP_MODULE}) - endif() - - if(ARG_SKIPLIST_FILE) - set(SKIPLIST_ARG --skiplist ${ARG_SKIPLIST_FILE}) - endif() - - if(ARG_SYNTHESIS) - set(SYNTHESIS_ARG --synthesis) - endif() - - # Get the list of RTL sources - get_ip_sources(RTL_SOURCES ${IP_LIB} SYSTEMVERILOG VERILOG) - get_ip_include_directories(RTL_INCDIRS ${IP_LIB} SYSTEMVERILOG) - foreach(_i ${RTL_INCDIRS}) - set(INCDIR_ARG ${INCDIR_ARG} --include ${_i}) - endforeach() - - find_python3() - set(__CMD ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/copy_rtl_files.py - ${TOP_MODULE_ARG} ${SKIPLIST_ARG} ${SYNTHESIS_ARG} - --deps_dir ${FETCHCONTENT_BASE_DIR} - ${INCDIR_ARG} - --outdir ${OUTDIR} - ${RTL_SOURCES} - ) - - # # Call the Python script with the output directory and the RTL files - # set(STAMP_FILE "${CMAKE_BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") - # add_custom_command( - # OUTPUT ${STAMP_FILE} - # COMMAND ${__CMD} - # COMMAND /bin/sh -c date > ${STAMP_FILE} - # COMMENT "Copying RTL files to ${OUTDIR}" - # VERBATIM - # ) - - # Create a target to run the custom command - add_custom_target( - ${IP_LIB}_copy_rtl - ALL # This forces the target to be run every time as outputs are not known in advance - COMMAND ${__CMD} - COMMENT "Copying RTL files to ${OUTDIR}" - DEPENDS ${IP_LIB} ${STAMP_FILE} - VERBATIM - ) - -endfunction() diff --git a/cmake/utils/copy_rtl_files/copy_rtl_files.py b/cmake/utils/copy_rtl_files/copy_rtl_files.py deleted file mode 100644 index ff49abd9..00000000 --- a/cmake/utils/copy_rtl_files/copy_rtl_files.py +++ /dev/null @@ -1,106 +0,0 @@ -import argparse -import shutil -import subprocess -import os -import sys - -def make_parser(): - parser = argparse.ArgumentParser(description="Filter RTL files based on module hierarchy.") - parser.add_argument("--top-module", dest="top_module", action="store", help="Specify top module name") - parser.add_argument("--skiplist", dest="skiplist", action="store", help="Optional list of modules to skip") - parser.add_argument("--synthesis", dest="synthesis", action="store_true", help="Define SYNTHESIS") - parser.add_argument("--deps_dir", dest="deps_dir", action="store", default="", help="Base directory of the dependencies") - parser.add_argument("--include", dest="inc_dirs", action='append', type=str, help="Directories where to look for include files") - parser.add_argument('--outdir', dest='outdir', action='store', default='.', help='Output directory where files will be copied') - parser.add_argument('sources', metavar='FILE', nargs='+', type=str, help='List of RTL file paths') - return parser - - -def main(): - parser = make_parser() - args = parser.parse_args() - - # Check if vhier is available - try: - vhier = shutil.which('vhier') - if vhier is None: - raise FileNotFoundError - except FileNotFoundError: - print("Error: 'vhier' executable not found", file=sys.stderr) - - # Initialize the output list with all the packages, - # because they're not retained by vhier - output_src = [f for f in args.sources if "_pkg" in f] - - # Set common vhier arguments - top_module = ('--top-module', args.top_module) if args.top_module is not None else () - skiplist = ('--skiplist', args.skiplist) if args.skiplist is not None else () - synthesis = ('--synthesis',) if args.synthesis is not None else () - vhier_base_args = [ - vhier, - '--no-missing', - *top_module, - *skiplist, - *synthesis, - *[f'+incdir+{i}' for i in args.inc_dirs], - *args.sources, - ] - - # Get the used files list from vhier - try: - cells_output = subprocess.run([*vhier_base_args, '--cells'], capture_output=True, check=True) - except subprocess.CalledProcessError as e: - print(f"Fatal: error({e.returncode}): {e.stderr.decode('ascii')}", file=sys.stderr) - raise - - output_src.extend(sorted(set([f.decode() for f in cells_output.stdout.split()]))) - - # Check if the output directory exists - if os.path.isdir(args.outdir): - # Clean everything inside if it exists - for filename in os.listdir(args.outdir): - file_path = os.path.join(args.outdir, filename) - try: - if os.path.isfile(file_path) or os.path.islink(file_path): - os.unlink(file_path) - elif os.path.isdir(file_path): - shutil.rmtree(file_path) - except Exception as e: - print('Failed to delete %s. Reason: %s' % (file_path, e)) - else: - # Create the directory - os.makedirs(args.outdir, exist_ok=False) - - # Copy files to output directory - copied_src = [] - for i in output_src: - if args.deps_dir in i: - dest_dir = os.path.join(args.outdir, i.replace(args.deps_dir, '').split('/')[1].rsplit('-', 1)[0]) - else: - dest_dir = args.outdir - os.makedirs(dest_dir, exist_ok=True) - copied_src.append(shutil.copy2(i, dest_dir)) - - # Write copied files list to outdir - with open(os.path.join(args.outdir, 'rtl_sources.f'), 'w') as outfile: - for file_path in copied_src: - # Keep only the relative path not to be user dependent - outfile.write(f'{os.path.relpath(file_path, args.outdir)}\n') - - # Get the includes list from vhier - try: - includes_output = subprocess.run([*vhier_base_args, '--includes'], capture_output=True, check=True) - except subprocess.CalledProcessError as e: - print(f"Fatal: error({e.returncode}): {e.stderr.decode('ascii')}", file=sys.stderr) - raise - - output_inc = sorted(set([f.decode() for f in includes_output.stdout.split()])) - - # Copy the include files in a include folder - dest_dir = os.path.join(args.outdir, 'include') - os.makedirs(dest_dir, exist_ok=True) - for i in output_inc: - shutil.copy2(i, dest_dir) - -if __name__ == "__main__": - main() diff --git a/cmake/utils/copy_rtl_files/vhier.cmake b/cmake/utils/copy_rtl_files/vhier.cmake deleted file mode 100644 index 2dbd9682..00000000 --- a/cmake/utils/copy_rtl_files/vhier.cmake +++ /dev/null @@ -1,54 +0,0 @@ -function(vhier IP_LIB) - cmake_parse_arguments(ARG "XML;FILES;MODULES;FOREST" "TOP_MODULE" "" ${ARGN}) - if(ARG_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") - endif() - - include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../hwip.cmake") - alias_dereference(IP_LIB ${IP_LIB}) - - get_target_property(IP_NAME ${IP_LIB} IP_NAME) - - get_ip_sources(RTL_SOURCES ${IP_LIB} SYSTEMVERILOG VERILOG) - get_ip_include_directories(INCDIRS ${IP_LIB} SYSTEMVERILOG VERILOG) - foreach(_i ${INCDIRS}) - set(INCDIR_ARG ${INCDIR_ARG} -y ${_i}) - endforeach() - - get_ip_compile_definitions(COMP_DEFS ${IP_LIB} SYSTEMVERILOG VERILOG) - foreach(_d ${COMP_DEFS}) - set(COMPDEF_ARG ${COMPDEF_ARG} -D${_d}) - endforeach() - - find_program(VHIER_EXECUTABLE vhier) - set(__CMD ${VHIER_EXECUTABLE} - --top-module $,${ARG_TOP_MODULE},${IP_NAME}> - ${RTL_SOURCES} - ${INCDIR_ARG} - ${COMPDEF_ARG} - $<$:--xml> - $<$:--module-files> - $<$:--modules> - $<$:--forest> - ) - - set(DESCRIPTION "Extract verilog hierarchy of ${IP_LIB} with ${CMAKE_CURRENT_FUNCTION}") - - set(OUT_FILE ${CMAKE_BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.$,xml,txt>) - set(STAMP_FILE "${CMAKE_BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") - add_custom_command( - OUTPUT ${STAMP_FILE} ${OUT_FILE} - COMMAND touch ${STAMP_FILE} - COMMAND ${__CMD} | tee ${OUT_FILE} - DEPENDS ${RTL_SOURCES} ${IP_LIB} - COMMENT ${DESCRIPTION} - ) - - add_custom_target( - ${IP_LIB}_${CMAKE_CURRENT_FUNCTION} - DEPENDS ${IP_LIB} ${STAMP_FILE} ${OUT_FILE} - ) - - set_property(TARGET ${IP_LIB}_${CMAKE_CURRENT_FUNCTION} PROPERTY DESCRIPTION ${DESCRIPTION}) -endfunction() - diff --git a/cmake/utils/generate_sources_list/generate_sources_list.cmake b/cmake/utils/generate_sources_list/generate_sources_list.cmake new file mode 100644 index 00000000..07e2eede --- /dev/null +++ b/cmake/utils/generate_sources_list/generate_sources_list.cmake @@ -0,0 +1,98 @@ +#[[[ +# Generates a filtered and organized list of RTL (Register Transfer Level) source files for a specified IP library target. +# +# This function collects all relevant RTL source files (excluding simulation, testbench, and FPGA-specific files) associated +# with the given ~IP_LIB~ target. It produces a file containing: +# * All source files required for synthesis, preserving their directory hierarchy. +# * All include directories and files needed for compilation. +# * Only the files instantiated in the design hierarchy, as determined by the `slang` tool. +# +# The hierarchy is parsed using `slang` (https://github.com/MikePopoloski/slang), ensuring that only the necessary +# files for the specified top module (if provided) and its dependencies are included. +# +# :param IP_LIB: Name of the IP library target to analyze. +# :type IP_LIB: string +# +# **Keyword Arguments** +# :keyword OUTDIR: (Optional) Output directory for the generated file lists. Defaults to ${CMAKE_BINARY_DIR}/ip_sources +# :type OUTDIR: string +# :keyword TOP_MODULE: (Optional) Name of the top module to use as the root of the hierarchy. Only modules below this point are included. An error is reported if the specified module does not exist. +# :type TOP_MODULE: string +# :keyword SLANG_ARGS: (Optional) Extra arguments to pass directly to slang. +# :type SLANG_ARGS: list +#]] +function(generate_sources_list IP_LIB) + cmake_parse_arguments(ARG "" "OUTDIR;TOP_MODULE;SLANG_ARGS" "" ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") + endif() + + # Find slang executable + find_program(SLANG_EXECUTABLE slang) + if(NOT SLANG_EXECUTABLE) + message(FATAL_ERROR "slang executable not found! Please install slang or set SLANG_EXECUTABLE.") + endif() + + # Initialize variables + set(INCDIR_ARG) + set(TOP_MODULE_ARG) + set(USER_SLANG_ARGS) + + include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../hwip.cmake") + alias_dereference(IP_LIB ${IP_LIB}) + + if(NOT ARG_OUTDIR) + set(OUTDIR ${CMAKE_BINARY_DIR}/ip_sources) + else() + set(OUTDIR ${ARG_OUTDIR}) + endif() + + # If a top module is provided, only modules in its hierarchy are included. + if(ARG_TOP_MODULE) + list(APPEND TOP_MODULE_ARG --top ${ARG_TOP_MODULE}) + endif() + + # Get the list of RTL sources + get_ip_sources(RTL_SOURCES ${IP_LIB} SYSTEMVERILOG VERILOG) + get_ip_include_directories(RTL_INCDIRS ${IP_LIB} SYSTEMVERILOG) + foreach(_i ${RTL_INCDIRS}) + list(APPEND INCDIR_ARG -I${_i}) + endforeach() + + if(ARG_SLANG_ARGS) + list(APPEND USER_SLANG_ARGS ${ARG_SLANG_ARGS}) + endif() + + set(RTL_FILE ${OUTDIR}/rtl_sources.f) + set(INCLUDE_FILE ${OUTDIR}/include_sources.f) + file(MAKE_DIRECTORY ${OUTDIR}) + + set(SLANG_CMD + ${SLANG_EXECUTABLE} + --depfile-trim --Mmodule ${RTL_FILE} --Minclude ${INCLUDE_FILE} + ${TOP_MODULE_ARG} + ${INCDIR_ARG} + ${USER_SLANG_ARGS} + ${RTL_SOURCES} + ) + + get_ip_links(DEPENDENT_TARGETS ${IP_LIB}) + + add_custom_command( + OUTPUT ${RTL_FILE} ${INCLUDE_FILE} + COMMAND ${SLANG_CMD} + DEPENDS ${DEPENDENT_TARGETS} ${RTL_SOURCES} + COMMENT "Generating list of the RTL source files in ${OUTDIR}" + VERBATIM + ) + + add_custom_target( + ${IP_LIB}_source_list + DEPENDS ${RTL_FILE} ${INCLUDE_FILE} + COMMENT "Target for generating filtered RTL source list for ${IP_LIB}" + VERBATIM + ) + + message(STATUS "To generate RTL source list for ${IP_LIB}, build the target: ${IP_LIB}_source_list") + +endfunction() diff --git a/cmake/utils/copy_rtl_files/read_rtl_sources.cmake b/cmake/utils/generate_sources_list/read_rtl_sources.cmake similarity index 100% rename from cmake/utils/copy_rtl_files/read_rtl_sources.cmake rename to cmake/utils/generate_sources_list/read_rtl_sources.cmake diff --git a/tests/tests/CMakeLists.txt b/tests/tests/CMakeLists.txt index 2dd24372..cf652c59 100644 --- a/tests/tests/CMakeLists.txt +++ b/tests/tests/CMakeLists.txt @@ -14,7 +14,6 @@ add_custom_target(check_cdash ) add_subdirectory(iverilog) -add_subdirectory(vhier) add_subdirectory(peakrdl) include("getcmaketest.cmake") diff --git a/tests/tests/vhier/CMakeLists.txt b/tests/tests/vhier/CMakeLists.txt deleted file mode 100644 index 28923830..00000000 --- a/tests/tests/vhier/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -include("../../../SoCMakeConfig.cmake") - -cmake_minimum_required(VERSION 3.25) -project(vhier_test) - -add_subdirectory("ips/mod1") - -add_ip(top - VENDOR test - LIBRARY ip - VERSION 0.0.1 - ) - -ip_sources(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl/top.sv - ) - -ip_include_directories(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl - ) - -ip_link(${IP} test::ip::mod1) - -vhier(${IP} FILES MODULES XML) - -include(CTest) - -add_test(NAME ${PROJECT_NAME} - COMMAND /bin/bash -c "make ${IP}_vhier && sed -i 's#${CMAKE_CURRENT_LIST_DIR}/##g' ${CMAKE_BINARY_DIR}/${IP}_vhier.xml && diff ${CMAKE_BINARY_DIR}/${IP}_vhier.xml ${CMAKE_CURRENT_LIST_DIR}/golden.xml" - # Need to do sed to make relative file paths, because of the golden.xml that was generated (and sed) on my filesystem, in CI it would be different - ) diff --git a/tests/tests/vhier/golden.xml b/tests/tests/vhier/golden.xml deleted file mode 100644 index fa685dce..00000000 --- a/tests/tests/vhier/golden.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - rtl/top.sv - ips/mod1/rtl/mod1.sv - ips/mod1/ips/submod1/rtl/submod1.sv - - diff --git a/tests/tests/vhier/ips/mod1/CMakeLists.txt b/tests/tests/vhier/ips/mod1/CMakeLists.txt deleted file mode 100644 index 57c48bc9..00000000 --- a/tests/tests/vhier/ips/mod1/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -add_ip(mod1 - VENDOR test - LIBRARY ip - VERSION 0.0.1 - ) - -add_subdirectory("./ips/submod1/") -add_subdirectory("./ips/submod2/") - -ip_sources(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl/mod1.sv - ) - -ip_include_directories(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl - ) - -ip_link(${IP} test::ip::submod1 test::ip::submod2) diff --git a/tests/tests/vhier/ips/mod1/ips/submod1/CMakeLists.txt b/tests/tests/vhier/ips/mod1/ips/submod1/CMakeLists.txt deleted file mode 100644 index 30df0d68..00000000 --- a/tests/tests/vhier/ips/mod1/ips/submod1/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_ip(submod1 - VENDOR test - LIBRARY ip - VERSION 0.0.1 - ) - -ip_sources(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl/submod1.sv - ) - -ip_include_directories(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl - ) diff --git a/tests/tests/vhier/ips/mod1/ips/submod1/rtl/submod1.sv b/tests/tests/vhier/ips/mod1/ips/submod1/rtl/submod1.sv deleted file mode 100644 index 2d6a785f..00000000 --- a/tests/tests/vhier/ips/mod1/ips/submod1/rtl/submod1.sv +++ /dev/null @@ -1,4 +0,0 @@ -module submod1; - -endmodule; - diff --git a/tests/tests/vhier/ips/mod1/ips/submod2/CMakeLists.txt b/tests/tests/vhier/ips/mod1/ips/submod2/CMakeLists.txt deleted file mode 100644 index 58890c34..00000000 --- a/tests/tests/vhier/ips/mod1/ips/submod2/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_ip(submod2 - VENDOR test - LIBRARY ip - VERSION 0.0.1 - ) - -ip_sources(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl/submod2.sv - ) - -ip_include_directories(${IP} SYSTEMVERILOG - ${CMAKE_CURRENT_LIST_DIR}/rtl - ) diff --git a/tests/tests/vhier/ips/mod1/ips/submod2/rtl/submod2.sv b/tests/tests/vhier/ips/mod1/ips/submod2/rtl/submod2.sv deleted file mode 100644 index 69f861f0..00000000 --- a/tests/tests/vhier/ips/mod1/ips/submod2/rtl/submod2.sv +++ /dev/null @@ -1,5 +0,0 @@ -module submod2; - -endmodule; - - diff --git a/tests/tests/vhier/ips/mod1/rtl/mod1.sv b/tests/tests/vhier/ips/mod1/rtl/mod1.sv deleted file mode 100644 index dbac705a..00000000 --- a/tests/tests/vhier/ips/mod1/rtl/mod1.sv +++ /dev/null @@ -1,5 +0,0 @@ -module mod1; - - submod1 submod1_i(); - -endmodule; diff --git a/tests/tests/vhier/rtl/top.sv b/tests/tests/vhier/rtl/top.sv deleted file mode 100644 index a3c0d65c..00000000 --- a/tests/tests/vhier/rtl/top.sv +++ /dev/null @@ -1,5 +0,0 @@ -module top; - - mod1 mod1_i(); - -endmodule;