Support variants for ECP5

This commit is contained in:
Miodrag Milanovic 2023-05-16 16:34:46 +02:00
parent 3d0b50a402
commit 97d4e7c1a5
14 changed files with 367 additions and 359 deletions

View File

@ -34,6 +34,7 @@
#include "router2.h" #include "router2.h"
#include "timing.h" #include "timing.h"
#include "util.h" #include "util.h"
#include "ecp5_available.h"
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
@ -48,60 +49,89 @@ void IdString::initialize_arch(const BaseCtx *ctx)
#undef X #undef X
} }
// ----------------------------------------------------------------------- // ---------------------------------------------------------------
static const ChipInfoPOD *get_chip_info(ArchArgs::ArchArgsTypes chip) static void get_chip_info(std::string device, const DeviceInfoPOD **device_info, const ChipInfoPOD **chip_info, const PackageInfoPOD **package_info,
const char **device_name, const char **package_name, Arch::ArchTypes *type, Arch::SpeedGrade *speed)
{ {
std::string chipdb; std::stringstream ss(available_devices);
if (chip == ArchArgs::LFE5U_12F || chip == ArchArgs::LFE5U_25F || chip == ArchArgs::LFE5UM_25F || std::string name;
chip == ArchArgs::LFE5UM5G_25F) { while (getline(ss, name, ';')) {
chipdb = "ecp5/chipdb-25k.bin"; std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
} else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) { auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
chipdb = "ecp5/chipdb-45k.bin"; if (!db_ptr)
} else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) { continue; // chipdb not available
chipdb = "ecp5/chipdb-85k.bin"; for (auto &dev : db_ptr->get()->devices) {
} else { for (auto &chip : dev.variants) {
log_error("Unknown chip\n"); for (auto &pkg : chip.packages) {
for (auto &speedgrade : chip.speed_grades) {
for (auto &rating : chip.suffixes) {
std::string devname = stringf("%s-%d%s%s", chip.name.get(), speedgrade.speed,
pkg.short_name.get(), rating.suffix.get());
if (device == devname) {
*device_info = &dev;
*chip_info = db_ptr->get();
*package_info = nullptr;
*package_name = pkg.name.get();
*device_name = chip.name.get();
*type = Arch::ArchTypes::NONE;
if (strcmp(*device_name,"LFE5U-12F")==0 || strcmp(*device_name,"LAE5U-12F")==0)
*type = Arch::ArchTypes::LFE5U_12F;
else if (strcmp(*device_name,"LFE5U-25F")==0)
*type = Arch::ArchTypes::LFE5U_25F;
else if (strcmp(*device_name,"LFE5U-45F")==0)
*type = Arch::ArchTypes::LFE5U_45F;
else if (strcmp(*device_name,"LFE5U-85F")==0)
*type = Arch::ArchTypes::LFE5U_85F;
else if (strcmp(*device_name,"LFE5UM-25F")==0 || strcmp(*device_name,"LAE5UM-25F")==0)
*type = Arch::ArchTypes::LFE5UM_25F;
else if (strcmp(*device_name,"LFE5UM-45F")==0 || strcmp(*device_name,"LAE5UM-45F")==0)
*type = Arch::ArchTypes::LFE5UM_45F;
else if (strcmp(*device_name,"LFE5UM-85F")==0 || strcmp(*device_name,"LAE5UM-85F")==0)
*type = Arch::ArchTypes::LFE5UM_85F;
else if (strcmp(*device_name,"LFE5UM5G-25F")==0)
*type = Arch::ArchTypes::LFE5UM5G_25F;
else if (strcmp(*device_name,"LFE5UM5G-45F")==0)
*type = Arch::ArchTypes::LFE5UM5G_45F;
else if (strcmp(*device_name,"LFE5UM5G-85F")==0)
*type = Arch::ArchTypes::LFE5UM5G_85F;
else
log_error("Unsupported device '%s'.\n", *device_name);
*speed = Arch::SpeedGrade(speedgrade.speed - 6);
if (strstr(*device_name,"LFE5UM5G")) {
*speed = Arch::SPEED_8_5G;
}
for (auto &pi : db_ptr->get()->package_info) {
if (strcasecmp(pkg.name.get(),pi.name.get())==0) {
*package_info = &pi;
break;
}
}
return;
}
}
}
}
}
}
} }
auto ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
if (ptr == nullptr)
return nullptr;
return ptr->get();
} }
bool Arch::is_available(ArchArgs::ArchArgsTypes chip) { return get_chip_info(chip) != nullptr; } // ---------------------------------------------------------------
std::vector<std::string> Arch::get_supported_packages(ArchArgs::ArchArgsTypes chip)
{
const ChipInfoPOD *chip_info = get_chip_info(chip);
std::vector<std::string> packages;
for (auto &pkg : chip_info->package_info)
packages.push_back(pkg.name.get());
return packages;
}
// -----------------------------------------------------------------------
Arch::Arch(ArchArgs args) : args(args) Arch::Arch(ArchArgs args) : args(args)
{ {
chip_info = get_chip_info(args.type); get_chip_info(args.device, &device_info, &chip_info, &package_info, &device_name, &package_name, &type, &speed);
if (chip_info == nullptr) if (chip_info == nullptr)
log_error("Unsupported ECP5 chip type.\n"); log_error("Unsupported device '%s'.\n", args.device.c_str());
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; speed_grade = &(chip_info->speed_grades[speed]);
for (auto &pkg : chip_info->package_info) {
if (args.package == pkg.name.get()) {
package_info = &pkg;
break;
}
}
speed_grade = &(chip_info->speed_grades[args.speed]);
if (!package_info) if (!package_info)
log_error("Unsupported package '%s' for '%s'.\n", args.package.c_str(), getChipName().c_str()); log_error("Unsupported package '%s' for '%s'.\n", package_name, getChipName().c_str());
tile_status.resize(chip_info->num_tiles); tile_status.resize(chip_info->num_tiles);
for (int i = 0; i < chip_info->num_tiles; i++) { for (int i = 0; i < chip_info->num_tiles; i++) {
@ -160,81 +190,35 @@ Arch::Arch(ArchArgs args) : args(args)
lutperm_allowed.resize(chip_info->width * chip_info->height * 4); lutperm_allowed.resize(chip_info->width * chip_info->height * 4);
} }
// ----------------------------------------------------------------------- void Arch::list_devices()
std::string Arch::getChipName() const
{ {
if (args.type == ArchArgs::LFE5U_12F) { log("Supported devices: \n");
return "LFE5U-12F"; std::stringstream ss(available_devices);
} else if (args.type == ArchArgs::LFE5U_25F) { std::string name;
return "LFE5U-25F"; while (getline(ss, name, ';')) {
} else if (args.type == ArchArgs::LFE5U_45F) { std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
return "LFE5U-45F"; auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
} else if (args.type == ArchArgs::LFE5U_85F) { if (!db_ptr)
return "LFE5U-85F"; continue; // chipdb not available
} else if (args.type == ArchArgs::LFE5UM_25F) { for (auto &dev : db_ptr->get()->devices) {
return "LFE5UM-25F"; for (auto &chip : dev.variants) {
} else if (args.type == ArchArgs::LFE5UM_45F) { for (auto &pkg : chip.packages) {
return "LFE5UM-45F"; for (auto &speedgrade : chip.speed_grades) {
} else if (args.type == ArchArgs::LFE5UM_85F) { for (auto &rating : chip.suffixes) {
return "LFE5UM-85F"; log(" %s-%d%s%s\n", chip.name.get(), speedgrade.speed, pkg.short_name.get(),
} else if (args.type == ArchArgs::LFE5UM5G_25F) { rating.suffix.get());
return "LFE5UM5G-25F"; }
} else if (args.type == ArchArgs::LFE5UM5G_45F) { }
return "LFE5UM5G-45F"; }
} else if (args.type == ArchArgs::LFE5UM5G_85F) { }
return "LFE5UM5G-85F";
} else {
log_error("Unknown chip\n");
} }
}
std::string Arch::get_full_chip_name() const
{
std::string name = getChipName();
name += "-";
switch (args.speed) {
case ArchArgs::SPEED_6:
name += "6";
break;
case ArchArgs::SPEED_7:
name += "7";
break;
case ArchArgs::SPEED_8:
case ArchArgs::SPEED_8_5G:
name += "8";
break;
} }
name += args.package;
return name;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
IdString Arch::archArgsToId(ArchArgs args) const std::string Arch::getChipName() const { return args.device; }
{ IdString Arch::archArgsToId(ArchArgs args) const { return id(args.device); }
if (args.type == ArchArgs::LFE5U_12F)
return id_lfe5u_12f;
if (args.type == ArchArgs::LFE5U_25F)
return id_lfe5u_25f;
if (args.type == ArchArgs::LFE5U_45F)
return id_lfe5u_45f;
if (args.type == ArchArgs::LFE5U_85F)
return id_lfe5u_85f;
if (args.type == ArchArgs::LFE5UM_25F)
return id_lfe5um_25f;
if (args.type == ArchArgs::LFE5UM_45F)
return id_lfe5um_45f;
if (args.type == ArchArgs::LFE5UM_85F)
return id_lfe5um_85f;
if (args.type == ArchArgs::LFE5UM5G_25F)
return id_lfe5um5g_25f;
if (args.type == ArchArgs::LFE5UM5G_45F)
return id_lfe5um5g_45f;
if (args.type == ArchArgs::LFE5UM5G_85F)
return id_lfe5um5g_85f;
return IdString();
}
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -500,7 +484,7 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second); int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second);
return (120 - 22 * args.speed) * return (120 - 22 * speed) *
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
} }
@ -578,7 +562,7 @@ delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdStr
int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y); int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y);
return (120 - 22 * args.speed) * return (120 - 22 * speed) *
(3 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); (3 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
} }

View File

@ -169,6 +169,28 @@ NPNR_PACKED_STRUCT(struct SpeedGradePOD {
RelSlice<PipDelayPOD> pip_classes; RelSlice<PipDelayPOD> pip_classes;
}); });
NPNR_PACKED_STRUCT(struct PackageSupportedPOD {
RelPtr<char> name;
RelPtr<char> short_name;
});
NPNR_PACKED_STRUCT(struct SuffixeSupportedPOD { RelPtr<char> suffix; });
NPNR_PACKED_STRUCT(struct SpeedSupportedPOD { int32_t speed; });
NPNR_PACKED_STRUCT(struct VariantInfoPOD {
RelPtr<char> name;
RelSlice<PackageSupportedPOD> packages;
RelSlice<SpeedSupportedPOD> speed_grades;
RelSlice<SuffixeSupportedPOD> suffixes;
});
NPNR_PACKED_STRUCT(struct DeviceInfoPOD {
RelPtr<char> family;
RelPtr<char> name;
RelSlice<VariantInfoPOD> variants;
});
NPNR_PACKED_STRUCT(struct ChipInfoPOD { NPNR_PACKED_STRUCT(struct ChipInfoPOD {
int32_t width, height; int32_t width, height;
int32_t num_tiles; int32_t num_tiles;
@ -181,6 +203,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelSlice<PIOInfoPOD> pio_info; RelSlice<PIOInfoPOD> pio_info;
RelSlice<TileInfoPOD> tile_info; RelSlice<TileInfoPOD> tile_info;
RelSlice<SpeedGradePOD> speed_grades; RelSlice<SpeedGradePOD> speed_grades;
RelSlice<DeviceInfoPOD> devices;
}); });
/************************ End of chipdb section. ************************/ /************************ End of chipdb section. ************************/
@ -394,28 +417,7 @@ struct PipRange
struct ArchArgs struct ArchArgs
{ {
enum ArchArgsTypes std::string device;
{
NONE,
LFE5U_12F,
LFE5U_25F,
LFE5U_45F,
LFE5U_85F,
LFE5UM_25F,
LFE5UM_45F,
LFE5UM_85F,
LFE5UM5G_25F,
LFE5UM5G_45F,
LFE5UM5G_85F,
} type = NONE;
std::string package;
enum SpeedGrade
{
SPEED_6 = 0,
SPEED_7,
SPEED_8,
SPEED_8_5G,
} speed = SPEED_6;
}; };
struct DelayKey struct DelayKey
@ -446,9 +448,34 @@ struct ArchRanges : BaseArchRanges
struct Arch : BaseArch<ArchRanges> struct Arch : BaseArch<ArchRanges>
{ {
const DeviceInfoPOD *device_info;
const ChipInfoPOD *chip_info; const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info; const PackageInfoPOD *package_info;
const SpeedGradePOD *speed_grade; const SpeedGradePOD *speed_grade;
const char *package_name;
const char *device_name;
enum ArchTypes
{
NONE,
LFE5U_12F,
LFE5U_25F,
LFE5U_45F,
LFE5U_85F,
LFE5UM_25F,
LFE5UM_45F,
LFE5UM_85F,
LFE5UM5G_25F,
LFE5UM5G_45F,
LFE5UM5G_85F,
} type = NONE;
enum SpeedGrade
{
SPEED_6 = 0,
SPEED_7,
SPEED_8,
SPEED_8_5G,
} speed = SPEED_6;
mutable dict<IdStringList, PipId> pip_by_name; mutable dict<IdStringList, PipId> pip_by_name;
@ -513,11 +540,9 @@ struct Arch : BaseArch<ArchRanges>
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
static bool is_available(ArchArgs::ArchArgsTypes chip); static void list_devices();
static std::vector<std::string> get_supported_packages(ArchArgs::ArchArgsTypes chip);
std::string getChipName() const override; std::string getChipName() const override;
std::string get_full_chip_name() const;
ArchArgs archArgs() const override { return args; } ArchArgs archArgs() const override { return args; }
IdString archArgsToId(ArchArgs args) const override; IdString archArgsToId(ArchArgs args) const override;

View File

@ -188,8 +188,8 @@ bool Arch::isBelLocationValid(BelId bel, bool explain_invalid) const
if (cell == nullptr) { if (cell == nullptr) {
return true; return true;
} else if (cell->type.in(id_DCUA, id_EXTREFB, id_PCSCLKDIV)) { } else if (cell->type.in(id_DCUA, id_EXTREFB, id_PCSCLKDIV)) {
return args.type != ArchArgs::LFE5U_25F && args.type != ArchArgs::LFE5U_45F && return type != Arch::ArchTypes::LFE5U_25F && type != Arch::ArchTypes::LFE5U_45F &&
args.type != ArchArgs::LFE5U_85F; type != Arch::ArchTypes::LFE5U_85F;
} else if (cell->type.in(id_MULT18X18D, id_ALU54B)) { } else if (cell->type.in(id_MULT18X18D, id_ALU54B)) {
return is_dsp_location_valid(cell); return is_dsp_location_valid(cell);
} else { } else {

View File

@ -30,7 +30,7 @@ NEXTPNR_NAMESPACE_BEGIN
void arch_wrap_python(py::module &m) void arch_wrap_python(py::module &m)
{ {
using namespace PythonConversion; using namespace PythonConversion;
py::class_<ArchArgs>(m, "ArchArgs").def_readwrite("type", &ArchArgs::type); py::class_<ArchArgs>(m, "ArchArgs").def_readwrite("device", &ArchArgs::device);
py::class_<BelId>(m, "BelId").def_readwrite("index", &BelId::index); py::class_<BelId>(m, "BelId").def_readwrite("index", &BelId::index);

View File

@ -5,7 +5,6 @@ NEXTPNR_NAMESPACE_BEGIN
namespace BaseConfigs { namespace BaseConfigs {
void config_empty_lfe5u_25f(ChipConfig &cc) void config_empty_lfe5u_25f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5U-25F";
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0");
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0");
cc.tiles["CIB_R49C42:VCIB_DCU0"].add_enum("CIB.JA1MUX", "0"); cc.tiles["CIB_R49C42:VCIB_DCU0"].add_enum("CIB.JA1MUX", "0");
@ -189,7 +188,6 @@ void config_empty_lfe5u_25f(ChipConfig &cc)
void config_empty_lfe5u_45f(ChipConfig &cc) void config_empty_lfe5u_45f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5U-45F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);
@ -522,7 +520,6 @@ void config_empty_lfe5u_45f(ChipConfig &cc)
void config_empty_lfe5u_85f(ChipConfig &cc) void config_empty_lfe5u_85f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5U-85F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);
@ -879,7 +876,6 @@ void config_empty_lfe5u_85f(ChipConfig &cc)
void config_empty_lfe5um_25f(ChipConfig &cc) void config_empty_lfe5um_25f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM-25F";
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0");
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0");
cc.tiles["CIB_R49C42:CIB_DCU0"].add_unknown(20, 10); cc.tiles["CIB_R49C42:CIB_DCU0"].add_unknown(20, 10);
@ -1063,7 +1059,6 @@ void config_empty_lfe5um_25f(ChipConfig &cc)
void config_empty_lfe5um_45f(ChipConfig &cc) void config_empty_lfe5um_45f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM-45F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);
@ -1396,7 +1391,6 @@ void config_empty_lfe5um_45f(ChipConfig &cc)
void config_empty_lfe5um5g_25f(ChipConfig &cc) void config_empty_lfe5um5g_25f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM5G-25F";
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JA3MUX", "0");
cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0"); cc.tiles["CIB_R49C3:CIB_PLL3"].add_enum("CIB.JB3MUX", "0");
cc.tiles["CIB_R49C42:CIB_DCU0"].add_unknown(20, 10); cc.tiles["CIB_R49C42:CIB_DCU0"].add_unknown(20, 10);
@ -1580,7 +1574,6 @@ void config_empty_lfe5um5g_25f(ChipConfig &cc)
void config_empty_lfe5um5g_45f(ChipConfig &cc) void config_empty_lfe5um5g_45f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM5G-45F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);
@ -1913,7 +1906,6 @@ void config_empty_lfe5um5g_45f(ChipConfig &cc)
void config_empty_lfe5um5g_85f(ChipConfig &cc) void config_empty_lfe5um5g_85f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM5G-85F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);
@ -2270,7 +2262,6 @@ void config_empty_lfe5um5g_85f(ChipConfig &cc)
void config_empty_lfe5um_85f(ChipConfig &cc) void config_empty_lfe5um_85f(ChipConfig &cc)
{ {
cc.chip_name = "LFE5UM-85F";
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(2, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(3, 0);
cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0); cc.tiles["CIB_R10C3:PVT_COUNT2"].add_unknown(5, 0);

View File

@ -443,8 +443,8 @@ struct ECP5Bitgen
void fix_tile_names() void fix_tile_names()
{ {
// Remove the V prefix/suffix on certain tiles if device is a SERDES variant // Remove the V prefix/suffix on certain tiles if device is a SERDES variant
if (ctx->args.type == ArchArgs::LFE5U_12F || ctx->args.type == ArchArgs::LFE5U_25F || if (ctx->type == Arch::ArchTypes::LFE5U_12F || ctx->type == Arch::ArchTypes::LFE5U_25F ||
ctx->args.type == ArchArgs::LFE5U_45F || ctx->args.type == ArchArgs::LFE5U_85F) { ctx->type == Arch::ArchTypes::LFE5U_45F || ctx->type == Arch::ArchTypes::LFE5U_85F) {
std::map<std::string, std::string> tiletype_xform; std::map<std::string, std::string> tiletype_xform;
for (const auto &tile : cc.tiles) { for (const auto &tile : cc.tiles) {
std::string newname = tile.first; std::string newname = tile.first;
@ -1370,36 +1370,35 @@ struct ECP5Bitgen
} }
config_file >> cc; config_file >> cc;
} else { } else {
switch (ctx->args.type) { switch (ctx->type) {
case ArchArgs::LFE5U_12F: case Arch::ArchTypes::LFE5U_12F:
BaseConfigs::config_empty_lfe5u_25f(cc);
cc.chip_name = "LFE5U-12F";
break;
case ArchArgs::LFE5U_25F:
BaseConfigs::config_empty_lfe5u_25f(cc); BaseConfigs::config_empty_lfe5u_25f(cc);
break; break;
case ArchArgs::LFE5U_45F: case Arch::ArchTypes::LFE5U_25F:
BaseConfigs::config_empty_lfe5u_25f(cc);
break;
case Arch::ArchTypes::LFE5U_45F:
BaseConfigs::config_empty_lfe5u_45f(cc); BaseConfigs::config_empty_lfe5u_45f(cc);
break; break;
case ArchArgs::LFE5U_85F: case Arch::ArchTypes::LFE5U_85F:
BaseConfigs::config_empty_lfe5u_85f(cc); BaseConfigs::config_empty_lfe5u_85f(cc);
break; break;
case ArchArgs::LFE5UM_25F: case Arch::ArchTypes::LFE5UM_25F:
BaseConfigs::config_empty_lfe5um_25f(cc); BaseConfigs::config_empty_lfe5um_25f(cc);
break; break;
case ArchArgs::LFE5UM_45F: case Arch::ArchTypes::LFE5UM_45F:
BaseConfigs::config_empty_lfe5um_45f(cc); BaseConfigs::config_empty_lfe5um_45f(cc);
break; break;
case ArchArgs::LFE5UM_85F: case Arch::ArchTypes::LFE5UM_85F:
BaseConfigs::config_empty_lfe5um_85f(cc); BaseConfigs::config_empty_lfe5um_85f(cc);
break; break;
case ArchArgs::LFE5UM5G_25F: case Arch::ArchTypes::LFE5UM5G_25F:
BaseConfigs::config_empty_lfe5um5g_25f(cc); BaseConfigs::config_empty_lfe5um5g_25f(cc);
break; break;
case ArchArgs::LFE5UM5G_45F: case Arch::ArchTypes::LFE5UM5G_45F:
BaseConfigs::config_empty_lfe5um5g_45f(cc); BaseConfigs::config_empty_lfe5um5g_45f(cc);
break; break;
case ArchArgs::LFE5UM5G_85F: case Arch::ArchTypes::LFE5UM5G_85F:
BaseConfigs::config_empty_lfe5um5g_85f(cc); BaseConfigs::config_empty_lfe5um5g_85f(cc);
break; break;
default: default:
@ -1407,7 +1406,9 @@ struct ECP5Bitgen
} }
} }
cc.metadata.push_back("Part: " + ctx->get_full_chip_name()); cc.chip_name = ctx->device_info->name.get();
cc.chip_variant = ctx->device_name;
cc.metadata.push_back("Part: " + ctx->getChipName());
// Clear out DCU tieoffs in base config if DCU used // Clear out DCU tieoffs in base config if DCU used
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
@ -1550,8 +1551,8 @@ struct ECP5Bitgen
Loc loc = ctx->getBelLocation(ci->bel); Loc loc = ctx->getBelLocation(ci->bel);
bool u = loc.y<15, r = loc.x> 15; bool u = loc.y<15, r = loc.x> 15;
std::string tiletype = fmt_str("DDRDLL_" << (u ? 'U' : 'L') << (r ? 'R' : 'L')); std::string tiletype = fmt_str("DDRDLL_" << (u ? 'U' : 'L') << (r ? 'R' : 'L'));
if ((ctx->args.type == ArchArgs::LFE5U_12F || ctx->args.type == ArchArgs::LFE5U_25F || if ((ctx->type == Arch::ArchTypes::LFE5U_12F || ctx->type == Arch::ArchTypes::LFE5U_25F ||
ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F) && ctx->type == Arch::ArchTypes::LFE5UM_25F || ctx->type == Arch::ArchTypes::LFE5UM5G_25F) &&
u) u)
tiletype += "A"; tiletype += "A";
std::string tile = ctx->get_tile_by_type(tiletype); std::string tile = ctx->get_tile_by_type(tiletype);

View File

@ -267,6 +267,7 @@ bool TileConfig::empty() const { return carcs.empty() && cwords.empty() && cenum
std::ostream &operator<<(std::ostream &out, const ChipConfig &cc) std::ostream &operator<<(std::ostream &out, const ChipConfig &cc)
{ {
out << ".device " << cc.chip_name << std::endl << std::endl; out << ".device " << cc.chip_name << std::endl << std::endl;
out << ".variant " << cc.chip_variant << std::endl << std::endl;
for (const auto &meta : cc.metadata) for (const auto &meta : cc.metadata)
out << ".comment " << meta << std::endl; out << ".comment " << meta << std::endl;
for (const auto &sc : cc.sysconfig) for (const auto &sc : cc.sysconfig)
@ -311,6 +312,8 @@ std::istream &operator>>(std::istream &in, ChipConfig &cc)
in >> verb; in >> verb;
if (verb == ".device") { if (verb == ".device") {
in >> cc.chip_name; in >> cc.chip_name;
} else if (verb == ".variant") {
in >> cc.chip_variant;
} else if (verb == ".comment") { } else if (verb == ".comment") {
std::string line; std::string line;
getline(in, line); getline(in, line);

View File

@ -111,6 +111,7 @@ class ChipConfig
{ {
public: public:
std::string chip_name; std::string chip_name;
std::string chip_variant;
std::vector<std::string> metadata; std::vector<std::string> metadata;
std::map<std::string, TileConfig> tiles; std::map<std::string, TileConfig> tiles;
std::vector<TileGroup> tilegroups; std::vector<TileGroup> tilegroups;

1
ecp5/ecp5_available.h.in Normal file
View File

@ -0,0 +1 @@
static const char *available_devices = "@ECP5_DEVICES@";

View File

@ -48,6 +48,9 @@ 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})
configure_file(${family}/ecp5_available.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/ecp5_available.h)
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}>)
target_sources(${family_target} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated/ecp5_available.h)
endforeach() endforeach()

View File

@ -49,29 +49,21 @@ 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::is_available(ArchArgs::LFE5U_12F)) specific.add_options()("device", po::value<std::string>(), "device name");
specific.add_options()("12k", "set device type to LFE5U-12F"); specific.add_options()("list-devices", "list all supported device names");
if (Arch::is_available(ArchArgs::LFE5U_25F)) specific.add_options()("12k", "set device type to LFE5U-12F (deprecated)");
specific.add_options()("25k", "set device type to LFE5U-25F"); specific.add_options()("25k", "set device type to LFE5U-25F (deprecated)");
if (Arch::is_available(ArchArgs::LFE5U_45F)) specific.add_options()("45k", "set device type to LFE5U-45F (deprecated)");
specific.add_options()("45k", "set device type to LFE5U-45F"); specific.add_options()("85k", "set device type to LFE5U-85F (deprecated)");
if (Arch::is_available(ArchArgs::LFE5U_85F)) specific.add_options()("um-25k", "set device type to LFE5UM-25F (deprecated)");
specific.add_options()("85k", "set device type to LFE5U-85F"); specific.add_options()("um-45k", "set device type to LFE5UM-45F (deprecated)");
if (Arch::is_available(ArchArgs::LFE5UM_25F)) specific.add_options()("um-85k", "set device type to LFE5UM-85F (deprecated)");
specific.add_options()("um-25k", "set device type to LFE5UM-25F"); specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F (deprecated)");
if (Arch::is_available(ArchArgs::LFE5UM_45F)) specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F (deprecated)");
specific.add_options()("um-45k", "set device type to LFE5UM-45F"); specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F (deprecated)");
if (Arch::is_available(ArchArgs::LFE5UM_85F))
specific.add_options()("um-85k", "set device type to LFE5UM-85F");
if (Arch::is_available(ArchArgs::LFE5UM5G_25F))
specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F");
if (Arch::is_available(ArchArgs::LFE5UM5G_45F))
specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F");
if (Arch::is_available(ArchArgs::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) (deprecated)");
specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)"); specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8) (deprecated)");
specific.add_options()("basecfg", po::value<std::string>(), specific.add_options()("basecfg", po::value<std::string>(),
"base chip configuration in Trellis text format (deprecated)"); "base chip configuration in Trellis text format (deprecated)");
@ -91,7 +83,10 @@ po::options_description ECP5CommandHandler::getArchOptions()
} }
void ECP5CommandHandler::validate() void ECP5CommandHandler::validate()
{ {
if ((vm.count("25k") + vm.count("45k") + vm.count("85k")) > 1) if ((vm.count("12k") + vm.count("25k") + vm.count("45k") + vm.count("85k") +
vm.count("um-25k") + vm.count("um-45k") + vm.count("um-85k") +
vm.count("um5g-25k") + vm.count("um5g-45k") + vm.count("um5g-85k") +
vm.count("device")) > 1)
log_error("Only one device type can be set\n"); log_error("Only one device type can be set\n");
} }
@ -117,70 +112,37 @@ void ECP5CommandHandler::customBitstream(Context *ctx)
} }
} }
static std::string speedString(ArchArgs::SpeedGrade speed)
{
switch (speed) {
case ArchArgs::SPEED_6:
return "6";
case ArchArgs::SPEED_7:
return "7";
case ArchArgs::SPEED_8:
return "8";
case ArchArgs::SPEED_8_5G:
return "8";
}
return "";
}
std::unique_ptr<Context> ECP5CommandHandler::createContext(dict<std::string, Property> &values) std::unique_ptr<Context> ECP5CommandHandler::createContext(dict<std::string, Property> &values)
{ {
ArchArgs chipArgs; ArchArgs chipArgs;
chipArgs.type = ArchArgs::NONE; if (vm.count("list-devices")) {
if (vm.count("12k")) Arch::list_devices();
chipArgs.type = ArchArgs::LFE5U_12F; exit(0);
if (vm.count("25k")) }
chipArgs.type = ArchArgs::LFE5U_25F; if (vm.count("device"))
if (vm.count("45k")) chipArgs.device = vm["device"].as<std::string>();
chipArgs.type = ArchArgs::LFE5U_45F; else if (vm.count("12k"))
if (vm.count("85k")) chipArgs.device = "LFE5U-12F";
chipArgs.type = ArchArgs::LFE5U_85F; else if (vm.count("25k"))
if (vm.count("um-25k")) chipArgs.device = "LFE5U-25F";
chipArgs.type = ArchArgs::LFE5UM_25F; else if (vm.count("45k"))
if (vm.count("um-45k")) chipArgs.device = "LFE5U-45F";
chipArgs.type = ArchArgs::LFE5UM_45F; else if (vm.count("85k"))
if (vm.count("um-85k")) chipArgs.device = "LFE5U-85F";
chipArgs.type = ArchArgs::LFE5UM_85F; else if (vm.count("um-25k"))
if (vm.count("um5g-25k")) chipArgs.device = "LFE5UM-25F";
chipArgs.type = ArchArgs::LFE5UM5G_25F; else if (vm.count("um-45k"))
if (vm.count("um5g-45k")) chipArgs.device = "LFE5UM-45F";
chipArgs.type = ArchArgs::LFE5UM5G_45F; else if (vm.count("um-85k"))
if (vm.count("um5g-85k")) chipArgs.device = "LFE5UM-85F";
chipArgs.type = ArchArgs::LFE5UM5G_85F; else if (vm.count("um5g-25k"))
if (vm.count("package")) chipArgs.device = "LFE5UM5G-25F";
chipArgs.package = vm["package"].as<std::string>(); else if (vm.count("um5g-45k"))
chipArgs.device = "LFE5UM5G-45F";
else if (vm.count("um5g-85k"))
chipArgs.device = "LFE5UM5G-85F";
if (vm.count("speed")) {
int speed = vm["speed"].as<int>();
switch (speed) {
case 6:
chipArgs.speed = ArchArgs::SPEED_6;
break;
case 7:
chipArgs.speed = ArchArgs::SPEED_7;
break;
case 8:
chipArgs.speed = ArchArgs::SPEED_8;
break;
default:
log_error("Unsupported speed grade '%d'\n", speed);
}
} else {
if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F ||
chipArgs.type == ArchArgs::LFE5UM5G_85F) {
chipArgs.speed = ArchArgs::SPEED_8;
} else
chipArgs.speed = ArchArgs::SPEED_6;
}
if (values.find("arch.name") != values.end()) { if (values.find("arch.name") != values.end()) {
std::string arch_name = values["arch.name"].as_string(); std::string arch_name = values["arch.name"].as_string();
if (arch_name != "ecp5") if (arch_name != "ecp5")
@ -188,71 +150,61 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext(dict<std::string, Pro
} }
if (values.find("arch.type") != values.end()) { if (values.find("arch.type") != values.end()) {
std::string arch_type = values["arch.type"].as_string(); std::string arch_type = values["arch.type"].as_string();
if (chipArgs.type != ArchArgs::NONE) if (!chipArgs.device.empty())
log_error("Overriding architecture is unsupported.\n"); log_error("Overriding architecture is unsupported.\n");
chipArgs.device = arch_type;
if (arch_type == "lfe5u_12f")
chipArgs.type = ArchArgs::LFE5U_12F;
if (arch_type == "lfe5u_25f")
chipArgs.type = ArchArgs::LFE5U_25F;
if (arch_type == "lfe5u_45f")
chipArgs.type = ArchArgs::LFE5U_45F;
if (arch_type == "lfe5u_85f")
chipArgs.type = ArchArgs::LFE5U_85F;
if (arch_type == "lfe5um_25f")
chipArgs.type = ArchArgs::LFE5UM_25F;
if (arch_type == "lfe5um_45f")
chipArgs.type = ArchArgs::LFE5UM_45F;
if (arch_type == "lfe5um_85f")
chipArgs.type = ArchArgs::LFE5UM_85F;
if (arch_type == "lfe5um5g_25f")
chipArgs.type = ArchArgs::LFE5UM5G_25F;
if (arch_type == "lfe5um5g_45f")
chipArgs.type = ArchArgs::LFE5UM5G_45F;
if (arch_type == "lfe5um5g_85f")
chipArgs.type = ArchArgs::LFE5UM5G_85F;
if (chipArgs.type == ArchArgs::NONE)
log_error("Unsupported FPGA type '%s'.\n", arch_type.c_str());
}
if (values.find("arch.package") != values.end()) {
if (vm.count("package"))
log_error("Overriding architecture is unsupported.\n");
chipArgs.package = values["arch.package"].as_string();
}
if (values.find("arch.speed") != values.end()) {
std::string arch_speed = values["arch.speed"].as_string();
if (arch_speed == "6")
chipArgs.speed = ArchArgs::SPEED_6;
else if (arch_speed == "7")
chipArgs.speed = ArchArgs::SPEED_7;
else if (arch_speed == "8")
chipArgs.speed = ArchArgs::SPEED_8;
else
log_error("Unsupported speed '%s'.\n", arch_speed.c_str());
}
if (chipArgs.type == ArchArgs::NONE)
chipArgs.type = ArchArgs::LFE5U_45F;
if (chipArgs.package.empty()) {
chipArgs.package = "CABGA381";
log_warning("Use of default value for --package is deprecated. Please add '--package %s' to arguments.\n",
chipArgs.package.c_str());
} }
if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F || if (chipArgs.device.empty())
chipArgs.type == ArchArgs::LFE5UM5G_85F) { chipArgs.device = "LFE5UM-45F";
if (chipArgs.speed != ArchArgs::SPEED_8)
log_error("Only speed grade 8 is available for 5G parts\n"); if (!vm.count("device")) {
else if (vm.count("speed")) {
chipArgs.speed = ArchArgs::SPEED_8_5G; int speed = vm["speed"].as<int>();
switch (speed) {
case 6:
chipArgs.device += "-6";
break;
case 7:
chipArgs.device += "-7";
break;
case 8:
chipArgs.device += "-8";
break;
default:
log_error("Unsupported speed grade '%d'\n", speed);
}
} else {
if (strstr(chipArgs.device.c_str(),"LFE5UM5G")) {
chipArgs.device += "-8";
} else
chipArgs.device += "-6";
}
if (vm.count("package")) {
std::string package = vm["package"].as<std::string>();
if (strcasecmp(package.c_str(), "csfBGA285")==0) {
chipArgs.device += "MG285C";
} else if (strcasecmp(package.c_str(), "caBGA256")==0) {
chipArgs.device += "BG256C";
} else if (strcasecmp(package.c_str(), "caBGA381")==0) {
chipArgs.device += "BG381C";
} else if (strcasecmp(package.c_str(), "caBGA554")==0) {
chipArgs.device += "BG554C";
} else if (strcasecmp(package.c_str(), "caBGA756")==0) {
chipArgs.device += "BG756C";
} else {
log_error("Unsupported package '%s'\n", package.c_str());
}
}
else {
chipArgs.device += "BG381C";
log_warning("Use of default value for --package is deprecated. Please add '--package caBGA381' to arguments.\n");
}
} }
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)
ctx->settings[ctx->id(val.first)] = val.second; ctx->settings[ctx->id(val.first)] = val.second;
ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package;
ctx->settings[ctx->id("arch.speed")] = speedString(ctx->archArgs().speed);
if (vm.count("out-of-context")) if (vm.count("out-of-context"))
ctx->settings[ctx->id("arch.ooc")] = 1; ctx->settings[ctx->id("arch.ooc")] = 1;
if (vm.count("disable-router-lutperm")) if (vm.count("disable-router-lutperm"))

View File

@ -582,7 +582,7 @@ class Ecp5Packer
BelId pinBel = ctx->get_package_pin_bel(pin); BelId pinBel = ctx->get_package_pin_bel(pin);
if (pinBel == BelId()) { if (pinBel == BelId()) {
log_error("IO pin '%s' constrained to pin '%s', which does not exist for package '%s'.\n", log_error("IO pin '%s' constrained to pin '%s', which does not exist for package '%s'.\n",
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str()); trio->name.c_str(ctx), pin.c_str(), ctx->package_name);
} else { } else {
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx), log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx),
ctx->nameOfBel(pinBel)); ctx->nameOfBel(pinBel));
@ -1323,19 +1323,19 @@ class Ecp5Packer
if (ci->attrs.count(id_LOC)) { if (ci->attrs.count(id_LOC)) {
std::string loc = ci->attrs.at(id_LOC).as_string(); std::string loc = ci->attrs.at(id_LOC).as_string();
if (loc == "DCU0" && if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F)) (ctx->type == Arch::ArchTypes::LFE5UM_25F || ctx->type == Arch::ArchTypes::LFE5UM5G_25F))
ci->attrs[id_BEL] = std::string("X42/Y50/DCU"); ci->attrs[id_BEL] = std::string("X42/Y50/DCU");
else if (loc == "DCU0" && else if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F)) (ctx->type == Arch::ArchTypes::LFE5UM_45F || ctx->type == Arch::ArchTypes::LFE5UM5G_45F))
ci->attrs[id_BEL] = std::string("X42/Y71/DCU"); ci->attrs[id_BEL] = std::string("X42/Y71/DCU");
else if (loc == "DCU1" && else if (loc == "DCU1" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F)) (ctx->type == Arch::ArchTypes::LFE5UM_45F || ctx->type == Arch::ArchTypes::LFE5UM5G_45F))
ci->attrs[id_BEL] = std::string("X69/Y71/DCU"); ci->attrs[id_BEL] = std::string("X69/Y71/DCU");
else if (loc == "DCU0" && else if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F)) (ctx->type == Arch::ArchTypes::LFE5UM_85F || ctx->type == Arch::ArchTypes::LFE5UM5G_85F))
ci->attrs[id_BEL] = std::string("X46/Y95/DCU"); ci->attrs[id_BEL] = std::string("X46/Y95/DCU");
else if (loc == "DCU1" && else if (loc == "DCU1" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F)) (ctx->type == Arch::ArchTypes::LFE5UM_85F || ctx->type == Arch::ArchTypes::LFE5UM5G_85F))
ci->attrs[id_BEL] = std::string("X71/Y95/DCU"); ci->attrs[id_BEL] = std::string("X71/Y95/DCU");
else else
log_error("no DCU location '%s' in device '%s'\n", loc.c_str(), ctx->getChipName().c_str()); log_error("no DCU location '%s' in device '%s'\n", loc.c_str(), ctx->getChipName().c_str());
@ -1378,19 +1378,19 @@ class Ecp5Packer
if (ci->attrs.count(id_LOC)) { if (ci->attrs.count(id_LOC)) {
std::string loc = ci->attrs.at(id_LOC).as_string(); std::string loc = ci->attrs.at(id_LOC).as_string();
if (loc == "EXTREF0" && if (loc == "EXTREF0" &&
(ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F)) (ctx->type == Arch::ArchTypes::LFE5UM_25F || ctx->type == Arch::ArchTypes::LFE5UM5G_25F))
loc_bel = std::string("X42/Y50/EXTREF"); loc_bel = std::string("X42/Y50/EXTREF");
else if (loc == "EXTREF0" && else if (loc == "EXTREF0" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F)) (ctx->type == Arch::ArchTypes::LFE5UM_45F || ctx->type == Arch::ArchTypes::LFE5UM5G_45F))
loc_bel = std::string("X42/Y71/EXTREF"); loc_bel = std::string("X42/Y71/EXTREF");
else if (loc == "EXTREF1" && else if (loc == "EXTREF1" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F)) (ctx->type == Arch::ArchTypes::LFE5UM_45F || ctx->type == Arch::ArchTypes::LFE5UM5G_45F))
loc_bel = std::string("X69/Y71/EXTREF"); loc_bel = std::string("X69/Y71/EXTREF");
else if (loc == "EXTREF0" && else if (loc == "EXTREF0" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F)) (ctx->type == Arch::ArchTypes::LFE5UM_85F || ctx->type == Arch::ArchTypes::LFE5UM5G_85F))
loc_bel = std::string("X46/Y95/EXTREF"); loc_bel = std::string("X46/Y95/EXTREF");
else if (loc == "EXTREF1" && else if (loc == "EXTREF1" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F)) (ctx->type == Arch::ArchTypes::LFE5UM_85F || ctx->type == Arch::ArchTypes::LFE5UM5G_85F))
loc_bel = std::string("X71/Y95/EXTREF"); loc_bel = std::string("X71/Y95/EXTREF");
} }
if (refo == nullptr) if (refo == nullptr)

View File

@ -167,6 +167,14 @@ def get_tiletype_index(name):
tiletype_names[name] = idx tiletype_names[name] = idx
return idx return idx
def package_shortname(long_name):
if long_name.startswith("caBGA"):
return "BG" + long_name[5:]
elif long_name.startswith("csfBGA"):
return "MG" + long_name[6:]
else:
print("unknown package name " + long_name)
sys.exit(-1)
constids = dict() constids = dict()
@ -241,6 +249,17 @@ def get_bel_index(ddrg, loc, name):
packages = {} packages = {}
pindata = [] pindata = []
devices = {}
def process_devices_db(family, device):
devicefile = path.join(database.get_db_root(), "devices.json")
with open(devicefile, 'r') as f:
devicedb = json.load(f)
for dev in device:
variants = {}
for varname, vardata in sorted(devicedb["families"][family]["devices"][dev]["variants"].items()):
variants[varname] = vardata
devices[dev] = variants
def process_pio_db(ddrg, device): def process_pio_db(ddrg, device):
piofile = path.join(database.get_db_root(), "ECP5", dev_names[device], "iodb.json") piofile = path.join(database.get_db_root(), "ECP5", dev_names[device], "iodb.json")
@ -640,6 +659,33 @@ def write_database(dev_name, chip, ddrg, endianness):
bba.r_slice("cell_timing_data_%s" % grade, len(speed_grade_cells[grade]), "cell_timings") bba.r_slice("cell_timing_data_%s" % grade, len(speed_grade_cells[grade]), "cell_timings")
bba.r_slice("pip_timing_data_%s" % grade, len(speed_grade_pips[grade]), "pip_classes") bba.r_slice("pip_timing_data_%s" % grade, len(speed_grade_pips[grade]), "pip_classes")
for _, dev_data in sorted(devices.items()):
for name, var_data in sorted(dev_data.items()):
bba.l("supported_packages_%s" % name, "PackageSupportedPOD")
for package in var_data["packages"]:
bba.s(package, "name")
bba.s(package_shortname(package), "short_name")
bba.l("supported_speed_grades_%s" % name, "SpeedSupportedPOD")
for speed in var_data["speeds"]:
bba.u32(speed, "speed")
bba.l("supported_suffixes_%s" % name, "SuffixeSupportedPOD")
for suffix in var_data["suffixes"]:
bba.s(suffix, "suffix")
for name, dev_data in sorted(devices.items()):
bba.l("variant_data_%s" % name, "VariantInfoPOD")
for name, var_data in sorted(dev_data.items()):
bba.s(name, "variant_name")
bba.r_slice("supported_packages_%s" % name, len(var_data["packages"]), "supported_packages")
bba.r_slice("supported_speed_grades_%s" % name, len(var_data["speeds"]), "supported_speed_grades")
bba.r_slice("supported_suffixes_%s" % name, len(var_data["suffixes"]), "supported_suffixes")
bba.l("devices_data", "DeviceInfoPOD")
for name, dev_data in sorted(devices.items()):
bba.s(chip.info.family, "family")
bba.s(name, "device_name")
bba.r_slice("variant_data_%s" % name, len(dev_data), "variant_info")
bba.l("chip_info") bba.l("chip_info")
bba.u32(max_col + 1, "width") bba.u32(max_col + 1, "width")
bba.u32(max_row + 1, "height") bba.u32(max_row + 1, "height")
@ -654,11 +700,12 @@ def write_database(dev_name, chip, ddrg, endianness):
bba.r_slice("pio_info", len(pindata), "pio_info") bba.r_slice("pio_info", len(pindata), "pio_info")
bba.r_slice("tiles_info", (max_col + 1) * (max_row + 1), "tile_info") bba.r_slice("tiles_info", (max_col + 1) * (max_row + 1), "tile_info")
bba.r_slice("speed_grade_data", len(speed_grade_names), "speed_grades") bba.r_slice("speed_grade_data", len(speed_grade_names), "speed_grades")
bba.r_slice("devices_data", len(devices), "device_info")
bba.pop() bba.pop()
return bba return bba
dev_names = {"25k": "LFE5UM5G-25F", "45k": "LFE5UM5G-45F", "85k": "LFE5UM5G-85F"} dev_names = {"25k": "LFE5UM-25F", "45k": "LFE5UM-45F", "85k": "LFE5UM-85F"}
def main(): def main():
global max_row, max_col, const_id_count global max_row, max_col, const_id_count
@ -692,6 +739,7 @@ def main():
process_timing_data() process_timing_data()
process_pio_db(ddrg, args.device) process_pio_db(ddrg, args.device)
process_loc_globals(chip) process_loc_globals(chip)
process_devices_db(chip.info.family, [ chip.info.name, chip.info.name.replace("LFE5UM","LFE5U") ])
# print("{} unique location types".format(len(ddrg.locationTypes))) # print("{} unique location types".format(len(ddrg.locationTypes)))
bba = write_database(args.device, chip, ddrg, "le") bba = write_database(args.device, chip, ddrg, "le")

View File

@ -20,7 +20,9 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <fstream> #include <fstream>
#include "bitstream.h" #include "bitstream.h"
#include "embed.h"
#include "log.h" #include "log.h"
#include "ecp5_available.h"
#include <QFileDialog> #include <QFileDialog>
#include <QInputDialog> #include <QInputDialog>
@ -47,7 +49,8 @@ MainWindow::~MainWindow() {}
void MainWindow::newContext(Context *ctx) void MainWindow::newContext(Context *ctx)
{ {
std::string title = "nextpnr-ecp5 - " + ctx->getChipName() + " ( " + ctx->archArgs().package + " )"; std::string title = "nextpnr-ecp5 - " + std::string(ctx->device_name) + " (" + std::string(ctx->package_name) +
") - Part : " + ctx->getChipName();
setWindowTitle(title.c_str()); setWindowTitle(title.c_str());
} }
@ -78,50 +81,46 @@ void MainWindow::createMenu()
void MainWindow::new_proj() void MainWindow::new_proj()
{ {
QMap<QString, int> arch; QList<QString> arch;
if (Arch::is_available(ArchArgs::LFE5U_25F))
arch.insert("Lattice ECP5 LFE5U-25F", ArchArgs::LFE5U_25F); std::stringstream ss(available_devices);
if (Arch::is_available(ArchArgs::LFE5U_45F)) std::string name;
arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F); while (getline(ss, name, ';')) {
if (Arch::is_available(ArchArgs::LFE5U_85F)) std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F); auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
if (Arch::is_available(ArchArgs::LFE5UM_25F)) if (!db_ptr)
arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F); continue; // chipdb not available
if (Arch::is_available(ArchArgs::LFE5UM_45F)) for (auto &dev : db_ptr->get()->devices) {
arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F); for (auto &chip : dev.variants) {
if (Arch::is_available(ArchArgs::LFE5UM_85F)) for (auto &pkg : chip.packages) {
arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F); for (auto &speedgrade : chip.speed_grades) {
if (Arch::is_available(ArchArgs::LFE5UM5G_25F)) for (auto &rating : chip.suffixes) {
arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F); std::string devname = stringf("%s-%d%s%s", chip.name.get(), speedgrade.speed,
if (Arch::is_available(ArchArgs::LFE5UM5G_45F)) pkg.short_name.get(), rating.suffix.get());
arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F); arch.append(QString::fromLocal8Bit(devname.c_str()));
if (Arch::is_available(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", "Part:", arch, 0, false, &ok);
if (ok && !item.isEmpty()) { if (ok && !item.isEmpty()) {
ArchArgs chipArgs; ArchArgs chipArgs;
chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); chipArgs.device = item.toUtf8().constData();
;
QStringList packages;
for (auto package : Arch::get_supported_packages(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()) {
handler->clear(); handler->clear();
currentProj = ""; currentProj = "";
disableActions(); disableActions();
chipArgs.package = package.toStdString().c_str();
ctx = std::unique_ptr<Context>(new Context(chipArgs)); ctx = std::unique_ptr<Context>(new Context(chipArgs));
actionLoadJSON->setEnabled(true); actionLoadJSON->setEnabled(true);
Q_EMIT contextChanged(ctx.get()); Q_EMIT contextChanged(ctx.get());
} }
}
} }
void MainWindow::open_lpf() void MainWindow::open_lpf()
{ {
QString fileName = QFileDialog::getOpenFileName(this, QString("Open LPF"), QString(), QString("*.lpf")); QString fileName = QFileDialog::getOpenFileName(this, QString("Open LPF"), QString(), QString("*.lpf"));