| 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 ${f4pga-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 |
| ${f4pga-arch-defs_SOURCE_DIR}/xilinx/common/utils/output_timing.tcl |
| -tclargs |
| ${f4pga-arch-defs_SOURCE_DIR}/xilinx/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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/${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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/common/utils/prjxray_pcf_to_xdc.py) |
| |
| add_custom_command( |
| OUTPUT ${NAME}.xdc |
| COMMAND |
| ${CMAKE_COMMAND} -E env PYTHONPATH=${f4pga-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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/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 ${f4pga-arch-defs_SOURCE_DIR}/xilinx/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() |