diff --git a/SoCMakeConfig.cmake b/SoCMakeConfig.cmake index 2ed12d3..a200e0e 100644 --- a/SoCMakeConfig.cmake +++ b/SoCMakeConfig.cmake @@ -40,6 +40,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/sim/verisc/verisc_install.cmake") # ==================================== include("${CMAKE_CURRENT_LIST_DIR}/cmake/peakrdl/peakrdl_regblock.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/peakrdl/peakrdl_regblock_wrap.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/peakrdl/peakrdl_halcpp.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/peakrdl/peakrdl_ipblocksvg.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/peakrdl/peakrdl_html/peakrdl_html.cmake") diff --git a/cmake/peakrdl/peakrdl_regblock_wrap.cmake b/cmake/peakrdl/peakrdl_regblock_wrap.cmake new file mode 100644 index 0000000..58fbe9b --- /dev/null +++ b/cmake/peakrdl/peakrdl_regblock_wrap.cmake @@ -0,0 +1,88 @@ +function(peakrdl_regblock_wrap IP_LIB) + # Parse keyword arguments + cmake_parse_arguments(ARG "TMR" "OUTDIR;RENAME;INTF" "" ${ARGN}) + # Check for any unknown argument + 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") + include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../utils/find_python.cmake") + + ip_assume_last(IP_LIB ${IP_LIB}) + get_target_property(BINARY_DIR ${IP_LIB} BINARY_DIR) + + # Default output directory is regblock/ + if(NOT ARG_OUTDIR) + if(NOT ARG_TMR) + set(OUTDIR ${BINARY_DIR}/regblock) + else() + set(OUTDIR ${BINARY_DIR}/regblock_tmr) + endif() + else() + set(OUTDIR ${ARG_OUTDIR}) + endif() + + if(NOT ARG_RENAME) + # The default name is the IP name + get_target_property(IP_NAME ${IP_LIB} IP_NAME) + else() + set(IP_NAME ${ARG_RENAME}) + endif() + + # The default interface used is apb3, set another on if the argument exists + if(ARG_INTF) + set(INTF_ARG --cpuif ${ARG_INTF}) + endif() + # Get the SystemRDL sources to generate the register block + # This function gets the IP sources and the deps + get_ip_sources(RDL_SOURCES ${IP_LIB} SYSTEMRDL) + + if(NOT RDL_SOURCES) + message(FATAL_ERROR "Library ${IP_LIB} does not have SYSTEMRDL_SOURCES property set, + unable to run ${CMAKE_CURRENT_FUNCTION}") + endif() + + # Generate the regblock and wrapper + find_python3() + if(ARG_TMR) + set(TMR_OPT "--tmr") + endif() + set(__CMD ${Python3_EXECUTABLE} -m peakrdl regblock_wrap + ${TMR_OPT} + # --rename ${IP_NAME} + # ${INTF_ARG} + -o ${OUTDIR} + ${RDL_SOURCES} + ) + + set(REGBLOCK_SV_GEN ${OUTDIR}/${IP_NAME}_regblock_pkg.sv ${OUTDIR}/${IP_NAME}_regblock.sv) + set(WRAP_SV_GEN ${OUTDIR}/${IP_NAME}.sv) + set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") + + add_custom_command( + # The output files are automtically marked as GENERATED (deleted by make clean among other things) + OUTPUT ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN} ${STAMP_FILE} + COMMAND ${__CMD} + COMMAND touch ${STAMP_FILE} + DEPENDS ${RDL_SOURCES} + COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" + ) + + # This target triggers the systemverilog register block generation using peakRDL regblock tool (_CMD) + set(TNAME ${IP_LIB}_regblock_wrap) + add_custom_target( + ${TNAME} + DEPENDS ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN} ${STAMP_FILE} + ) + ip_sources(${IP_LIB} SYSTEMVERILOG PREPEND ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN}) + + if(ARG_TMR) + set_tmrg_sources(${IP_LIB} ${REGBLOCK_SV_GEN}) + set_sv2v_sources(${IP_LIB} ${REGBLOCK_SV_GEN}) + else() + add_dependencies(${IP_LIB} ${TNAME}) + endif() +endfunction() + diff --git a/cmake/synth/hwif_sed.sh b/cmake/synth/hwif_sed.sh new file mode 100755 index 0000000..6e2c173 --- /dev/null +++ b/cmake/synth/hwif_sed.sh @@ -0,0 +1,6 @@ +#! /bin/bash + +width_in=$(grep -E 'wire.*hwif_in' $1 | cut -d '[' -f2 | cut -d ']' -f1) +width_out=$(grep -E 'wire.*hwif_out' $1 | cut -d '[' -f2 | cut -d ']' -f1) +sed -i "s/TO_CHANGE_HWIF_IN/$width_in/" $2 +sed -i "s/TO_CHANGE_HWIF_OUT/$width_out/" $2 diff --git a/cmake/synth/sv2v.cmake b/cmake/synth/sv2v.cmake index bad131a..dbfaddd 100644 --- a/cmake/synth/sv2v.cmake +++ b/cmake/synth/sv2v.cmake @@ -1,14 +1,34 @@ # TODO iterate over linked libraries and replace SYSTEMVERILOG_SOURCES with VERILOG_SOURCES instead include_guard(GLOBAL) +function(set_sv2v_sources IP_LIB) + cmake_parse_arguments(ARG "" "" "" ${ARGN}) + + # If only IP name is given without full VLNV, assume rest from the project variables + ip_assume_last(_reallib ${IP_LIB}) + + # Get any prior TMRG sources + get_sv2v_sources(_sv2v_src ${IP_LIB}) + + set(_sv2v_src ${_sv2v_src} ${ARGN}) + # Set the target property with the new list of source files + set_property(TARGET ${_reallib} PROPERTY SV2V ${_sv2v_src}) +endfunction() + +function(get_sv2v_sources OUT_VAR IP_LIB) + # If only IP name is given without full VLNV, assume rest from the project variables + ip_assume_last(IP_LIB ${IP_LIB}) + get_ip_property(SV2V_SRC ${IP_LIB} SV2V) + list(REMOVE_DUPLICATES SV2V_SRC) + set(${OUT_VAR} ${SV2V_SRC} PARENT_SCOPE) +endfunction() + function(sv2v IP_LIB) - cmake_parse_arguments(ARG "REPLACE" "OUTDIR" "" ${ARGN}) + cmake_parse_arguments(ARG "REPLACE;TMR;HWIF_WIRE" "OUTDIR" "" ${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") - ip_assume_last(IP_LIB ${IP_LIB}) get_target_property(BINARY_DIR ${IP_LIB} BINARY_DIR) @@ -19,14 +39,18 @@ function(sv2v IP_LIB) endif() execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTDIR}) - get_ip_sources(V_SOURCES ${IP_LIB} VERILOG) # TODO make merge source files group function - get_ip_sources(SOURCES ${IP_LIB} SYSTEMVERILOG) - list(PREPEND SOURCES ${V_SOURCES}) + get_sv2v_sources(SV2V_SRC ${IP_LIB}) + foreach(vfile ${SV2V_SRC}) + get_filename_component(V_SOURCE_WO_EXT ${vfile} NAME_WE) + if(NOT ${V_SOURCE_WO_EXT} MATCHES ".*regblock_pkg$") + list(APPEND V_GEN "${OUTDIR}/${V_SOURCE_WO_EXT}.v") + endif() + endforeach() + set_source_files_properties(${V_GEN} PROPERTIES GENERATED TRUE) get_ip_include_directories(SYSTEMVERILOG_INCLUDE_DIRS ${IP_LIB} SYSTEMVERILOG) get_ip_include_directories(VERILOG_INCLUDE_DIRS ${IP_LIB} VERILOG) set(INCDIRS ${SYSTEMVERILOG_INCLUDE_DIRS} ${VERILOG_INCLUDE_DIRS}) - foreach(dir ${INCDIRS}) list(APPEND INCDIR_ARG -I${dir}) endforeach() @@ -38,31 +62,63 @@ function(sv2v IP_LIB) list(APPEND CMP_DEFS_ARG -D${def}) endforeach() - set(V_GEN ${OUTDIR}/${IP_LIB}.v) - - set_source_files_properties(${V_GEN} PROPERTIES GENERATED TRUE) + # HACK ALERT!! + if(ARG_HWIF_WIRE) + get_target_property(TOP_MODULE ${IP_LIB} IP_NAME) + set(SED_COMMAND + COMMAND ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hwif_sed.sh ${OUTDIR}/${TOP_MODULE}_regblock.v ${OUTDIR}/../regblock/${TOP_MODULE}.sv + ) + endif() set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") add_custom_command( OUTPUT ${STAMP_FILE} ${V_GEN} - COMMAND sv2v - ${SOURCES} ${INCDIR_ARG} ${CMP_DEFS_ARG} - -w ${V_GEN} - + COMMAND sv2v ${SV2V_SRC} ${INCDIR_ARG} ${CMP_DEFS_ARG} -w ${OUTDIR} + ${SED_COMMAND} COMMAND touch ${STAMP_FILE} - DEPENDS ${SOURCES} + DEPENDS ${SV2V_SRC} COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" - ) + ) add_custom_target( ${IP_LIB}_${CMAKE_CURRENT_FUNCTION} - DEPENDS ${STAMP_FILE} ${SOURCES} ${V_GEN} - ) + DEPENDS ${STAMP_FILE} ${SV2V_SRC} ${V_GEN} + ) if(ARG_REPLACE) - set_property(TARGET ${IP_LIB} PROPERTY VERILOG_SOURCES ${V_GEN}) - set_property(TARGET ${IP_LIB} PROPERTY SYSTEMVERILOG_SOURCES "") - add_dependencies(${IP_LIB} ${IP_LIB}_${CMAKE_CURRENT_FUNCTION}) + # Get original sources + get_ip_sources(SV_SRC ${IP_LIB} SYSTEMVERILOG) + get_ip_sources(V_SRC ${IP_LIB} VERILOG) + + # Remove SV2V files from original sources + list(REMOVE_ITEM SV_SRC ${SV2V_SRC}) + list(REMOVE_ITEM V_SRC ${SV2V_SRC}) + + # Append generated files to Verilog source lists + list(APPEND V_SRC ${V_GEN}) + + # Set the file list properties + set_property(TARGET ${IP_LIB} PROPERTY SYSTEMVERILOG_SOURCES ${SV_SRC}) + set_property(TARGET ${IP_LIB} PROPERTY VERILOG_SOURCES ${V_SRC}) + + # If TMR is set, remove original .sv files from TMRG list and replace with .v outputs + if(ARG_TMR) + get_tmrg_sources(TMRG_SRC ${IP_LIB}) + foreach(i ${SV2V_SRC}) + if(i IN_LIST TMRG_SRC) + list(REMOVE_ITEM TMRG_SRC ${i}) + get_filename_component(V_SOURCE_WO_EXT ${i} NAME_WE) + set(_i_v "${OUTDIR}/${V_SOURCE_WO_EXT}.v") + if(_i_v IN_LIST V_GEN) + list(APPEND TMRG_SRC ${_i_v}) + endif() + endif() + endforeach() + set_property(TARGET ${IP_LIB} PROPERTY TMRG ${TMRG_SRC}) + else() + # Add dependency to the IP + add_dependencies(${IP_LIB} ${IP_LIB}_${CMAKE_CURRENT_FUNCTION}) + endif() endif() endfunction() diff --git a/cmake/tmrg/tmrg/tmrg.cmake b/cmake/tmrg/tmrg/tmrg.cmake index 9d4ad08..eb0a96b 100644 --- a/cmake/tmrg/tmrg/tmrg.cmake +++ b/cmake/tmrg/tmrg/tmrg.cmake @@ -1,16 +1,34 @@ -# TODO iterate over linked libraries and replace SYSTEMVERILOG_SOURCES with VERILOG_SOURCES instead -# TODO create a new library instead??? include_guard(GLOBAL) +function(set_tmrg_sources IP_LIB) + cmake_parse_arguments(ARG "" "" "" ${ARGN}) + + # If only IP name is given without full VLNV, assume rest from the project variables + ip_assume_last(_reallib ${IP_LIB}) + + # Get any prior TMRG sources + get_tmrg_sources(_tmrg_src ${IP_LIB}) + + set(_tmrg_src ${_tmrg_src} ${ARGN}) + # Set the target property with the new list of source files + set_property(TARGET ${_reallib} PROPERTY TMRG ${_tmrg_src}) +endfunction() + +function(get_tmrg_sources OUT_VAR IP_LIB) + # If only IP name is given without full VLNV, assume rest from the project variables + ip_assume_last(IP_LIB ${IP_LIB}) + get_ip_property(TMRG_SRC ${IP_LIB} TMRG) + list(REMOVE_DUPLICATES TMRG_SRC) + set(${OUT_VAR} ${TMRG_SRC} PARENT_SCOPE) +endfunction() + function(tmrg IP_LIB) - cmake_parse_arguments(ARG "REPLACE;SED_WOR;NO_COMMON_DEFINITIONS" "OUTDIR" "" ${ARGN}) + cmake_parse_arguments(ARG "REPLACE;SED_WOR;NO_COMMON_DEFINITIONS" "OUTDIR;CONFIG_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") - ip_assume_last(IP_LIB ${IP_LIB}) get_target_property(BINARY_DIR ${IP_LIB} BINARY_DIR) @@ -21,27 +39,30 @@ function(tmrg IP_LIB) endif() execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTDIR}) - get_ip_sources(V_SOURCES ${IP_LIB} VERILOG) # TODO make merge source files group function - get_ip_sources(SOURCES ${IP_LIB} SYSTEMVERILOG) - list(PREPEND SOURCES ${V_SOURCES}) - list(REMOVE_DUPLICATES SOURCES) + if(ARG_CONFIG_FILE) + set(ARG_CONFIG_FILE -c ${ARG_CONFIG_FILE}) + else() + unset(ARG_CONFIG_FILE) + endif() - foreach(vfile ${SOURCES}) + get_tmrg_sources(TMRG_SRC ${IP_LIB}) + foreach(vfile ${TMRG_SRC}) get_filename_component(V_SOURCE_WO_EXT ${vfile} NAME_WE) get_filename_component(V_SOURCE_EXT ${vfile} EXT) list(APPEND V_GEN "${OUTDIR}/${V_SOURCE_WO_EXT}TMR${V_SOURCE_EXT}") - # execute_process(COMMAND touch ${V_GEN}) # TODO Needed??? endforeach() set_source_files_properties(${V_GEN} PROPERTIES GENERATED TRUE) set(TMRG_COMMAND - tmrg --stats --tmr-dir=${OUTDIR} ${SOURCES}; - ) + ${Python3_VIRTUAL_ENV}/bin/tmrg --stats --tmr-dir=${OUTDIR} ${ARG_CONFIG_FILE} ${TMRG_SRC} + ) + + if(ARG_NO_COMMON_DEFINITIONS) + set(TMRG_COMMAND ${TMRG_COMMAND} --no-common-definitions) + endif() if(ARG_SED_WOR) - set(SED_COMMAND - COMMAND sed -i "s/wor/wire/g" ${V_GEN} - ) + set(SED_COMMAND COMMAND sed -i "s/wor/wire/g" ${V_GEN}) endif() set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") @@ -50,21 +71,43 @@ function(tmrg IP_LIB) COMMAND ${TMRG_COMMAND} ${SED_COMMAND} COMMAND touch ${STAMP_FILE} - DEPENDS ${SOURCES} + DEPENDS ${TMRG_SRC} COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" - ) + ) add_custom_target( ${IP_LIB}_${CMAKE_CURRENT_FUNCTION} - DEPENDS ${STAMP_FILE} ${SOURCES} ${V_GEN} - ) + DEPENDS ${STAMP_FILE} ${TMRG_SRC} ${V_GEN} + ) if(ARG_REPLACE) + # Replace top module name adding TMR get_target_property(TOP_MODULE ${IP_LIB} IP_NAME) set_property(TARGET ${IP_LIB} PROPERTY IP_NAME ${TOP_MODULE}TMR) - set_property(TARGET ${IP_LIB} PROPERTY VERILOG_SOURCES ${V_GEN}) - set_property(TARGET ${IP_LIB} PROPERTY SYSTEMVERILOG_SOURCES "") + # Get original sources + get_ip_sources(SV_SRC ${IP_LIB} SYSTEMVERILOG) + get_ip_sources(V_SRC ${IP_LIB} VERILOG) + + # Remove TMRG files from original sources + list(REMOVE_ITEM SV_SRC ${TMRG_SRC}) + list(REMOVE_ITEM V_SRC ${TMRG_SRC}) + + # Append generated files to correct source lists + foreach(i ${V_GEN}) + get_filename_component(FILE_EXT ${i} EXT) + if("${FILE_EXT}" STREQUAL ".sv") + list(APPEND SV_SRC ${i}) + elseif("${FILE_EXT}" STREQUAL ".v") + list(APPEND V_SRC ${i}) + endif() + endforeach() + + # Set the file list properties + set_property(TARGET ${IP_LIB} PROPERTY SYSTEMVERILOG_SOURCES ${SV_SRC}) + set_property(TARGET ${IP_LIB} PROPERTY VERILOG_SOURCES ${V_SRC}) + + # Add dependency to the IP add_dependencies(${IP_LIB} ${IP_LIB}_${CMAKE_CURRENT_FUNCTION}) endif()