Simplify and improve chipdb embedding/loading.

This commit is contained in:
whitequark 2020-06-25 15:11:47 +00:00
parent dc209f6344
commit 89e0cc8078
21 changed files with 270 additions and 345 deletions

46
common/embed.cc Normal file
View File

@ -0,0 +1,46 @@
#if defined(WIN32)
#include <windows.h>
#endif
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/filesystem.hpp>
#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<std::string, boost::iostreams::mapped_file> 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

50
common/embed.h Normal file
View File

@ -0,0 +1,50 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2020 whitequark <whitequark@whitequark.org>
*
* 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

View File

@ -27,6 +27,7 @@
#include "globals.h" #include "globals.h"
#include "log.h" #include "log.h"
#include "nextpnr.h" #include "nextpnr.h"
#include "embed.h"
#include "placer1.h" #include "placer1.h"
#include "placer_heap.h" #include "placer_heap.h"
#include "router1.h" #include "router1.h"
@ -60,69 +61,52 @@ void IdString::initialize_arch(const BaseCtx *ctx)
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); } 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");
}
#if defined(WIN32) auto ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
void load_chipdb(); if (ptr == nullptr)
#endif return nullptr;
return ptr->get();
}
#if defined(EXTERNAL_CHIPDB_ROOT) bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip)
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 { return get_chip_info(chip) != nullptr;
// 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);
}
} }
void load_chipdb() std::vector<std::string> Arch::getSupportedPackages(ArchArgs::ArchArgsTypes chip)
{ {
chipdb_blob_25k = mmap_file(0, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-25k.bin"); const ChipInfoPOD *chip_info = get_chip_info(chip);
chipdb_blob_45k = mmap_file(1, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-45k.bin"); std::vector<std::string> packages;
chipdb_blob_85k = mmap_file(2, EXTERNAL_CHIPDB_ROOT "/ecp5/chipdb-85k.bin"); for (int i = 0; i < chip_info->num_packages; i++)
packages.push_back(chip_info->package_info[i].name.get());
return packages;
} }
#endif
//#define LFE5U_45F_ONLY // -----------------------------------------------------------------------
Arch::Arch(ArchArgs args) : args(args) Arch::Arch(ArchArgs args) : args(args)
{ {
#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) chip_info = get_chip_info(args.type);
load_chipdb(); if (chip_info == nullptr)
#endif
#ifdef LFE5U_45F_ONLY
if (args.type == ArchArgs::LFE5U_45F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k));
} else {
log_error("Unsupported ECP5 chip type.\n"); 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<const RelPtr<ChipInfoPOD> *>(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<const RelPtr<ChipInfoPOD> *>(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<const RelPtr<ChipInfoPOD> *>(chipdb_blob_85k));
} else {
log_error("Unsupported ECP5 chip type.\n");
}
#endif
if (chip_info->const_id_count != DB_CONST_ID_COUNT) 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 " log_error("Chip database 'bba' and nextpnr code are out of sync; please rebuild (or contact distribution "
"maintainer)!\n"); "maintainer)!\n");
package_info = nullptr; package_info = nullptr;
for (int i = 0; i < chip_info->num_packages; i++) { for (int i = 0; i < chip_info->num_packages; i++) {
if (args.package == chip_info->package_info[i].name.get()) { if (args.package == chip_info->package_info[i].name.get()) {

View File

@ -207,16 +207,6 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelPtr<SpeedGradePOD> speed_grades; RelPtr<SpeedGradePOD> 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. ************************/ /************************ End of chipdb section. ************************/
struct BelIterator struct BelIterator
@ -494,6 +484,9 @@ struct Arch : BaseCtx
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
static std::vector<std::string> getSupportedPackages(ArchArgs::ArchArgsTypes chip);
std::string getChipName() const; std::string getChipName() const;
std::string getFullChipName() const; std::string getFullChipName() const;

View File

@ -30,9 +30,14 @@ foreach(device ${ECP5_DEVICES})
endif() endif()
endforeach() endforeach()
if(WIN32) if(WIN32)
list(APPEND chipdb_sources set(chipdb_rc ${CMAKE_CURRENT_BINARY_DIR}/${family}/resource/chipdb.rc)
${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/embed.cc list(APPEND chipdb_sources ${chipdb_rc})
${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/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() endif()
add_custom_target(chipdb-${family}-bins DEPENDS ${chipdb_sources} ${chipdb_binaries}) add_custom_target(chipdb-${family}-bins DEPENDS ${chipdb_sources} ${chipdb_binaries})

View File

@ -49,15 +49,25 @@ ECP5CommandHandler::ECP5CommandHandler(int argc, char **argv) : CommandHandler(a
po::options_description ECP5CommandHandler::getArchOptions() po::options_description ECP5CommandHandler::getArchOptions()
{ {
po::options_description specific("Architecture specific options"); po::options_description specific("Architecture specific options");
if (Arch::isAvailable(ArchArgs::LFE5U_12F))
specific.add_options()("12k", "set device type to 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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()("um5g-85k", "set device type to LFE5UM5G-85F");
specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)"); specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)");

View File

@ -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"

View File

@ -1,28 +0,0 @@
#include <cstdio>
#include <windows.h>
#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<const char *>(::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

View File

@ -1,4 +0,0 @@
#define BINARYFILE 256
#define IDR_CHIPDB_25K 101
#define IDR_CHIPDB_45K 102
#define IDR_CHIPDB_85K 103

View File

@ -391,7 +391,9 @@ def write_database(dev_name, chip, ddrg, endianness):
bba = BinaryBlobAssembler() bba = BinaryBlobAssembler()
bba.pre('#include "nextpnr.h"') bba.pre('#include "nextpnr.h"')
bba.pre('#include "embed.h"')
bba.pre('NEXTPNR_NAMESPACE_BEGIN') 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.post('NEXTPNR_NAMESPACE_END')
bba.push("chipdb_blob_%s" % dev_name) bba.push("chipdb_blob_%s" % dev_name)
bba.r("chip_info", "chip_info") bba.r("chip_info", "chip_info")

View File

@ -76,48 +76,38 @@ void MainWindow::createMenu()
menuDesign->addAction(actionSaveConfig); menuDesign->addAction(actionSaveConfig);
} }
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *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<const RelPtr<ChipInfoPOD> *>(chipdb_blob_25k));
} else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k));
} else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(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() void MainWindow::new_proj()
{ {
QMap<QString, int> arch; QMap<QString, int> arch;
if (Arch::isAvailable(ArchArgs::LFE5U_25F))
arch.insert("Lattice ECP5 LFE5U-25F", 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); arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F);
if (Arch::isAvailable(ArchArgs::LFE5U_85F))
arch.insert("Lattice ECP5 LFE5U-85F", 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); arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F);
if (Arch::isAvailable(ArchArgs::LFE5UM_45F))
arch.insert("Lattice ECP5 LFE5UM-45F", 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); arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F);
if (Arch::isAvailable(ArchArgs::LFE5UM5G_25F))
arch.insert("Lattice ECP5 LFE5UM5G-25F", 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); arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F);
if (Arch::isAvailable(ArchArgs::LFE5UM5G_85F))
arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F); arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F);
bool ok; bool ok;
QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
if (ok && !item.isEmpty()) { if (ok && !item.isEmpty()) {
ArchArgs chipArgs; ArchArgs chipArgs;
chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item);
QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), QStringList packages;
0, false, &ok); 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()) { if (ok && !item.isEmpty()) {
currentProj = ""; currentProj = "";

View File

@ -1,3 +0,0 @@
if(ICE40_HX1K_ONLY)
target_compile_definitions(gui_${family} PRIVATE ICE40_HX1K_ONLY=1)
endif()

View File

@ -74,59 +74,34 @@ void MainWindow::createMenu()
menuDesign->addAction(actionSaveAsc); menuDesign->addAction(actionSaveAsc);
} }
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *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<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
} else {
log_error("Unsupported iCE40 chip type.\n");
}
#else
if (chip == ArchArgs::LP384) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_384));
} else if (chip == ArchArgs::LP1K || chip == ArchArgs::HX1K) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
} else if (chip == ArchArgs::UP5K) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k));
} else if (chip == ArchArgs::LP8K || chip == ArchArgs::HX8K) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(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() void MainWindow::new_proj()
{ {
QMap<QString, int> arch; QMap<QString, int> arch;
#ifdef ICE40_HX1K_ONLY if (Arch::isAvailable(ArchArgs::LP384))
arch.insert("Lattice HX1K", ArchArgs::HX1K);
#else
arch.insert("Lattice LP384", ArchArgs::LP384); arch.insert("Lattice LP384", ArchArgs::LP384);
if (Arch::isAvailable(ArchArgs::LP1K))
arch.insert("Lattice LP1K", ArchArgs::LP1K); arch.insert("Lattice LP1K", ArchArgs::LP1K);
if (Arch::isAvailable(ArchArgs::HX1K))
arch.insert("Lattice HX1K", 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); arch.insert("Lattice UP5K", ArchArgs::UP5K);
if (Arch::isAvailable(ArchArgs::LP8K))
arch.insert("Lattice LP8K", ArchArgs::LP8K); arch.insert("Lattice LP8K", ArchArgs::LP8K);
if (Arch::isAvailable(ArchArgs::HX8K))
arch.insert("Lattice HX8K", ArchArgs::HX8K); arch.insert("Lattice HX8K", ArchArgs::HX8K);
#endif
bool ok; bool ok;
QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
if (ok && !item.isEmpty()) { if (ok && !item.isEmpty()) {
ArchArgs chipArgs; ArchArgs chipArgs;
chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item);
QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), QStringList packages;
0, false, &ok); 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()) { if (ok && !item.isEmpty()) {
currentProj = ""; currentProj = "";

View File

@ -19,12 +19,12 @@
*/ */
#include <algorithm> #include <algorithm>
#include <boost/iostreams/device/mapped_file.hpp>
#include <cmath> #include <cmath>
#include "cells.h" #include "cells.h"
#include "gfx.h" #include "gfx.h"
#include "log.h" #include "log.h"
#include "nextpnr.h" #include "nextpnr.h"
#include "embed.h"
#include "placer1.h" #include "placer1.h"
#include "placer_heap.h" #include "placer_heap.h"
#include "router1.h" #include "router1.h"
@ -44,75 +44,51 @@ void IdString::initialize_arch(const BaseCtx *ctx)
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); } 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");
}
#if defined(WIN32) auto ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
void load_chipdb(); if (ptr == nullptr)
#endif return nullptr;
return ptr->get();
}
#if defined(EXTERNAL_CHIPDB_ROOT) bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip)
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 { return get_chip_info(chip) != nullptr;
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);
}
} }
void load_chipdb() std::vector<std::string> Arch::getSupportedPackages(ArchArgs::ArchArgsTypes chip)
{ {
chipdb_blob_384 = mmap_file(0, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-384.bin"); const ChipInfoPOD *chip_info = get_chip_info(chip);
chipdb_blob_1k = mmap_file(1, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-1k.bin"); std::vector<std::string> packages;
chipdb_blob_5k = mmap_file(2, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-5k.bin"); for (int i = 0; i < chip_info->num_packages; i++)
chipdb_blob_u4k = mmap_file(3, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-u4k.bin"); packages.push_back(chip_info->packages_data[i].name.get());
chipdb_blob_8k = mmap_file(4, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-8k.bin"); return packages;
} }
#endif
// -----------------------------------------------------------------------
Arch::Arch(ArchArgs args) : args(args) Arch::Arch(ArchArgs args) : args(args)
{ {
#if defined(WIN32) || defined(EXTERNAL_CHIPDB_ROOT) fast_part = (args.type == ArchArgs::HX8K || args.type == ArchArgs::HX1K);
load_chipdb();
#endif
#ifdef ICE40_HX1K_ONLY chip_info = get_chip_info(args.type);
if (args.type == ArchArgs::HX1K) { if (chip_info == nullptr)
fast_part = true;
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
} else {
log_error("Unsupported iCE40 chip type.\n"); log_error("Unsupported iCE40 chip type.\n");
}
#else
if (args.type == ArchArgs::LP384) {
fast_part = false;
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(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<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
} else if (args.type == ArchArgs::UP5K) {
fast_part = false;
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k));
} else if (args.type == ArchArgs::U4K) {
fast_part = false;
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(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<const RelPtr<ChipInfoPOD> *>(chipdb_blob_8k));
} else {
log_error("Unsupported iCE40 chip type.\n");
}
#endif
package_info = nullptr; package_info = nullptr;
for (int i = 0; i < chip_info->num_packages; i++) { 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 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) { if (args.type == ArchArgs::LP384) {
return "Lattice LP384"; return "Lattice LP384";
} else if (args.type == ArchArgs::LP1K) { } else if (args.type == ArchArgs::LP1K) {
@ -159,7 +128,6 @@ std::string Arch::getChipName() const
} else { } else {
log_error("Unknown chip\n"); log_error("Unknown chip\n");
} }
#endif
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -642,13 +610,10 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
budget = 0; budget = 0;
else { else {
switch (args.type) { switch (args.type) {
#ifndef ICE40_HX1K_ONLY
case ArchArgs::HX8K: case ArchArgs::HX8K:
#endif
case ArchArgs::HX1K: case ArchArgs::HX1K:
budget = cin ? 190 : (same_y ? 260 : 560); budget = cin ? 190 : (same_y ? 260 : 560);
break; break;
#ifndef ICE40_HX1K_ONLY
case ArchArgs::LP384: case ArchArgs::LP384:
case ArchArgs::LP1K: case ArchArgs::LP1K:
case ArchArgs::LP8K: case ArchArgs::LP8K:
@ -658,7 +623,6 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
case ArchArgs::U4K: case ArchArgs::U4K:
budget = cin ? 560 : (same_y ? 660 : 1220); budget = cin ? 560 : (same_y ? 660 : 1220);
break; break;
#endif
default: default:
log_error("Unsupported iCE40 chip type.\n"); log_error("Unsupported iCE40 chip type.\n");
} }

View File

@ -244,20 +244,6 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelPtr<RelPtr<char>> tile_wire_names; RelPtr<RelPtr<char>> 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. ************************/ /************************ End of chipdb section. ************************/
struct BelIterator struct BelIterator
@ -428,6 +414,9 @@ struct Arch : BaseCtx
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
static std::vector<std::string> getSupportedPackages(ArchArgs::ArchArgsTypes chip);
std::string getChipName() const; std::string getChipName() const;
IdString archId() const { return id("ice40"); } IdString archId() const { return id("ice40"); }

View File

@ -1113,7 +1113,9 @@ class BinaryBlobAssembler:
bba = BinaryBlobAssembler() bba = BinaryBlobAssembler()
bba.pre('#include "nextpnr.h"') bba.pre('#include "nextpnr.h"')
bba.pre('#include "embed.h"')
bba.pre('NEXTPNR_NAMESPACE_BEGIN') 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.post('NEXTPNR_NAMESPACE_END')
bba.push("chipdb_blob_%s" % dev_name) bba.push("chipdb_blob_%s" % dev_name)
bba.r("chip_info_%s" % dev_name, "chip_info") bba.r("chip_info_%s" % dev_name, "chip_info")

View File

@ -30,9 +30,14 @@ foreach(device ${ICE40_DEVICES})
endif() endif()
endforeach() endforeach()
if(WIN32) if(WIN32)
list(APPEND chipdb_sources set(chipdb_rc ${CMAKE_CURRENT_BINARY_DIR}/${family}/resource/chipdb.rc)
${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/embed.cc list(APPEND chipdb_sources ${chipdb_rc})
${CMAKE_CURRENT_SOURCE_DIR}/${family}/resource/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() endif()
add_custom_target(chipdb-${family}-bins DEPENDS ${chipdb_sources} ${chipdb_binaries}) 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_options(chipdb-${family} PRIVATE -g0 -O0 -w)
target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) target_compile_definitions(chipdb-${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family})
target_include_directories(chipdb-${family} PRIVATE ${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}) foreach(family_target ${family_targets})
target_sources(${family_target} PRIVATE $<TARGET_OBJECTS:chipdb-${family}>) target_sources(${family_target} PRIVATE $<TARGET_OBJECTS:chipdb-${family}>)

View File

@ -50,17 +50,20 @@ Ice40CommandHandler::Ice40CommandHandler(int argc, char **argv) : CommandHandler
po::options_description Ice40CommandHandler::getArchOptions() po::options_description Ice40CommandHandler::getArchOptions()
{ {
po::options_description specific("Architecture specific options"); po::options_description specific("Architecture specific options");
#ifdef ICE40_HX1K_ONLY if (Arch::isAvailable(ArchArgs::LP384))
specific.add_options()("hx1k", "set device type to iCE40HX1K");
#else
specific.add_options()("lp384", "set device type to iCE40LP384"); specific.add_options()("lp384", "set device type to iCE40LP384");
if (Arch::isAvailable(ArchArgs::LP1K))
specific.add_options()("lp1k", "set device type to iCE40LP1K"); specific.add_options()("lp1k", "set device type to iCE40LP1K");
if (Arch::isAvailable(ArchArgs::LP8K))
specific.add_options()("lp8k", "set device type to iCE40LP8K"); specific.add_options()("lp8k", "set device type to iCE40LP8K");
if (Arch::isAvailable(ArchArgs::HX1K))
specific.add_options()("hx1k", "set device type to iCE40HX1K"); specific.add_options()("hx1k", "set device type to iCE40HX1K");
if (Arch::isAvailable(ArchArgs::HX8K))
specific.add_options()("hx8k", "set device type to iCE40HX8K"); specific.add_options()("hx8k", "set device type to iCE40HX8K");
if (Arch::isAvailable(ArchArgs::UP5K))
specific.add_options()("up5k", "set device type to iCE40UP5K"); 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()("u4k", "set device type to iCE5LP4K");
#endif
specific.add_options()("package", po::value<std::string>(), "set device package"); specific.add_options()("package", po::value<std::string>(), "set device package");
specific.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest"); specific.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest");
specific.add_options()("asc", po::value<std::string>(), "asc bitstream file to write"); specific.add_options()("asc", po::value<std::string>(), "asc bitstream file to write");
@ -204,11 +207,6 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext(std::unordered_map<s
chipArgs.type = ArchArgs::HX1K; chipArgs.type = ArchArgs::HX1K;
chipArgs.package = "tq144"; chipArgs.package = "tq144";
} }
#ifdef ICE40_HX1K_ONLY
if (chipArgs.type != ArchArgs::HX1K) {
log_error("This version of nextpnr-ice40 is built with HX1K-support only.\n");
}
#endif
auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
for (auto &val : values) for (auto &val : values)

View File

@ -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"

View File

@ -1,32 +0,0 @@
#include <cstdio>
#include <windows.h>
#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<const char *>(::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

View File

@ -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