|  | function(PARSE_INSTALL_LISTS) | 
|  | # ~~~ | 
|  | # PARSE_INSTALL_LISTS | 
|  | # | 
|  | # Parses lists of architectures and devices to be installed as given by a | 
|  | # user. Converts them to CMake lists and sets them in the global scope. | 
|  | # | 
|  | # There are INSTALL_* and NO_INSTALL_* global variables. Each of them holds | 
|  | # a comma-separated list of entities to install and not to install. | 
|  | # | 
|  | # When none of these two is set then all entities are considered for installation | 
|  | # If INSTALL_* is set then only entities present there are to be installed. | 
|  | # The NO_INSTALL_* list contains entities that should NOT be installed. | 
|  | # | 
|  | # For example: If one wants to install only the Xilinx 7-series familly one | 
|  | # would run the CMake with -DINSTALL_FAMILIES=xc7. If one wants to install | 
|  | # all supported families BUT Xilinx 7-series one would do -DNO_INSTALL_FAMILIES=xc7 | 
|  | # The same principle applies to the architecture and the device lists. | 
|  |  | 
|  | # Device lists | 
|  | if (NOT "${INSTALL_DEVICES}" STREQUAL "") | 
|  | string(REPLACE "," ";" DEVICE_INSTALL_LIST ${INSTALL_DEVICES}) | 
|  | else () | 
|  | set(DEVICE_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_DEVICE_INSTALL_LIST ${DEVICE_INSTALL_LIST} CACHE INTERNAL "List of devices to install" FORCE) | 
|  |  | 
|  | if (NOT "${NO_INSTALL_DEVICES}" STREQUAL "") | 
|  | string(REPLACE "," ";" DEVICE_NO_INSTALL_LIST ${NO_INSTALL_DEVICES}) | 
|  | else () | 
|  | set(DEVICE_NO_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_DEVICE_NO_INSTALL_LIST ${DEVICE_NO_INSTALL_LIST} CACHE INTERNAL "List of devices not to install" FORCE) | 
|  |  | 
|  | # Architecture lists | 
|  | if (NOT "${INSTALL_ARCHS}" STREQUAL "") | 
|  | string(REPLACE "," ";" ARCH_INSTALL_LIST ${INSTALL_ARCHS}) | 
|  | else () | 
|  | set(ARCH_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_ARCH_INSTALL_LIST ${ARCH_INSTALL_LIST} CACHE INTERNAL "List of architectures to install" FORCE) | 
|  |  | 
|  | if (NOT "${NO_INSTALL_ARCHS}" STREQUAL "") | 
|  | string(REPLACE "," ";" ARCH_NO_INSTALL_LIST ${NO_INSTALL_ARCHS}) | 
|  | else () | 
|  | set(ARCH_NO_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_ARCH_NO_INSTALL_LIST ${ARCH_NO_INSTALL_LIST} CACHE INTERNAL "List of acritectures not to install" FORCE) | 
|  |  | 
|  | # Family lists | 
|  | if (NOT "${INSTALL_FAMILIES}" STREQUAL "") | 
|  | string(REPLACE "," ";" FAMILY_INSTALL_LIST ${INSTALL_FAMILIES}) | 
|  | else () | 
|  | set(FAMILY_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_FAMILY_INSTALL_LIST ${FAMILY_INSTALL_LIST} CACHE INTERNAL "List of device families to install" FORCE) | 
|  |  | 
|  | if (NOT "${NO_INSTALL_FAMILIES}" STREQUAL "") | 
|  | string(REPLACE "," ";" FAMILY_NO_INSTALL_LIST ${NO_INSTALL_FAMILIES}) | 
|  | else () | 
|  | set(FAMILY_NO_INSTALL_LIST "") | 
|  | endif () | 
|  | set(SYMBIFLOW_FAMILY_NO_INSTALL_LIST ${FAMILY_NO_INSTALL_LIST} CACHE INTERNAL "List of families not to install" FORCE) | 
|  |  | 
|  | endfunction() | 
|  |  | 
|  |  | 
|  | function(CHECK_INSTALL_LIST) | 
|  | # ~~~ | 
|  | # CHECK_INSTALL_LIST | 
|  | #  <entity> | 
|  | #  <variable> | 
|  | #  <install list> | 
|  | #  <no-install list> | 
|  | # | 
|  | # Checks if the given device is to be installed by examining it through | 
|  | # installation lists. Sets the given variable to TRUE or FALSE | 
|  | # ~~~ | 
|  |  | 
|  | set(options) | 
|  | set(oneValueArgs ENTITY VAR) | 
|  | set(multiValueArgs INSTALL_LIST NO_INSTALL_LIST) | 
|  | cmake_parse_arguments( | 
|  | CHECK_INSTALL_LIST | 
|  | "${options}" | 
|  | "${oneValueArgs}" | 
|  | "${multiValueArgs}" | 
|  | ${ARGN} | 
|  | ) | 
|  |  | 
|  | set(ENTITY          ${CHECK_INSTALL_LIST_ENTITY}) | 
|  | set(INSTALL_LIST    ${CHECK_INSTALL_LIST_INSTALL_LIST}) | 
|  | set(NO_INSTALL_LIST ${CHECK_INSTALL_LIST_NO_INSTALL_LIST}) | 
|  | set(VAR             ${CHECK_INSTALL_LIST_VAR}) | 
|  |  | 
|  | # Initially accept | 
|  | set(RET TRUE) | 
|  |  | 
|  | # The install list provided, check against it. No install list means accept all | 
|  | if (INSTALL_LIST) | 
|  | if (NOT "${ENTITY}" IN_LIST INSTALL_LIST) | 
|  | message(DEBUG "INSTALL: Skipping entity '${ENTITY}' as not on the install list") | 
|  | set(RET FALSE) | 
|  | endif () | 
|  | endif () | 
|  |  | 
|  | # The no-install list provided, check against it | 
|  | if (NO_INSTALL_LIST) | 
|  | if ("${ENTITY}" IN_LIST NO_INSTALL_LIST) | 
|  | message(DEBUG "INSTALL: Skipping entity '${ENTITY}' as on the no-install list") | 
|  | set(RET FALSE) | 
|  | endif () | 
|  | endif () | 
|  |  | 
|  | # Return | 
|  | set(${VAR} ${RET} PARENT_SCOPE) | 
|  |  | 
|  | endfunction() | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  | function(CHECK_ARCH_INSTALL ARCH VAR) | 
|  | # ~~~ | 
|  | # CHECK_ARCH_INSTALL | 
|  | #  <arch> | 
|  | #  <variable> | 
|  | # | 
|  | # Checks if the given architecture is to be installed. | 
|  | # ~~~ | 
|  |  | 
|  | get_target_property_required(FAMILY ${ARCH} FAMILY) | 
|  |  | 
|  | # Initially accept | 
|  | set(RET TRUE) | 
|  |  | 
|  | # Check the arch against the list | 
|  | check_install_list( | 
|  | ENTITY          ${ARCH} | 
|  | INSTALL_LIST    ${SYMBIFLOW_ARCH_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_ARCH_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | if(NOT ${RET}) | 
|  | message(STATUS "INSTALL: Skipping architecture '${ARCH}' due to installation list") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Check the individual property of the arch | 
|  | get_target_property_required(NO_INSTALL ${ARCH} NO_INSTALL) | 
|  | if(${NO_INSTALL}) | 
|  | message(STATUS "INSTALL: Skipping architecture '${ARCH}' as marked as NO_INSTALL") | 
|  | set(RET FALSE) | 
|  | endif() | 
|  |  | 
|  | # Check the family against the list | 
|  | check_install_list( | 
|  | ENTITY          ${FAMILY} | 
|  | INSTALL_LIST    ${SYMBIFLOW_FAMILY_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_FAMILY_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | if(NOT ${RET}) | 
|  | message(STATUS "INSTALL: Skipping architecture '${ARCH}' due to its family '${FAMILY}' (not) on an installation list") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Get list of devices of the given architecture | 
|  | get_target_property_required(DEVICES ${ARCH} DEVICES) | 
|  |  | 
|  | # No devices, don't install this arch | 
|  | if (NOT DEVICES) | 
|  | message(STATUS "INSTALL: Skipping architecture '${ARCH}' as there are no devices") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif () | 
|  |  | 
|  | # Examine each device | 
|  | set(RET FALSE) | 
|  | foreach(DEVICE ${DEVICES}) | 
|  |  | 
|  | # Check the device against the list | 
|  | check_install_list( | 
|  | ENTITY          ${DEVICE} | 
|  | INSTALL_LIST    ${SYMBIFLOW_DEVICE_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_DEVICE_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | # Check the individual property of the device | 
|  | if(${RET}) | 
|  | get_target_property_required(NO_INSTALL ${DEVICE} NO_INSTALL) | 
|  | if(NOT ${NO_INSTALL}) | 
|  | break() | 
|  | endif() | 
|  | endif() | 
|  |  | 
|  | endforeach() | 
|  |  | 
|  | if(NOT RET) | 
|  | message(STATUS "INSTALL: Skipping architecture '${ARCH}' as none of its devices it to be installed") | 
|  | endif() | 
|  |  | 
|  | # Return | 
|  | set(${VAR} ${RET} PARENT_SCOPE) | 
|  |  | 
|  | endfunction() | 
|  |  | 
|  |  | 
|  | function(CHECK_DEVICE_INSTALL DEVICE VAR) | 
|  | # ~~~ | 
|  | # CHECK_DEVICE_INSTALL | 
|  | #  <device> | 
|  | #  <variable> | 
|  | # | 
|  | # Checks if the given device is to be installed by examining it and its | 
|  | # architecture + family through the installation lists. Also checks individual | 
|  | # NO_INSTALL properties of the device and its architecture | 
|  | # ~~~ | 
|  |  | 
|  | get_target_property_required(ARCH   ${DEVICE} ARCH) | 
|  | get_target_property_required(FAMILY ${ARCH}   FAMILY) | 
|  |  | 
|  | # Initially accept | 
|  | set(RET TRUE) | 
|  |  | 
|  | # Check the device against the list | 
|  | check_install_list( | 
|  | ENTITY          ${DEVICE} | 
|  | INSTALL_LIST    ${SYMBIFLOW_DEVICE_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_DEVICE_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | if(NOT ${RET}) | 
|  | message(STATUS "INSTALL: Skipping device '${DEVICE}' due to installation list") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Check the individual property of the device | 
|  | get_target_property_required(NO_INSTALL ${DEVICE} NO_INSTALL) | 
|  | if(${NO_INSTALL}) | 
|  | message(STATUS "INSTALL: Skipping device '${DEVICE}' as marked as NO_INSTALL") | 
|  | set(RET FALSE) | 
|  | endif() | 
|  |  | 
|  | # Check the architecture against the list | 
|  | check_install_list( | 
|  | ENTITY          ${ARCH} | 
|  | INSTALL_LIST    ${SYMBIFLOW_ARCH_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_ARCH_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | if(NOT ${RET}) | 
|  | message(STATUS "INSTALL: Skipping device '${DEVICE}' due to its architecture '${ARCH}' (not) on an installation list") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Check the individual property of the architecture | 
|  | get_target_property_required(NO_INSTALL ${ARCH} NO_INSTALL) | 
|  | if(${NO_INSTALL}) | 
|  | message(STATUS "INSTALL: Skipping device '${DEVICE}' as its architecture '${ARCH}' is marked as NO_INSTALL") | 
|  | set(RET FALSE) | 
|  | endif() | 
|  |  | 
|  | # Check the family against the list | 
|  | check_install_list( | 
|  | ENTITY          ${FAMILY} | 
|  | INSTALL_LIST    ${SYMBIFLOW_FAMILY_INSTALL_LIST} | 
|  | NO_INSTALL_LIST ${SYMBIFLOW_FAMILY_NO_INSTALL_LIST} | 
|  | VAR             RET | 
|  | ) | 
|  |  | 
|  | if(NOT ${RET}) | 
|  | message(STATUS "INSTALL: Skipping device '${DEVICE}' due to its family '${FAMILY}' (not) on an installation list") | 
|  | set(${VAR} FALSE PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Return | 
|  | set(${VAR} ${RET} PARENT_SCOPE) | 
|  |  | 
|  | endfunction() | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  | function(INSTALL_DEVICE_FILES) | 
|  | # ~~~ | 
|  | # INSTALL_DEVICE_FILES( | 
|  | #   DEVICE <device> | 
|  | #   PACKAGE <package> | 
|  | #   DEVICE_TYPE <device_type> | 
|  | #   ) | 
|  | # ~~~ | 
|  | # | 
|  | set(options) | 
|  | set(oneValueArgs DEVICE PACKAGE DEVICE_TYPE) | 
|  | set(multiValueArgs) | 
|  | cmake_parse_arguments( | 
|  | INSTALL_DEVICE_FILES | 
|  | "${options}" | 
|  | "${oneValueArgs}" | 
|  | "${multiValueArgs}" | 
|  | ${ARGN} | 
|  | ) | 
|  |  | 
|  | set(DEVICE ${INSTALL_DEVICE_FILES_DEVICE}) | 
|  | set(DEVICE_TYPE ${INSTALL_DEVICE_FILES_DEVICE_TYPE}) | 
|  | set(PACKAGE ${INSTALL_DEVICE_FILES_PACKAGE}) | 
|  |  | 
|  | get_target_property(USE_ROI ${DEVICE_TYPE} USE_ROI) | 
|  | if(USE_ROI OR USE_ROI STREQUAL "USE_ROI-NOTFOUND") | 
|  | message(STATUS "Skipping device files installation for ${DEVICE}-${PACKAGE} type: ${DEVICE_TYPE}") | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | get_target_property(LIMIT_GRAPH_TO_DEVICE ${DEVICE_TYPE} LIMIT_GRAPH_TO_DEVICE) | 
|  | if(LIMIT_GRAPH_TO_DEVICE OR LIMIT_GRAPH_TO_DEVICE STREQUAL "LIMIT_GRAPH_TO_DEVICE-NOTFOUND") | 
|  | message(STATUS "Graph limited to a sub-area of the device. Skipping files installation for ${DEVICE}-${PACKAGE} type: ${DEVICE_TYPE}") | 
|  | return() | 
|  | endif() | 
|  |  | 
|  | # Check if the device should be installed | 
|  | check_device_install(${DEVICE} DO_INSTALL) | 
|  | if (NOT DO_INSTALL) | 
|  | return() | 
|  | endif () | 
|  |  | 
|  | set(INSTALL_FILES) | 
|  |  | 
|  | # Get files to be installed | 
|  | get_target_property_required(HAS_LOOKAHEAD ${DEVICE} "${PACKAGE}_HAS_LOOKAHEAD_CACHE") | 
|  | get_target_property_required(HAS_PLACE_DELAY ${DEVICE} "${PACKAGE}_HAS_PLACE_DELAY_CACHE") | 
|  | if(${HAS_LOOKAHEAD}) | 
|  | get_target_property(LOOKAHEAD_FILE ${DEVICE} ${PACKAGE}_LOOKAHEAD_FILE) | 
|  | list(APPEND INSTALL_FILES ${LOOKAHEAD_FILE}) | 
|  | endif() | 
|  | if(${HAS_PLACE_DELAY}) | 
|  | get_target_property(PLACE_DELAY_FILE ${DEVICE} ${PACKAGE}_PLACE_DELAY_FILE) | 
|  | list(APPEND INSTALL_FILES ${PLACE_DELAY_FILE}) | 
|  | endif() | 
|  | get_target_property_required(RR_GRAPH_FILE ${DEVICE} ${PACKAGE}_OUT_RRBIN_REAL) | 
|  | list(APPEND INSTALL_FILES ${RR_GRAPH_FILE}) | 
|  |  | 
|  | get_target_property_required(ARCH_FILE ${DEVICE_TYPE} DEVICE_MERGED_FILE) | 
|  | list(APPEND INSTALL_FILES ${ARCH_FILE}) | 
|  |  | 
|  | get_target_property(VPR_GRID_MAP_FILE ${DEVICE_TYPE} VPR_GRID_MAP) | 
|  | if(NOT ${VPR_GRID_MAP_FILE} STREQUAL "VPR_GRID_MAP_FILE-NOTFOUND") | 
|  | list(APPEND INSTALL_FILES ${VPR_GRID_MAP_FILE}) | 
|  | endif() | 
|  |  | 
|  | # Extra files for the device (common to all packages) | 
|  | get_target_property(EXTRA_FILES ${DEVICE} EXTRA_INSTALL_FILES) | 
|  | if(NOT ${EXTRA_FILES} MATCHES ".*-NOTFOUND" AND NOT ${EXTRA_FILES} STREQUAL "") | 
|  | list(APPEND INSTALL_FILES ${EXTRA_FILES}) | 
|  | endif() | 
|  |  | 
|  | # Generate installation target for the files | 
|  | foreach(FILE ${INSTALL_FILES}) | 
|  | get_file_location(SRC_FILE ${FILE}) | 
|  | get_filename_component(SRC_FILE_REAL ${SRC_FILE} REALPATH) | 
|  | get_filename_component(FILE_NAME ${SRC_FILE} NAME) | 
|  | append_file_dependency(DEPS ${FILE}) | 
|  | # Create a custom target and add it to ALL target. | 
|  | # We do this because install targets depend only on | 
|  | # all. | 
|  | add_custom_target( | 
|  | "INSTALL_${DEVICE}_${PACKAGE}_${FILE_NAME}" | 
|  | ALL | 
|  | DEPENDS ${DEPS}) | 
|  | install(FILES ${SRC_FILE_REAL} | 
|  | DESTINATION "share/f4pga/arch/${DEVICE}_${PACKAGE}" | 
|  | RENAME ${FILE_NAME} | 
|  | ) | 
|  | endforeach() | 
|  |  | 
|  | endfunction() | 
|  |  |