| function(COMMON_VIVADO_TARGETS) | |
| # ~~~ | |
| # COMMON_VIVADO_TARGETS( | |
| # NAME <name> | |
| # WORK_DIR <working directory> | |
| # BITSTREAM <bitstream> | |
| # DEPS <dependency list> | |
| # [MAKE_DIFF_FASM] | |
| # ) | |
| # ~~~ | |
| # | |
| # Generates common Vivado targets for running Vivado tcl scripts to generate | |
| # the Vivado checkpoint and project, and creates the following dummy targets: | |
| # | |
| # - ${NAME}_load_dcp - Load generated checkpoint. This contains routing and | |
| # placement details. | |
| # - ${NAME}_load_xpr - Load generated project. This can be used for | |
| # behavioral simulation. | |
| # - ${NAME}_sim - Load project and launches simulation. | |
| # | |
| # The MAKE_DIFF_FASM option generates a diff between the input BITSTREAM | |
| # and the output from Vivado, and attaches that diff generation to | |
| # "all_xc7_diff_fasm" which can used to verify FASM. | |
| # | |
| set(options MAKE_DIFF_FASM) | |
| set(oneValueArgs NAME PRJRAY_DIR PRJRAY_DB_DIR WORK_DIR BITSTREAM) | |
| set(multiValueArgs DEPS) | |
| cmake_parse_arguments( | |
| COMMON_VIVADO_TARGETS | |
| "${options}" | |
| "${oneValueArgs}" | |
| "${multiValueArgs}" | |
| ${ARGN} | |
| ) | |
| get_target_property_required(PYTHON3 env PYTHON3) | |
| get_target_property_required(BITREAD env BITREAD) | |
| set(NAME ${COMMON_VIVADO_TARGETS_NAME}) | |
| set(WORK_DIR ${COMMON_VIVADO_TARGETS_WORK_DIR}) | |
| set(PRJRAY_DIR ${COMMON_VIVADO_TARGETS_PRJRAY_DIR}) | |
| set(PRJRAY_DB_DIR ${COMMON_VIVADO_TARGETS_PRJRAY_DB_DIR}) | |
| set(DEPS ${COMMON_VIVADO_TARGETS_DEPS}) | |
| set(BITSTREAM ${COMMON_VIVADO_TARGETS_BITSTREAM}) | |
| add_custom_command( | |
| OUTPUT | |
| ${WORK_DIR}/design_${NAME}.dcp | |
| ${WORK_DIR}/design_${NAME}.xpr | |
| ${WORK_DIR}/design_${NAME}.bit | |
| ${WORK_DIR}/design_${NAME}_utilization.rpt | |
| ${WORK_DIR}/design_${NAME}_clock_utilization.rpt | |
| ${WORK_DIR}/design_${NAME}_power.rpt | |
| ${WORK_DIR}/design_${NAME}_timing_summary.rpt | |
| ${WORK_DIR}/design_${NAME}_route_status.rpt | |
| COMMAND ${CMAKE_COMMAND} -E remove -f ${WORK_DIR}/design_${NAME}.dcp | |
| COMMAND ${CMAKE_COMMAND} -E remove -f ${WORK_DIR}/design_${NAME}.xpr | |
| COMMAND ${PRJRAY_DIR}/utils/vivado.sh -mode batch -source | |
| ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_runme.tcl | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/vivado.stdout.log | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS ${DEPS} ${NAME}_runme.tcl | |
| ) | |
| add_custom_target( | |
| ${NAME}_load_dcp | |
| COMMAND ${PRJRAY_DIR}/utils/vivado.sh design_${NAME}.dcp | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS ${WORK_DIR}/design_${NAME}.dcp | |
| ) | |
| add_custom_target( | |
| ${NAME}_load_xpr | |
| COMMAND ${PRJRAY_DIR}/utils/vivado.sh design_${NAME}.xpr | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS ${WORK_DIR}/design_${NAME}.xpr | |
| ) | |
| add_custom_target( | |
| ${NAME}_sim | |
| COMMAND ${PRJRAY_DIR}/utils/vivado.sh | |
| design_${NAME}.xpr -source ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_sim.tcl | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS ${WORK_DIR}/design_${NAME}.xpr ${NAME}_sim.tcl | |
| ) | |
| set(CLEAN_JSON5 ${symbiflow-arch-defs_SOURCE_DIR}/utils/clean_json5.py) | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR}/timing_${NAME}.json | |
| COMMAND ${PRJRAY_DIR}/utils/vivado.sh | |
| design_${NAME}.dcp | |
| -mode batch | |
| -source | |
| ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/output_timing.tcl | |
| -tclargs | |
| ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/timing_utils.tcl | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/timing_${NAME}.json5 | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/vivado_timing.stdout.log | |
| COMMAND ${PYTHON3} ${CLEAN_JSON5} | |
| < ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/timing_${NAME}.json5 | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/timing_${NAME}.json | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS | |
| ${WORK_DIR}/design_${NAME}.dcp | |
| ${PYTHON3} | |
| ) | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR}/design_${NAME}.bit.fasm | |
| COMMAND | |
| ${CMAKE_COMMAND} -E env PYTHONPATH=${PRJRAY_DIR}:${PRJRAY_DIR}/third_party/fasm | |
| ${PYTHON3} ${PRJRAY_DIR}/utils/bit2fasm.py | |
| --part ${PART} | |
| --db-root ${PRJRAY_DB_DIR}/${PRJRAY_ARCH} | |
| --bitread ${BITREAD} | |
| --verbose | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/design_${NAME}.bit | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/design_${NAME}.bit.fasm | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS | |
| ${PYTHON3} | |
| ${WORK_DIR}/design_${NAME}.bit | |
| ) | |
| get_file_location(BITSTREAM_LOCATION ${BITSTREAM}) | |
| append_file_dependency(DEPS ${BITSTREAM}) | |
| add_custom_target(${NAME} DEPENDS ${WORK_DIR}/design_${NAME}.dcp) | |
| add_custom_target(${NAME}_timing DEPENDS ${WORK_DIR}/timing_${NAME}.json) | |
| add_custom_target(${NAME}_fasm DEPENDS ${WORK_DIR}/design_${NAME}.bit.fasm) | |
| if(${COMMON_VIVADO_TARGETS_MAKE_DIFF_FASM}) | |
| add_custom_target(${NAME}_diff_fasm | |
| COMMAND diff -u | |
| ${BITSTREAM_LOCATION}.fasm | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/design_${NAME}.bit.fasm | |
| DEPENDS | |
| ${DEPS} | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/design_${NAME}.bit.fasm | |
| ) | |
| endif() | |
| endfunction() | |
| function(ADD_VIVADO_TARGET) | |
| # ~~~ | |
| # ADD_VIVADO_TARGET( | |
| # NAME <name> | |
| # PARENT_NAME <name> | |
| # CLOCK_PINS list of clock pins | |
| # CLOCK_PERIODS list of clock periods | |
| # [XDC <xdc file>] | |
| # [DISABLE_DIFF_TEST] | |
| # ) | |
| # ~~~ | |
| # | |
| # ADD_VIVADO_TARGET generates a Vivado project and design checkpoint from | |
| # the output of a 7-series FPGA target. | |
| # | |
| # Inputs to Vivado are the output of the FASM to verilog process. | |
| # | |
| # PARENT_NAME is the name of the FPGA target being used as input for these | |
| # targets. | |
| # | |
| # CLOCK_PINS and CLOCK_PERIODS should be lists of the same length. | |
| # CLOCK_PERIODS should be in nanoseconds. | |
| # | |
| # XDC should be a filename with XDC commands to run prior to analysis. | |
| # | |
| # DISABLE_DIFF_TEST can be added to not add this target to all_xc7_diff_fasm. | |
| # | |
| # New targets: | |
| # <NAME>_load_dcp - Launch vivado loading post-routing design checkpoint. | |
| # <NAME>_load_xpr - Launch vivado loading project. | |
| # <NAME>_sim - Launch vivado and setup simulation and clock forces. | |
| set(options DISABLE_DIFF_TEST) | |
| set(oneValueArgs NAME PARENT_NAME XDC) | |
| set(multiValueArgs CLOCK_PINS CLOCK_PERIODS) | |
| cmake_parse_arguments( | |
| ADD_VIVADO_TARGET | |
| "${options}" | |
| "${oneValueArgs}" | |
| "${multiValueArgs}" | |
| ${ARGN} | |
| ) | |
| set(NAME ${ADD_VIVADO_TARGET_NAME}) | |
| if(NOT DEFINED ENV{XRAY_VIVADO_SETTINGS}) | |
| message( WARNING "Vivado targets for ${NAME} not emitted, XRAY_VIVADO_SETTINGS env var must be set to point to Vivado settings.sh" ) | |
| return() | |
| endif() | |
| get_target_property_required(BITSTREAM ${ADD_VIVADO_TARGET_PARENT_NAME} BIT) | |
| get_target_property_required(BIT_VERILOG ${ADD_VIVADO_TARGET_PARENT_NAME} BIT_V) | |
| get_target_property_required(TOP ${ADD_VIVADO_TARGET_PARENT_NAME} TOP) | |
| get_target_property_required(BOARD ${ADD_VIVADO_TARGET_PARENT_NAME} BOARD) | |
| get_target_property_required(DEVICE ${BOARD} DEVICE) | |
| get_target_property_required(ARCH ${DEVICE} ARCH) | |
| get_target_property_required(PRJRAY_ARCH ${ARCH} PRJRAY_ARCH) | |
| get_target_property_required(PART ${BOARD} PART) | |
| get_target_property_required(FAMILY ${ARCH} FAMILY) | |
| get_target_property_required(DOC_PRJ ${ARCH} DOC_PRJ) | |
| get_target_property_required(DOC_PRJ_DB ${ARCH} DOC_PRJ_DB) | |
| set(PRJRAY_DIR ${DOC_PRJ}) | |
| set(PRJRAY_DB_DIR ${DOC_PRJ_DB}) | |
| set(DEPS) | |
| append_file_dependency(DEPS ${BIT_VERILOG}) | |
| get_file_location(BIT_VERILOG_LOCATION ${BIT_VERILOG}) | |
| set(BIT_XDC_LOCATION ${BIT_VERILOG_LOCATION}.xdc) | |
| if(NOT "${ADD_VIVADO_TARGET_CLOCK_PINS}" STREQUAL "") | |
| list(LENGTH ${ADD_VIVADO_TARGET_CLOCK_PINS} NUM_CLOCKS) | |
| list(LENGTH ${ADD_VIVADO_TARGET_CLOCK_PERIODS} NUM_CLOCK_PERIODS) | |
| if(NOT ${NUM_CLOCKS} EQUAL ${NUM_CLOCK_PERIODS}) | |
| message( FATAL_ERROR "Number of clock pins (${NUM_CLOCKS}) must match number of periods (${NUM_CLOCK_PERIODS})") | |
| endif() | |
| set(CLOCK_ARGS --clock_pins "${ADD_VIVADO_TARGET_CLOCK_PINS}" --clock_periods "${ADD_VIVADO_TARGET_CLOCK_PERIODS}") | |
| elseif() | |
| set(CLOCK_ARGS "") | |
| endif() | |
| if(NOT "${ADD_VIVADO_TARGET_XDC}" STREQUAL "") | |
| append_file_dependency(DEPS ${ADD_VIVADO_TARGET_XDC}) | |
| get_file_location(XDC_LOCATION ${ADD_VIVADO_TARGET_XDC}) | |
| set(XDC_ARGS --additional_xdc "${XDC_LOCATION}") | |
| set(CREATE_DCP_ARGS XDC ${ADD_VIVADO_TARGET_XDC}) | |
| elseif() | |
| set(XDC_ARGS "") | |
| set(CREATE_DCP_ARGS "") | |
| endif() | |
| get_target_property_required(PYTHON3 env PYTHON3) | |
| set(CREATE_RUNME ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/vivado_create_runme.py) | |
| add_custom_command( | |
| OUTPUT ${NAME}_runme.tcl | |
| COMMAND ${PYTHON3} ${CREATE_RUNME} | |
| --name ${NAME} | |
| --verilog ${BIT_VERILOG_LOCATION} | |
| --routing_xdc ${BIT_XDC_LOCATION} | |
| --top ${TOP} | |
| --part ${PART} | |
| --output_tcl ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_runme.tcl | |
| ${CLOCK_ARGS} | |
| ${XDC_ARGS} | |
| DEPENDS | |
| ${PYTHON3} | |
| ${CREATE_RUNME} | |
| ) | |
| set(CREATE_SIM ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/vivado_create_sim.py) | |
| add_custom_command( | |
| OUTPUT ${NAME}_sim.tcl | |
| COMMAND ${PYTHON3} ${CREATE_SIM} | |
| --top ${TOP} | |
| --output_tcl ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_sim.tcl | |
| ${CLOCK_ARGS} | |
| DEPENDS | |
| ${PYTHON3} | |
| ${CREATE_SIM} | |
| ) | |
| # Run Vivado in the same directory as VPR was run, this ensures a unique | |
| # directory, and presents Vivado filename collisions. | |
| get_filename_component(WORK_DIR ${BIT_VERILOG} DIRECTORY) | |
| COMMON_VIVADO_TARGETS( | |
| NAME ${NAME} | |
| PRJRAY_DIR ${PRJRAY_DIR} | |
| PRJRAY_DB_DIR ${PRJRAY_DB_DIR} | |
| WORK_DIR ${WORK_DIR} | |
| DEPS ${DEPS} | |
| BITSTREAM ${BITSTREAM} | |
| MAKE_DIFF_FASM) | |
| get_target_property_required(RAPIDWRIGHT_INSTALLED rapidwright RAPIDWRIGHT_INSTALLED) | |
| if(${RAPIDWRIGHT_INSTALLED}) | |
| CREATE_DCP_BY_INTERCHANGE( | |
| NAME ${NAME}_interchange | |
| PARENT_NAME ${ADD_VIVADO_TARGET_PARENT_NAME} | |
| WORK_DIR ${WORK_DIR}/interchange | |
| ${CREATE_DCP_ARGS} | |
| ) | |
| endif() | |
| if(NOT ${ADD_VIVADO_TARGET_DISABLE_DIFF_TEST}) | |
| if(${ALL_XC7_DIFF_FASM_VERILOG}) | |
| if(${ALL_XC7_DIFF_FASM_CHECK_VERILOG}) | |
| add_dependencies(all_${ARCH}_diff_fasm ${NAME}_diff_fasm) | |
| else() | |
| add_dependencies(all_${ARCH}_diff_fasm ${NAME}_fasm) | |
| endif() | |
| endif() | |
| if(${RAPIDWRIGHT_INSTALLED} AND ${ALL_XC7_DIFF_FASM_INTERCHANGE}) | |
| add_dependencies(all_${ARCH}_diff_fasm ${NAME}_interchange_diff_fasm) | |
| endif() | |
| endif() | |
| endfunction() | |
| function(ADD_VIVADO_PNR_TARGET) | |
| # ~~~ | |
| # ADD_VIVADO_PNR_TARGET( | |
| # NAME <name> | |
| # PARENT_NAME <name> | |
| # CLOCK_PINS list of clock pins | |
| # CLOCK_PERIODS list of clock periods | |
| # [IOSTANDARD <iostandard>] | |
| # [XDC <xdc file>] | |
| # ) | |
| # ~~~ | |
| # | |
| # ADD_VIVADO_PNR_TARGET generates a Vivado project and design checkpoint from | |
| # the output of 7-series synthesis. | |
| # | |
| # Inputs to Vivado are the output verilog from the synthesis tool. | |
| # | |
| # PARENT_NAME is the name of the FPGA target being used as input for these | |
| # targets. | |
| # | |
| # CLOCK_PINS and CLOCK_PERIODS should be lists of the same length. | |
| # CLOCK_PERIODS should be in nanoseconds. | |
| # | |
| # Vivado requires pin constraints for all top-level IO. ADD_VIVADO_PNR_TARGET | |
| # can generate constrains for a fixed IOSTANDARD if the IOSTANDARD argument | |
| # is supplied. The XDC argument can be used if an existing constraint file | |
| # already exists. For consistency, the port location constraints in the XDC | |
| # file should match the PCF file used for VPR. | |
| # | |
| # New targets: | |
| # <NAME>_load_dcp - Launch vivado loading post-routing design checkpoint. | |
| # <NAME>_load_xpr - Launch vivado loading project. | |
| # <NAME>_sim - Launch vivado and setup simulation and clock forces. | |
| set(options) | |
| set(oneValueArgs NAME PARENT_NAME IOSTANDARD XDC) | |
| set(multiValueArgs CLOCK_PINS CLOCK_PERIODS) | |
| cmake_parse_arguments( | |
| ADD_VIVADO_PNR_TARGET | |
| "${options}" | |
| "${oneValueArgs}" | |
| "${multiValueArgs}" | |
| ${ARGN} | |
| ) | |
| set(NAME ${ADD_VIVADO_PNR_TARGET_NAME}) | |
| get_target_property_required(BITSTREAM ${ADD_VIVADO_PNR_TARGET_PARENT_NAME} BIT) | |
| get_target_property_required(SYNTH_V ${ADD_VIVADO_PNR_TARGET_PARENT_NAME} SYNTH_V) | |
| get_target_property_required(TOP ${ADD_VIVADO_PNR_TARGET_PARENT_NAME} TOP) | |
| get_target_property_required(BOARD ${ADD_VIVADO_PNR_TARGET_PARENT_NAME} BOARD) | |
| get_target_property_required(DEVICE ${BOARD} DEVICE) | |
| get_target_property_required(ARCH ${DEVICE} ARCH) | |
| get_target_property_required(PRJRAY_ARCH ${ARCH} PRJRAY_ARCH) | |
| get_target_property_required(PART ${BOARD} PART) | |
| get_target_property_required(YOSYS env YOSYS) | |
| get_target_property_required(QUIET_CMD env QUIET_CMD) | |
| get_target_property_required(PYTHON3 env PYTHON3) | |
| get_target_property_required(FAMILY ${ARCH} FAMILY) | |
| get_target_property_required(DOC_PRJ ${ARCH} DOC_PRJ) | |
| get_target_property_required(DOC_PRJ_DB ${ARCH} DOC_PRJ_DB) | |
| set(PRJRAY_DIR ${DOC_PRJ}) | |
| set(PRJRAY_DB_DIR ${DOC_PRJ_DB}) | |
| set(DEPS "") | |
| append_file_dependency(SYNTH_DEPS ${SYNTH_V}) | |
| get_file_location(SYNTH_V_LOC ${SYNTH_V}) | |
| # Unmap VPR specific things from synthesis output. | |
| get_filename_component(SYNTH_OUT_BASE ${SYNTH_V_LOC} NAME) | |
| get_file_location(BITSTREAM_LOC ${BITSTREAM}) | |
| get_filename_component(BASE_WORK_DIR ${BITSTREAM_LOC} DIRECTORY) | |
| set(SYNTH_OUT ${BASE_WORK_DIR}/${SYNTH_OUT_BASE}.vivado.v) | |
| set(UNMAP_V ${symbiflow-arch-defs_SOURCE_DIR}/xc/${FAMILY}/techmap/unmap.v) | |
| add_custom_command( | |
| OUTPUT ${SYNTH_OUT} | |
| COMMAND ${QUIET_CMD} ${YOSYS} | |
| -b verilog -o ${SYNTH_OUT} | |
| -p "techmap -map ${UNMAP_V}" | |
| ${SYNTH_V_LOC}.premap.v | |
| DEPENDS ${YOSYS} | |
| ${QUIET_CMD} | |
| ${SYNTH_DEPS} ${SYNTH_V_LOC}.premap.v ${UNMAP_V} | |
| ) | |
| string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" SYNTH_OUT_REL ${SYNTH_OUT}) | |
| add_file_target(FILE ${SYNTH_OUT_REL} GENERATED) | |
| append_file_dependency(DEPS ${SYNTH_OUT_REL}) | |
| # Set or generate the XDC file | |
| set(XDC_FILE "") | |
| if(NOT ${ADD_VIVADO_PNR_TARGET_XDC} STREQUAL "UNDEFINED") | |
| get_file_location(XDC_FILE ${ADD_VIVADO_PNR_TARGET_XDC}) | |
| append_file_dependency(DEPS ${ADD_VIVADO_PNR_TARGET_XDC}) | |
| endif() | |
| if(NOT ${ADD_VIVADO_PNR_TARGET_IOSTANDARD} STREQUAL "UNDEFINED") | |
| if(NOT ${XDC_FILE} STREQUAL "") | |
| message(FATAL_ERROR "Cannot specify both XDC and IOSTANDARD") | |
| endif() | |
| get_target_property_required( | |
| INPUT_IO_FILE | |
| ${ADD_VIVADO_PNR_TARGET_PARENT_NAME} INPUT_IO_FILE) | |
| set(XDC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.xdc) | |
| set(XDC_DEPS) | |
| append_file_dependency(XDC_DEPS ${INPUT_IO_FILE}) | |
| get_file_location(PCF_FILE ${INPUT_IO_FILE}) | |
| set(PCF_TO_XDC_TOOL ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/prjxray_pcf_to_xdc.py) | |
| add_custom_command( | |
| OUTPUT ${NAME}.xdc | |
| COMMAND | |
| ${CMAKE_COMMAND} -E env PYTHONPATH=${symbiflow-arch-defs_SOURCE_DIR}/utils | |
| ${PYTHON3} ${PCF_TO_XDC_TOOL} | |
| --pcf ${PCF_FILE} | |
| --xdc ${XDC_FILE} | |
| --iostandard ${ADD_VIVADO_PNR_TARGET_IOSTANDARD} | |
| DEPENDS ${PYTHON3} ${PCF_TO_XDC_TOOL} ${XDC_DEPS} | |
| ) | |
| add_file_target(FILE ${NAME}.xdc GENERATED) | |
| append_file_dependency(DEPS ${NAME}.xdc) | |
| endif() | |
| if(${XDC_FILE} STREQUAL "") | |
| message(FATAL_ERROR "Must specify either XDC or IOSTANDARD") | |
| endif() | |
| set(CREATE_RUNME ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/vivado_create_runme.py) | |
| add_custom_command( | |
| OUTPUT ${NAME}_runme.tcl | |
| COMMAND ${PYTHON3} ${CREATE_RUNME} | |
| --name ${NAME} | |
| --verilog ${SYNTH_OUT} | |
| --routing_xdc ${XDC_FILE} | |
| --place_and_route | |
| --top ${TOP} | |
| --part ${PART} | |
| --clock_pins "${ADD_VIVADO_PNR_TARGET_CLOCK_PINS}" | |
| --clock_periods "${ADD_VIVADO_PNR_TARGET_CLOCK_PERIODS}" | |
| --output_tcl ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_runme.tcl | |
| DEPENDS | |
| ${PYTHON3} | |
| ${CREATE_RUNME} | |
| ) | |
| set(CREATE_SIM ${symbiflow-arch-defs_SOURCE_DIR}/xc/common/utils/vivado_create_sim.py) | |
| add_custom_command( | |
| OUTPUT ${NAME}_sim.tcl | |
| COMMAND ${PYTHON3} ${CREATE_SIM} | |
| --top ${TOP} | |
| --clock_pins "${ADD_VIVADO_PNR_TARGET_CLOCK_PINS}" | |
| --clock_periods "${ADD_VIVADO_PNR_TARGET_CLOCK_PERIODS}" | |
| --output_tcl ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_sim.tcl | |
| DEPENDS | |
| ${PYTHON3} | |
| ${CREATE_SIM} | |
| ) | |
| # Run vivado in another directory. | |
| set(WORK_DIR ${BASE_WORK_DIR}/vivado_pnr) | |
| string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" WORK_DIR ${WORK_DIR}) | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR} | |
| COMMAND ${CMAKE_COMMAND} -E make_directory ${WORK_DIR} | |
| ) | |
| list(APPEND DEPS ${WORK_DIR}) | |
| COMMON_VIVADO_TARGETS( | |
| NAME ${NAME} | |
| PRJRAY_DIR ${PRJRAY_DIR} | |
| PRJRAY_DB_DIR ${PRJRAY_DB_DIR} | |
| WORK_DIR ${WORK_DIR} | |
| DEPS ${DEPS} | |
| BITSTREAM ${BITSTREAM}) | |
| endfunction() | |
| function(PREPARE_RAPIDWRIGHT) | |
| # Creates a target rapidwright with the following envirnoment variables: | |
| # RAPIDWRIGHT_INSTALLED - True if a valid RapidWright installation is | |
| # found at the variable RAPIDWRIGHT_PATH. | |
| # RAPIDWRIGHT_PATH - If RAPIDWRIGHT_INSTALLED=TRUE, this points to the | |
| # directory where RapidWright is located. | |
| # JAVA - If RAPIDWRIGHT_INSTALLED=TRUE, this points to the location of | |
| # the Java runtime executable needed invoke RapidWright entry | |
| # points. | |
| # INVOKE_RAPIDWRIGHT - If RAPIDWRIGHT_INSTALLED=TRUE, this points to the | |
| # location of the invoke_rapidwright.sh script which can be used to | |
| # invoke RapidWright. | |
| add_custom_target(rapidwright) | |
| set_target_properties(rapidwright PROPERTIES RAPIDWRIGHT_INSTALLED FALSE) | |
| set(HAVE_RAPIDWRIGHT FALSE) | |
| set(HAVE_JAVA FALSE) | |
| set(HAVE_URAY_VIVADO FALSE) | |
| if(DEFINED RAPIDWRIGHT_PATH) | |
| elseif(DEFINED ENV{RAPIDWRIGHT_PATH}) | |
| set(RAPIDWRIGHT_PATH $ENV{RAPIDWRIGHT_PATH}) | |
| endif() | |
| if(EXISTS "${RAPIDWRIGHT_PATH}" AND EXISTS ${RAPIDWRIGHT_PATH}/interchange AND EXISTS ${RAPIDWRIGHT_PATH}/scripts/invoke_rapidwright.sh) | |
| set(HAVE_RAPIDWRIGHT TRUE) | |
| endif() | |
| if(${HAVE_RAPIDWRIGHT}) | |
| find_program(JAVA java) | |
| if(EXISTS ${JAVA}) | |
| set(HAVE_JAVA TRUE) | |
| endif() | |
| endif() | |
| if(DEFINED ENV{URAY_VIVADO_SETTINGS}) | |
| set(HAVE_URAY_VIVADO TRUE) | |
| endif() | |
| if(${HAVE_RAPIDWRIGHT} AND ${HAVE_JAVA} AND ${HAVE_URAY_VIVADO}) | |
| set_target_properties(rapidwright PROPERTIES | |
| RAPIDWRIGHT_INSTALLED TRUE | |
| RAPIDWRIGHT_PATH "${RAPIDWRIGHT_PATH}" | |
| INVOKE_RAPIDWRIGHT "${RAPIDWRIGHT_PATH}/scripts/invoke_rapidwright.sh" | |
| JAVA ${JAVA}) | |
| elseif(NOT ${HAVE_RAPIDWRIGHT}) | |
| message(STATUS "RAPIDWRIGHT_PATH not defined. Interchange support not enabled.") | |
| elseif(NOT ${HAVE_JAVA}) | |
| message(WARNING "RAPIDWRIGHT_PATH defined, but JAVA not found. Interchange support not enabled.") | |
| elseif(NOT ${HAVE_URAY_VIVADO}) | |
| message(WARNING "RAPIDWRIGHT_PATH defined, but URAY_VIVADO_SETTINGS not found. Interchange support not enabled.") | |
| endif() | |
| get_target_property_required(RAPIDWRIGHT_INSTALLED rapidwright RAPIDWRIGHT_INSTALLED) | |
| if(NOT ${ALL_XC7_DIFF_FASM_VERILOG} AND ${ALL_XC7_DIFF_FASM_INTERCHANGE} AND NOT ${RAPIDWRIGHT_INSTALLED}) | |
| message(SEND_ERROR "all_xc7_diff_fasm is set to only include interchange, but interchange support is not enabled.") | |
| endif() | |
| endfunction() | |
| function(CREATE_DCP_BY_INTERCHANGE) | |
| # ~~~ | |
| # CREATE_DCP_BY_INTERCHANGE( | |
| # NAME <name> | |
| # PARENT_NAME <parent name> | |
| # WORK_DIR <work directory> | |
| # ) | |
| # ~~~ | |
| # | |
| # Creates a DCP of parent target using the FPGA interchange and RapidWright. | |
| # | |
| # PARENT_NAME is the name of the FPGA target being used as input for these | |
| # new targets. | |
| # | |
| # New targets: | |
| # <NAME> - Create the DCP and output a bitstream based on the DCP. | |
| # <NAME>_diff_fasm - Diff the FASM between the PARENT_NAME bitstream and | |
| # the bitstream generated from the DCP. | |
| set(options) | |
| set(oneValueArgs NAME PARENT_NAME WORK_DIR XDC) | |
| set(multiValueArgs) | |
| cmake_parse_arguments( | |
| CREATE_DCP | |
| "${options}" | |
| "${oneValueArgs}" | |
| "${multiValueArgs}" | |
| ${ARGN} | |
| ) | |
| set(NAME ${CREATE_DCP_NAME}) | |
| set(WORK_DIR ${CREATE_DCP_WORK_DIR}) | |
| get_target_property_required(BITREAD env BITREAD) | |
| get_target_property_required(BITSTREAM ${CREATE_DCP_PARENT_NAME} BIT) | |
| get_target_property_required(BIT_VERILOG ${CREATE_DCP_PARENT_NAME} BIT_V) | |
| get_target_property_required(BOARD ${CREATE_DCP_PARENT_NAME} BOARD) | |
| get_target_property_required(DEVICE ${BOARD} DEVICE) | |
| get_target_property_required(ARCH ${DEVICE} ARCH) | |
| get_target_property_required(PRJRAY_ARCH ${ARCH} PRJRAY_ARCH) | |
| get_target_property_required(PART ${BOARD} PART) | |
| get_target_property_required(PRJRAY_DIR ${ARCH} DOC_PRJ) | |
| get_target_property_required(PRJRAY_DB_DIR ${ARCH} DOC_PRJ_DB) | |
| set(DEPS) | |
| append_file_dependency(DEPS ${BIT_VERILOG}) | |
| get_file_location(BIT_VERILOG_LOCATION ${BIT_VERILOG}) | |
| get_target_property_required(JAVA rapidwright JAVA) | |
| get_target_property_required(RAPIDWRIGHT_PATH rapidwright RAPIDWRIGHT_PATH) | |
| get_target_property_required(INVOKE_RAPIDWRIGHT rapidwright INVOKE_RAPIDWRIGHT) | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR}/${NAME}.dcp | |
| COMMAND ${CMAKE_COMMAND} -E make_directory ${WORK_DIR} | |
| COMMAND ${CMAKE_COMMAND} -E env | |
| JAVA=${JAVA} | |
| RAPIDWRIGHT_PATH=${RAPIDWRIGHT_PATH} | |
| ${INVOKE_RAPIDWRIGHT} | |
| com.xilinx.rapidwright.interchange.PhysicalNetlistToDcp | |
| ${BIT_VERILOG_LOCATION}.netlist | |
| ${BIT_VERILOG_LOCATION}.phys | |
| ${BIT_VERILOG_LOCATION}.inter.xdc | |
| ${WORK_DIR}/${NAME}.dcp | |
| DEPENDS ${DEPS} | |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | |
| ) | |
| add_file_target(FILE ${WORK_DIR}/${NAME}.dcp GENERATED) | |
| get_file_target(DCP_TARGET ${WORK_DIR}/${NAME}.dcp) | |
| add_custom_target(${NAME}) | |
| add_dependencies(${NAME} ${DCP_TARGET}) | |
| set(RUNME ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/${NAME}_runme.tcl) | |
| set(RUNME_DEPS) | |
| append_file_dependency(RUNME_DEPS ${WORK_DIR}/${NAME}.dcp) | |
| set(XDC_EXTRA_ARGS "") | |
| if(NOT "${CREATE_DCP_XDC}" STREQUAL "") | |
| get_file_location(XDC_LOCATION ${CREATE_DCP_XDC}) | |
| set(XDC_EXTRA_ARGS "read_xdc -no_add ${XDC_LOCATION}") | |
| append_file_dependency(RUNME_DEPS ${CREATE_DCP_XDC}) | |
| endif() | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR}/${NAME}_runme.tcl | |
| COMMAND ${CMAKE_COMMAND} -E make_directory ${WORK_DIR} | |
| COMMAND ${CMAKE_COMMAND} -E echo "open_checkpoint ${NAME}.dcp" > ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "${XDC_EXTRA_ARGS}" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "set_property CFGBVS VCCO [current_design]" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "set_property CONFIG_VOLTAGE 3.3 [current_design]" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "set_property IS_ENABLED 0 [get_drc_checks {LUTLP-1}]" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "set_property IS_ENABLED 0 [get_drc_checks {RTRES-2}]" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "report_utilization -file ${NAME}_utilization.rpt" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "report_clock_utilization -file ${NAME}_clock_utilization.rpt" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "report_timing_summary -datasheet -max_paths 10 -file ${NAME}_timing_summary.rpt" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "report_power -file ${NAME}_power.rpt" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "report_route_status -file ${NAME}_route_status.rpt" >> ${RUNME} | |
| COMMAND ${CMAKE_COMMAND} -E echo "write_bitstream -force ${NAME}.bit" >> ${RUNME} | |
| ) | |
| add_file_target(FILE ${WORK_DIR}/${NAME}_runme.tcl GENERATED) | |
| append_file_dependency(RUNME_DEPS ${WORK_DIR}/${NAME}_runme.tcl) | |
| add_custom_command( | |
| OUTPUT | |
| ${WORK_DIR}/${NAME}.bit | |
| ${WORK_DIR}/${NAME}_utilization.rpt | |
| ${WORK_DIR}/${NAME}_clock_utilization.rpt | |
| ${WORK_DIR}/${NAME}_power.rpt | |
| ${WORK_DIR}/${NAME}_timing_summary.rpt | |
| ${WORK_DIR}/${NAME}_route_status.rpt | |
| COMMAND ${CMAKE_COMMAND} -E env XRAY_VIVADO_SETTINGS=$ENV{URAY_VIVADO_SETTINGS} ${PRJRAY_DIR}/utils/vivado.sh -mode batch -source ${RUNME} | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/vivado.stdout.log | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS ${RUNME_DEPS} | |
| ) | |
| add_file_target(FILE ${WORK_DIR}/${NAME}.bit GENERATED) | |
| set(BIT2FASM_DEPS) | |
| append_file_dependency(BIT2FASM_DEPS ${WORK_DIR}/${NAME}.bit) | |
| add_custom_command( | |
| OUTPUT ${WORK_DIR}/${NAME}.bit.fasm | |
| COMMAND | |
| ${CMAKE_COMMAND} -E env PYTHONPATH=${PRJRAY_DIR}:${PRJRAY_DIR}/third_party/fasm | |
| ${PYTHON3} ${PRJRAY_DIR}/utils/bit2fasm.py | |
| --part ${PART} | |
| --db-root ${PRJRAY_DB_DIR}/${PRJRAY_ARCH} | |
| --bitread ${BITREAD} | |
| --verbose | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/${NAME}.bit | |
| > ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/${NAME}.bit.fasm | |
| WORKING_DIRECTORY ${WORK_DIR} | |
| DEPENDS | |
| ${BIT2FASM_DEPS} | |
| ) | |
| add_file_target(FILE ${WORK_DIR}/${NAME}.bit.fasm GENERATED) | |
| set(DIFF_FASM_DEPS) | |
| append_file_dependency(DIFF_FASM_DEPS ${WORK_DIR}/${NAME}.bit.fasm) | |
| append_file_dependency(DIFF_FASM_DEPS ${BITSTREAM}) | |
| get_file_location(BITSTREAM_LOCATION ${BITSTREAM}) | |
| add_custom_target(${NAME}_diff_fasm | |
| COMMAND diff -u | |
| ${BITSTREAM_LOCATION}.fasm | |
| ${CMAKE_CURRENT_BINARY_DIR}/${WORK_DIR}/${NAME}.bit.fasm | |
| DEPENDS | |
| ${DIFF_FASM_DEPS} | |
| ) | |
| endfunction() |