Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support variants for ECP5 #1154

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/kernel/command.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,15 @@ bool CommandHandler::executeBeforeContext()
<< " -- Next Generation Place and Route (Version " GIT_DESCRIBE_STR ")\n";
return true;
}
validate();

if (vm.count("quiet")) {
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::WARNING_MSG));
} else {
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::LOG_MSG));
}

validate();

if (vm.count("Werror")) {
log_warn_as_error = true;
}
Expand Down
206 changes: 95 additions & 111 deletions ecp5/arch.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "router2.h"
#include "timing.h"
#include "util.h"
#include "ecp5_available.h"

NEXTPNR_NAMESPACE_BEGIN

Expand All @@ -48,60 +49,89 @@ void IdString::initialize_arch(const BaseCtx *ctx)
#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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you create a struct or something for all these fields rather than tons of ** arguments?

const char **device_name, const char **package_name, Arch::ArchTypes *type, Arch::SpeedGrade *speed)
{
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");
std::stringstream ss(available_devices);
std::string name;
while (getline(ss, name, ';')) {
std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
if (!db_ptr)
continue; // chipdb not available
for (auto &dev : db_ptr->get()->devices) {
for (auto &chip : dev.variants) {
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would definitely prefer using C++ or Boost string stuff to the old C functions

*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)
{
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)
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)
log_error("Chip database 'bba' and nextpnr code are out of sync; please rebuild (or contact distribution "
"maintainer)!\n");

package_info = nullptr;
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]);
speed_grade = &(chip_info->speed_grades[speed]);
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);
for (int i = 0; i < chip_info->num_tiles; i++) {
Expand Down Expand Up @@ -160,81 +190,35 @@ Arch::Arch(ArchArgs args) : args(args)
lutperm_allowed.resize(chip_info->width * chip_info->height * 4);
}

// -----------------------------------------------------------------------

std::string Arch::getChipName() const
void Arch::list_devices()
{
if (args.type == ArchArgs::LFE5U_12F) {
return "LFE5U-12F";
} else if (args.type == ArchArgs::LFE5U_25F) {
return "LFE5U-25F";
} else if (args.type == ArchArgs::LFE5U_45F) {
return "LFE5U-45F";
} else if (args.type == ArchArgs::LFE5U_85F) {
return "LFE5U-85F";
} else if (args.type == ArchArgs::LFE5UM_25F) {
return "LFE5UM-25F";
} else if (args.type == ArchArgs::LFE5UM_45F) {
return "LFE5UM-45F";
} else if (args.type == ArchArgs::LFE5UM_85F) {
return "LFE5UM-85F";
} else if (args.type == ArchArgs::LFE5UM5G_25F) {
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;
log("Supported devices: \n");
std::stringstream ss(available_devices);
std::string name;
while (getline(ss, name, ';')) {
std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
if (!db_ptr)
continue; // chipdb not available
for (auto &dev : db_ptr->get()->devices) {
for (auto &chip : dev.variants) {
for (auto &pkg : chip.packages) {
for (auto &speedgrade : chip.speed_grades) {
for (auto &rating : chip.suffixes) {
log(" %s-%d%s%s\n", chip.name.get(), speedgrade.speed, pkg.short_name.get(),
rating.suffix.get());
}
}
}
}
}
}
name += args.package;
return name;
}

// -----------------------------------------------------------------------

IdString Arch::archArgsToId(ArchArgs args) const
{
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();
}
std::string Arch::getChipName() const { return args.device; }
IdString Arch::archArgsToId(ArchArgs args) const { return id(args.device); }

// -----------------------------------------------------------------------

Expand Down Expand Up @@ -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);

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)));
}

Expand Down Expand Up @@ -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);

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)));
}

Expand Down
75 changes: 50 additions & 25 deletions ecp5/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,28 @@ NPNR_PACKED_STRUCT(struct SpeedGradePOD {
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 {
int32_t width, height;
int32_t num_tiles;
Expand All @@ -181,6 +203,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelSlice<PIOInfoPOD> pio_info;
RelSlice<TileInfoPOD> tile_info;
RelSlice<SpeedGradePOD> speed_grades;
RelSlice<DeviceInfoPOD> devices;
});

/************************ End of chipdb section. ************************/
Expand Down Expand Up @@ -394,28 +417,7 @@ struct PipRange

struct ArchArgs
{
enum ArchArgsTypes
{
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;
std::string device;
};

struct DelayKey
Expand Down Expand Up @@ -446,9 +448,34 @@ struct ArchRanges : BaseArchRanges

struct Arch : BaseArch<ArchRanges>
{
const DeviceInfoPOD *device_info;
const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info;
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;

Expand Down Expand Up @@ -513,11 +540,9 @@ struct Arch : BaseArch<ArchRanges>
ArchArgs args;
Arch(ArchArgs args);

static bool is_available(ArchArgs::ArchArgsTypes chip);
static std::vector<std::string> get_supported_packages(ArchArgs::ArchArgsTypes chip);
static void list_devices();

std::string getChipName() const override;
std::string get_full_chip_name() const;

ArchArgs archArgs() const override { return args; }
IdString archArgsToId(ArchArgs args) const override;
Expand Down
Loading