aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/archcheck.cc4
-rw-r--r--common/nextpnr.cc22
-rw-r--r--common/nextpnr.h26
-rw-r--r--common/place_common.cc7
-rw-r--r--common/placer1.cc8
-rw-r--r--common/placer_heap.cc4
-rw-r--r--common/timing_opt.cc9
-rw-r--r--ecp5/arch.cc15
-rw-r--r--ecp5/arch.h13
-rw-r--r--ecp5/arch_pybindings.h2
-rw-r--r--ecp5/globals.cc6
-rw-r--r--ecp5/pack.cc46
12 files changed, 101 insertions, 61 deletions
diff --git a/common/archcheck.cc b/common/archcheck.cc
index f5760c88..412feca9 100644
--- a/common/archcheck.cc
+++ b/common/archcheck.cc
@@ -36,10 +36,10 @@ void archcheck_names(const Context *ctx)
log_info("Checking bel names..\n");
for (BelId bel : ctx->getBels()) {
- IdString name = ctx->getBelName(bel);
+ IdStringList name = ctx->getBelName(bel);
BelId bel2 = ctx->getBelByName(name);
if (bel != bel2) {
- log_error("bel != bel2, name = %s\n", name.c_str(ctx));
+ log_error("bel != bel2, name = %s\n", ctx->nameOfBel(bel));
}
}
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 57baedf9..c9084a75 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -111,6 +111,14 @@ TimingConstrObjectId BaseCtx::timingWildcardObject()
return id;
}
+std::string &StrRingBuffer::next()
+{
+ std::string &s = buffer.at(index++);
+ if (index >= N)
+ index = 0;
+ return s;
+}
+
TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain)
{
NPNR_ASSERT(clockDomain->clkconstr != nullptr);
@@ -283,7 +291,9 @@ void BaseCtx::removeConstraint(IdString constrName)
const char *BaseCtx::nameOfBel(BelId bel) const
{
const Context *ctx = getCtx();
- return ctx->getBelName(bel).c_str(ctx);
+ std::string &s = ctx->log_strs.next();
+ ctx->getBelName(bel).build_str(ctx, s);
+ return s.c_str();
}
const char *BaseCtx::nameOfWire(WireId wire) const
@@ -304,6 +314,12 @@ const char *BaseCtx::nameOfGroup(GroupId group) const
return ctx->getGroupName(group).c_str(ctx);
}
+BelId BaseCtx::getBelByNameStr(const std::string &str)
+{
+ Context *ctx = getCtx();
+ return ctx->getBelByName(IdStringList::parse(ctx, str));
+}
+
WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
{
if (net_info->driver.cell == nullptr)
@@ -655,7 +671,7 @@ void BaseCtx::archInfoToAttributes()
if (ci->attrs.find(id("BEL")) != ci->attrs.end()) {
ci->attrs.erase(ci->attrs.find(id("BEL")));
}
- ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(this);
+ ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(getCtx());
ci->attrs[id("BEL_STRENGTH")] = (int)ci->belStrength;
}
if (ci->constr_x != ci->UNCONSTR)
@@ -707,7 +723,7 @@ void BaseCtx::attributesToArchInfo()
if (str != ci->attrs.end())
strength = (PlaceStrength)str->second.as_int64();
- BelId b = getCtx()->getBelByName(id(val->second.as_string()));
+ BelId b = getCtx()->getBelByNameStr(val->second.as_string());
getCtx()->bindBel(b, ci, strength);
}
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 66f31867..9523e418 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -148,14 +148,13 @@ NEXTPNR_NAMESPACE_BEGIN
// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise
template <typename T, size_t N> class SSOArray
{
+ private:
union
{
T data_static[N];
T *data_heap;
};
size_t m_size;
-
- private:
inline bool is_heap() const { return (m_size > N); }
void alloc()
{
@@ -224,8 +223,8 @@ struct IdStringList
SSOArray<IdString, 4> ids;
IdStringList(){};
- explicit IdStringList(size_t n) : ids(n, IdString()){};
- explicit IdStringList(IdString id) : ids(1, id){};
+ IdStringList(size_t n) : ids(n, IdString()){};
+ IdStringList(IdString id) : ids(1, id){};
template <typename Tlist> IdStringList(const Tlist &list) : ids(list){};
static IdStringList parse(Context *ctx, const std::string &str);
@@ -238,6 +237,19 @@ struct IdStringList
const IdString &operator[](size_t idx) const { return ids[idx]; }
};
+// A ring buffer of strings, so we can return a simple const char * pointer for %s formatting - inspired by how logging
+// in Yosys works Let's just hope noone tries to log more than 100 things in one call....
+class StrRingBuffer
+{
+ private:
+ static const size_t N = 100;
+ std::array<std::string, N> buffer;
+ size_t index = 0;
+
+ public:
+ std::string &next();
+};
+
struct GraphicElement
{
enum type_t
@@ -760,6 +772,9 @@ struct BaseCtx
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str;
+ // Temporary string backing store for logging
+ mutable StrRingBuffer log_strs;
+
// Project settings and config switches
std::unordered_map<IdString, Property> settings;
@@ -875,6 +890,9 @@ struct BaseCtx
const char *nameOfPip(PipId pip) const;
const char *nameOfGroup(GroupId group) const;
+ // Overrides of arch functions that take a string and handle IdStringList parsing
+ BelId getBelByNameStr(const std::string &str);
+
// --------------------------------------------------------------
bool allUiReload = true;
diff --git a/common/place_common.cc b/common/place_common.cc
index 3f89169a..6526c38e 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -158,8 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
all_placed = true;
}
if (ctx->verbose)
- log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
- ctx->getBelName(best_bel).c_str(ctx));
+ log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->nameOfBel(best_bel));
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
cell = ripup_target;
@@ -375,7 +374,7 @@ class ConstraintLegaliseWorker
if (confl_cell != nullptr) {
if (ctx->verbose)
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
- ctx->getBelName(confl_cell->bel).c_str(ctx));
+ ctx->nameOfBel(confl_cell->bel));
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target);
rippedCells.insert(confl_cell->name);
@@ -489,7 +488,7 @@ class ConstraintLegaliseWorker
for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0)
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
- ctx->getBelName(cell.second->bel).c_str(ctx));
+ ctx->nameOfBel(cell.second->bel));
return score;
}
};
diff --git a/common/placer1.cc b/common/placer1.cc
index 1c039090..c54c3cf2 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -154,7 +154,7 @@ class SAPlacer
auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string();
- BelId bel = ctx->getBelByName(ctx->id(loc_name));
+ BelId bel = ctx->getBelByNameStr(loc_name);
if (bel == BelId()) {
log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n",
@@ -409,18 +409,18 @@ class SAPlacer
if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
+ ctx->nameOfBel(bel), cell_text.c_str());
} else {
log_error("post-placement validity check failed for Bel '%s' "
"(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
+ ctx->nameOfBel(bel), cell_text.c_str());
}
}
}
for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0)
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
- ctx->getBelName(cell.second->bel).c_str(ctx));
+ ctx->nameOfBel(cell.second->bel));
timing_analysis(ctx);
ctx->unlock();
return true;
diff --git a/common/placer_heap.cc b/common/placer_heap.cc
index d149a5b0..7882c8da 100644
--- a/common/placer_heap.cc
+++ b/common/placer_heap.cc
@@ -305,7 +305,7 @@ class HeAPPlacer
if (ctx->getBoundBelCell(cell.second->bel) != cell.second)
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
if (ctx->debug)
- log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->getBelName(cell.second->bel).c_str(ctx));
+ log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel));
}
ctx->unlock();
@@ -379,7 +379,7 @@ class HeAPPlacer
auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string();
- BelId bel = ctx->getBelByName(ctx->id(loc_name));
+ BelId bel = ctx->getBelByNameStr(loc_name);
if (bel == BelId()) {
log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n",
diff --git a/common/timing_opt.cc b/common/timing_opt.cc
index 025084b7..7ee7b805 100644
--- a/common/timing_opt.cc
+++ b/common/timing_opt.cc
@@ -427,7 +427,7 @@ class TimingOptimiser
if (pn->users.at(i).cell == port->cell && pn->users.at(i).port == port->port)
crit = net_crit.at(pn->name).criticality.at(i);
log_info(" %s.%s at %s crit %0.02f\n", port->cell->name.c_str(ctx), port->port.c_str(ctx),
- ctx->getBelName(port->cell->bel).c_str(ctx), crit);
+ ctx->nameOfBel(port->cell->bel), crit);
}
if (std::find(path_cells.begin(), path_cells.end(), port->cell->name) != path_cells.end())
continue;
@@ -472,10 +472,9 @@ class TimingOptimiser
if (ctx->debug) {
for (auto cell : path_cells) {
- log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx),
- ctx->getBelName(ctx->cells[cell]->bel).c_str(ctx));
+ log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx), ctx->nameOfBel(ctx->cells[cell]->bel));
for (auto neigh : cell_neighbour_bels.at(cell)) {
- log_info(" %s\n", ctx->getBelName(neigh).c_str(ctx));
+ log_info(" %s\n", ctx->nameOfBel(neigh));
}
}
}
@@ -597,7 +596,7 @@ class TimingOptimiser
CellInfo *cell = ctx->cells.at(rt_entry.first).get();
cell_swap_bel(cell, rt_entry.second);
if (ctx->debug)
- log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->getBelName(rt_entry.second).c_str(ctx));
+ log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->nameOfBel(rt_entry.second));
}
} else {
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 25f95c53..928a9c5f 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -128,6 +128,11 @@ Arch::Arch(ArchArgs args) : args(args)
bucket.name = bel_type;
buckets.push_back(bucket);
}
+
+ for (int i = 0; i < chip_info->width; i++)
+ x_ids.push_back(id(stringf("X%d", i)));
+ for (int i = 0; i < chip_info->height; i++)
+ y_ids.push_back(id(stringf("Y%d", i)));
}
// -----------------------------------------------------------------------
@@ -208,16 +213,18 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
-BelId Arch::getBelByName(IdString name) const
+BelId Arch::getBelByName(IdStringList name) const
{
+ // TODO: take advantage of IdStringList for fast parsing
BelId ret;
+#if 0
auto it = bel_by_name.find(name);
if (it != bel_by_name.end())
return it->second;
-
+#endif
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(getCtx()));
ret.location = loc;
const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->bel_data.size()); i++) {
@@ -226,8 +233,10 @@ BelId Arch::getBelByName(IdString name) const
break;
}
}
+#if 0
if (ret.index >= 0)
bel_by_name[name] = ret;
+#endif
return ret;
}
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 6b32f284..303d9afe 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -450,6 +450,9 @@ struct Arch : BaseCtx
std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<WireId, int> wire_fanout;
+ // fast access to X and Y IdStrings for building object names
+ std::vector<IdString> x_ids, y_ids;
+
ArchArgs args;
Arch(ArchArgs args);
@@ -475,19 +478,19 @@ struct Arch : BaseCtx
// -------------------------------------------------
- BelId getBelByName(IdString name) const;
+ BelId getBelByName(IdStringList name) const;
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
}
- IdString getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
- std::stringstream name;
- name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get();
- return id(name.str());
+ std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
+ id(locInfo(bel)->bel_data[bel.index].name.get())};
+ return IdStringList(ids);
}
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index dd3161ae..90c7c757 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -30,7 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); }
std::string to_str(Context *ctx, BelId id)
{
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 218090e1..ad99272e 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -176,8 +176,8 @@ class Ecp5GlobalRouter
}
}
if (upstream.size() > 30000) {
- log_error("failed to route HPBX%02d00 to %s.%s\n", global_index,
- ctx->getBelName(user.cell->bel).c_str(ctx), user.port.c_str(ctx));
+ log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, ctx->nameOfBel(user.cell->bel),
+ user.port.c_str(ctx));
}
}
// Set all the pips we found along the way
@@ -300,7 +300,7 @@ class Ecp5GlobalRouter
if (drv.cell == nullptr) {
return 0;
} else if (drv.cell->attrs.count(ctx->id("BEL"))) {
- drv_bel = ctx->getBelByName(ctx->id(drv.cell->attrs.at(ctx->id("BEL")).as_string()));
+ drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(ctx->id("BEL")).as_string());
} else {
// Check if driver is a singleton
BelId last_bel;
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index b60d6c7d..8d21c5b3 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -522,7 +522,7 @@ class Ecp5Packer
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
} else {
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx),
- ctx->getBelName(pinBel).c_str(ctx));
+ ctx->nameOfBel(pinBel));
}
trio->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
}
@@ -1657,7 +1657,7 @@ class Ecp5Packer
CellInfo *dcu = clki->driver.cell;
if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
- BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(dcu->attrs.at(ctx->id("BEL")).as_string());
if (bel == BelId())
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
Loc loc = ctx->getBelLocation(bel);
@@ -1704,7 +1704,7 @@ class Ecp5Packer
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
- available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL")).as_string())));
+ available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
}
// Place PLL connected to fixed drivers such as IO close to their source
for (auto cell : sorted(ctx->cells)) {
@@ -1716,7 +1716,7 @@ class Ecp5Packer
const CellInfo *drivercell = drivernet->driver.cell;
if (!drivercell->attrs.count(ctx->id("BEL")))
continue;
- BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId drvbel = ctx->getBelByNameStr(drivercell->attrs.at(ctx->id("BEL")).as_string());
Loc drvloc = ctx->getBelLocation(drvbel);
BelId closest_pll;
int closest_distance = std::numeric_limits<int>::max();
@@ -1848,8 +1848,8 @@ class Ecp5Packer
WireId next;
while (true) {
if (upstream.empty() || upstream.size() > 30000)
- log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk,
- ctx->getBelName(usr_bel).c_str(ctx), usr_port.name.c_str(ctx));
+ log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk, ctx->nameOfBel(usr_bel),
+ usr_port.name.c_str(ctx));
next = upstream.front();
upstream.pop();
if (ctx->debug)
@@ -1913,17 +1913,17 @@ class Ecp5Packer
log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input"
"(while processing '%s').\n",
ci->name.c_str(ctx));
- BelId pio_bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId pio_bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(pio_bel != BelId());
Loc pio_loc = ctx->getBelLocation(pio_bel);
if (pio_loc.z != 0)
log_error("PIO '%s' does not appear to be a DQS site (expecting an 'A' pin).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
pio_loc.z = 8;
BelId dqsbuf = ctx->getBelByLocation(pio_loc);
if (dqsbuf == BelId() || ctx->getBelType(dqsbuf) != id_DQSBUFM)
log_error("PIO '%s' does not appear to be a DQS site (didn't find a DQSBUFM).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
ci->attrs[ctx->id("BEL")] = ctx->getBelName(dqsbuf).str(ctx);
bool got_dqsg = ctx->getPIODQSGroup(pio_bel, dqsbuf_dqsg[ci->name].first, dqsbuf_dqsg[ci->name].second);
NPNR_ASSERT(got_dqsg);
@@ -2078,15 +2078,14 @@ class Ecp5Packer
log_error("IOLOGIC functionality (DDR, DELAY, DQS, etc) can only be used with pin-constrained PIO "
"(while processing '%s').\n",
curr->name.c_str(ctx));
- BelId bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(bel != BelId());
return bel;
};
auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) {
BelId bel = get_pio_bel(pio, curr);
- log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx),
- ctx->getBelName(bel).c_str(ctx));
+ log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
Loc loc = ctx->getBelLocation(bel);
bool s = false;
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1))
@@ -2292,8 +2291,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("D2"), iol, id_TXDATA2);
replace_port(ci, ctx->id("D3"), iol, id_TXDATA3);
if (ci->type == ctx->id("ODDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("D4"), iol, id_TXDATA4);
@@ -2326,8 +2324,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("Q2"), iol, id_RXDATA2);
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
if (ci->type == ctx->id("IDDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
@@ -2579,7 +2576,7 @@ class Ecp5Packer
if (!user.cell->attrs.count(ctx->id("BEL")))
continue;
Loc user_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
continue;
@@ -2594,8 +2591,8 @@ class Ecp5Packer
CellInfo *drv = input->driver.cell;
if (!drv->attrs.count(ctx->id("BEL")))
continue;
- Loc drv_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string())));
+ Loc drv_loc =
+ ctx->getBelLocation(ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string()));
BelId closest;
int closest_x = -1; // aim for same side of chip
for (auto bel : ctx->getBels()) {
@@ -2639,7 +2636,7 @@ class Ecp5Packer
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
continue;
- BelId bel = ctx->getBelByName(ctx->id(str_or_default(ci->attrs, ctx->id("BEL"))));
+ BelId bel = ctx->getBelByNameStr(str_or_default(ci->attrs, ctx->id("BEL")));
NPNR_ASSERT(bel != BelId());
Loc pioLoc = ctx->getBelLocation(bel);
if (ci->type == id_DQSBUFM)
@@ -2683,8 +2680,7 @@ class Ecp5Packer
const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO);
if (eclki != nullptr && eclki->driver.cell != nullptr) {
if (eclki->driver.cell->type == id_ECLKBRIDGECS) {
- BelId bel =
- ctx->getBelByName(ctx->id(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string());
Loc loc = ctx->getBelLocation(bel);
ci->attrs[ctx->id("BEL")] =
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
@@ -2697,7 +2693,7 @@ class Ecp5Packer
for (auto user : eclko->users) {
if (user.cell->type == id_TRELLIS_ECLKBUF) {
Loc eckbuf_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKSYNCB)
continue;
@@ -2726,7 +2722,7 @@ class Ecp5Packer
const CellInfo *uc = usr.cell;
if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL")))
continue;
- BelId dqsb_bel = ctx->getBelByName(ctx->id(uc->attrs.at(ctx->id("BEL")).as_string()));
+ BelId dqsb_bel = ctx->getBelByNameStr(uc->attrs.at(ctx->id("BEL")).as_string());
Loc dqsb_loc = ctx->getBelLocation(dqsb_bel);
if (dqsb_loc.x > 15)
right_bank_users = true;
@@ -2809,7 +2805,7 @@ class Ecp5Packer
CellInfo *drv = clki->driver.cell;
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
continue;
- BelId bel = ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string());
// Find a CLKDIVF that is routeable from the ECLKSYNC
std::queue<WireId> visit;
visit.push(ctx->getBelPinWire(bel, id_ECLKO));