From 89e0cc8078ecbb57ca450cc6c8a40f6b634b8c9c Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 25 Jun 2020 15:11:47 +0000 Subject: [PATCH] Simplify and improve chipdb embedding/loading. --- common/embed.cc | 46 ++++++++++++++++ common/embed.h | 50 +++++++++++++++++ ecp5/arch.cc | 86 ++++++++++++----------------- ecp5/arch.h | 13 ++--- ecp5/family.cmake | 11 ++-- ecp5/main.cc | 30 +++++++---- ecp5/resource/chipdb.rc | 5 -- ecp5/resource/embed.cc | 28 ---------- ecp5/resource/resource.h | 4 -- ecp5/trellis_import.py | 2 + gui/ecp5/mainwindow.cc | 56 ++++++++----------- gui/ice40/family.cmake | 3 -- gui/ice40/mainwindow.cc | 63 +++++++--------------- ice40/arch.cc | 110 +++++++++++++------------------------- ice40/arch.h | 17 ++---- ice40/chipdb.py | 2 + ice40/family.cmake | 14 ++--- ice40/main.cc | 30 +++++------ ice40/resource/chipdb.rc | 7 --- ice40/resource/embed.cc | 32 ----------- ice40/resource/resource.h | 6 --- 21 files changed, 270 insertions(+), 345 deletions(-) create mode 100644 common/embed.cc create mode 100644 common/embed.h delete mode 100644 ecp5/resource/chipdb.rc delete mode 100644 ecp5/resource/embed.cc delete mode 100644 ecp5/resource/resource.h delete mode 100644 ice40/resource/chipdb.rc delete mode 100644 ice40/resource/embed.cc delete mode 100644 ice40/resource/resource.h diff --git a/common/embed.cc b/common/embed.cc new file mode 100644 index 00000000..f8f439b5 --- /dev/null +++ b/common/embed.cc @@ -0,0 +1,46 @@ +#if defined(WIN32) +#include +#endif +#include +#include +#include "nextpnr.h" +#include "embed.h" + +NEXTPNR_NAMESPACE_BEGIN + +#if defined(EXTERNAL_CHIPDB_ROOT) + +const void *get_chipdb(const std::string &filename) { + static std::map files; + if (!files.count(filename)) { + std::string full_filename = EXTERNAL_CHIPDB_ROOT "/" + filename; + if (boost::filesystem::exists(full_filename)) + files[filename].open(full_filename, boost::iostreams::mapped_file::priv); + } + if (files.count(filename)) + return files.at(filename).data(); + return nullptr; +} + +#elif defined(WIN32) + +const void *get_chipdb(const std::string &filename) { + HRSRC rc = ::FindResource(nullptr, filename.c_str(), RT_RCDATA); + HGLOBAL rcData = ::LoadResource(nullptr, rc); + return ::LockResource(rcData); +} + +#else + +EmbeddedFile *EmbeddedFile::head = nullptr; + +const void *get_chipdb(const std::string &filename) { + for (EmbeddedFile *file = EmbeddedFile::head; file; file = file->next) + if (file->filename == filename) + return file->content; + return nullptr; +} + +#endif + +NEXTPNR_NAMESPACE_END diff --git a/common/embed.h b/common/embed.h new file mode 100644 index 00000000..6111bf1f --- /dev/null +++ b/common/embed.h @@ -0,0 +1,50 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2020 whitequark + * + * 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. + * + */ + +#ifndef EMBED_H +#define EMBED_H + +#include "nextpnr.h" +NEXTPNR_NAMESPACE_BEGIN + +#if !defined(EXTERNAL_CHIPDB_ROOT) && !defined(WIN32) + +struct EmbeddedFile +{ + static EmbeddedFile *head; + + std::string filename; + const void *content; + EmbeddedFile *next = nullptr; + + EmbeddedFile(const std::string &filename, const void *content) + : filename(filename), content(content) + { + next = head; + head = this; + } +}; + +#endif + +const void *get_chipdb(const std::string &filename); + +NEXTPNR_NAMESPACE_END + +#endif // EMBED_H diff --git a/ecp5/arch.cc b/ecp5/arch.cc index f947783e..a9ffd1e9 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -27,6 +27,7 @@ #include "globals.h" #include "log.h" #include "nextpnr.h" +#include "embed.h" #include "placer1.h" #include "placer_heap.h" #include "router1.h" @@ -60,69 +61,52 @@ void IdString::initialize_arch(const BaseCtx *ctx) // ----------------------------------------------------------------------- -static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } - -#if defined(WIN32) -void load_chipdb(); -#endif - -#if defined(EXTERNAL_CHIPDB_ROOT) -const char *chipdb_blob_25k = nullptr; -const char *chipdb_blob_45k = nullptr; -const char *chipdb_blob_85k = nullptr; - -boost::iostreams::mapped_file blob_files[3]; - -const char *mmap_file(int index, const char *filename) -{ - try { - // WASI only supports MAP_PRIVATE - blob_files[index].open(filename, boost::iostreams::mapped_file::priv); - if (!blob_files[index].is_open()) - log_error("Unable to read chipdb %s\n", filename); - return (const char *)blob_files[index].data(); - } catch (...) { - log_error("Unable to read chipdb %s\n", filename); +static const ChipInfoPOD *get_chip_info(ArchArgs::ArchArgsTypes chip) { + std::string chipdb; + if (chip == ArchArgs::LFE5U_12F || chip == ArchArgs::LFE5U_25F || + chip == ArchArgs::LFE5UM_25F || chip == ArchArgs::LFE5UM5G_25F) { + chipdb = "ecp5/chipdb-25k.bin"; + } else if (chip == ArchArgs::LFE5U_45F || + chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) { + chipdb = "ecp5/chipdb-45k.bin"; + } else if (chip == ArchArgs::LFE5U_85F || + chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) { + chipdb = "ecp5/chipdb-85k.bin"; + } else { + log_error("Unknown chip\n"); } + + auto ptr = reinterpret_cast *>(get_chipdb(chipdb)); + if (ptr == nullptr) + return nullptr; + return ptr->get(); } -void load_chipdb() +bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip) { - chipdb_blob_25k = mmap_file(0, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-25k.bin"); - chipdb_blob_45k = mmap_file(1, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-45k.bin"); - chipdb_blob_85k = mmap_file(2, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-85k.bin"); + return get_chip_info(chip) != nullptr; } -#endif -//#define LFE5U_45F_ONLY + +std::vector Arch::getSupportedPackages(ArchArgs::ArchArgsTypes chip) +{ + const ChipInfoPOD *chip_info = get_chip_info(chip); + std::vector packages; + for (int i = 0; i < chip_info->num_packages; i++) + packages.push_back(chip_info->package_info[i].name.get()); + return packages; +} + +// ----------------------------------------------------------------------- Arch::Arch(ArchArgs args) : args(args) { -#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) - load_chipdb(); -#endif -#ifdef LFE5U_45F_ONLY - if (args.type == ArchArgs::LFE5U_45F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_45k)); - } else { + chip_info = get_chip_info(args.type); + if (chip_info == nullptr) log_error("Unsupported ECP5 chip type.\n"); - } -#else - if (args.type == ArchArgs::LFE5U_12F || args.type == ArchArgs::LFE5U_25F || args.type == ArchArgs::LFE5UM_25F || - args.type == ArchArgs::LFE5UM5G_25F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_25k)); - } else if (args.type == ArchArgs::LFE5U_45F || args.type == ArchArgs::LFE5UM_45F || - args.type == ArchArgs::LFE5UM5G_45F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_45k)); - } else if (args.type == ArchArgs::LFE5U_85F || args.type == ArchArgs::LFE5UM_85F || - args.type == ArchArgs::LFE5UM5G_85F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_85k)); - } else { - log_error("Unsupported ECP5 chip type.\n"); - } -#endif if (chip_info->const_id_count != DB_CONST_ID_COUNT) log_error("Chip database 'bba' and nextpnr code are out of sync; please rebuild (or contact distribution " "maintainer)!\n"); + package_info = nullptr; for (int i = 0; i < chip_info->num_packages; i++) { if (args.package == chip_info->package_info[i].name.get()) { diff --git a/ecp5/arch.h b/ecp5/arch.h index c13f2041..0f351319 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -207,16 +207,6 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr speed_grades; }); -#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) -extern const char *chipdb_blob_25k; -extern const char *chipdb_blob_45k; -extern const char *chipdb_blob_85k; -#else -extern const char chipdb_blob_25k[]; -extern const char chipdb_blob_45k[]; -extern const char chipdb_blob_85k[]; -#endif - /************************ End of chipdb section. ************************/ struct BelIterator @@ -494,6 +484,9 @@ struct Arch : BaseCtx ArchArgs args; Arch(ArchArgs args); + static bool isAvailable(ArchArgs::ArchArgsTypes chip); + static std::vector getSupportedPackages(ArchArgs::ArchArgsTypes chip); + std::string getChipName() const; std::string getFullChipName() const; diff --git a/ecp5/family.cmake b/ecp5/family.cmake index 0f96811a..cc97ae5e 100644 --- a/ecp5/family.cmake +++ b/ecp5/family.cmake @@ -30,9 +30,14 @@ foreach(device ${ECP5_DEVICES}) endif() endforeach() if(WIN32) - list(APPEND chipdb_sources - ${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/embed.cc - ${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/chipdb.rc) + set(chipdb_rc ${CMAKE_CURRENT_BINARY_DIR}/${family}/resource/chipdb.rc) + list(APPEND chipdb_sources ${chipdb_rc}) + + file(WRITE ${chipdb_rc}) + foreach(device ${ECP5_DEVICES}) + file(APPEND ${chipdb_rc} + "${family}/chipdb-${device}.bin RCDATA \"${CMAKE_CURRENT_BINARY_DIR}/${family}/chipdb/chipdb-${device}.bin\"") + endforeach() endif() add_custom_target(chipdb-${family}-bins DEPENDS ${chipdb_sources} ${chipdb_binaries}) diff --git a/ecp5/main.cc b/ecp5/main.cc index f1cb9760..311f5401 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -49,16 +49,26 @@ ECP5CommandHandler::ECP5CommandHandler(int argc, char **argv) : CommandHandler(a po::options_description ECP5CommandHandler::getArchOptions() { po::options_description specific("Architecture specific options"); - specific.add_options()("12k", "set device type to LFE5U-12F"); - specific.add_options()("25k", "set device type to LFE5U-25F"); - specific.add_options()("45k", "set device type to LFE5U-45F"); - specific.add_options()("85k", "set device type to LFE5U-85F"); - specific.add_options()("um-25k", "set device type to LFE5UM-25F"); - specific.add_options()("um-45k", "set device type to LFE5UM-45F"); - specific.add_options()("um-85k", "set device type to LFE5UM-85F"); - specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F"); - specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F"); - specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F"); + if (Arch::isAvailable(ArchArgs::LFE5U_12F)) + specific.add_options()("12k", "set device type to LFE5U-12F"); + if (Arch::isAvailable(ArchArgs::LFE5U_25F)) + specific.add_options()("25k", "set device type to LFE5U-25F"); + if (Arch::isAvailable(ArchArgs::LFE5U_45F)) + specific.add_options()("45k", "set device type to LFE5U-45F"); + if (Arch::isAvailable(ArchArgs::LFE5U_85F)) + specific.add_options()("85k", "set device type to LFE5U-85F"); + if (Arch::isAvailable(ArchArgs::LFE5UM_25F)) + specific.add_options()("um-25k", "set device type to LFE5UM-25F"); + if (Arch::isAvailable(ArchArgs::LFE5UM_45F)) + specific.add_options()("um-45k", "set device type to LFE5UM-45F"); + if (Arch::isAvailable(ArchArgs::LFE5UM_85F)) + specific.add_options()("um-85k", "set device type to LFE5UM-85F"); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_25F)) + specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F"); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_45F)) + specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F"); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_85F)) + specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F"); specific.add_options()("package", po::value(), "select device package (defaults to CABGA381)"); specific.add_options()("speed", po::value(), "select device speedgrade (6, 7 or 8)"); diff --git a/ecp5/resource/chipdb.rc b/ecp5/resource/chipdb.rc deleted file mode 100644 index 60f690c6..00000000 --- a/ecp5/resource/chipdb.rc +++ /dev/null @@ -1,5 +0,0 @@ -#include "resource.h" - -IDR_CHIPDB_25K BINARYFILE "ecp5/chipdb/chipdb-25k.bin" -IDR_CHIPDB_45K BINARYFILE "ecp5/chipdb/chipdb-45k.bin" -IDR_CHIPDB_88K BINARYFILE "ecp5/chipdb/chipdb-85k.bin" diff --git a/ecp5/resource/embed.cc b/ecp5/resource/embed.cc deleted file mode 100644 index adbb7781..00000000 --- a/ecp5/resource/embed.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include "nextpnr.h" -#include "resource.h" - -NEXTPNR_NAMESPACE_BEGIN - -const char *chipdb_blob_25k; -const char *chipdb_blob_45k; -const char *chipdb_blob_85k; - -const char *LoadFileInResource(int name, int type, DWORD &size) -{ - HMODULE handle = ::GetModuleHandle(NULL); - HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name), MAKEINTRESOURCE(type)); - HGLOBAL rcData = ::LoadResource(handle, rc); - size = ::SizeofResource(handle, rc); - return static_cast(::LockResource(rcData)); -} -void load_chipdb() -{ - DWORD size = 0; - chipdb_blob_25k = LoadFileInResource(IDR_CHIPDB_25K, BINARYFILE, size); - chipdb_blob_45k = LoadFileInResource(IDR_CHIPDB_45K, BINARYFILE, size); - chipdb_blob_85k = LoadFileInResource(IDR_CHIPDB_85K, BINARYFILE, size); -} - -NEXTPNR_NAMESPACE_END \ No newline at end of file diff --git a/ecp5/resource/resource.h b/ecp5/resource/resource.h deleted file mode 100644 index 1a18bee2..00000000 --- a/ecp5/resource/resource.h +++ /dev/null @@ -1,4 +0,0 @@ -#define BINARYFILE 256 -#define IDR_CHIPDB_25K 101 -#define IDR_CHIPDB_45K 102 -#define IDR_CHIPDB_85K 103 diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py index b591e09f..174f475f 100755 --- a/ecp5/trellis_import.py +++ b/ecp5/trellis_import.py @@ -391,7 +391,9 @@ def write_database(dev_name, chip, ddrg, endianness): bba = BinaryBlobAssembler() bba.pre('#include "nextpnr.h"') + bba.pre('#include "embed.h"') bba.pre('NEXTPNR_NAMESPACE_BEGIN') + bba.post('EmbeddedFile chipdb_file_%s("ecp5/chipdb-%s.bin", chipdb_blob_%s);' % (dev_name, dev_name, dev_name)) bba.post('NEXTPNR_NAMESPACE_END') bba.push("chipdb_blob_%s" % dev_name) bba.r("chip_info", "chip_info") diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 880af047..5ae1e50f 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -76,48 +76,38 @@ void MainWindow::createMenu() menuDesign->addAction(actionSaveConfig); } -static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } - -static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip) -{ - QStringList packages; - const ChipInfoPOD *chip_info; - if (chip == ArchArgs::LFE5U_25F || chip == ArchArgs::LFE5UM_25F || chip == ArchArgs::LFE5UM5G_25F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_25k)); - } else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_45k)); - } else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_85k)); - } else { - log_error("Unsupported ECP5 chip type.\n"); - } - - for (int i = 0; i < chip_info->num_packages; i++) { - packages << chip_info->package_info[i].name.get(); - } - return packages; -} - void MainWindow::new_proj() { QMap arch; - arch.insert("Lattice ECP5 LFE5U-25F", ArchArgs::LFE5U_25F); - arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F); - arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F); - arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F); - arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F); - arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F); - arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F); - arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F); - arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F); + if (Arch::isAvailable(ArchArgs::LFE5U_25F)) + arch.insert("Lattice ECP5 LFE5U-25F", ArchArgs::LFE5U_25F); + if (Arch::isAvailable(ArchArgs::LFE5U_45F)) + arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F); + if (Arch::isAvailable(ArchArgs::LFE5U_85F)) + arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F); + if (Arch::isAvailable(ArchArgs::LFE5UM_25F)) + arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F); + if (Arch::isAvailable(ArchArgs::LFE5UM_45F)) + arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F); + if (Arch::isAvailable(ArchArgs::LFE5UM_85F)) + arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_25F)) + arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_45F)) + arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F); + if (Arch::isAvailable(ArchArgs::LFE5UM5G_85F)) + arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F); + bool ok; QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); if (ok && !item.isEmpty()) { ArchArgs chipArgs; chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); - QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), - 0, false, &ok); + QStringList packages; + for (auto package : Arch::getSupportedPackages(chipArgs.type)) + packages.append(QLatin1String(package.data(), package.size())); + QString package = QInputDialog::getItem(this, "Select package", "Package:", packages, 0, false, &ok); if (ok && !item.isEmpty()) { currentProj = ""; diff --git a/gui/ice40/family.cmake b/gui/ice40/family.cmake index ede5b805..e69de29b 100644 --- a/gui/ice40/family.cmake +++ b/gui/ice40/family.cmake @@ -1,3 +0,0 @@ -if(ICE40_HX1K_ONLY) - target_compile_definitions(gui_${family} PRIVATE ICE40_HX1K_ONLY=1) -endif() diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index dc8a3a23..3dcf90ae 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -74,59 +74,34 @@ void MainWindow::createMenu() menuDesign->addAction(actionSaveAsc); } -static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } - -static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip) -{ - QStringList packages; - const ChipInfoPOD *chip_info; -#ifdef ICE40_HX1K_ONLY - if (chip == ArchArgs::HX1K) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); - } else { - log_error("Unsupported iCE40 chip type.\n"); - } -#else - if (chip == ArchArgs::LP384) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_384)); - } else if (chip == ArchArgs::LP1K || chip == ArchArgs::HX1K) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); - } else if (chip == ArchArgs::UP5K) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_5k)); - } else if (chip == ArchArgs::LP8K || chip == ArchArgs::HX8K) { - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_8k)); - } else { - log_error("Unsupported iCE40 chip type.\n"); - } -#endif - - for (int i = 0; i < chip_info->num_packages; i++) { - packages << chip_info->packages_data[i].name.get(); - } - return packages; -} - void MainWindow::new_proj() { QMap arch; -#ifdef ICE40_HX1K_ONLY - arch.insert("Lattice HX1K", ArchArgs::HX1K); -#else - arch.insert("Lattice LP384", ArchArgs::LP384); - arch.insert("Lattice LP1K", ArchArgs::LP1K); - arch.insert("Lattice HX1K", ArchArgs::HX1K); - arch.insert("Lattice UP5K", ArchArgs::UP5K); - arch.insert("Lattice LP8K", ArchArgs::LP8K); - arch.insert("Lattice HX8K", ArchArgs::HX8K); -#endif + if (Arch::isAvailable(ArchArgs::LP384)) + arch.insert("Lattice LP384", ArchArgs::LP384); + if (Arch::isAvailable(ArchArgs::LP1K)) + arch.insert("Lattice LP1K", ArchArgs::LP1K); + if (Arch::isAvailable(ArchArgs::HX1K)) + arch.insert("Lattice HX1K", ArchArgs::HX1K); + if (Arch::isAvailable(ArchArgs::U4K)) + arch.insert("Lattice U4K", ArchArgs::U4K); + if (Arch::isAvailable(ArchArgs::UP5K)) + arch.insert("Lattice UP5K", ArchArgs::UP5K); + if (Arch::isAvailable(ArchArgs::LP8K)) + arch.insert("Lattice LP8K", ArchArgs::LP8K); + if (Arch::isAvailable(ArchArgs::HX8K)) + arch.insert("Lattice HX8K", ArchArgs::HX8K); + bool ok; QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); if (ok && !item.isEmpty()) { ArchArgs chipArgs; chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); - QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), - 0, false, &ok); + QStringList packages; + for (auto package : Arch::getSupportedPackages(chipArgs.type)) + packages.append(QLatin1String(package.data(), package.size())); + QString package = QInputDialog::getItem(this, "Select package", "Package:", packages, 0, false, &ok); if (ok && !item.isEmpty()) { currentProj = ""; diff --git a/ice40/arch.cc b/ice40/arch.cc index 545066ce..cdef91df 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -19,12 +19,12 @@ */ #include -#include #include #include "cells.h" #include "gfx.h" #include "log.h" #include "nextpnr.h" +#include "embed.h" #include "placer1.h" #include "placer_heap.h" #include "router1.h" @@ -44,75 +44,51 @@ void IdString::initialize_arch(const BaseCtx *ctx) // ----------------------------------------------------------------------- -static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } - -#if defined(WIN32) -void load_chipdb(); -#endif - -#if defined(EXTERNAL_CHIPDB_ROOT) -const char *chipdb_blob_384 = nullptr; -const char *chipdb_blob_1k = nullptr; -const char *chipdb_blob_5k = nullptr; -const char *chipdb_blob_u4k = nullptr; -const char *chipdb_blob_8k = nullptr; - -boost::iostreams::mapped_file blob_files[5]; - -const char *mmap_file(int index, const char *filename) -{ - try { - blob_files[index].open(filename, boost::iostreams::mapped_file::priv); - if (!blob_files[index].is_open()) - log_error("Unable to read chipdb %s\n", filename); - return (const char *)blob_files[index].data(); - } catch (...) { - log_error("Unable to read chipdb %s\n", filename); +static const ChipInfoPOD *get_chip_info(ArchArgs::ArchArgsTypes chip) { + std::string chipdb; + if (chip == ArchArgs::LP384) { + chipdb = "ice40/chipdb-384.bin"; + } else if (chip == ArchArgs::LP1K || chip == ArchArgs::HX1K) { + chipdb = "ice40/chipdb-1k.bin"; + } else if (chip == ArchArgs::U4K) { + chipdb = "ice40/chipdb-u4k.bin"; + } else if (chip == ArchArgs::UP5K) { + chipdb = "ice40/chipdb-5k.bin"; + } else if (chip == ArchArgs::LP8K || chip == ArchArgs::HX8K) { + chipdb = "ice40/chipdb-8k.bin"; + } else { + log_error("Unknown chip\n"); } + + auto ptr = reinterpret_cast *>(get_chipdb(chipdb)); + if (ptr == nullptr) + return nullptr; + return ptr->get(); } -void load_chipdb() +bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip) { - chipdb_blob_384 = mmap_file(0, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-384.bin"); - chipdb_blob_1k = mmap_file(1, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-1k.bin"); - chipdb_blob_5k = mmap_file(2, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-5k.bin"); - chipdb_blob_u4k = mmap_file(3, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-u4k.bin"); - chipdb_blob_8k = mmap_file(4, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-8k.bin"); + return get_chip_info(chip) != nullptr; } -#endif + +std::vector Arch::getSupportedPackages(ArchArgs::ArchArgsTypes chip) +{ + const ChipInfoPOD *chip_info = get_chip_info(chip); + std::vector packages; + for (int i = 0; i < chip_info->num_packages; i++) + packages.push_back(chip_info->packages_data[i].name.get()); + return packages; +} + +// ----------------------------------------------------------------------- + Arch::Arch(ArchArgs args) : args(args) { -#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) - load_chipdb(); -#endif + fast_part = (args.type == ArchArgs::HX8K || args.type == ArchArgs::HX1K); -#ifdef ICE40_HX1K_ONLY - if (args.type == ArchArgs::HX1K) { - fast_part = true; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); - } else { + chip_info = get_chip_info(args.type); + if (chip_info == nullptr) log_error("Unsupported iCE40 chip type.\n"); - } -#else - if (args.type == ArchArgs::LP384) { - fast_part = false; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_384)); - } else if (args.type == ArchArgs::LP1K || args.type == ArchArgs::HX1K) { - fast_part = args.type == ArchArgs::HX1K; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); - } else if (args.type == ArchArgs::UP5K) { - fast_part = false; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_5k)); - } else if (args.type == ArchArgs::U4K) { - fast_part = false; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_u4k)); - } else if (args.type == ArchArgs::LP8K || args.type == ArchArgs::HX8K) { - fast_part = args.type == ArchArgs::HX8K; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_8k)); - } else { - log_error("Unsupported iCE40 chip type.\n"); - } -#endif package_info = nullptr; for (int i = 0; i < chip_info->num_packages; i++) { @@ -135,13 +111,6 @@ Arch::Arch(ArchArgs args) : args(args) std::string Arch::getChipName() const { -#ifdef ICE40_HX1K_ONLY - if (args.type == ArchArgs::HX1K) { - return "Lattice LP1K"; - } else { - log_error("Unsupported iCE40 chip type.\n"); - } -#else if (args.type == ArchArgs::LP384) { return "Lattice LP384"; } else if (args.type == ArchArgs::LP1K) { @@ -159,7 +128,6 @@ std::string Arch::getChipName() const } else { log_error("Unknown chip\n"); } -#endif } // ----------------------------------------------------------------------- @@ -642,13 +610,10 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay budget = 0; else { switch (args.type) { -#ifndef ICE40_HX1K_ONLY case ArchArgs::HX8K: -#endif case ArchArgs::HX1K: budget = cin ? 190 : (same_y ? 260 : 560); break; -#ifndef ICE40_HX1K_ONLY case ArchArgs::LP384: case ArchArgs::LP1K: case ArchArgs::LP8K: @@ -658,7 +623,6 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay case ArchArgs::U4K: budget = cin ? 560 : (same_y ? 660 : 1220); break; -#endif default: log_error("Unsupported iCE40 chip type.\n"); } diff --git a/ice40/arch.h b/ice40/arch.h index 356891ce..0d8e7d76 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -244,20 +244,6 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr> tile_wire_names; }); -#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) -extern const char *chipdb_blob_384; -extern const char *chipdb_blob_1k; -extern const char *chipdb_blob_5k; -extern const char *chipdb_blob_u4k; -extern const char *chipdb_blob_8k; -#else -extern const char chipdb_blob_384[]; -extern const char chipdb_blob_1k[]; -extern const char chipdb_blob_5k[]; -extern const char chipdb_blob_u4k[]; -extern const char chipdb_blob_8k[]; -#endif - /************************ End of chipdb section. ************************/ struct BelIterator @@ -428,6 +414,9 @@ struct Arch : BaseCtx ArchArgs args; Arch(ArchArgs args); + static bool isAvailable(ArchArgs::ArchArgsTypes chip); + static std::vector getSupportedPackages(ArchArgs::ArchArgsTypes chip); + std::string getChipName() const; IdString archId() const { return id("ice40"); } diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 195c08ae..7b3ad999 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -1113,7 +1113,9 @@ class BinaryBlobAssembler: bba = BinaryBlobAssembler() bba.pre('#include "nextpnr.h"') +bba.pre('#include "embed.h"') bba.pre('NEXTPNR_NAMESPACE_BEGIN') +bba.post('EmbeddedFile chipdb_file_%s("ice40/chipdb-%s.bin", chipdb_blob_%s);' % (dev_name, dev_name, dev_name)) bba.post('NEXTPNR_NAMESPACE_END') bba.push("chipdb_blob_%s" % dev_name) bba.r("chip_info_%s" % dev_name, "chip_info") diff --git a/ice40/family.cmake b/ice40/family.cmake index 5921fa3c..fd16df40 100644 --- a/ice40/family.cmake +++ b/ice40/family.cmake @@ -30,9 +30,14 @@ foreach(device ${ICE40_DEVICES}) endif() endforeach() if(WIN32) - list(APPEND chipdb_sources - ${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/embed.cc - ${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/chipdb.rc) + set(chipdb_rc ${CMAKE_CURRENT_BINARY_DIR}/${family}/resource/chipdb.rc) + list(APPEND chipdb_sources ${chipdb_rc}) + + file(WRITE ${chipdb_rc}) + foreach(device ${ICE40_DEVICES}) + file(APPEND ${chipdb_rc} + "${family}/chipdb-${device}.bin RCDATA \"${CMAKE_CURRENT_BINARY_DIR}/${family}/chipdb/chipdb-${device}.bin\"") + endforeach() endif() add_custom_target(chipdb-${family}-bins DEPENDS ${chipdb_sources} ${chipdb_binaries}) @@ -42,9 +47,6 @@ add_dependencies(chipdb-${family} chipdb-${family}-bins) target_compile_options(chipdb-${family} PRIVATE -g0 -O0 -w) target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) target_include_directories(chipdb-${family} PRIVATE ${family}) -if(ICE40_DEVICES STREQUAL "1k") - target_compile_definitions(chipdb-${family} PUBLIC ICE40_HX1K_ONLY=1) -endif() foreach(family_target ${family_targets}) target_sources(${family_target} PRIVATE $) diff --git a/ice40/main.cc b/ice40/main.cc index 07c91399..497d580b 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -50,17 +50,20 @@ Ice40CommandHandler::Ice40CommandHandler(int argc, char **argv) : CommandHandler po::options_description Ice40CommandHandler::getArchOptions() { po::options_description specific("Architecture specific options"); -#ifdef ICE40_HX1K_ONLY - specific.add_options()("hx1k", "set device type to iCE40HX1K"); -#else - specific.add_options()("lp384", "set device type to iCE40LP384"); - specific.add_options()("lp1k", "set device type to iCE40LP1K"); - specific.add_options()("lp8k", "set device type to iCE40LP8K"); - specific.add_options()("hx1k", "set device type to iCE40HX1K"); - specific.add_options()("hx8k", "set device type to iCE40HX8K"); - specific.add_options()("up5k", "set device type to iCE40UP5K"); - specific.add_options()("u4k", "set device type to iCE5LP4K"); -#endif + if (Arch::isAvailable(ArchArgs::LP384)) + specific.add_options()("lp384", "set device type to iCE40LP384"); + if (Arch::isAvailable(ArchArgs::LP1K)) + specific.add_options()("lp1k", "set device type to iCE40LP1K"); + if (Arch::isAvailable(ArchArgs::LP8K)) + specific.add_options()("lp8k", "set device type to iCE40LP8K"); + if (Arch::isAvailable(ArchArgs::HX1K)) + specific.add_options()("hx1k", "set device type to iCE40HX1K"); + if (Arch::isAvailable(ArchArgs::HX8K)) + specific.add_options()("hx8k", "set device type to iCE40HX8K"); + if (Arch::isAvailable(ArchArgs::UP5K)) + specific.add_options()("up5k", "set device type to iCE40UP5K"); + if (Arch::isAvailable(ArchArgs::U4K)) + specific.add_options()("u4k", "set device type to iCE5LP4K"); specific.add_options()("package", po::value(), "set device package"); specific.add_options()("pcf", po::value(), "PCF constraints file to ingest"); specific.add_options()("asc", po::value(), "asc bitstream file to write"); @@ -204,11 +207,6 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map(new Context(chipArgs)); for (auto &val : values) diff --git a/ice40/resource/chipdb.rc b/ice40/resource/chipdb.rc deleted file mode 100644 index 0b248d74..00000000 --- a/ice40/resource/chipdb.rc +++ /dev/null @@ -1,7 +0,0 @@ -#include "resource.h" - -IDR_CHIPDB_384 BINARYFILE "ice40/chipdb/chipdb-384.bin" -IDR_CHIPDB_1K BINARYFILE "ice40/chipdb/chipdb-1k.bin" -IDR_CHIPDB_5K BINARYFILE "ice40/chipdb/chipdb-5k.bin" -IDR_CHIPDB_U4K BINARYFILE "ice40/chipdb/chipdb-u4k.bin" -IDR_CHIPDB_8K BINARYFILE "ice40/chipdb/chipdb-8k.bin" diff --git a/ice40/resource/embed.cc b/ice40/resource/embed.cc deleted file mode 100644 index 048ac474..00000000 --- a/ice40/resource/embed.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include "nextpnr.h" -#include "resource.h" - -NEXTPNR_NAMESPACE_BEGIN - -const char *chipdb_blob_384; -const char *chipdb_blob_1k; -const char *chipdb_blob_5k; -const char *chipdb_blob_u4k; -const char *chipdb_blob_8k; - -const char *LoadFileInResource(int name, int type, DWORD &size) -{ - HMODULE handle = ::GetModuleHandle(NULL); - HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name), MAKEINTRESOURCE(type)); - HGLOBAL rcData = ::LoadResource(handle, rc); - size = ::SizeofResource(handle, rc); - return static_cast(::LockResource(rcData)); -} -void load_chipdb() -{ - DWORD size = 0; - chipdb_blob_384 = LoadFileInResource(IDR_CHIPDB_384, BINARYFILE, size); - chipdb_blob_1k = LoadFileInResource(IDR_CHIPDB_1K, BINARYFILE, size); - chipdb_blob_5k = LoadFileInResource(IDR_CHIPDB_5K, BINARYFILE, size); - chipdb_blob_u4k = LoadFileInResource(IDR_CHIPDB_U4K, BINARYFILE, size); - chipdb_blob_8k = LoadFileInResource(IDR_CHIPDB_8K, BINARYFILE, size); -} - -NEXTPNR_NAMESPACE_END diff --git a/ice40/resource/resource.h b/ice40/resource/resource.h deleted file mode 100644 index 4dacbf61..00000000 --- a/ice40/resource/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#define BINARYFILE 256 -#define IDR_CHIPDB_384 101 -#define IDR_CHIPDB_1K 102 -#define IDR_CHIPDB_5K 103 -#define IDR_CHIPDB_8K 104 -#define IDR_CHIPDB_U4K 105