diff --git a/.github/ci/build_himbaechel.sh b/.github/ci/build_himbaechel.sh index b13e5b04..49dcc640 100644 --- a/.github/ci/build_himbaechel.sh +++ b/.github/ci/build_himbaechel.sh @@ -8,7 +8,7 @@ function build_nextpnr { mkdir build pushd build cmake .. -DARCH=himbaechel -DHIMBAECHEL_UARCH=example -DHIMBAECHEL_EXAMPLE_DEVICES=example - make nextpnr-himbaechel chipdb-himbaechel-example -j`nproc` + make nextpnr-himbaechel -j`nproc` popd } diff --git a/.gitignore b/.gitignore index 087c35ac..34a30ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/generated/ /objs/ /nextpnr-generic* /nextpnr-ice40* diff --git a/CMakeLists.txt b/CMakeLists.txt index b354da26..ed686846 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,17 +19,16 @@ if (CMAKE_EXPORT_COMPILE_COMMANDS) endif() option(BUILD_GUI "Build GUI" OFF) -option(BUILD_PYTHON "Build Python Integration" ON) +option(BUILD_PYTHON "Build Python integration" ON) +option(BUILD_RUST "Build Rust integration" OFF) option(BUILD_TESTS "Build tests" OFF) option(USE_OPENMP "Use OpenMP to accelerate analytic placer" OFF) -option(COVERAGE "Add code coverage info" OFF) option(STATIC_BUILD "Create static build" OFF) option(EXTERNAL_CHIPDB "Create build with pre-built chipdb binaries" OFF) option(SERIALIZE_CHIPDBS "Serialize device data preprocessing to minimize memory use" ON) option(WERROR "pass -Werror to compiler (used for CI)" OFF) option(PROFILER "Link against libprofiler" OFF) option(USE_IPO "Compile nextpnr with IPO" ON) -option(USE_RUST "Enable Rust bindings" OFF) set(PROGRAM_PREFIX "" CACHE STRING "Name prefix for executables") @@ -58,12 +57,12 @@ endif() check_cxx_compiler_hash_embed(HAS_HASH_EMBED CXX_FLAGS_HASH_EMBED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_HASH_EMBED}") -if (HAS_HASH_EMBED) +if (EXTERNAL_CHIPDB) + set(BBASM_MODE "binary") +elseif (HAS_HASH_EMBED) set(BBASM_MODE "embed") elseif (WIN32) set(BBASM_MODE "resource") -elseif (EXTERNAL_CHIPDB) - set(BBASM_MODE "binary") else() set(BBASM_MODE "string") endif() @@ -71,12 +70,7 @@ endif() set(BBASM_SERIALIZE ${SERIALIZE_CHIPDBS}) find_package(Threads) -if (Threads_FOUND) - find_package(TBB QUIET) - if (TBB_FOUND) - add_definitions(-DNEXTPNR_USE_TBB) - endif() -else() +if (NOT Threads_FOUND) add_definitions(-DNPNR_DISABLE_THREADS) endif() @@ -91,9 +85,9 @@ if (WASI) endif() endif() -set(link_param "") if (STATIC_BUILD) set(Boost_USE_STATIC_LIBS ON) + set(Python_USE_STATIC_LIBS ON) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") if (MSVC) @@ -101,12 +95,11 @@ if (STATIC_BUILD) set(CMAKE_CXX_FLAGS_DEBUG "/MTd") endif() else() - set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so") - set(link_param "-static") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") if (BUILD_PYTHON) find_package(ZLIB) find_package(EXPAT) - find_package(Threads) endif() endif() endif() @@ -188,14 +181,17 @@ if (BUILD_PYTHON) message(STATUS "Using built-in pybind11") add_subdirectory(3rdparty/pybind11 EXCLUDE_FROM_ALL) endif() + include_directories(${Python3_INCLUDE_DIRS}) else() find_package(Python3 3.5 REQUIRED COMPONENTS Interpreter) add_definitions("-DNO_PYTHON") endif() -if (USE_RUST) +if (BUILD_RUST) add_subdirectory(3rdparty/corrosion) corrosion_import_crate(MANIFEST_PATH rust/Cargo.toml PROFILE "release" IMPORTED_CRATES RUST_CRATES) +else() + add_definitions("-DNO_RUST") endif() if (BUILD_GUI) @@ -205,7 +201,7 @@ if (BUILD_GUI) # For higher quality backtraces set(CMAKE_ENABLE_EXPORTS ON) - add_subdirectory(3rdparty/QtPropertyBrowser ${CMAKE_CURRENT_BINARY_DIR}/generated/3rdparty/QtPropertyBrowser EXCLUDE_FROM_ALL) + add_subdirectory(3rdparty/QtPropertyBrowser EXCLUDE_FROM_ALL) else() add_definitions(-DNO_GUI) endif() @@ -219,12 +215,8 @@ add_subdirectory(3rdparty/oourafft) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/3rdparty/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) find_package(Sanitizers) -if (COVERAGE) - include(CodeCoverage) -endif() - if (BUILD_TESTS) - add_subdirectory(3rdparty/googletest/googletest ${CMAKE_CURRENT_BINARY_DIR}/generated/3rdparty/googletest EXCLUDE_FROM_ALL) + add_subdirectory(3rdparty/googletest/googletest EXCLUDE_FROM_ALL) enable_testing() endif() @@ -238,26 +230,7 @@ endif() include(BBAsm) -if (NOT DEFINED CURRENT_GIT_VERSION) - # Get the latest abbreviated commit hash of the working branch - # if not already defined outside (e.g. by package manager when building - # outside of git repository) - execute_process( - COMMAND git describe --tags --always - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE CURRENT_GIT_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif() - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/common/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/version.h) - -include_directories( - common/kernel - ${Boost_INCLUDE_DIRS} - ${Python3_INCLUDE_DIRS} -) - +add_subdirectory(common) add_subdirectory(common/kernel) add_subdirectory(common/place) add_subdirectory(common/route) @@ -265,131 +238,141 @@ add_subdirectory(frontend) add_subdirectory(json) add_subdirectory(rust) -set(COMMON_LIBRARIES - nextpnr_kernel - nextpnr_place - nextpnr_route - nextpnr_frontend - nextpnr_json - Eigen3::Eigen - oourafft -) +add_subdirectory(tests/gui) -set(EXTRA_LIB_DEPS) -if (PROFILER) - list(APPEND EXTRA_LIB_DEPS profiler) -endif() -if (TBB_FOUND) - list(APPEND EXTRA_LIB_DEPS TBB::tbb) -endif() +function(add_nextpnr_architecture target) + cmake_parse_arguments(arg "" "MAIN_SOURCE" "CORE_SOURCES;TEST_SOURCES" ${ARGN}) + + # Defs library: used by everything + # + # This library doesn't include any code, and is used to share compiler options. + + add_library(nextpnr-${target}-defs INTERFACE) + + target_include_directories(nextpnr-${target}-defs INTERFACE + ${CMAKE_SOURCE_DIR}/common/kernel + ${CMAKE_CURRENT_SOURCE_DIR} + ) + + string(TOUPPER ${family} family_upper) + target_compile_definitions(nextpnr-${target}-defs INTERFACE + NEXTPNR_NAMESPACE=nextpnr_${family} + ARCHNAME=${family} + ARCH_${family_upper} + ) + + # Core library: used by both CLI/GUI and tests + + add_library(nextpnr-${target}-core INTERFACE) + + target_sources(nextpnr-${target}-core INTERFACE + ${arg_CORE_SOURCES} + ) + + target_link_libraries(nextpnr-${target}-core INTERFACE + nextpnr-${target}-defs + nextpnr_kernel + nextpnr_place + nextpnr_route + nextpnr_frontend + nextpnr_json + ) + + target_link_libraries(nextpnr-${target}-core INTERFACE + Boost::headers + ${Boost_LIBRARIES} + Eigen3::Eigen + oourafft + ) + + if (Threads_FOUND) + target_link_libraries(nextpnr-${target}-core INTERFACE Threads::Threads) + endif() + + if (BUILD_GUI) + add_subdirectory(${CMAKE_SOURCE_DIR}/gui ${CMAKE_CURRENT_BINARY_DIR}/gui) + + # Upsettingly, there is a cyclic dependency between `common/kernel` and `gui`, so these + # two libraries have to be added separately to all executable targets. + endif() + + if (BUILD_PYTHON) + target_link_libraries(nextpnr-${target}-core INTERFACE ${Python3_LIBRARIES}) + if (STATIC_BUILD) + target_link_libraries(nextpnr-${target}-core INTERFACE ZLIB::ZLIB EXPAT::EXPAT) + endif() + endif() + + if (BUILD_RUST) + foreach (crate ${RUST_CRATES}) + target_link_libraries(nextpnr-${target}-core INTERFACE ${crate}) + endforeach() + endif() + + if (PROFILER) + target_link_libraries(nextpnr-${target}-core INTERFACE profiler) + endif() + + add_sanitizers(nextpnr-${target}-core) + + # Chip database + + add_library(nextpnr-${target}-chipdb INTERFACE) + + target_link_libraries(nextpnr-${target}-core INTERFACE nextpnr-${target}-chipdb) + + # CLI/GUI runner + + add_executable(nextpnr-${target} ${arg_MAIN_SOURCE}) + set_property(TARGET nextpnr-${target} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + set_property(TARGET nextpnr-${target} PROPERTY OUTPUT_NAME ${PROGRAM_PREFIX}nextpnr-${target}) + if (WASI) + # set(CMAKE_EXECUTABLE_SUFFIX) breaks CMake tests for some reason + set_property(TARGET nextpnr-${target} PROPERTY SUFFIX ".wasm") + endif() + + target_link_libraries(nextpnr-${target} PRIVATE nextpnr-${target}-core) + if (BUILD_GUI) + target_link_libraries(nextpnr-${target} PRIVATE nextpnr-${target}-gui) + endif() + + install(TARGETS nextpnr-${target} RUNTIME DESTINATION bin) + + # Test runner + + if (BUILD_TESTS) + add_test(NAME nextpnr-${target}-test COMMAND nextpnr-${target}-test) + + add_executable(nextpnr-${target}-test ${arg_TEST_SOURCES}) + set_property(TARGET nextpnr-${target}-test PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + + target_include_directories(nextpnr-${target}-test PRIVATE ${CMAKE_SOURCE_DIR}/3rdparty/googletest/googletest/include) + + target_link_libraries(nextpnr-${target}-test PRIVATE gtest_main nextpnr-${target}-core) + if (BUILD_GUI) + target_link_libraries(nextpnr-${target}-test PRIVATE nextpnr-${target}-gui) + target_link_libraries(nextpnr-${target}-test PRIVATE nextpnr_test_gui) + endif() + endif() + +endfunction() foreach (family ${ARCH}) message(STATUS "Configuring architecture: ${family}") - string(TOUPPER ${family} ufamily) - aux_source_directory(${family}/ ${ufamily}_FILES) - - if (BUILD_GUI) - add_subdirectory(gui ${CMAKE_CURRENT_BINARY_DIR}/generated/gui/${family} EXCLUDE_FROM_ALL) - endif() - - # Add the CLI binary target - add_executable(${PROGRAM_PREFIX}nextpnr-${family} ${${ufamily}_FILES}) - target_link_libraries(${PROGRAM_PREFIX}nextpnr-${family} PRIVATE ${COMMON_LIBRARIES}) - if (WASI) - # set(CMAKE_EXECUTABLE_SUFFIX) breaks CMake tests for some reason - set_property(TARGET ${PROGRAM_PREFIX}nextpnr-${family} PROPERTY SUFFIX ".wasm") - endif() - install(TARGETS ${PROGRAM_PREFIX}nextpnr-${family} RUNTIME DESTINATION bin) - target_compile_definitions(${PROGRAM_PREFIX}nextpnr-${family} PRIVATE MAIN_EXECUTABLE) - - # Add any new per-architecture targets here - if (BUILD_TESTS) - if (COVERAGE) - APPEND_COVERAGE_COMPILER_FLAGS() - set(COVERAGE_LCOV_EXCLUDES '/usr/include/*' '3rdparty/*' 'generated/*' 'bba/*' 'tests/*') - SETUP_TARGET_FOR_COVERAGE_LCOV( - NAME ${family}-coverage - EXECUTABLE ${PROGRAM_PREFIX}nextpnr-${family}-test - DEPENDENCIES ${PROGRAM_PREFIX}nextpnr-${family}-test - ) - endif() - - aux_source_directory(tests/${family}/ ${ufamily}_TEST_FILES) - if (BUILD_GUI) - aux_source_directory(tests/gui/ GUI_TEST_FILES) - endif() - - add_executable(${PROGRAM_PREFIX}nextpnr-${family}-test ${${ufamily}_TEST_FILES} - ${${ufamily}_FILES} ${GUI_TEST_FILES}) - target_link_libraries(${PROGRAM_PREFIX}nextpnr-${family}-test PRIVATE ${COMMON_LIBRARIES} gtest_main) - add_sanitizers(${PROGRAM_PREFIX}nextpnr-${family}-test) - - add_test(${family}-test ${CMAKE_CURRENT_BINARY_DIR}/nextpnr-${family}-test) - endif() - - # Set ${family_targets} to the list of targets being build for this family - set(family_targets ${PROGRAM_PREFIX}nextpnr-${family}) - - if (BUILD_TESTS) - set(family_targets ${family_targets} ${PROGRAM_PREFIX}nextpnr-${family}-test) - set(family_test_targets ${PROGRAM_PREFIX}nextpnr-${family}-test) - endif() - - # Include the family-specific CMakeFile add_subdirectory(${family}) - # include(${family}/family.cmake) - foreach (target ${family_targets}) - foreach (lib_dep ${EXTRA_LIB_DEPS}) - target_link_libraries(${target} PRIVATE ${lib_dep}) - endforeach() - - # Include family-specific source files to all family targets and set defines appropriately - target_include_directories(${target} PRIVATE ${family}/ ${CMAKE_CURRENT_BINARY_DIR}/generated/ rust/) - target_compile_definitions(${target} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family} ARCH_${ufamily} ARCHNAME=${family}) - target_link_libraries(${target} LINK_PUBLIC ${Boost_LIBRARIES} ${link_param}) - if (NOT MSVC) - target_link_libraries(${target} LINK_PUBLIC pthread) - endif() - add_sanitizers(${target}) - if (BUILD_GUI) - target_compile_definitions(${target} PRIVATE QT_NO_KEYWORDS) - target_include_directories(${target} PRIVATE gui/${family}/ gui/) - target_link_libraries(${target} LINK_PUBLIC gui_${family}) - endif() - if (BUILD_PYTHON) - target_link_libraries(${target} LINK_PUBLIC ${Python3_LIBRARIES}) - if (STATIC_BUILD) - target_link_libraries(${target} LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES} ${EXPAT_LIBRARIES}) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") - else() - target_link_libraries(${target} LINK_PUBLIC -lutil) - endif() - endif() - endif() - if (USE_RUST) - target_sources(${target} PRIVATE ${RUST_FILES}) - target_compile_definitions(${target} PRIVATE USE_RUST) - foreach (crate ${RUST_CRATES}) - target_link_libraries(${target} PRIVATE ${crate}) - endforeach() - endif() - endforeach() endforeach() file(GLOB_RECURSE CLANGFORMAT_FILES *.cc *.h) string(REGEX REPLACE "[^;]*/ice40/chipdb/chipdb-[^;]*.cc" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") string(REGEX REPLACE "[^;]*/ecp5/chipdb/chipdb-[^;]*.cc" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") -string(REGEX REPLACE "[^;]*nexus/chipdb/chipdb-[^;]*.cc" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") +string(REGEX REPLACE "[^;]*/nexus/chipdb/chipdb-[^;]*.cc" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") string(REGEX REPLACE "[^;]*/machxo2/chipdb/chipdb-[^;]*.cc" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") -string(REGEX REPLACE "[^;]*/3rdparty[^;]*" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") -string(REGEX REPLACE "[^;]*/generated[^;]*" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") +string(REGEX REPLACE "[^;]*/3rdparty/[^;]*" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") string(REGEX REPLACE "[^;]*/libmistral/[^;]*" "" CLANGFORMAT_FILES "${CLANGFORMAT_FILES}") -add_custom_target( - clangformat +add_custom_target(clangformat COMMAND clang-format - -style=file - -i - ${CLANGFORMAT_FILES} + -style=file + -i + ${CLANGFORMAT_FILES} ) diff --git a/cmake/BBAsm.cmake b/cmake/BBAsm.cmake index 991aa994..1e456c5f 100644 --- a/cmake/BBAsm.cmake +++ b/cmake/BBAsm.cmake @@ -58,30 +58,32 @@ endfunction() # Example usage: # # add_bba_compile_command( -# TARGET chipdb-ice40 -# OUTPUT ${CMAKE_BINARY_DIR}/chipdb/ice40/chipdb-1k.bin -# INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-1k.bba -# IDENT ice40/chipdb-1k.bba -# MODE binary +# TARGET chipdb-ice40 +# OUTPUT ice40/chipdb-1k.bin +# INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-1k.bba +# MODE binary # ) # # Paths must be absolute. # function(add_bba_compile_command) - cmake_parse_arguments(arg "" "TARGET;OUTPUT;INPUT;IDENT;MODE" "" ${ARGN}) + cmake_parse_arguments(arg "" "TARGET;OUTPUT;INPUT;MODE" "" ${ARGN}) cmake_path(GET arg_OUTPUT PARENT_PATH arg_OUTPUT_DIR) - file(MAKE_DIRECTORY ${arg_OUTPUT_DIR}) + cmake_path(GET arg_OUTPUT FILENAME arg_OUTPUT_NAME) + + set(arg_PRODUCT ${CMAKE_BINARY_DIR}/share/${arg_OUTPUT}) + cmake_path(GET arg_PRODUCT PARENT_PATH arg_PRODUCT_DIR) if (arg_MODE STREQUAL "binary" OR arg_MODE STREQUAL "resource") add_custom_command( OUTPUT - ${arg_OUTPUT} + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} COMMAND bbasm ${BBASM_ENDIAN_FLAG} ${arg_INPUT} - ${arg_OUTPUT} + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} DEPENDS bbasm ${arg_INPUT} @@ -91,18 +93,37 @@ function(add_bba_compile_command) if (arg_MODE STREQUAL "resource") file(WRITE ${arg_OUTPUT}.rc - "${arg_IDENT} RCDATA \"${arg_OUTPUT}\"") + "${arg_OUTPUT} RCDATA \"${arg_OUTPUT}\"") target_sources( - ${arg_TARGET} PRIVATE - ${arg_OUTPUT}.rc + ${arg_TARGET} PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.rc ) else() target_sources( - ${arg_TARGET} PRIVATE - ${arg_OUTPUT} + ${arg_TARGET} PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} + ) + + add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} + COMMAND + ${CMAKE_COMMAND} -E make_directory + ${arg_PRODUCT_DIR} + COMMAND + ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} + ${arg_PRODUCT} + APPEND + VERBATIM + ) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} + DESTINATION share/nextpnr/${arg_OUTPUT_DIR} ) endif() @@ -111,13 +132,13 @@ function(add_bba_compile_command) add_custom_command( OUTPUT - ${arg_OUTPUT}.cc - ${arg_OUTPUT} + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} COMMAND bbasm ${BBASM_ENDIAN_FLAG} --e ${arg_INPUT} - ${arg_OUTPUT}.cc - ${arg_OUTPUT} + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME} DEPENDS bbasm ${arg_INPUT} @@ -125,19 +146,19 @@ function(add_bba_compile_command) ) target_sources( - ${arg_TARGET} PRIVATE - ${arg_OUTPUT}.cc + ${arg_TARGET} PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc ) elseif (arg_MODE STREQUAL "string") add_custom_command( OUTPUT - ${arg_OUTPUT}.cc + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc COMMAND bbasm ${BBASM_ENDIAN_FLAG} --c ${arg_INPUT} - ${arg_OUTPUT}.cc + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc DEPENDS bbasm ${arg_INPUT} @@ -146,14 +167,14 @@ function(add_bba_compile_command) if (NOT MSVC) set_source_files_properties( - ${arg_OUTPUT}.cc PROPERTIES + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc PROPERTIES COMPILE_OPTIONS "-w;-g0;-O0" ) endif() target_sources( - ${arg_TARGET} PRIVATE - ${arg_OUTPUT}.cc + ${arg_TARGET} PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc ) endif() diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 00000000..157b8c82 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,20 @@ +if (NOT DEFINED CURRENT_GIT_VERSION) + # Get the latest abbreviated commit hash of the working branch if not already defined outside + # (e.g. by package manager when building outside of git repository). + execute_process( + COMMAND git describe --tags --always + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE CURRENT_GIT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +add_library(nextpnr_version INTERFACE) + +target_include_directories(nextpnr_version INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) + +target_sources(nextpnr_version INTERFACE + ${CMAKE_CURRENT_BINARY_DIR}/version.h +) diff --git a/common/kernel/CMakeLists.txt b/common/kernel/CMakeLists.txt index e9eb4f1f..fe0b1b4b 100644 --- a/common/kernel/CMakeLists.txt +++ b/common/kernel/CMakeLists.txt @@ -68,6 +68,7 @@ target_sources(nextpnr_kernel PUBLIC ) target_link_libraries(nextpnr_kernel INTERFACE + nextpnr_version nextpnr_frontend nextpnr_json nextpnr_rust @@ -75,6 +76,10 @@ target_link_libraries(nextpnr_kernel INTERFACE ) if (BUILD_PYTHON) + target_include_directories(nextpnr_kernel INTERFACE + ${Python3_INCLUDE_DIRS} + ) + target_link_libraries(nextpnr_kernel INTERFACE pybind11::headers ) diff --git a/common/kernel/command.cc b/common/kernel/command.cc index d760c0be..a51f9576 100644 --- a/common/kernel/command.cc +++ b/common/kernel/command.cc @@ -19,7 +19,6 @@ */ #ifndef NO_GUI -#include #include "application.h" #include "mainwindow.h" #endif diff --git a/common/kernel/pybindings.cc b/common/kernel/pybindings.cc index 737bccd5..7e21b0f8 100644 --- a/common/kernel/pybindings.cc +++ b/common/kernel/pybindings.cc @@ -249,7 +249,7 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m) m.def("parse_json", parse_json_shim); m.def("load_design", load_design_shim, py::return_value_policy::take_ownership); -#ifdef USE_RUST +#ifndef NO_RUST m.def("example_printnets", example_printnets); #endif @@ -311,21 +311,17 @@ void (*python_sighandler)(int) = nullptr; void init_python(const char *executable) { -#ifdef MAIN_EXECUTABLE static const char *python_argv[1]; python_argv[0] = executable; py::initialize_interpreter(true, 1, python_argv); py::module::import(TOSTRING(MODULE_NAME)); PyRun_SimpleString("from " TOSTRING(MODULE_NAME) " import *"); python_sighandler = signal(SIGINT, SIG_DFL); -#endif } void deinit_python() { -#ifdef MAIN_EXECUTABLE py::finalize_interpreter(); -#endif } void execute_python_file(const char *python_file) diff --git a/ecp5/CMakeLists.txt b/ecp5/CMakeLists.txt index 3b1c6276..cbeb4f85 100644 --- a/ecp5/CMakeLists.txt +++ b/ecp5/CMakeLists.txt @@ -1,12 +1,36 @@ include(FindTrellis) -add_library(chipdb-${family} OBJECT) -target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(chipdb-${family} PRIVATE .) +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_place.cc + arch_pybindings.cc + arch_pybindings.h + baseconfigs.cc + bitstream.cc + bitstream.h + cells.cc + cells.h + config.cc + config.h + constids.inc + dcu_bitstream.h + gfx.cc + gfx.h + globals.cc + globals.h + iotypes.inc + lpf.cc + pack.cc + pio.cc + pio.h +) -foreach (family_target ${family_targets}) - target_link_libraries(${family_target} PRIVATE chipdb-${family}) -endforeach() +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) set(ALL_ECP5_DEVICES 25k 45k 85k) set(ECP5_DEVICES ${ALL_ECP5_DEVICES} CACHE STRING @@ -37,10 +61,9 @@ foreach (device ${ECP5_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-${family} - OUTPUT ${CMAKE_BINARY_DIR}/share/${family}/chipdb-${device}.bin + TARGET nextpnr-${family}-chipdb + OUTPUT ${family}/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba - IDENT ${family}/chipdb-${device}.bin MODE ${BBASM_MODE} ) endforeach() diff --git a/ecp5/main.cc b/ecp5/main.cc index 55754cd4..9aa92c1e 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -17,8 +17,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "bitstream.h" #include "command.h" @@ -298,5 +296,3 @@ int main(int argc, char *argv[]) ECP5CommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt index d406ad63..cc4f8f6b 100644 --- a/frontend/CMakeLists.txt +++ b/frontend/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(nextpnr_frontend INTERFACE) target_include_directories(nextpnr_frontend INTERFACE .) -target_sources(nextpnr_frontend PUBLIC +target_sources(nextpnr_frontend INTERFACE frontend_base.h json_frontend.cc json_frontend.h diff --git a/generic/CMakeLists.txt b/generic/CMakeLists.txt index 2ca2269f..51955530 100644 --- a/generic/CMakeLists.txt +++ b/generic/CMakeLists.txt @@ -1,7 +1,37 @@ -set(VIADUCT_UARCHES "example" "okami" "fabulous") -foreach (uarch ${VIADUCT_UARCHES}) - aux_source_directory(viaduct/${uarch} UARCH_FILES) - foreach (target ${family_targets}) - target_sources(${target} PRIVATE ${UARCH_FILES}) - endforeach() -endforeach() +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_pybindings.cc + arch_pybindings.h + cells.cc + cells.h + pack.cc + viaduct_api.cc + viaduct_api.h + viaduct_constids.h + viaduct_helpers.cc + viaduct_helpers.h + viaduct/example/constids.inc + viaduct/example/example.cc + viaduct/fabulous/constids.inc + viaduct/fabulous/fab_cfg.h + viaduct/fabulous/fab_defs.h + viaduct/fabulous/fabric_parsing.h + viaduct/fabulous/fabulous.cc + viaduct/fabulous/fasm.cc + viaduct/fabulous/fasm.h + viaduct/fabulous/pack.cc + viaduct/fabulous/pack.h + viaduct/fabulous/validity_check.cc + viaduct/fabulous/validity_check.h + viaduct/okami/constids.inc + viaduct/okami/okami.cc +) + +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) + +target_sources(nextpnr-${family}-chipdb PUBLIC chipdb.cc) diff --git a/generic/chipdb.cc b/generic/chipdb.cc new file mode 100644 index 00000000..6f5d5543 --- /dev/null +++ b/generic/chipdb.cc @@ -0,0 +1 @@ +/* Intentionally left empty */ diff --git a/generic/main.cc b/generic/main.cc index f1ce373b..f263a92b 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -17,8 +17,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "command.h" #include "design_utils.h" @@ -102,5 +100,3 @@ int main(int argc, char *argv[]) GenericCommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/gowin/CMakeLists.txt b/gowin/CMakeLists.txt index 7f045ccf..4c154a48 100644 --- a/gowin/CMakeLists.txt +++ b/gowin/CMakeLists.txt @@ -1,12 +1,27 @@ include(FindApycula) -add_library(chipdb-${family} OBJECT) -target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(chipdb-${family} PRIVATE .) +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_pybindings.cc + arch_pybindings.h + cells.cc + cells.h + constids.inc + cst.cc + cst.h + gfx.cc + gfx.h + globals.cc + globals.h + pack.cc +) -foreach (family_target ${family_targets}) - target_link_libraries(${family_target} PRIVATE chipdb-${family}) -endforeach() +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) set(ALL_GOWIN_DEVICES GW1N-1 GW1NZ-1 GW1N-4 GW1N-9 GW1N-9C GW1NS-2 GW1NS-4 GW2A-18) set(GOWIN_DEVICES ${ALL_GOWIN_DEVICES} CACHE STRING @@ -30,10 +45,9 @@ foreach (device ${GOWIN_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-${family} - OUTPUT ${CMAKE_BINARY_DIR}/share/${family}/chipdb-${device}.bin + TARGET nextpnr-${family}-chipdb + OUTPUT ${family}/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba - IDENT ${family}/chipdb-${device}.bin MODE ${BBASM_MODE} ) endforeach() diff --git a/gowin/main.cc b/gowin/main.cc index 13f16fa7..aa0a242b 100644 --- a/gowin/main.cc +++ b/gowin/main.cc @@ -18,8 +18,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include #include @@ -126,4 +124,3 @@ int main(int argc, char *argv[]) GowinCommandHandler handler(argc, argv); return handler.exec(); } -#endif diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index a109a707..07f728f9 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -1,8 +1,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) -add_compile_definitions(QT_NO_KEYWORDS) - set(GUI_SOURCES application.cc application.h @@ -34,39 +32,43 @@ qt5_add_resources(GUI_QT_RESOURCES ${family}/nextpnr.qrc ) -add_library(gui_${family} STATIC +add_library(nextpnr-${target}-gui OBJECT ${GUI_SOURCES} ${GUI_QT_RESOURCES} ) -target_include_directories(gui_${family} PRIVATE +target_compile_definitions(nextpnr-${target}-gui PUBLIC + QT_NO_KEYWORDS +) + +target_include_directories(nextpnr-${target}-gui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${family} - ${CMAKE_SOURCE_DIR}/${family} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_include_directories(nextpnr-${target}-gui PRIVATE + ${CMAKE_SOURCE_DIR}/frontend + ${CMAKE_SOURCE_DIR}/json ${CMAKE_SOURCE_DIR}/3rdparty/QtPropertyBrowser/src ${CMAKE_SOURCE_DIR}/3rdparty/imgui ${CMAKE_SOURCE_DIR}/3rdparty/qtimgui - ${CMAKE_BINARY_DIR}/generated ) -target_compile_definitions(gui_${family} PRIVATE - NEXTPNR_NAMESPACE=nextpnr_${family} - ARCH_${ufamily} - ARCHNAME=${family} -) - -target_link_libraries(gui_${family} PUBLIC +target_link_libraries(nextpnr-${target}-gui PUBLIC Qt5::Widgets ) -target_link_libraries(gui_${family} PRIVATE - nextpnr_kernel + +target_link_libraries(nextpnr-${target}-gui PRIVATE + nextpnr-${target}-defs + nextpnr_version Qt5::OpenGL QtPropertyBrowser - ${EXTRA_LIB_DEPS} + pybind11_headers ) # Currently always the case when the GUI is built. if (BUILD_PYTHON) - target_sources(gui_${family} PRIVATE + target_sources(nextpnr-${target}-gui PRIVATE ../3rdparty/python-console/ColumnFormatter.cpp ../3rdparty/python-console/ParseHelper.cpp ../3rdparty/python-console/ParseHelper.BlockParseState.cpp @@ -83,7 +85,7 @@ if (BUILD_PYTHON) ../3rdparty/qtimgui/QtImGui.cpp ) - target_include_directories(gui_${family} PRIVATE + target_include_directories(nextpnr-${target}-gui PRIVATE ../3rdparty/python-console ../3rdparty/python-console/modified ) diff --git a/gui/quadtree.h b/gui/quadtree.h index 26769535..6629bc49 100644 --- a/gui/quadtree.h +++ b/gui/quadtree.h @@ -226,7 +226,7 @@ template class QuadTreeNode return *this; bound_ = other.bound_; max_elems_ = other.max_elems_; - children_ = other.max_children_; + // children_ = other.max_children_; children_ = other.children_; splitx_ = other.splitx_; splity_ = other.splity_; diff --git a/himbaechel/CMakeLists.txt b/himbaechel/CMakeLists.txt index bfe81b5a..e71468df 100644 --- a/himbaechel/CMakeLists.txt +++ b/himbaechel/CMakeLists.txt @@ -1,3 +1,37 @@ +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_pybindings.cc + arch_pybindings.h + chipdb.h + himbaechel_api.cc + himbaechel_api.h + himbaechel_constids.h + himbaechel_gfxids.h + himbaechel_helpers.cc + himbaechel_helpers.h +) + +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) + +function(add_nextpnr_himbaechel_microarchitecture microtarget) + cmake_parse_arguments(arg "" "" "CORE_SOURCES;TEST_SOURCES" ${ARGN}) + + target_sources(nextpnr-himbaechel-core INTERFACE ${arg_CORE_SOURCES}) + + add_library(nextpnr-himbaechel-${microtarget}-chipdb INTERFACE) + + target_link_libraries(nextpnr-himbaechel-core INTERFACE nextpnr-himbaechel-${microtarget}-chipdb) + + if (BUILD_TESTS) + target_sources(nextpnr-himbaechel-test PRIVATE ${arg_TEST_SOURCES}) + endif() +endfunction() + set(HIMBAECHEL_UARCHES example gowin xilinx ng-ultra) set(HIMBAECHEL_UARCH "" CACHE STRING "Microarchitectures for nextpnr-himbaechel build") @@ -5,7 +39,7 @@ set_property(CACHE HIMBAECHEL_UARCH PROPERTY STRINGS ${HIMBAECHEL_UARCHES}) if (NOT HIMBAECHEL_UARCH) message(STATUS "Microarchitecture needs to be set, set desired one with -DHIMBAECHEL_UARCH=xxx") - message(STATUS "Supported Himbaechel microarchitectures are :") + message(STATUS "Supported Himbächel microarchitectures are :") message(STATUS " all") foreach (item ${HIMBAECHEL_UARCHES}) message(STATUS " ${item}") @@ -19,18 +53,9 @@ endif() foreach (uarch ${HIMBAECHEL_UARCH}) if (NOT uarch IN_LIST HIMBAECHEL_UARCHES) - message(FATAL_ERROR "Microarchitecture ${uarch} is not a supported Himbaechel microarchitecture") + message(FATAL_ERROR "Microarchitecture ${uarch} is not a supported Himbächel microarchitecture") endif() + message(STATUS "Configuring Himbächel microarchitecture: ${uarch}") add_subdirectory(uarch/${uarch}) - aux_source_directory(uarch/${uarch} HM_UARCH_FILES) - foreach (target ${family_targets}) - target_sources(${target} PRIVATE ${HM_UARCH_FILES}) - endforeach() - if (BUILD_TESTS) - foreach (target ${family_test_targets}) - aux_source_directory(uarch/${uarch}/tests/ HM_UARCH_TEST_FILES) - target_sources(${target} PRIVATE ${HM_UARCH_TEST_FILES}) - endforeach() - endif() endforeach() diff --git a/himbaechel/main.cc b/himbaechel/main.cc index 8e25f114..b0023944 100644 --- a/himbaechel/main.cc +++ b/himbaechel/main.cc @@ -17,8 +17,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "command.h" #include "design_utils.h" @@ -106,5 +104,3 @@ int main(int argc, char *argv[]) HimbaechelCommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/himbaechel/uarch/example/CMakeLists.txt b/himbaechel/uarch/example/CMakeLists.txt index d9e6dc77..9b4acc74 100644 --- a/himbaechel/uarch/example/CMakeLists.txt +++ b/himbaechel/uarch/example/CMakeLists.txt @@ -1,7 +1,12 @@ -add_custom_target(chipdb-himbaechel-example) -foreach (target ${family_targets}) - add_dependencies(${target} chipdb-himbaechel-example) -endforeach() +set(SOURCES + constids.inc + example.cc + gfxids.inc +) + +add_nextpnr_himbaechel_microarchitecture(${uarch} + CORE_SOURCES ${SOURCES} +) set(ALL_HIMBAECHEL_EXAMPLE_DEVICES example) set(HIMBAECHEL_EXAMPLE_DEVICES ${ALL_HIMBAECHEL_EXAMPLE_DEVICES} CACHE STRING @@ -26,14 +31,9 @@ foreach (device ${HIMBAECHEL_EXAMPLE_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-himbaechel-example - OUTPUT ${CMAKE_BINARY_DIR}/share/himbaechel/example/chipdb-${device}.bin + TARGET nextpnr-himbaechel-example-chipdb + OUTPUT himbaechel/example/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba MODE binary ) endforeach() - -install( - DIRECTORY ${CMAKE_BINARY_DIR}/share/himbaechel/example - DESTINATION share/nextpnr/himbaechel/example -) diff --git a/himbaechel/uarch/gowin/CMakeLists.txt b/himbaechel/uarch/gowin/CMakeLists.txt index a7daf2f5..e2c0bbbe 100644 --- a/himbaechel/uarch/gowin/CMakeLists.txt +++ b/himbaechel/uarch/gowin/CMakeLists.txt @@ -1,9 +1,22 @@ include(FindApycula) -add_custom_target(chipdb-himbaechel-gowin ALL) -foreach (target ${family_targets}) - add_dependencies(${target} chipdb-himbaechel-gowin) -endforeach() +set(SOURCES + constids.inc + cst.cc + cst.h + globals.cc + globals.h + gowin.cc + gowin.h + gowin_utils.cc + gowin_utils.h + pack.cc + pack.h +) + +add_nextpnr_himbaechel_microarchitecture(${uarch} + CORE_SOURCES ${SOURCES} +) set(ALL_HIMBAECHEL_GOWIN_DEVICES GW1N-1 GW1NZ-1 GW1N-4 GW1N-9 GW1N-9C GW1NS-4 GW2A-18 GW2A-18C) set(HIMBAECHEL_GOWIN_DEVICES ${ALL_HIMBAECHEL_GOWIN_DEVICES} CACHE STRING @@ -31,14 +44,9 @@ foreach (device ${HIMBAECHEL_GOWIN_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-himbaechel-gowin - OUTPUT ${CMAKE_BINARY_DIR}/share/himbaechel/gowin/chipdb-${device}.bin + TARGET nextpnr-himbaechel-gowin-chipdb + OUTPUT himbaechel/gowin/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba MODE binary ) endforeach() - -install( - DIRECTORY ${CMAKE_BINARY_DIR}/share/himbaechel/gowin - DESTINATION share/nextpnr/himbaechel/gowin -) diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 7ec19123..1f163034 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -114,7 +114,7 @@ struct GowinArch : HimbaechelArch { return std::make_unique(); } -} gowinrArch; +} gowinArch; void GowinImpl::init_database(Arch *arch) { diff --git a/himbaechel/uarch/ng-ultra/CMakeLists.txt b/himbaechel/uarch/ng-ultra/CMakeLists.txt index a5e7ee8a..54b40cc6 100644 --- a/himbaechel/uarch/ng-ultra/CMakeLists.txt +++ b/himbaechel/uarch/ng-ultra/CMakeLists.txt @@ -1,14 +1,33 @@ +set(SOURCES + bitstream.cc + cells.cc + constids.inc + csv.cc + extra_data.h + location_map.cc + location_map.h + ng_ultra.cc + ng_ultra.h + pack.cc + pack.h +) + +set(TEST_SOURCES + tests/lut_dff.cc + tests/main.cc +) + +add_nextpnr_himbaechel_microarchitecture(${uarch} + CORE_SOURCES ${SOURCES} + TEST_SOURCES ${TEST_SOURCES} +) + set(HIMBAECHEL_PRJBEYOND_DB "" CACHE STRING "Path to a Project Beyond database") if (NOT HIMBAECHEL_PRJBEYOND_DB) message(FATAL_ERROR "HIMBAECHEL_PRJBEYOND_DB must be set to a prjbeyond database checkout") endif() -add_custom_target(chipdb-himbaechel-ng-ultra) -foreach (target ${family_targets}) - add_dependencies(${target} chipdb-himbaechel-ng-ultra) -endforeach() - set(ALL_HIMBAECHEL_NGULTRA_DEVICES ng-ultra) set(HIMBAECHEL_NGULTRA_DEVICES ${ALL_HIMBAECHEL_NGULTRA_DEVICES} CACHE STRING "Include support for these NG-Ultra devices (available: ${ALL_HIMBAECHEL_NGULTRA_DEVICES})") @@ -19,13 +38,13 @@ foreach (device ${HIMBAECHEL_NGULTRA_DEVICES}) message(FATAL_ERROR "Device ${device} is not a supported NG-Ultra device") endif() - string(TOUPPER ${device} upcase_device) + string(TOUPPER ${device} device_upper) add_bba_produce_command( COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen/arch_gen.py --db ${HIMBAECHEL_PRJBEYOND_DB} - --device ${upcase_device} + --device ${device_upper} --bba ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba.new OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba @@ -35,14 +54,9 @@ foreach (device ${HIMBAECHEL_NGULTRA_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-himbaechel-ng-ultra - OUTPUT ${CMAKE_BINARY_DIR}/share/himbaechel/ng-ultra/chipdb-${device}.bin + TARGET nextpnr-himbaechel-ng-ultra-chipdb + OUTPUT himbaechel/ng-ultra/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba MODE binary ) endforeach() - -install( - DIRECTORY ${CMAKE_BINARY_DIR}/share/himbaechel/ng-ultra - DESTINATION share/nextpnr/himbaechel/ng-ultra -) diff --git a/himbaechel/uarch/xilinx/CMakeLists.txt b/himbaechel/uarch/xilinx/CMakeLists.txt index f027551a..002f6d65 100644 --- a/himbaechel/uarch/xilinx/CMakeLists.txt +++ b/himbaechel/uarch/xilinx/CMakeLists.txt @@ -1,14 +1,33 @@ +set(SOURCES + cells.cc + constids.inc + extra_data.h + fasm.cc + pack_carry.cc + pack.cc + pack_clocking.cc + pack_dram.cc + pack_dsp_xc7.cc + pack.h + pack_io.cc + pins.cc + pins.h + xdc.cc + xilinx.cc + xilinx.h + xilinx_place.cc +) + +add_nextpnr_himbaechel_microarchitecture(${uarch} + CORE_SOURCES ${SOURCES} +) + set(HIMBAECHEL_PRJXRAY_DB "" CACHE STRING "Path to a project x-ray database") if (NOT HIMBAECHEL_PRJXRAY_DB) message(FATAL_ERROR "HIMBAECHEL_PRJXRAY_DB must be set to a prjxray database checkout") endif() -add_custom_target(chipdb-himbaechel-xilinx) -foreach (target ${family_targets}) - add_dependencies(${target} chipdb-himbaechel-xilinx) -endforeach() - set(HIMBAECHEL_XILINX_DEVICES "" CACHE STRING "Include support for these Xilinx devices") message(STATUS "Enabled Himbaechel-Xilinx devices: ${HIMBAECHEL_XILINX_DEVICES}") @@ -27,14 +46,9 @@ foreach (device ${HIMBAECHEL_XILINX_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-himbaechel-xilinx - OUTPUT ${CMAKE_BINARY_DIR}/share/himbaechel/xilinx/chipdb-${device}.bin + TARGET nextpnr-himbaechel-xilinx-chipdb + OUTPUT himbaechel/xilinx/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba MODE binary ) endforeach() - -install( - DIRECTORY ${CMAKE_BINARY_DIR}/share/himbaechel/xilinx - DESTINATION share/nextpnr/himbaechel/xilinx -) diff --git a/ice40/CMakeLists.txt b/ice40/CMakeLists.txt index ef12a69d..73c1f891 100644 --- a/ice40/CMakeLists.txt +++ b/ice40/CMakeLists.txt @@ -1,12 +1,42 @@ include(FindIceStorm) -add_library(chipdb-${family} OBJECT) -target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(chipdb-${family} PRIVATE .) +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_place.cc + arch_pybindings.cc + arch_pybindings.h + bitstream.cc + bitstream.h + cells.cc + cells.h + chains.cc + chains.h + constids.inc + delay.cc + gfx.cc + gfx.h + pack.cc + pcf.cc + pcf.h +) -foreach (family_target ${family_targets}) - target_link_libraries(${family_target} PRIVATE chipdb-${family}) -endforeach() +set(TEST_SOURCES + tests/hx1k.cc + tests/hx8k.cc + tests/lp1k.cc + tests/lp384.cc + tests/lp8k.cc + tests/main.cc + tests/up5k.cc +) + +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + TEST_SOURCES ${TEST_SOURCES} + MAIN_SOURCE main.cc +) set(ALL_ICE40_DEVICES 384 1k 5k u4k 8k) set(ICE40_DEVICES ${ALL_ICE40_DEVICES} CACHE STRING @@ -50,10 +80,9 @@ foreach (device ${ICE40_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-${family} - OUTPUT ${CMAKE_BINARY_DIR}/share/${family}/chipdb-${device}.bin + TARGET nextpnr-${family}-chipdb + OUTPUT ${family}/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba - IDENT ${family}/chipdb-${device}.bin MODE ${BBASM_MODE} ) endforeach() diff --git a/ice40/main.cc b/ice40/main.cc index f16ba83d..20b4dee7 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -18,8 +18,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "bitstream.h" #include "command.h" @@ -280,5 +278,3 @@ int main(int argc, char *argv[]) Ice40CommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/ice40/tests/hx1k.cc b/ice40/tests/hx1k.cc new file mode 100644 index 00000000..28139c5a --- /dev/null +++ b/ice40/tests/hx1k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class HX1KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::HX1K; + chipArgs.package = "tq144"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(HX1KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 1418); +} + +TEST_F(HX1KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 32802); +} + +TEST_F(HX1KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 345504); +} + +TEST_F(HX1KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(HX1KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/tests/hx8k.cc b/ice40/tests/hx8k.cc new file mode 100644 index 00000000..42bb7b4d --- /dev/null +++ b/ice40/tests/hx8k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class HX8KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::HX8K; + chipArgs.package = "ct256"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(HX8KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 7979); +} + +TEST_F(HX8KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 165894); +} + +TEST_F(HX8KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1806080); +} + +TEST_F(HX8KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(HX8KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/tests/lp1k.cc b/ice40/tests/lp1k.cc new file mode 100644 index 00000000..332c0c32 --- /dev/null +++ b/ice40/tests/lp1k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP1KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP1K; + chipArgs.package = "tq144"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP1KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 1418); +} + +TEST_F(LP1KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 32802); +} + +TEST_F(LP1KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 345504); +} + +TEST_F(LP1KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP1KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/tests/lp384.cc b/ice40/tests/lp384.cc new file mode 100644 index 00000000..dfa855ee --- /dev/null +++ b/ice40/tests/lp384.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP384Test : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP384; + chipArgs.package = "qn32"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP384Test, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 449); +} + +TEST_F(LP384Test, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 9830); +} + +TEST_F(LP384Test, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 94544); +} + +TEST_F(LP384Test, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP384Test, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/tests/lp8k.cc b/ice40/tests/lp8k.cc new file mode 100644 index 00000000..00a5f640 --- /dev/null +++ b/ice40/tests/lp8k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class LP8KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::LP8K; + chipArgs.package = "ct256"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(LP8KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 7979); +} + +TEST_F(LP8KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 165894); +} + +TEST_F(LP8KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1806080); +} + +TEST_F(LP8KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(LP8KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/ice40/tests/main.cc b/ice40/tests/main.cc new file mode 100644 index 00000000..b3a2a07f --- /dev/null +++ b/ice40/tests/main.cc @@ -0,0 +1,27 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/ice40/tests/up5k.cc b/ice40/tests/up5k.cc new file mode 100644 index 00000000..cf6adad9 --- /dev/null +++ b/ice40/tests/up5k.cc @@ -0,0 +1,106 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Xenia Wolf + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include "gtest/gtest.h" +#include "nextpnr.h" + +USING_NEXTPNR_NAMESPACE + +class UP5KTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + chipArgs.type = ArchArgs::UP5K; + chipArgs.package = "sg48"; + ctx = new Context(chipArgs); + } + + virtual void TearDown() { delete ctx; } + + ArchArgs chipArgs; + Context *ctx; +}; + +TEST_F(UP5KTest, bel_names) +{ + int bel_count = 0; + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); + ASSERT_EQ(bel, ctx->getBelByName(name)); + bel_count++; + } + ASSERT_EQ(bel_count, 5438); +} + +TEST_F(UP5KTest, wire_names) +{ + int wire_count = 0; + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); + assert(wire == ctx->getWireByName(name)); + wire_count++; + } + ASSERT_EQ(wire_count, 124523); +} + +TEST_F(UP5KTest, pip_names) +{ + int pip_count = 0; + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); + assert(pip == ctx->getPipByName(name)); + pip_count++; + } + ASSERT_EQ(pip_count, 1324704); +} + +TEST_F(UP5KTest, uphill_to_downhill) +{ + for (auto dst : ctx->getWires()) { + for (auto uphill_pip : ctx->getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : ctx->getPipsDownhill(ctx->getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_downhill); + found_downhill = true; + } + } + ASSERT_TRUE(found_downhill); + } + } +} + +TEST_F(UP5KTest, downhill_to_uphill) +{ + for (auto dst : ctx->getWires()) { + for (auto downhill_pip : ctx->getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : ctx->getPipsUphill(ctx->getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + ASSERT_FALSE(found_uphill); + found_uphill = true; + } + } + ASSERT_TRUE(found_uphill); + } + } +} diff --git a/json/CMakeLists.txt b/json/CMakeLists.txt index c29667ed..306a3a1e 100644 --- a/json/CMakeLists.txt +++ b/json/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(nextpnr_json INTERFACE) target_include_directories(nextpnr_json INTERFACE .) -target_sources(nextpnr_json PUBLIC +target_sources(nextpnr_json INTERFACE jsonwrite.cc jsonwrite.h ) diff --git a/machxo2/CMakeLists.txt b/machxo2/CMakeLists.txt index 3f21d75e..ee6f5262 100644 --- a/machxo2/CMakeLists.txt +++ b/machxo2/CMakeLists.txt @@ -1,12 +1,31 @@ include(FindTrellis) -add_library(chipdb-${family} OBJECT) -target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(chipdb-${family} PRIVATE .) +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_place.cc + arch_pybindings.cc + arch_pybindings.h + baseconfigs.cc + bitstream.cc + bitstream.h + cells.cc + cells.h + config.cc + config.h + constids.inc + gfx.cc + gfx.h + globals.cc + lpf.cc + pack.cc +) -foreach (family_target ${family_targets}) - target_link_libraries(${family_target} PRIVATE chipdb-${family}) -endforeach() +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) # Note that the four *X (MachXO) devices fail to import with prjtrellis commit 14ac883fa. set(ALL_MACHXO2_DEVICES 256X 640X 1200X 2280X 256 640 1200 2000 4000 7000 1300 2100 4300 6900 9400 4300D 9400D) @@ -14,9 +33,9 @@ set(MACHXO2_DEVICES 1200 6900 CACHE STRING "Include support for these MachXO2/XO3 devices (available: ${ALL_MACHXO2_DEVICES})") message(STATUS "Enabled MachXO2/XO3 devices: ${MACHXO2_DEVICES}") -configure_file(machxo2_available.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/machxo2_available.h) -target_sources(chipdb-${family} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated/machxo2_available.h) -target_include_directories(chipdb-${family} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/generated) +configure_file(machxo2_available.h.in ${CMAKE_CURRENT_BINARY_DIR}/machxo2_available.h) +target_sources(nextpnr-${family}-core PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/machxo2_available.h) +target_include_directories(nextpnr-${family}-core INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) foreach (device ${MACHXO2_DEVICES}) if (NOT device IN_LIST ALL_MACHXO2_DEVICES) @@ -42,10 +61,9 @@ foreach (device ${MACHXO2_DEVICES}) ) add_bba_compile_command( - TARGET chipdb-${family} - OUTPUT ${CMAKE_BINARY_DIR}/share/${family}/chipdb-${device}.bin + TARGET nextpnr-${family}-chipdb + OUTPUT ${family}/chipdb-${device}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${device}.bba - IDENT ${family}/chipdb-${device}.bin MODE ${BBASM_MODE} ) endforeach() diff --git a/machxo2/main.cc b/machxo2/main.cc index 54a226da..ae9af7a7 100644 --- a/machxo2/main.cc +++ b/machxo2/main.cc @@ -18,8 +18,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "bitstream.h" #include "command.h" @@ -121,5 +119,3 @@ int main(int argc, char *argv[]) MachXO2CommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/mistral/CMakeLists.txt b/mistral/CMakeLists.txt index 80a477ac..1f1be406 100644 --- a/mistral/CMakeLists.txt +++ b/mistral/CMakeLists.txt @@ -1,3 +1,27 @@ +set(SOURCES + arch.cc + archdefs.cc + archdefs.h + arch.h + arch_pybindings.cc + arch_pybindings.h + bitstream.cc + constids.inc + delay.cc + globals.cc + io.cc + lab.cc + m10k.cc + pack.cc + pins.cc + qsf.cc +) + +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) + set(MISTRAL_ROOT "" CACHE STRING "Mistral install path") set(MISTRAL_DONT_INSTALL ON) @@ -7,7 +31,14 @@ add_subdirectory(${MISTRAL_ROOT}/libmistral ${CMAKE_CURRENT_BINARY_DIR}/libmistr find_package(LibLZMA REQUIRED) -foreach (family_target ${family_targets}) - target_include_directories(${family_target} PRIVATE ${MISTRAL_ROOT}/libmistral ${CMAKE_CURRENT_BINARY_DIR}/tools ${CMAKE_CURRENT_BINARY_DIR}/libmistral ${LIBLZMA_INCLUDE_DIRS}) - target_link_libraries(${family_target} PRIVATE mistral ${LIBLZMA_LIBRARIES}) -endforeach() +target_include_directories(nextpnr-${family}-core INTERFACE + ${MISTRAL_ROOT}/libmistral + ${CMAKE_CURRENT_BINARY_DIR}/tools + ${CMAKE_CURRENT_BINARY_DIR}/libmistral + ${LIBLZMA_INCLUDE_DIRS} +) + +target_link_libraries(nextpnr-${family}-core INTERFACE + mistral + ${LIBLZMA_LIBRARIES} +) diff --git a/mistral/main.cc b/mistral/main.cc index a2df7fd9..232655b0 100644 --- a/mistral/main.cc +++ b/mistral/main.cc @@ -17,8 +17,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "command.h" #include "design_utils.h" @@ -99,5 +97,3 @@ int main(int argc, char *argv[]) MistralCommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/nexus/CMakeLists.txt b/nexus/CMakeLists.txt index e49a05a2..1c7d59a7 100644 --- a/nexus/CMakeLists.txt +++ b/nexus/CMakeLists.txt @@ -1,19 +1,34 @@ include(FindOxide) +set(SOURCES + arch.cc + archdefs.h + arch.h + arch_place.cc + arch_pybindings.cc + arch_pybindings.h + bba_version.inc + constids.inc + fasm.cc + global.cc + io.cc + pack.cc + pdc.cc + pins.cc + post_place.cc +) + +add_nextpnr_architecture(${family} + CORE_SOURCES ${SOURCES} + MAIN_SOURCE main.cc +) + # NOTE: Unlike iCE40 and ECP5; one database can cover all densities of a given family set(ALL_NEXUS_FAMILIES LIFCL) set(NEXUS_FAMILIES ${ALL_NEXUS_FAMILIES} CACHE STRING "Include support for these Nexus families (available: ${ALL_NEXUS_FAMILIES})") message(STATUS "Enabled Nexus families: ${NEXUS_FAMILIES}") -add_library(chipdb-${family} OBJECT) -target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(chipdb-${family} PRIVATE .) - -foreach (family_target ${family_targets}) - target_link_libraries(${family_target} PRIVATE chipdb-${family}) -endforeach() - foreach (subfamily ${NEXUS_FAMILIES}) if (NOT subfamily IN_LIST ALL_NEXUS_FAMILIES) message(FATAL_ERROR "${subfamily} is not a supported Nexus family") @@ -32,10 +47,9 @@ foreach (subfamily ${NEXUS_FAMILIES}) ) add_bba_compile_command( - TARGET chipdb-${family} - OUTPUT ${CMAKE_BINARY_DIR}/share/${family}/chipdb-${subfamily}.bin + TARGET nextpnr-${family}-chipdb + OUTPUT ${family}/chipdb-${subfamily}.bin INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-${subfamily}.bba - IDENT ${family}/chipdb-${subfamily}.bin MODE ${BBASM_MODE} ) endforeach() diff --git a/nexus/main.cc b/nexus/main.cc index 208b25d7..66282c90 100644 --- a/nexus/main.cc +++ b/nexus/main.cc @@ -17,8 +17,6 @@ * */ -#ifdef MAIN_EXECUTABLE - #include #include "command.h" #include "design_utils.h" @@ -115,5 +113,3 @@ int main(int argc, char *argv[]) NexusCommandHandler handler(argc, argv); return handler.exec(); } - -#endif diff --git a/rust/CMakeLists.txt b/rust/CMakeLists.txt index 9bd1b70e..2b6fce99 100644 --- a/rust/CMakeLists.txt +++ b/rust/CMakeLists.txt @@ -2,9 +2,7 @@ add_library(nextpnr_rust INTERFACE) target_include_directories(nextpnr_rust INTERFACE .) -if (USE_RUST) - target_sources(nextpnr_rust PUBLIC - rust.cc - rust.h - ) +target_sources(nextpnr_rust INTERFACE rust.h) +if (BUILD_RUST) + target_sources(nextpnr_rust INTERFACE rust.cc) endif() diff --git a/rust/rust.h b/rust/rust.h index 2ca2ffe0..c3bad7f0 100644 --- a/rust/rust.h +++ b/rust/rust.h @@ -20,7 +20,7 @@ #ifndef RUST_H #define RUST_H -#ifdef USE_RUST +#ifndef NO_RUST #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/tests b/tests index d2d5b69d..ce154121 160000 --- a/tests +++ b/tests @@ -1 +1 @@ -Subproject commit d2d5b69dd34b1a9a1e4e9466599ed18e9254fee9 +Subproject commit ce154121819a04ec921a4a6f6850c28f33c81b6c