Compare commits
3 Commits
master
...
micko/ecp5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ccf9d00d82 | ||
![]() |
97d4e7c1a5 | ||
![]() |
3d0b50a402 |
@ -97,7 +97,6 @@ bool CommandHandler::executeBeforeContext()
|
|||||||
<< " -- Next Generation Place and Route (Version " GIT_DESCRIBE_STR ")\n";
|
<< " -- Next Generation Place and Route (Version " GIT_DESCRIBE_STR ")\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
validate();
|
|
||||||
|
|
||||||
if (vm.count("quiet")) {
|
if (vm.count("quiet")) {
|
||||||
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::WARNING_MSG));
|
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::WARNING_MSG));
|
||||||
@ -105,6 +104,8 @@ bool CommandHandler::executeBeforeContext()
|
|||||||
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::LOG_MSG));
|
log_streams.push_back(std::make_pair(&std::cerr, LogLevel::LOG_MSG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate();
|
||||||
|
|
||||||
if (vm.count("Werror")) {
|
if (vm.count("Werror")) {
|
||||||
log_warn_as_error = true;
|
log_warn_as_error = true;
|
||||||
}
|
}
|
||||||
|
304
ecp5/arch.cc
304
ecp5/arch.cc
@ -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,68 +49,103 @@ void IdString::initialize_arch(const BaseCtx *ctx)
|
|||||||
#undef X
|
#undef X
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
static const ChipInfoPOD *get_chip_info(ArchArgs::ArchArgsTypes chip)
|
bool is_equal(const std::string& a, const std::string& b)
|
||||||
{
|
{
|
||||||
std::string chipdb;
|
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
|
||||||
if (chip == ArchArgs::LFE5U_12F || chip == ArchArgs::LFE5U_25F || chip == ArchArgs::LFE5UM_25F ||
|
[](char a, char b) { return tolower(a) == tolower(b); });
|
||||||
chip == ArchArgs::LFE5UM5G_25F) {
|
}
|
||||||
chipdb = "ecp5/chipdb-25k.bin";
|
|
||||||
} else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) {
|
static void get_chip_info(std::string device, ArchDevice *selected_device)
|
||||||
chipdb = "ecp5/chipdb-45k.bin";
|
{
|
||||||
} else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) {
|
std::stringstream ss(available_devices);
|
||||||
chipdb = "ecp5/chipdb-85k.bin";
|
std::string name;
|
||||||
} else {
|
while (getline(ss, name, ';')) {
|
||||||
log_error("Unknown chip\n");
|
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) {
|
||||||
|
selected_device->device_info = &dev;
|
||||||
|
selected_device->chip_info = db_ptr->get();
|
||||||
|
selected_device->package_info = nullptr;
|
||||||
|
selected_device->package_name = pkg.name.get();
|
||||||
|
selected_device->device_name = chip.name.get();
|
||||||
|
selected_device->type = ArchDevice::NONE;
|
||||||
|
std::string device_name = chip.name.get();
|
||||||
|
if ((device_name == "LFE5U-12F")|| (device_name == "LAE5U-12F"))
|
||||||
|
selected_device->type = ArchDevice::LFE5U_12F;
|
||||||
|
else if (device_name == "LFE5U-25F")
|
||||||
|
selected_device->type = ArchDevice::LFE5U_25F;
|
||||||
|
else if (device_name == "LFE5U-45F")
|
||||||
|
selected_device->type = ArchDevice::LFE5U_45F;
|
||||||
|
else if (device_name == "LFE5U-85F")
|
||||||
|
selected_device->type = ArchDevice::LFE5U_85F;
|
||||||
|
else if ((device_name == "LFE5UM-25F") || (device_name == "LAE5UM-25F"))
|
||||||
|
selected_device->type = ArchDevice::LFE5UM_25F;
|
||||||
|
else if ((device_name == "LFE5UM-45F") || (device_name == "LAE5UM-45F"))
|
||||||
|
selected_device->type = ArchDevice::LFE5UM_45F;
|
||||||
|
else if ((device_name == "LFE5UM-85F") || (device_name == "LAE5UM-85F"))
|
||||||
|
selected_device->type = ArchDevice::LFE5UM_85F;
|
||||||
|
else if (device_name == "LFE5UM5G-25F")
|
||||||
|
selected_device->type = ArchDevice::LFE5UM5G_25F;
|
||||||
|
else if (device_name == "LFE5UM5G-45F")
|
||||||
|
selected_device->type = ArchDevice::LFE5UM5G_45F;
|
||||||
|
else if (device_name == "LFE5UM5G-85F")
|
||||||
|
selected_device->type = ArchDevice::LFE5UM5G_85F;
|
||||||
|
else
|
||||||
|
log_error("Unsupported device '%s'.\n", device_name.c_str());
|
||||||
|
|
||||||
|
selected_device->speed = ArchDevice::SpeedGrade(speedgrade.speed - 6);
|
||||||
|
if (device_name.rfind("LFE5UM5G")==0) {
|
||||||
|
selected_device->speed = ArchDevice::SPEED_8_5G;
|
||||||
|
}
|
||||||
|
selected_device->speed_grade = &(selected_device->chip_info->speed_grades[selected_device->speed]);
|
||||||
|
for (auto &pi : db_ptr->get()->package_info) {
|
||||||
|
if (is_equal(pkg.name.get(),pi.name.get())) {
|
||||||
|
selected_device->package_info = π
|
||||||
|
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);
|
||||||
if (chip_info == nullptr)
|
if (device.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 (device.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;
|
if (!device.package_info)
|
||||||
for (auto &pkg : chip_info->package_info) {
|
log_error("Unsupported package '%s' for '%s'.\n", device.package_name, getChipName().c_str());
|
||||||
if (args.package == pkg.name.get()) {
|
|
||||||
package_info = &pkg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
speed_grade = &(chip_info->speed_grades[args.speed]);
|
|
||||||
if (!package_info)
|
|
||||||
log_error("Unsupported package '%s' for '%s'.\n", args.package.c_str(), getChipName().c_str());
|
|
||||||
|
|
||||||
tile_status.resize(chip_info->num_tiles);
|
tile_status.resize(device.chip_info->num_tiles);
|
||||||
for (int i = 0; i < chip_info->num_tiles; i++) {
|
for (int i = 0; i < device.chip_info->num_tiles; i++) {
|
||||||
auto &ts = tile_status.at(i);
|
auto &ts = tile_status.at(i);
|
||||||
auto &tile_data = chip_info->tile_info[i];
|
auto &tile_data = device.chip_info->tile_info[i];
|
||||||
ts.boundcells.resize(chip_info->locations[chip_info->location_type[i]].bel_data.size(), nullptr);
|
ts.boundcells.resize(device.chip_info->locations[device.chip_info->location_type[i]].bel_data.size(), nullptr);
|
||||||
for (auto &name : tile_data.tile_names) {
|
for (auto &name : tile_data.tile_names) {
|
||||||
if (strcmp(chip_info->tiletype_names[name.type_idx].get(), "PLC2") == 0) {
|
if (strcmp(device.chip_info->tiletype_names[name.type_idx].get(), "PLC2") == 0) {
|
||||||
// Is a logic tile
|
// Is a logic tile
|
||||||
ts.lts = new LogicTileStatus();
|
ts.lts = new LogicTileStatus();
|
||||||
break;
|
break;
|
||||||
@ -120,121 +156,75 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
BaseArch::init_cell_types();
|
BaseArch::init_cell_types();
|
||||||
BaseArch::init_bel_buckets();
|
BaseArch::init_bel_buckets();
|
||||||
|
|
||||||
for (int i = 0; i < chip_info->width; i++)
|
for (int i = 0; i < device.chip_info->width; i++)
|
||||||
x_ids.push_back(idf("X%d", i));
|
x_ids.push_back(idf("X%d", i));
|
||||||
for (int i = 0; i < chip_info->height; i++)
|
for (int i = 0; i < device.chip_info->height; i++)
|
||||||
y_ids.push_back(idf("Y%d", i));
|
y_ids.push_back(idf("Y%d", i));
|
||||||
|
|
||||||
for (int i = 0; i < chip_info->width; i++) {
|
for (int i = 0; i < device.chip_info->width; i++) {
|
||||||
IdString x_id = idf("X%d", i);
|
IdString x_id = idf("X%d", i);
|
||||||
x_ids.push_back(x_id);
|
x_ids.push_back(x_id);
|
||||||
id_to_x[x_id] = i;
|
id_to_x[x_id] = i;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < chip_info->height; i++) {
|
for (int i = 0; i < device.chip_info->height; i++) {
|
||||||
IdString y_id = idf("Y%d", i);
|
IdString y_id = idf("Y%d", i);
|
||||||
y_ids.push_back(y_id);
|
y_ids.push_back(y_id);
|
||||||
id_to_y[y_id] = i;
|
id_to_y[y_id] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
wire_tile_vecidx.resize(chip_info->num_tiles, -1);
|
wire_tile_vecidx.resize(device.chip_info->num_tiles, -1);
|
||||||
int n_wires = 0;
|
int n_wires = 0;
|
||||||
for (auto e : getWires()) {
|
for (auto e : getWires()) {
|
||||||
if (e.index == 0) {
|
if (e.index == 0) {
|
||||||
wire_tile_vecidx.at(e.location.y * chip_info->width + e.location.x) = n_wires;
|
wire_tile_vecidx.at(e.location.y * device.chip_info->width + e.location.x) = n_wires;
|
||||||
}
|
}
|
||||||
n_wires++;
|
n_wires++;
|
||||||
}
|
}
|
||||||
wire2net.resize(n_wires, nullptr);
|
wire2net.resize(n_wires, nullptr);
|
||||||
wire_fanout.resize(n_wires, 0);
|
wire_fanout.resize(n_wires, 0);
|
||||||
|
|
||||||
pip_tile_vecidx.resize(chip_info->num_tiles, -1);
|
pip_tile_vecidx.resize(device.chip_info->num_tiles, -1);
|
||||||
int n_pips = 0;
|
int n_pips = 0;
|
||||||
for (auto e : getPips()) {
|
for (auto e : getPips()) {
|
||||||
if (e.index == 0) {
|
if (e.index == 0) {
|
||||||
pip_tile_vecidx.at(e.location.y * chip_info->width + e.location.x) = n_pips;
|
pip_tile_vecidx.at(e.location.y * device.chip_info->width + e.location.x) = n_pips;
|
||||||
}
|
}
|
||||||
n_pips++;
|
n_pips++;
|
||||||
}
|
}
|
||||||
pip2net.resize(n_pips, nullptr);
|
pip2net.resize(n_pips, nullptr);
|
||||||
|
|
||||||
lutperm_allowed.resize(chip_info->width * chip_info->height * 4);
|
lutperm_allowed.resize(device.chip_info->width * device.chip_info->height * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Arch::list_devices()
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::string Arch::getChipName() 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 "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;
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
@ -261,12 +251,12 @@ BelRange Arch::getBelsByTile(int x, int y) const
|
|||||||
{
|
{
|
||||||
BelRange br;
|
BelRange br;
|
||||||
|
|
||||||
br.b.cursor_tile = y * chip_info->width + x;
|
br.b.cursor_tile = y * device.chip_info->width + x;
|
||||||
br.e.cursor_tile = y * chip_info->width + x;
|
br.e.cursor_tile = y * device.chip_info->width + x;
|
||||||
br.b.cursor_index = 0;
|
br.b.cursor_index = 0;
|
||||||
br.e.cursor_index = chip_info->locations[chip_info->location_type[br.b.cursor_tile]].bel_data.ssize() - 1;
|
br.e.cursor_index = device.chip_info->locations[device.chip_info->location_type[br.b.cursor_tile]].bel_data.ssize() - 1;
|
||||||
br.b.chip = chip_info;
|
br.b.chip = device.chip_info;
|
||||||
br.e.chip = chip_info;
|
br.e.chip = device.chip_info;
|
||||||
if (br.e.cursor_index == -1)
|
if (br.e.cursor_index == -1)
|
||||||
++br.e.cursor_index;
|
++br.e.cursor_index;
|
||||||
else
|
else
|
||||||
@ -369,7 +359,7 @@ IdStringList Arch::getPipName(PipId pip) const
|
|||||||
|
|
||||||
BelId Arch::get_package_pin_bel(const std::string &pin) const
|
BelId Arch::get_package_pin_bel(const std::string &pin) const
|
||||||
{
|
{
|
||||||
for (auto &ppin : package_info->pin_data) {
|
for (auto &ppin : device.package_info->pin_data) {
|
||||||
if (ppin.name.get() == pin) {
|
if (ppin.name.get() == pin) {
|
||||||
BelId bel;
|
BelId bel;
|
||||||
bel.location = ppin.abs_loc;
|
bel.location = ppin.abs_loc;
|
||||||
@ -382,7 +372,7 @@ BelId Arch::get_package_pin_bel(const std::string &pin) const
|
|||||||
|
|
||||||
std::string Arch::get_bel_package_pin(BelId bel) const
|
std::string Arch::get_bel_package_pin(BelId bel) const
|
||||||
{
|
{
|
||||||
for (auto &ppin : package_info->pin_data) {
|
for (auto &ppin : device.package_info->pin_data) {
|
||||||
if (Location(ppin.abs_loc) == bel.location && ppin.bel_index == bel.index) {
|
if (Location(ppin.abs_loc) == bel.location && ppin.bel_index == bel.index) {
|
||||||
return ppin.name.get();
|
return ppin.name.get();
|
||||||
}
|
}
|
||||||
@ -392,7 +382,7 @@ std::string Arch::get_bel_package_pin(BelId bel) const
|
|||||||
|
|
||||||
int Arch::get_pio_bel_bank(BelId bel) const
|
int Arch::get_pio_bel_bank(BelId bel) const
|
||||||
{
|
{
|
||||||
for (auto &pio : chip_info->pio_info) {
|
for (auto &pio : device.chip_info->pio_info) {
|
||||||
if (Location(pio.abs_loc) == bel.location && pio.bel_index == bel.index) {
|
if (Location(pio.abs_loc) == bel.location && pio.bel_index == bel.index) {
|
||||||
return pio.bank;
|
return pio.bank;
|
||||||
}
|
}
|
||||||
@ -402,7 +392,7 @@ int Arch::get_pio_bel_bank(BelId bel) const
|
|||||||
|
|
||||||
std::string Arch::get_pio_function_name(BelId bel) const
|
std::string Arch::get_pio_function_name(BelId bel) const
|
||||||
{
|
{
|
||||||
for (auto &pio : chip_info->pio_info) {
|
for (auto &pio : device.chip_info->pio_info) {
|
||||||
if (Location(pio.abs_loc) == bel.location && pio.bel_index == bel.index) {
|
if (Location(pio.abs_loc) == bel.location && pio.bel_index == bel.index) {
|
||||||
const char *func = pio.function_name.get();
|
const char *func = pio.function_name.get();
|
||||||
if (func == nullptr)
|
if (func == nullptr)
|
||||||
@ -416,7 +406,7 @@ std::string Arch::get_pio_function_name(BelId bel) const
|
|||||||
|
|
||||||
BelId Arch::get_pio_by_function_name(const std::string &name) const
|
BelId Arch::get_pio_by_function_name(const std::string &name) const
|
||||||
{
|
{
|
||||||
for (auto &pio : chip_info->pio_info) {
|
for (auto &pio : device.chip_info->pio_info) {
|
||||||
const char *func = pio.function_name.get();
|
const char *func = pio.function_name.get();
|
||||||
if (func != nullptr && func == name) {
|
if (func != nullptr && func == name) {
|
||||||
BelId bel;
|
BelId bel;
|
||||||
@ -444,9 +434,9 @@ std::vector<IdString> Arch::getBelPins(BelId bel) const
|
|||||||
|
|
||||||
BelId Arch::getBelByLocation(Loc loc) const
|
BelId Arch::getBelByLocation(Loc loc) const
|
||||||
{
|
{
|
||||||
if (loc.x >= chip_info->width || loc.y >= chip_info->height)
|
if (loc.x >= device.chip_info->width || loc.y >= device.chip_info->height)
|
||||||
return BelId();
|
return BelId();
|
||||||
const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[loc.y * chip_info->width + loc.x]];
|
const LocationTypePOD &locI = device.chip_info->locations[device.chip_info->location_type[loc.y * device.chip_info->width + loc.x]];
|
||||||
for (int i = 0; i < locI.bel_data.ssize(); i++) {
|
for (int i = 0; i < locI.bel_data.ssize(); i++) {
|
||||||
if (locI.bel_data[i].z == loc.z) {
|
if (locI.bel_data[i].z == loc.z) {
|
||||||
BelId bi;
|
BelId bi;
|
||||||
@ -500,7 +490,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 * device.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 +568,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 * device.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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,7 +691,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
int y = decal.location.y;
|
int y = decal.location.y;
|
||||||
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
|
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
|
||||||
GfxTileWireId tilewire = GfxTileWireId(loc_info(wire)->wire_data[wire.index].tile_wire);
|
GfxTileWireId tilewire = GfxTileWireId(loc_info(wire)->wire_data[wire.index].tile_wire);
|
||||||
gfxTileWire(ret, x, y, chip_info->width, chip_info->height, wire_type, tilewire, style);
|
gfxTileWire(ret, x, y, device.chip_info->width, device.chip_info->height, wire_type, tilewire, style);
|
||||||
} else if (decal.type == DecalId::TYPE_PIP) {
|
} else if (decal.type == DecalId::TYPE_PIP) {
|
||||||
PipId pip;
|
PipId pip;
|
||||||
pip.index = decal.z;
|
pip.index = decal.z;
|
||||||
@ -713,7 +703,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
GfxTileWireId src_id = GfxTileWireId(loc_info(src_wire)->wire_data[src_wire.index].tile_wire);
|
GfxTileWireId src_id = GfxTileWireId(loc_info(src_wire)->wire_data[src_wire.index].tile_wire);
|
||||||
GfxTileWireId dst_id = GfxTileWireId(loc_info(dst_wire)->wire_data[dst_wire.index].tile_wire);
|
GfxTileWireId dst_id = GfxTileWireId(loc_info(dst_wire)->wire_data[dst_wire.index].tile_wire);
|
||||||
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN;
|
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN;
|
||||||
gfxTilePip(ret, x, y, chip_info->width, chip_info->height, src_wire, getWireType(src_wire), src_id, dst_wire,
|
gfxTilePip(ret, x, y, device.chip_info->width, device.chip_info->height, src_wire, getWireType(src_wire), src_id, dst_wire,
|
||||||
getWireType(dst_wire), dst_id, style);
|
getWireType(dst_wire), dst_id, style);
|
||||||
} else if (decal.type == DecalId::TYPE_BEL) {
|
} else if (decal.type == DecalId::TYPE_BEL) {
|
||||||
BelId bel;
|
BelId bel;
|
||||||
@ -724,7 +714,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
|||||||
int y = decal.location.y;
|
int y = decal.location.y;
|
||||||
int z = loc_info(bel)->bel_data[bel.index].z;
|
int z = loc_info(bel)->bel_data[bel.index].z;
|
||||||
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
|
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
|
||||||
gfxTileBel(ret, x, y, z, chip_info->width, chip_info->height, bel_type, style);
|
gfxTileBel(ret, x, y, z, device.chip_info->width, device.chip_info->height, bel_type, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -779,7 +769,7 @@ bool Arch::get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, De
|
|||||||
delay = fnd_dk->second.second;
|
delay = fnd_dk->second.second;
|
||||||
return fnd_dk->second.first;
|
return fnd_dk->second.first;
|
||||||
}
|
}
|
||||||
for (auto &tc : speed_grade->cell_timings) {
|
for (auto &tc : device.speed_grade->cell_timings) {
|
||||||
if (tc.cell_type == tctype.index) {
|
if (tc.cell_type == tctype.index) {
|
||||||
for (auto &dly : tc.prop_delays) {
|
for (auto &dly : tc.prop_delays) {
|
||||||
if (dly.from_port == from.index && dly.to_port == to.index) {
|
if (dly.from_port == from.index && dly.to_port == to.index) {
|
||||||
@ -798,7 +788,7 @@ bool Arch::get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, De
|
|||||||
void Arch::get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayPair &setup,
|
void Arch::get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayPair &setup,
|
||||||
DelayPair &hold) const
|
DelayPair &hold) const
|
||||||
{
|
{
|
||||||
for (auto &tc : speed_grade->cell_timings) {
|
for (auto &tc : device.speed_grade->cell_timings) {
|
||||||
if (tc.cell_type == tctype.index) {
|
if (tc.cell_type == tctype.index) {
|
||||||
for (auto &sh : tc.setup_holds) {
|
for (auto &sh : tc.setup_holds) {
|
||||||
if (sh.clock_port == clock.index && sh.sig_port == port.index) {
|
if (sh.clock_port == clock.index && sh.sig_port == port.index) {
|
||||||
@ -1188,22 +1178,22 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
|||||||
std::vector<std::pair<std::string, std::string>> Arch::get_tiles_at_loc(int row, int col)
|
std::vector<std::pair<std::string, std::string>> Arch::get_tiles_at_loc(int row, int col)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> ret;
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
|
auto &tileloc = device.chip_info->tile_info[row * device.chip_info->width + col];
|
||||||
for (auto &tn : tileloc.tile_names) {
|
for (auto &tn : tileloc.tile_names) {
|
||||||
ret.push_back(std::make_pair(tn.name.get(), chip_info->tiletype_names[tn.type_idx].get()));
|
ret.push_back(std::make_pair(tn.name.get(), device.chip_info->tiletype_names[tn.type_idx].get()));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalInfoPOD Arch::global_info_at_loc(Location loc)
|
GlobalInfoPOD Arch::global_info_at_loc(Location loc)
|
||||||
{
|
{
|
||||||
int locidx = loc.y * chip_info->width + loc.x;
|
int locidx = loc.y * device.chip_info->width + loc.x;
|
||||||
return chip_info->location_glbinfo[locidx];
|
return device.chip_info->location_glbinfo[locidx];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::get_pio_dqs_group(BelId pio, bool &dqsright, int &dqsrow)
|
bool Arch::get_pio_dqs_group(BelId pio, bool &dqsright, int &dqsrow)
|
||||||
{
|
{
|
||||||
for (auto &ppio : chip_info->pio_info) {
|
for (auto &ppio : device.chip_info->pio_info) {
|
||||||
if (Location(ppio.abs_loc) == pio.location && ppio.bel_index == pio.index) {
|
if (Location(ppio.abs_loc) == pio.location && ppio.bel_index == pio.index) {
|
||||||
int dqs = ppio.dqsgroup;
|
int dqs = ppio.dqsgroup;
|
||||||
if (dqs == -1)
|
if (dqs == -1)
|
||||||
@ -1222,7 +1212,7 @@ BelId Arch::get_dqsbuf(bool dqsright, int dqsrow)
|
|||||||
{
|
{
|
||||||
BelId bel;
|
BelId bel;
|
||||||
bel.location.y = dqsrow;
|
bel.location.y = dqsrow;
|
||||||
bel.location.x = (dqsright ? (chip_info->width - 1) : 0);
|
bel.location.x = (dqsright ? (device.chip_info->width - 1) : 0);
|
||||||
for (int i = 0; i < loc_info(bel)->bel_data.ssize(); i++) {
|
for (int i = 0; i < loc_info(bel)->bel_data.ssize(); i++) {
|
||||||
auto &bd = loc_info(bel)->bel_data[i];
|
auto &bd = loc_info(bel)->bel_data[i];
|
||||||
if (bd.type == id_DQSBUFM.index) {
|
if (bd.type == id_DQSBUFM.index) {
|
||||||
@ -1275,8 +1265,8 @@ std::vector<GroupId> Arch::getGroups() const
|
|||||||
{
|
{
|
||||||
std::vector<GroupId> ret;
|
std::vector<GroupId> ret;
|
||||||
|
|
||||||
for (int y = 1; y < chip_info->height - 1; y++) {
|
for (int y = 1; y < device.chip_info->height - 1; y++) {
|
||||||
for (int x = 1; x < chip_info->width - 1; x++) {
|
for (int x = 1; x < device.chip_info->width - 1; x++) {
|
||||||
GroupId group;
|
GroupId group;
|
||||||
group.type = GroupId::TYPE_SWITCHBOX;
|
group.type = GroupId::TYPE_SWITCHBOX;
|
||||||
group.location.x = x;
|
group.location.x = x;
|
||||||
|
141
ecp5/arch.h
141
ecp5/arch.h
@ -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
|
||||||
@ -444,11 +446,40 @@ struct ArchRanges : BaseArchRanges
|
|||||||
using AllPipsRangeT = AllPipRange;
|
using AllPipsRangeT = AllPipRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Arch : BaseArch<ArchRanges>
|
struct ArchDevice {
|
||||||
{
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Arch : BaseArch<ArchRanges>
|
||||||
|
{
|
||||||
|
ArchDevice device;
|
||||||
|
|
||||||
mutable dict<IdStringList, PipId> pip_by_name;
|
mutable dict<IdStringList, PipId> pip_by_name;
|
||||||
|
|
||||||
@ -513,11 +544,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;
|
||||||
@ -526,8 +555,8 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
static const int max_loc_bels = 32;
|
static const int max_loc_bels = 32;
|
||||||
|
|
||||||
int getGridDimX() const override { return chip_info->width; };
|
int getGridDimX() const override { return device.chip_info->width; };
|
||||||
int getGridDimY() const override { return chip_info->height; };
|
int getGridDimY() const override { return device.chip_info->height; };
|
||||||
int getTileBelDimZ(int, int) const override { return max_loc_bels; };
|
int getTileBelDimZ(int, int) const override { return max_loc_bels; };
|
||||||
int getTilePipDimZ(int, int) const override { return 1; };
|
int getTilePipDimZ(int, int) const override { return 1; };
|
||||||
char getNameDelimiter() const override { return '/'; }
|
char getNameDelimiter() const override { return '/'; }
|
||||||
@ -538,12 +567,12 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
template <typename Id> const LocationTypePOD *loc_info(Id &id) const
|
template <typename Id> const LocationTypePOD *loc_info(Id &id) const
|
||||||
{
|
{
|
||||||
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
|
return &(device.chip_info->locations[device.chip_info->location_type[id.location.y * device.chip_info->width + id.location.x]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Id> inline int tile_index(Id id) const
|
template <typename Id> inline int tile_index(Id id) const
|
||||||
{
|
{
|
||||||
return id.location.y * chip_info->width + id.location.x;
|
return id.location.y * device.chip_info->width + id.location.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdStringList getBelName(BelId bel) const override
|
IdStringList getBelName(BelId bel) const override
|
||||||
@ -559,7 +588,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
int get_slice_index(int x, int y, int slice) const
|
int get_slice_index(int x, int y, int slice) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(slice >= 0 && slice < 4);
|
NPNR_ASSERT(slice >= 0 && slice < 4);
|
||||||
return (y * chip_info->width + x) * 4 + slice;
|
return (y * device.chip_info->width + x) * 4 + slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_bel(BelId bel, CellInfo *old_cell, CellInfo *new_cell)
|
void update_bel(BelId bel, CellInfo *old_cell, CellInfo *new_cell)
|
||||||
@ -650,11 +679,11 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
BelRange range;
|
BelRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
range.b.cursor_index = -1;
|
range.b.cursor_index = -1;
|
||||||
range.b.chip = chip_info;
|
range.b.chip = device.chip_info;
|
||||||
++range.b; //-1 and then ++ deals with the case of no Bels in the first tile
|
++range.b; //-1 and then ++ deals with the case of no Bels in the first tile
|
||||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
range.e.cursor_tile = device.chip_info->width * device.chip_info->height;
|
||||||
range.e.cursor_index = 0;
|
range.e.cursor_index = 0;
|
||||||
range.e.chip = chip_info;
|
range.e.chip = device.chip_info;
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +736,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
uint32_t get_wire_vecidx(const WireId &e) const
|
uint32_t get_wire_vecidx(const WireId &e) const
|
||||||
{
|
{
|
||||||
uint32_t tile = e.location.y * chip_info->width + e.location.x;
|
uint32_t tile = e.location.y * device.chip_info->width + e.location.x;
|
||||||
int32_t base = wire_tile_vecidx.at(tile);
|
int32_t base = wire_tile_vecidx.at(tile);
|
||||||
NPNR_ASSERT(base != -1);
|
NPNR_ASSERT(base != -1);
|
||||||
int32_t i = base + e.index;
|
int32_t i = base + e.index;
|
||||||
@ -754,11 +783,11 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
WireRange range;
|
WireRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
range.b.cursor_index = -1;
|
range.b.cursor_index = -1;
|
||||||
range.b.chip = chip_info;
|
range.b.chip = device.chip_info;
|
||||||
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
||||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
range.e.cursor_tile = device.chip_info->width * device.chip_info->height;
|
||||||
range.e.cursor_index = 0;
|
range.e.cursor_index = 0;
|
||||||
range.e.chip = chip_info;
|
range.e.chip = device.chip_info;
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,7 +815,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
uint32_t get_pip_vecidx(const PipId &e) const
|
uint32_t get_pip_vecidx(const PipId &e) const
|
||||||
{
|
{
|
||||||
uint32_t tile = e.location.y * chip_info->width + e.location.x;
|
uint32_t tile = e.location.y * device.chip_info->width + e.location.x;
|
||||||
int32_t base = pip_tile_vecidx.at(tile);
|
int32_t base = pip_tile_vecidx.at(tile);
|
||||||
NPNR_ASSERT(base != -1);
|
NPNR_ASSERT(base != -1);
|
||||||
int32_t i = base + e.index;
|
int32_t i = base + e.index;
|
||||||
@ -859,11 +888,11 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
AllPipRange range;
|
AllPipRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
range.b.cursor_index = -1;
|
range.b.cursor_index = -1;
|
||||||
range.b.chip = chip_info;
|
range.b.chip = device.chip_info;
|
||||||
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
||||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
range.e.cursor_tile = device.chip_info->width * device.chip_info->height;
|
||||||
range.e.cursor_index = 0;
|
range.e.cursor_index = 0;
|
||||||
range.e.chip = chip_info;
|
range.e.chip = device.chip_info;
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,11 +919,11 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
int fanout = wire_fanout[get_wire_vecidx(getPipSrcWire(pip))];
|
int fanout = wire_fanout[get_wire_vecidx(getPipSrcWire(pip))];
|
||||||
delay_t min_dly =
|
delay_t min_dly =
|
||||||
speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_base_delay +
|
device.speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_base_delay +
|
||||||
fanout * speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_fanout_adder;
|
fanout * device.speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_fanout_adder;
|
||||||
delay_t max_dly =
|
delay_t max_dly =
|
||||||
speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_base_delay +
|
device.speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_base_delay +
|
||||||
fanout * speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_fanout_adder;
|
fanout * device.speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_fanout_adder;
|
||||||
return DelayQuad(min_dly, max_dly);
|
return DelayQuad(min_dly, max_dly);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +951,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
std::string get_pip_tilename(PipId pip) const
|
std::string get_pip_tilename(PipId pip) const
|
||||||
{
|
{
|
||||||
auto &tileloc = chip_info->tile_info[pip.location.y * chip_info->width + pip.location.x];
|
auto &tileloc = device.chip_info->tile_info[pip.location.y * device.chip_info->width + pip.location.x];
|
||||||
for (auto &tn : tileloc.tile_names) {
|
for (auto &tn : tileloc.tile_names) {
|
||||||
if (tn.type_idx == loc_info(pip)->pip_data[pip.index].tile_type)
|
if (tn.type_idx == loc_info(pip)->pip_data[pip.index].tile_type)
|
||||||
return tn.name.get();
|
return tn.name.get();
|
||||||
@ -932,7 +961,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
std::string get_pip_tiletype(PipId pip) const
|
std::string get_pip_tiletype(PipId pip) const
|
||||||
{
|
{
|
||||||
return chip_info->tiletype_names[loc_info(pip)->pip_data[pip.index].tile_type].get();
|
return device.chip_info->tiletype_names[loc_info(pip)->pip_data[pip.index].tile_type].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Loc getPipLocation(PipId pip) const override
|
Loc getPipLocation(PipId pip) const override
|
||||||
@ -1021,9 +1050,9 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
std::vector<std::pair<std::string, std::string>> get_tiles_at_loc(int row, int col);
|
std::vector<std::pair<std::string, std::string>> get_tiles_at_loc(int row, int col);
|
||||||
std::string get_tile_by_type_loc(int row, int col, std::string type) const
|
std::string get_tile_by_type_loc(int row, int col, std::string type) const
|
||||||
{
|
{
|
||||||
auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
|
auto &tileloc = device.chip_info->tile_info[row * device.chip_info->width + col];
|
||||||
for (auto &tn : tileloc.tile_names) {
|
for (auto &tn : tileloc.tile_names) {
|
||||||
if (chip_info->tiletype_names[tn.type_idx].get() == type)
|
if (device.chip_info->tiletype_names[tn.type_idx].get() == type)
|
||||||
return tn.name.get();
|
return tn.name.get();
|
||||||
}
|
}
|
||||||
NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type " +
|
NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type " +
|
||||||
@ -1032,9 +1061,9 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
std::string get_tile_by_type_loc(int row, int col, const std::set<std::string> &type) const
|
std::string get_tile_by_type_loc(int row, int col, const std::set<std::string> &type) const
|
||||||
{
|
{
|
||||||
auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
|
auto &tileloc = device.chip_info->tile_info[row * device.chip_info->width + col];
|
||||||
for (auto &tn : tileloc.tile_names) {
|
for (auto &tn : tileloc.tile_names) {
|
||||||
if (type.count(chip_info->tiletype_names[tn.type_idx].get()))
|
if (type.count(device.chip_info->tiletype_names[tn.type_idx].get()))
|
||||||
return tn.name.get();
|
return tn.name.get();
|
||||||
}
|
}
|
||||||
NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type in set");
|
NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type in set");
|
||||||
@ -1042,10 +1071,10 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
std::string get_tile_by_type(std::string type) const
|
std::string get_tile_by_type(std::string type) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < chip_info->height * chip_info->width; i++) {
|
for (int i = 0; i < device.chip_info->height * device.chip_info->width; i++) {
|
||||||
auto &tileloc = chip_info->tile_info[i];
|
auto &tileloc = device.chip_info->tile_info[i];
|
||||||
for (auto &tn : tileloc.tile_names)
|
for (auto &tn : tileloc.tile_names)
|
||||||
if (chip_info->tiletype_names[tn.type_idx].get() == type)
|
if (device.chip_info->tiletype_names[tn.type_idx].get() == type)
|
||||||
return tn.name.get();
|
return tn.name.get();
|
||||||
}
|
}
|
||||||
NPNR_ASSERT_FALSE_STR("no tile with type " + type);
|
NPNR_ASSERT_FALSE_STR("no tile with type " + type);
|
||||||
|
@ -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 device.type != ArchDevice::LFE5U_25F && device.type != ArchDevice::LFE5U_45F &&
|
||||||
args.type != ArchArgs::LFE5U_85F;
|
device.type != ArchDevice::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 {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -195,7 +195,7 @@ struct ECP5Bitgen
|
|||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("bad PIO location");
|
NPNR_ASSERT_FALSE("bad PIO location");
|
||||||
}
|
}
|
||||||
} else if (bel.location.y == ctx->chip_info->height - 1) {
|
} else if (bel.location.y == ctx->device.chip_info->height - 1) {
|
||||||
if (pio_name == "PIOA") {
|
if (pio_name == "PIOA") {
|
||||||
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, pioa_b);
|
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, pioa_b);
|
||||||
} else if (pio_name == "PIOB") {
|
} else if (pio_name == "PIOB") {
|
||||||
@ -205,7 +205,7 @@ struct ECP5Bitgen
|
|||||||
}
|
}
|
||||||
} else if (bel.location.x == 0) {
|
} else if (bel.location.x == 0) {
|
||||||
return ctx->get_tile_by_type_loc(bel.location.y + 1, bel.location.x, pioabcd_l);
|
return ctx->get_tile_by_type_loc(bel.location.y + 1, bel.location.x, pioabcd_l);
|
||||||
} else if (bel.location.x == ctx->chip_info->width - 1) {
|
} else if (bel.location.x == ctx->device.chip_info->width - 1) {
|
||||||
return ctx->get_tile_by_type_loc(bel.location.y + 1, bel.location.x, pioabcd_r);
|
return ctx->get_tile_by_type_loc(bel.location.y + 1, bel.location.x, pioabcd_r);
|
||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("bad PIO location");
|
NPNR_ASSERT_FALSE("bad PIO location");
|
||||||
@ -232,7 +232,7 @@ struct ECP5Bitgen
|
|||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("bad PIO location");
|
NPNR_ASSERT_FALSE("bad PIO location");
|
||||||
}
|
}
|
||||||
} else if (bel.location.y == ctx->chip_info->height - 1) {
|
} else if (bel.location.y == ctx->device.chip_info->height - 1) {
|
||||||
if (pio_name == "PIOA") {
|
if (pio_name == "PIOA") {
|
||||||
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, pica_b);
|
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, pica_b);
|
||||||
} else if (pio_name == "PIOB") {
|
} else if (pio_name == "PIOB") {
|
||||||
@ -248,7 +248,7 @@ struct ECP5Bitgen
|
|||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("bad PIO location");
|
NPNR_ASSERT_FALSE("bad PIO location");
|
||||||
}
|
}
|
||||||
} else if (bel.location.x == ctx->chip_info->width - 1) {
|
} else if (bel.location.x == ctx->device.chip_info->width - 1) {
|
||||||
if (pio_name == "PIOA" || pio_name == "PIOB") {
|
if (pio_name == "PIOA" || pio_name == "PIOB") {
|
||||||
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, picab_r);
|
return ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, picab_r);
|
||||||
} else if (pio_name == "PIOC" || pio_name == "PIOD") {
|
} else if (pio_name == "PIOC" || pio_name == "PIOD") {
|
||||||
@ -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->device.type == ArchDevice::LFE5U_12F || ctx->device.type == ArchDevice::LFE5U_25F ||
|
||||||
ctx->args.type == ArchArgs::LFE5U_45F || ctx->args.type == ArchArgs::LFE5U_85F) {
|
ctx->device.type == ArchDevice::LFE5U_45F || ctx->device.type == ArchDevice::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->device.type) {
|
||||||
case ArchArgs::LFE5U_12F:
|
case ArchDevice::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 ArchDevice::LFE5U_25F:
|
||||||
|
BaseConfigs::config_empty_lfe5u_25f(cc);
|
||||||
|
break;
|
||||||
|
case ArchDevice::LFE5U_45F:
|
||||||
BaseConfigs::config_empty_lfe5u_45f(cc);
|
BaseConfigs::config_empty_lfe5u_45f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5U_85F:
|
case ArchDevice::LFE5U_85F:
|
||||||
BaseConfigs::config_empty_lfe5u_85f(cc);
|
BaseConfigs::config_empty_lfe5u_85f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM_25F:
|
case ArchDevice::LFE5UM_25F:
|
||||||
BaseConfigs::config_empty_lfe5um_25f(cc);
|
BaseConfigs::config_empty_lfe5um_25f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM_45F:
|
case ArchDevice::LFE5UM_45F:
|
||||||
BaseConfigs::config_empty_lfe5um_45f(cc);
|
BaseConfigs::config_empty_lfe5um_45f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM_85F:
|
case ArchDevice::LFE5UM_85F:
|
||||||
BaseConfigs::config_empty_lfe5um_85f(cc);
|
BaseConfigs::config_empty_lfe5um_85f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM5G_25F:
|
case ArchDevice::LFE5UM5G_25F:
|
||||||
BaseConfigs::config_empty_lfe5um5g_25f(cc);
|
BaseConfigs::config_empty_lfe5um5g_25f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM5G_45F:
|
case ArchDevice::LFE5UM5G_45F:
|
||||||
BaseConfigs::config_empty_lfe5um5g_45f(cc);
|
BaseConfigs::config_empty_lfe5um5g_45f(cc);
|
||||||
break;
|
break;
|
||||||
case ArchArgs::LFE5UM5G_85F:
|
case ArchDevice::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.device_info->name.get();
|
||||||
|
cc.chip_variant = ctx->device.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->device.type == ArchDevice::LFE5U_12F || ctx->device.type == ArchDevice::LFE5U_25F ||
|
||||||
ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F) &&
|
ctx->device.type == ArchDevice::LFE5UM_25F || ctx->device.type == ArchDevice::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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
1
ecp5/ecp5_available.h.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
static const char *available_devices = "@ECP5_DEVICES@";
|
@ -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()
|
||||||
|
230
ecp5/main.cc
230
ecp5/main.cc
@ -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("45k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5U_45F;
|
|
||||||
if (vm.count("85k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5U_85F;
|
|
||||||
if (vm.count("um-25k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM_25F;
|
|
||||||
if (vm.count("um-45k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM_45F;
|
|
||||||
if (vm.count("um-85k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM_85F;
|
|
||||||
if (vm.count("um5g-25k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM5G_25F;
|
|
||||||
if (vm.count("um5g-45k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM5G_45F;
|
|
||||||
if (vm.count("um5g-85k"))
|
|
||||||
chipArgs.type = ArchArgs::LFE5UM5G_85F;
|
|
||||||
if (vm.count("package"))
|
|
||||||
chipArgs.package = vm["package"].as<std::string>();
|
|
||||||
|
|
||||||
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 (vm.count("device"))
|
||||||
|
chipArgs.device = vm["device"].as<std::string>();
|
||||||
|
else if (vm.count("12k"))
|
||||||
|
chipArgs.device = "LFE5U-12F";
|
||||||
|
else if (vm.count("25k"))
|
||||||
|
chipArgs.device = "LFE5U-25F";
|
||||||
|
else if (vm.count("45k"))
|
||||||
|
chipArgs.device = "LFE5U-45F";
|
||||||
|
else if (vm.count("85k"))
|
||||||
|
chipArgs.device = "LFE5U-85F";
|
||||||
|
else if (vm.count("um-25k"))
|
||||||
|
chipArgs.device = "LFE5UM-25F";
|
||||||
|
else if (vm.count("um-45k"))
|
||||||
|
chipArgs.device = "LFE5UM-45F";
|
||||||
|
else if (vm.count("um-85k"))
|
||||||
|
chipArgs.device = "LFE5UM-85F";
|
||||||
|
else if (vm.count("um5g-25k"))
|
||||||
|
chipArgs.device = "LFE5UM5G-25F";
|
||||||
|
else if (vm.count("um5g-45k"))
|
||||||
|
chipArgs.device = "LFE5UM5G-45F";
|
||||||
|
else if (vm.count("um5g-85k"))
|
||||||
|
chipArgs.device = "LFE5UM5G-85F";
|
||||||
|
|
||||||
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"))
|
||||||
|
26
ecp5/pack.cc
26
ecp5/pack.cc
@ -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->device.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));
|
||||||
@ -665,7 +665,7 @@ class Ecp5Packer
|
|||||||
{
|
{
|
||||||
bool start_of_chain = true;
|
bool start_of_chain = true;
|
||||||
std::vector<CellChain> chains;
|
std::vector<CellChain> chains;
|
||||||
const int max_length = (ctx->chip_info->width - 4) * 4 - 2;
|
const int max_length = (ctx->device.chip_info->width - 4) * 4 - 2;
|
||||||
auto curr_cell = carryc.cells.begin();
|
auto curr_cell = carryc.cells.begin();
|
||||||
while (curr_cell != carryc.cells.end()) {
|
while (curr_cell != carryc.cells.end()) {
|
||||||
CellInfo *cell = *curr_cell;
|
CellInfo *cell = *curr_cell;
|
||||||
@ -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->device.type == ArchDevice::LFE5UM_25F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_45F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_45F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_85F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_85F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_25F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_45F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_45F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_85F || ctx->device.type == ArchDevice::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->device.type == ArchDevice::LFE5UM_85F || ctx->device.type == ArchDevice::LFE5UM5G_85F))
|
||||||
loc_bel = std::string("X71/Y95/EXTREF");
|
loc_bel = std::string("X71/Y95/EXTREF");
|
||||||
}
|
}
|
||||||
if (refo == nullptr)
|
if (refo == nullptr)
|
||||||
@ -1859,7 +1859,7 @@ class Ecp5Packer
|
|||||||
log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
|
log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||||
Loc loc = ctx->getBelLocation(bel);
|
Loc loc = ctx->getBelLocation(bel);
|
||||||
bool s = false;
|
bool s = false;
|
||||||
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1))
|
if (loc.y == 0 || loc.y == (ctx->device.chip_info->height - 1))
|
||||||
s = true;
|
s = true;
|
||||||
std::unique_ptr<CellInfo> iol =
|
std::unique_ptr<CellInfo> iol =
|
||||||
create_ecp5_cell(ctx, s ? id_SIOLOGIC : id_IOLOGIC, pio->name.str(ctx) + "$IOL");
|
create_ecp5_cell(ctx, s ? id_SIOLOGIC : id_IOLOGIC, pio->name.str(ctx) + "$IOL");
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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.device_name) + " (" + std::string(ctx->device.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);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5U_45F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5U_85F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM_25F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM_45F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM_85F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM5G_25F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM5G_45F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F);
|
|
||||||
if (Arch::is_available(ArchArgs::LFE5UM5G_85F))
|
|
||||||
arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F);
|
|
||||||
|
|
||||||
bool ok;
|
std::stringstream ss(available_devices);
|
||||||
QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
|
std::string name;
|
||||||
if (ok && !item.isEmpty()) {
|
while (getline(ss, name, ';')) {
|
||||||
ArchArgs chipArgs;
|
std::string chipdb = stringf("ecp5/chipdb-%s.bin", name.c_str());
|
||||||
chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item);
|
auto db_ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
|
||||||
|
if (!db_ptr)
|
||||||
QStringList packages;
|
continue; // chipdb not available
|
||||||
for (auto package : Arch::get_supported_packages(chipArgs.type))
|
for (auto &dev : db_ptr->get()->devices) {
|
||||||
packages.append(QLatin1String(package.data(), package.size()));
|
for (auto &chip : dev.variants) {
|
||||||
QString package = QInputDialog::getItem(this, "Select package", "Package:", packages, 0, false, &ok);
|
for (auto &pkg : chip.packages) {
|
||||||
|
for (auto &speedgrade : chip.speed_grades) {
|
||||||
if (ok && !item.isEmpty()) {
|
for (auto &rating : chip.suffixes) {
|
||||||
handler->clear();
|
std::string devname = stringf("%s-%d%s%s", chip.name.get(), speedgrade.speed,
|
||||||
currentProj = "";
|
pkg.short_name.get(), rating.suffix.get());
|
||||||
disableActions();
|
arch.append(QString::fromLocal8Bit(devname.c_str()));
|
||||||
chipArgs.package = package.toStdString().c_str();
|
}
|
||||||
ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
}
|
||||||
actionLoadJSON->setEnabled(true);
|
}
|
||||||
|
}
|
||||||
Q_EMIT contextChanged(ctx.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
QString item = QInputDialog::getItem(this, "Select new context", "Part:", arch, 0, false, &ok);
|
||||||
|
if (ok && !item.isEmpty()) {
|
||||||
|
ArchArgs chipArgs;
|
||||||
|
chipArgs.device = item.toUtf8().constData();
|
||||||
|
;
|
||||||
|
|
||||||
|
handler->clear();
|
||||||
|
currentProj = "";
|
||||||
|
disableActions();
|
||||||
|
ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||||
|
actionLoadJSON->setEnabled(true);
|
||||||
|
|
||||||
|
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"));
|
||||||
|
Loading…
Reference in New Issue
Block a user