diff options
-rw-r--r-- | common/archcheck.cc | 4 | ||||
-rw-r--r-- | common/nextpnr.cc | 22 | ||||
-rw-r--r-- | common/nextpnr.h | 26 | ||||
-rw-r--r-- | common/place_common.cc | 7 | ||||
-rw-r--r-- | common/placer1.cc | 8 | ||||
-rw-r--r-- | common/placer_heap.cc | 4 | ||||
-rw-r--r-- | common/timing_opt.cc | 9 | ||||
-rw-r--r-- | ecp5/arch.cc | 15 | ||||
-rw-r--r-- | ecp5/arch.h | 13 | ||||
-rw-r--r-- | ecp5/arch_pybindings.h | 2 | ||||
-rw-r--r-- | ecp5/globals.cc | 6 | ||||
-rw-r--r-- | ecp5/pack.cc | 46 |
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)); |