| function(QUICKLOGIC_DEFINE_DEVICE_TYPE) |
| # ~~~ |
| # QUICKLOGIC_DEFINE_DEVICE_TYPE( |
| # FAMILY <family> |
| # ARCH <arch> |
| # DEVICE <device> |
| # PACKAGES <package> <package> ... |
| # [GRID_LIMIT <xmin>,<ymin>,<xmax>,<ymax>] |
| # PB_TYPES <pb_type> <pb_type> ... |
| # TECHFILE_NAME <techfile name> |
| # ROUTING_TIMING_FILE_NAME <routing timing CSV file> |
| # LIB_TIMING_FILES <list timing lib files [can be wildcard]> |
| # RAM_TIMING_SDF <name of the RAM timing data> |
| # RAM_PBTYPE_COPY <name of the RAM pb_type to use> |
| # ) |
| # ~~~ |
| set(options) |
| set(oneValueArgs FAMILY DEVICE ARCH GRID_LIMIT TECHFILE_NAME ROUTING_TIMING_FILE_NAME RAM_TIMING_SDF RAM_PBTYPE_COPY) |
| set(multiValueArgs PACKAGES PB_TYPES LIB_TIMING_FILES DONT_NORMALIZE_FILES) |
| cmake_parse_arguments( |
| QUICKLOGIC_DEFINE_DEVICE_TYPE |
| "${options}" |
| "${oneValueArgs}" |
| "${multiValueArgs}" |
| ${ARGN} |
| ) |
| |
| set(TECHFILE_NAME ${QUICKLOGIC_DEFINE_DEVICE_TYPE_TECHFILE_NAME}) |
| set(FAMILY ${QUICKLOGIC_DEFINE_DEVICE_TYPE_FAMILY}) |
| set(DEVICE ${QUICKLOGIC_DEFINE_DEVICE_TYPE_DEVICE}) |
| set(ARCH ${QUICKLOGIC_DEFINE_DEVICE_TYPE_ARCH}) |
| set(GRID_LIMIT ${QUICKLOGIC_DEFINE_DEVICE_TYPE_GRID_LIMIT}) |
| set(PB_TYPES ${QUICKLOGIC_DEFINE_DEVICE_TYPE_PB_TYPES}) |
| set(ROUTING_TIMING_FILE_NAME ${QUICKLOGIC_DEFINE_DEVICE_TYPE_ROUTING_TIMING_FILE_NAME}) |
| set(LIB_TIMING_FILES ${QUICKLOGIC_DEFINE_DEVICE_TYPE_LIB_TIMING_FILES}) |
| set(DONT_NORMALIZE_FILES ${QUICKLOGIC_DEFINE_DEVICE_TYPE_DONT_NORMALIZE_FILES}) |
| set(RAM_TIMING_SDF ${QUICKLOGIC_DEFINE_DEVICE_TYPE_RAM_TIMING_SDF}) |
| set(RAM_PBTYPE_COPY ${QUICKLOGIC_DEFINE_DEVICE_TYPE_RAM_PBTYPE_COPY}) |
| |
| set(DEVICE_TYPE ${DEVICE}-virt) |
| |
| get_target_property_required(PYTHON3 env PYTHON3) |
| |
| set(PHY_DB_FILE "db_phy.pickle") |
| set(VPR_DB_FILE "db_vpr.pickle") |
| set(ARCH_XML "arch.xml") |
| |
| set(DEVICE_DIR_DATA ${DEVICE}) |
| if(${DEVICE} STREQUAL "ql-pp3") |
| set(DEVICE_DIR_DATA "ql-eos-s3") # FIXME: use PP3 timing data when it will be available |
| endif() |
| |
| # The techfile and routing timing file |
| set(TECHFILE "${f4pga-arch-defs_SOURCE_DIR}/third_party/${DEVICE}/Device Architecture Files/${TECHFILE_NAME}") |
| set(ROUTING_TIMING "${f4pga-arch-defs_SOURCE_DIR}/third_party/${DEVICE_DIR_DATA}/Timing Data Files/${ROUTING_TIMING_FILE_NAME}") |
| |
| # Import data from the techfile |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PHY_DB_FILE} |
| COMMAND python3 -m f4pga.utils.quicklogic.pp3.data_import |
| --techfile ${TECHFILE} |
| --routing-timing ${ROUTING_TIMING} |
| --db ${PHY_DB_FILE} |
| DEPENDS ${TECHFILE} ${ROUTING_TIMING} |
| ) |
| add_file_target(FILE ${PHY_DB_FILE} GENERATED) |
| |
| # Generate SDF files with timing data |
| set(LIB_TIMING_DIR "${f4pga-arch-defs_SOURCE_DIR}/third_party/${DEVICE_DIR_DATA}/Timing Data Files/") |
| set(SDF_TIMING_DIR "sdf") |
| |
| get_target_property_required(QUICKLOGIC_TIMINGS_IMPORTER env QUICKLOGIC_TIMINGS_IMPORTER) |
| |
| # TODO: How to handle different timing cases that depend on a cell config? |
| # For example BIDIR cells have different timings for different voltages. |
| # |
| # One idea is to have a different model for each in VPR. |
| # |
| # For now only files with the worst case scenario timings are taken. |
| set(TIMING_FILES "") |
| foreach(LIB ${LIB_TIMING_FILES}) |
| |
| file(GLOB TIMING_FILE |
| "${LIB_TIMING_DIR}/${LIB}" |
| ) |
| list(APPEND TIMING_FILES ${TIMING_FILE}) |
| endforeach() |
| |
| set(SDF_FILE_TARGETS "") |
| foreach(LIB_TIMING_FILE ${TIMING_FILES}) |
| |
| get_filename_component(FILE_NAME ${LIB_TIMING_FILE} NAME) |
| get_filename_component(FILE_TITLE ${FILE_NAME} NAME_WE) |
| |
| set(IMPORTER_OPTS "") |
| if(NOT ${FILE_NAME} IN_LIST DONT_NORMALIZE_FILES) |
| list(APPEND IMPORTER_OPTS "--normalize-cell-names") |
| list(APPEND IMPORTER_OPTS "--normalize-port-names") |
| endif() |
| |
| set(SDF_TIMING_FILE ${SDF_TIMING_DIR}/${FILE_TITLE}.sdf) |
| |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SDF_TIMING_FILE} |
| COMMAND ${CMAKE_COMMAND} -E make_directory ${SDF_TIMING_DIR} |
| COMMAND ${PYTHON3} -m quicklogic_timings_importer |
| ${LIB_TIMING_FILE} |
| ${SDF_TIMING_FILE} |
| ${IMPORTER_OPTS} |
| DEPENDS ${PYTHON3} ${LIB_TIMING_FILE} |
| ) |
| |
| add_file_target(FILE ${SDF_TIMING_FILE} GENERATED) |
| append_file_dependency(SDF_FILE_TARGETS ${SDF_TIMING_FILE}) |
| |
| endforeach() |
| |
| |
| # Process the database, create the VPR database |
| get_file_target(PHY_DB_TARGET ${PHY_DB_FILE}) |
| |
| if(NOT "${GRID_LIMIT}" STREQUAL "") |
| separate_arguments(GRID_LIMIT_ARGS UNIX_COMMAND "--grid-limit ${GRID_LIMIT}") |
| else() |
| set(GRID_LIMIT_ARGS "") |
| endif() |
| |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${VPR_DB_FILE} |
| COMMAND python3 -m f4pga.utils.quicklogic.pp3.prepare_vpr_database |
| --phy-db ${PHY_DB_FILE} |
| --vpr-db ${VPR_DB_FILE} |
| --sdf-dir ${SDF_TIMING_DIR} |
| ${GRID_LIMIT_ARGS} |
| DEPENDS ${PHY_DB_TARGET} ${SDF_FILE_TARGETS} |
| ) |
| add_file_target(FILE ${VPR_DB_FILE} GENERATED) |
| |
| # Get dependencies for arch.xml |
| set(XML_DEPS "") |
| foreach(PB_TYPE ${PB_TYPES}) |
| string(TOLOWER ${PB_TYPE} PB_TYPE_LOWER) |
| set(PB_TYPE_XML ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/${FAMILY}/primitives/${PB_TYPE_LOWER}/${PB_TYPE_LOWER}.pb_type.xml) |
| set(MODEL_XML ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/${FAMILY}/primitives/${PB_TYPE_LOWER}/${PB_TYPE_LOWER}.model.xml) |
| append_file_dependency(XML_DEPS ${PB_TYPE_XML}) |
| append_file_dependency(XML_DEPS ${MODEL_XML}) |
| endforeach() |
| |
| # Generate model and pb_type XML for RAM |
| # This will generate model XML and pb_type XMLs. Since there are 4 RAMs |
| # there will be one pb_type for each of them with appropriate timings. Since |
| # we cannot model that in the VPR for now we simply use one for all 4 RAMs. |
| set(RAM_GENERATOR ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/${FAMILY}/primitives/ram/make_rams.py) |
| set(RAM_MODE_DEFS ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/${FAMILY}/primitives/ram/ram_modes.json) |
| set(RAM_SDF_FILE ${SDF_TIMING_DIR}/${RAM_TIMING_SDF}.sdf) |
| |
| set(RAM_MODEL_XML "ram.model.xml") |
| set(RAM_PBTYPE_XML "ram.pb_type.xml") |
| |
| set(RAM_CELLS_SIM "ram_sim.v") |
| set(RAM_CELLS_MAP "ram_map.v") |
| |
| get_file_target(RAM_SDF_FILE_TARGET ${RAM_SDF_FILE}) |
| |
| add_custom_command( |
| OUTPUT ${RAM_MODEL_XML} ${RAM_PBTYPE_XML} ${RAM_CELLS_SIM} ${RAM_CELLS_MAP} |
| COMMAND ${PYTHON3} ${RAM_GENERATOR} |
| --device ${DEVICE} |
| --sdf ${RAM_SDF_FILE} |
| --mode-defs ${RAM_MODE_DEFS} |
| --xml-path ${CMAKE_CURRENT_BINARY_DIR} |
| --vlog-path ${CMAKE_CURRENT_BINARY_DIR} |
| COMMAND ${CMAKE_COMMAND} -E copy ${RAM_PBTYPE_COPY} ${RAM_PBTYPE_XML} |
| DEPENDS ${PYTHON3} ${RAM_GENERATOR} ${RAM_MODE_DEFS} ${RAM_SDF_FILE_TARGET} |
| ) |
| |
| add_file_target(FILE ${RAM_MODEL_XML} GENERATED) |
| add_file_target(FILE ${RAM_PBTYPE_XML} GENERATED) |
| |
| add_file_target(FILE ${RAM_CELLS_SIM} GENERATED) |
| add_file_target(FILE ${RAM_CELLS_MAP} GENERATED) |
| |
| # Generate the arch.xml |
| get_file_target(RAM_MODEL_XML_TARGET ${RAM_MODEL_XML}) |
| get_file_target(RAM_PBTYPE_XML_TARGET ${RAM_PBTYPE_XML}) |
| |
| get_file_target(VPR_DB_TARGET ${VPR_DB_FILE}) |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ARCH_XML} |
| COMMAND python3 -m f4pga.utils.quicklogic.pp3.arch_import |
| --vpr-db ${VPR_DB_FILE} |
| --arch-out ${ARCH_XML} |
| --device ${DEVICE} |
| DEPENDS ${VPR_DB_TARGET} ${XML_DEPS} ${RAM_MODEL_XML_TARGET} ${RAM_PBTYPE_XML_TARGET} |
| ) |
| add_file_target(FILE ${ARCH_XML} GENERATED) |
| |
| # Timing import stuff |
| set(UPDATE_ARCH_TIMINGS ${f4pga-arch-defs_SOURCE_DIR}/utils/update_arch_timings.py) |
| set(PYTHON_SDF_TIMING_DIR ${f4pga-arch-defs_SOURCE_DIR}/third_party/python-sdf-timing) |
| |
| set(BELS_MAP ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/${FAMILY}/${DEVICE}-bels.json) |
| |
| set(TIMING_IMPORT |
| "${CMAKE_COMMAND} -E env PYTHONPATH=${PYTHON_SDF_TIMING_DIR}:$PYTHONPATH \ |
| ${PYTHON3} ${UPDATE_ARCH_TIMINGS} \ |
| --sdf_dir ${SDF_TIMING_DIR} \ |
| --bels_map ${BELS_MAP} \ |
| --out_arch /dev/stdout \ |
| --input_arch /dev/stdin \ |
| ") |
| |
| set(TIMING_DEPS ${SDF_FILE_TARGETS} ${BELS_MAP}) |
| |
| # Define the device type |
| define_device_type( |
| DEVICE_TYPE ${DEVICE_TYPE} |
| ARCH ${ARCH} |
| ARCH_XML ${ARCH_XML} |
| SCRIPT_OUTPUT_NAME timing |
| SCRIPTS TIMING_IMPORT |
| SCRIPT_DEPS TIMING_DEPS |
| ) |
| |
| # Set the device type properties |
| if(NOT "${GRID_LIMIT}" STREQUAL "") |
| set_target_properties(${DEVICE_TYPE} PROPERTIES USE_ROI TRUE) |
| else() |
| set_target_properties(${DEVICE_TYPE} PROPERTIES USE_ROI FALSE) |
| endif() |
| |
| set_target_properties( |
| ${DEVICE_TYPE} |
| PROPERTIES |
| PHY_DB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${PHY_DB_FILE} |
| VPR_DB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${VPR_DB_FILE} |
| CELLS_SIM ${CMAKE_CURRENT_SOURCE_DIR}/${RAM_CELLS_SIM} |
| CELLS_MAP ${CMAKE_CURRENT_SOURCE_DIR}/${RAM_CELLS_MAP} |
| LIMIT_GRAPH_TO_DEVICE FALSE |
| ) |
| |
| endfunction() |
| |
| |
| function(QUICKLOGIC_DEFINE_DEVICE) |
| # ~~~ |
| # QUICKLOGIC_DEFINE_DEVICE( |
| # FAMILY <family> |
| # ARCH <arch> |
| # DEVICES <device> <device> ... |
| # PACKAGES <package> <package> ... |
| # ) |
| # ~~~ |
| set(options) |
| set(oneValueArgs FAMILY ARCH) |
| set(multiValueArgs DEVICES PACKAGES) |
| cmake_parse_arguments( |
| QUICKLOGIC_DEFINE_DEVICE |
| "${options}" |
| "${oneValueArgs}" |
| "${multiValueArgs}" |
| ${ARGN} |
| ) |
| |
| set(FAMILY ${QUICKLOGIC_DEFINE_DEVICE_FAMILY}) |
| set(ARCH ${QUICKLOGIC_DEFINE_DEVICE_ARCH}) |
| set(DEVICES ${QUICKLOGIC_DEFINE_DEVICE_DEVICES}) |
| set(PACKAGES ${QUICKLOGIC_DEFINE_DEVICE_PACKAGES}) |
| |
| # For each device specified |
| list(LENGTH DEVICES DEVICE_COUNT) |
| math(EXPR DEVICE_COUNT_N_1 "${DEVICE_COUNT} - 1") |
| foreach(INDEX RANGE ${DEVICE_COUNT_N_1}) |
| list(GET DEVICES ${INDEX} DEVICE) |
| |
| # Include the device type subdirectory |
| set(DEVICE_TYPE ${DEVICE}-virt) |
| add_subdirectory(${DEVICE_TYPE}) |
| |
| # Get the VPR db file to add as dependency to RR graph patch |
| get_target_property_required(PHY_DB_FILE ${DEVICE_TYPE} PHY_DB_FILE) |
| get_target_property_required(VPR_DB_FILE ${DEVICE_TYPE} VPR_DB_FILE) |
| |
| # RR graph patch dependencies |
| set(DEVICE_RR_PATCH_DEPS "") |
| append_file_dependency(DEVICE_RR_PATCH_DEPS ${VPR_DB_FILE}) |
| |
| # Define the device |
| define_device( |
| DEVICE ${DEVICE} |
| ARCH ${ARCH} |
| DEVICE_TYPE ${DEVICE_TYPE} |
| PACKAGES ${PACKAGES} |
| WIRE_EBLIF ${f4pga-arch-defs_SOURCE_DIR}/quicklogic/passthrough.eblif |
| RR_PATCH_DEPS ${DEVICE_RR_PATCH_DEPS} |
| CACHE_PLACE_DELAY |
| CACHE_LOOKAHEAD |
| CACHE_ARGS |
| --constant_net_method route |
| --clock_modeling route |
| --place_delay_model delta_override |
| --router_lookahead extended_map |
| --disable_errors check_unbuffered_edges:check_route:check_place |
| --suppress_warnings sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:set_rr_graph_tool_comment |
| --route_chan_width 500 |
| --allow_dangling_combinational_nodes on |
| --allowed_tiles_for_delay_model TL-LOGIC # TODO: Make this a parameter ! |
| --allow_unrelated_clustering on |
| --balance_block_type_utilization on |
| --target_ext_pin_util 1.0 |
| EXTRA_INSTALL_FILES |
| ${PHY_DB_FILE} |
| ) |
| |
| endforeach() |
| endfunction() |