blob: 0c48bba6c53878ac0610d4c2c8aff64e4fdb9876 [file] [log] [blame] [edit]
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()