From 90edf33c95de975b7f8204624a995c4826c52b84 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 11:01:36 +0000 Subject: common: Adding IdStringList type Using an optimised storage for <=4 objects to avoid excessive heap allocations. Signed-off-by: D. Shah --- common/nextpnr.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/common/nextpnr.h b/common/nextpnr.h index b4f68f93..68a341f3 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -145,6 +145,73 @@ template <> struct hash NEXTPNR_NAMESPACE_BEGIN +// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise +template class SSOArray +{ + union + { + T data_static[N]; + T *data_heap; + }; + size_t m_size; + + private: + inline bool is_heap() { return (m_size > N); } + void alloc() + { + if (is_heap()) { + data_heap = new T[m_size]; + } + } + + public: + T *data() { return is_heap() ? data_heap : &data_static; } + const T *data() const { return is_heap() ? data_heap : &data_static; } + size_t size() const { return m_size; } + + T *begin() { return data(); } + T *end() { return data() + m_size; } + const T *begin() const { return data(); } + const T *end() const { return data() + m_size; } + + SSOArray(size_t size, const T &init = T()) : m_size(size) + { + alloc(); + std::fill(begin(), end(), init); + } + + template SSOArray(const Tother &other) : m_size(other.size()) + { + alloc(); + std::copy(other.begin(), other.end(), begin()); + } + + ~SSOArray() + { + if (is_heap()) { + delete[] data_heap; + } + } + + bool operator==(const SSOArray &other) const + { + if (size() != other.size()) + return false; + return std::equal(begin(), end(), other.begin()); + } + bool operator!=(const SSOArray &other) const + { + if (size() != other.size()) + return true; + return !std::equal(begin(), end(), other.begin()); + } +}; + +struct IdStringList +{ + SSOArray ids; +}; + struct GraphicElement { enum type_t -- cgit v1.2.3 From ff92d19fed274c6469720cc726e80dc777fa767f Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 11:11:08 +0000 Subject: arch: Add getNameDelimiter API for string lists Signed-off-by: D. Shah --- common/arch_pybindings_shared.h | 3 +++ docs/archapi.md | 5 ++++- ecp5/arch.h | 1 + generic/arch.h | 1 + gowin/arch.h | 1 + ice40/arch.h | 1 + nexus/arch.h | 1 + 7 files changed, 12 insertions(+), 1 deletion(-) diff --git a/common/arch_pybindings_shared.h b/common/arch_pybindings_shared.h index 5295c6ab..1cd70c99 100644 --- a/common/arch_pybindings_shared.h +++ b/common/arch_pybindings_shared.h @@ -10,6 +10,9 @@ readonly_wrapper, conv_from_str>::def_wrap(ctx_cls, "top_module"); +fn_wrapper_0a>::def_wrap( + ctx_cls, "getNameDelimiter"); + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getNetByAlias"); fn_wrapper_2a_v, diff --git a/docs/archapi.md b/docs/archapi.md index 49183c63..6b9b0913 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -92,6 +92,10 @@ Get Z dimension for the specified tile for bels. All bels with at specified X an Get Z dimension for the specified tile for pips. All pips with at specified X and Y coordinates must have a Z coordinate in the range `0 .. getTileDimZ(X,Y)-1` (inclusive). +### char getNameDelimiter() const + +Returns a delimiter that can be used to build up bel, wire and pip names out of hierarchical components (such as tiles and sites) to avoid the high memory usage of storing full names for every object. + Cell Methods ----------- @@ -99,7 +103,6 @@ Cell Methods Get list of cell types that this architecture accepts. - Bel Methods ----------- diff --git a/ecp5/arch.h b/ecp5/arch.h index 18a70fe8..6b32f284 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -471,6 +471,7 @@ struct Arch : BaseCtx int getGridDimY() const { return chip_info->height; }; int getTileBelDimZ(int, int) const { return max_loc_bels; }; int getTilePipDimZ(int, int) const { return 1; }; + char getNameDelimiter() const { return '/'; } // ------------------------------------------------- diff --git a/generic/arch.h b/generic/arch.h index f3e26bb5..3ec9dc5d 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -187,6 +187,7 @@ struct Arch : BaseCtx int getGridDimY() const { return gridDimY; } int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } + char getNameDelimiter() const { return '/'; } BelId getBelByName(IdString name) const; IdString getBelName(BelId bel) const; diff --git a/gowin/arch.h b/gowin/arch.h index f12c604e..6337255a 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -323,6 +323,7 @@ struct Arch : BaseCtx int getGridDimY() const { return gridDimY; } int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } + char getNameDelimiter() const { return '/'; } BelId getBelByName(IdString name) const; IdString getBelName(BelId bel) const; diff --git a/ice40/arch.h b/ice40/arch.h index fd92d988..b9934dad 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -407,6 +407,7 @@ struct Arch : BaseCtx int getGridDimY() const { return chip_info->height; } int getTileBelDimZ(int, int) const { return 8; } int getTilePipDimZ(int, int) const { return 1; } + char getNameDelimiter() const { return '/'; } // ------------------------------------------------- diff --git a/nexus/arch.h b/nexus/arch.h index ee66599a..3063ce67 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -909,6 +909,7 @@ struct Arch : BaseCtx int getGridDimY() const { return chip_info->height; } int getTileBelDimZ(int, int) const { return 256; } int getTilePipDimZ(int, int) const { return 1; } + char getNameDelimiter() const { return '/'; } // ------------------------------------------------- -- cgit v1.2.3 From 0dbe7f96a39640c42dbb2ebb41324d0edf2a5f4b Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 11:29:32 +0000 Subject: common: First pass at IdStringList methods Signed-off-by: D. Shah --- common/nextpnr.cc | 35 +++++++++++++++++++++++++++++++++++ common/nextpnr.h | 32 +++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 9a856b99..57baedf9 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -69,6 +69,41 @@ void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx) ctx->idstring_idx_to_str->push_back(&insert_rc.first->first); } +IdStringList IdStringList::parse(Context *ctx, const std::string &str) +{ + char delim = ctx->getNameDelimiter(); + size_t id_count = std::count(str.begin(), str.end(), delim) + 1; + IdStringList list(id_count); + size_t start = 0; + for (size_t i = 0; i < id_count; i++) { + size_t end = str.find(delim, start); + NPNR_ASSERT((i == (id_count - 1)) || (end != std::string::npos)); + list.ids[i] = ctx->id(str.substr(start, end - start)); + start = end + 1; + } + return list; +} + +void IdStringList::build_str(const Context *ctx, std::string &str) const +{ + char delim = ctx->getNameDelimiter(); + bool first = true; + str.clear(); + for (auto entry : ids) { + if (!first) + str += delim; + str += entry.str(ctx); + first = false; + } +} + +std::string IdStringList::str(const Context *ctx) const +{ + std::string s; + build_str(ctx, s); + return s; +} + TimingConstrObjectId BaseCtx::timingWildcardObject() { TimingConstrObjectId id; diff --git a/common/nextpnr.h b/common/nextpnr.h index 68a341f3..66f31867 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -156,7 +156,7 @@ template class SSOArray size_t m_size; private: - inline bool is_heap() { return (m_size > N); } + inline bool is_heap() const { return (m_size > N); } void alloc() { if (is_heap()) { @@ -165,8 +165,8 @@ template class SSOArray } public: - T *data() { return is_heap() ? data_heap : &data_static; } - const T *data() const { return is_heap() ? data_heap : &data_static; } + T *data() { return is_heap() ? data_heap : data_static; } + const T *data() const { return is_heap() ? data_heap : data_static; } size_t size() const { return m_size; } T *begin() { return data(); } @@ -174,6 +174,8 @@ template class SSOArray const T *begin() const { return data(); } const T *end() const { return data() + m_size; } + SSOArray() : m_size(0){}; + SSOArray(size_t size, const T &init = T()) : m_size(size) { alloc(); @@ -205,11 +207,35 @@ template class SSOArray return true; return !std::equal(begin(), end(), other.begin()); } + T &operator[](size_t idx) + { + NPNR_ASSERT(idx < m_size); + return data()[idx]; + } + const T &operator[](size_t idx) const + { + NPNR_ASSERT(idx < m_size); + return data()[idx]; + } }; struct IdStringList { SSOArray ids; + + IdStringList(){}; + explicit IdStringList(size_t n) : ids(n, IdString()){}; + explicit IdStringList(IdString id) : ids(1, id){}; + template IdStringList(const Tlist &list) : ids(list){}; + + static IdStringList parse(Context *ctx, const std::string &str); + void build_str(const Context *ctx, std::string &str) const; + std::string str(const Context *ctx) const; + + size_t size() const { return ids.size(); } + const IdString *begin() const { return ids.begin(); } + const IdString *end() const { return ids.end(); } + const IdString &operator[](size_t idx) const { return ids[idx]; } }; struct GraphicElement -- cgit v1.2.3 From 6d23461bcd83d27c6b365948a5e85db80389832e Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 12:12:12 +0000 Subject: ecp5: Proof-of-concept using IdStringList for bel names This uses the new IdStringList API to store bel names for the ECP5. Note that other arches and the GUI do not yet build with this proof-of-concept patch. getBelByName still uses the old implementation and could be more efficiently implemented with further development. Signed-off-by: D. Shah --- common/archcheck.cc | 4 ++-- common/nextpnr.cc | 22 +++++++++++++++++++--- common/nextpnr.h | 26 ++++++++++++++++++++++---- common/place_common.cc | 7 +++---- common/placer1.cc | 8 ++++---- common/placer_heap.cc | 4 ++-- common/timing_opt.cc | 9 ++++----- ecp5/arch.cc | 15 ++++++++++++--- ecp5/arch.h | 13 ++++++++----- ecp5/arch_pybindings.h | 2 +- ecp5/globals.cc | 6 +++--- 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 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 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 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 buffer; + size_t index = 0; + + public: + std::string &next(); +}; + struct GraphicElement { enum type_t @@ -760,6 +772,9 @@ struct BaseCtx mutable std::unordered_map *idstring_str_to_idx; mutable std::vector *idstring_idx_to_str; + // Temporary string backing store for logging + mutable StrRingBuffer log_strs; + // Project settings and config switches std::unordered_map 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 pip_to_net; std::unordered_map wire_fanout; + // fast access to X and Y IdStrings for building object names + std::vector 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 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 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 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::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 visit; visit.push(ctx->getBelPinWire(bel, id_ECLKO)); -- cgit v1.2.3 From 9388df19d3ab3ca1b127defafe6fa3f71147f451 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 12:58:41 +0000 Subject: refactor: Replace getXName().c_str(ctx) with ctx->nameOfX This makes the ongoing migration to IdStringList easier. Signed-off-by: D. Shah --- common/archcheck.cc | 8 ++++---- common/placer1.cc | 6 +++--- common/timing.cc | 3 +-- ecp5/globals.cc | 13 ++++++------- ecp5/pack.cc | 2 +- gui/designwidget.cc | 22 ++++++++++------------ gui/fpgaviewwidget.cc | 8 ++++---- ice40/delay.cc | 2 +- ice40/pack.cc | 9 ++++----- 9 files changed, 34 insertions(+), 39 deletions(-) diff --git a/common/archcheck.cc b/common/archcheck.cc index 412feca9..6efa3a1e 100644 --- a/common/archcheck.cc +++ b/common/archcheck.cc @@ -48,7 +48,7 @@ void archcheck_names(const Context *ctx) IdString name = ctx->getWireName(wire); WireId wire2 = ctx->getWireByName(name); if (wire != wire2) { - log_error("wire != wire2, name = %s\n", name.c_str(ctx)); + log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire)); } } @@ -67,7 +67,7 @@ void archcheck_names(const Context *ctx) IdString name = ctx->getPipName(pip); PipId pip2 = ctx->getPipByName(name); if (pip != pip2) { - log_error("pip != pip2, name = %s\n", name.c_str(ctx)); + log_error("pip != pip2, name = %s\n", ctx->nameOfPip(pip)); } } #endif @@ -109,7 +109,7 @@ void archcheck_locs(const Context *ctx) if (bel == BelId()) continue; Loc loc = ctx->getBelLocation(bel); - dbg(" + %d %s\n", z, ctx->getBelName(bel).c_str(ctx)); + dbg(" + %d %s\n", z, ctx->nameOfBel(bel)); log_assert(x == loc.x); log_assert(y == loc.y); log_assert(z == loc.z); @@ -118,7 +118,7 @@ void archcheck_locs(const Context *ctx) for (BelId bel : ctx->getBelsByTile(x, y)) { Loc loc = ctx->getBelLocation(bel); - dbg(" - %d %s\n", loc.z, ctx->getBelName(bel).c_str(ctx)); + dbg(" - %d %s\n", loc.z, ctx->nameOfBel(bel)); log_assert(x == loc.x); log_assert(y == loc.y); log_assert(usedz.count(loc.z)); diff --git a/common/placer1.cc b/common/placer1.cc index c54c3cf2..280dd02e 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -563,9 +563,9 @@ class SAPlacer } commit_cost_changes(moveChange); #if 0 - log_info("swap %s -> %s\n", cell->name.c_str(ctx), ctx->getBelName(newBel).c_str(ctx)); + log_info("swap %s -> %s\n", cell->name.c_str(ctx), ctx->nameOfBel(newBel)); if (other_cell != nullptr) - log_info("swap %s -> %s\n", other_cell->name.c_str(ctx), ctx->getBelName(oldBel).c_str(ctx)); + log_info("swap %s -> %s\n", other_cell->name.c_str(ctx), ctx->nameOfBel(oldBel)); #endif return true; swap_fail: @@ -590,7 +590,7 @@ class SAPlacer { BelId oldBel = cell->bel; #if 0 - log_info("%s old: %s new: %s\n", cell->name.c_str(ctx), ctx->getBelName(cell->bel).c_str(ctx), ctx->getBelName(newBel).c_str(ctx)); + log_info("%s old: %s new: %s\n", cell->name.c_str(ctx), ctx->nameOfBel(cell->bel), ctx->nameOfBel(newBel)); #endif CellInfo *bound = ctx->getBoundBelCell(newBel); if (bound != nullptr) diff --git a/common/timing.cc b/common/timing.cc index d8445989..9fb14a33 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -885,8 +885,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p auto pip = it->second.pip; NPNR_ASSERT(pip != PipId()); delay = ctx->getPipDelay(pip).maxDelay(); - log_info(" %1.3f %s\n", ctx->getDelayNS(delay), - ctx->getPipName(pip).c_str(ctx)); + log_info(" %1.3f %s\n", ctx->getDelayNS(delay), ctx->nameOfPip(pip)); cursor = ctx->getPipSrcWire(pip); } } diff --git a/ecp5/globals.cc b/ecp5/globals.cc index ad99272e..478e5fac 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -238,8 +238,7 @@ class Ecp5GlobalRouter if (visit.empty() || visit.size() > 50000) { if (allow_fail) return false; - log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx), - ctx->getWireName(dst).c_str(ctx)); + log_error("cannot route global from %s to %s.\n", ctx->nameOfWire(src), ctx->nameOfWire(dst)); } cursor = visit.front(); visit.pop(); @@ -325,8 +324,8 @@ class Ecp5GlobalRouter } else { // Check for dedicated routing if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) { - // log_info("dedicated route %s -> %s\n", ctx->getWireName(ctx->getBelPinWire(drv_bel, - // drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx)); + // log_info("dedicated route %s -> %s\n", ctx->nameOfWire(ctx->getBelPinWire(drv_bel, + // drv.port)), ctx->nameOfWire(dcc->bel)); dedicated_routing = true; return 0; } @@ -347,8 +346,8 @@ class Ecp5GlobalRouter while (true) { if (visit.empty() || visit.size() > 10000) { - // log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx), - // ctx->getWireName(dst).c_str(ctx)); + // log_info ("dist %s -> %s = inf\n", ctx->nameOfWire(src), + // ctx->nameOfWire(dst)); return false; } cursor = visit.front(); @@ -372,7 +371,7 @@ class Ecp5GlobalRouter cursor = ctx->getPipSrcWire(fnd->second); length++; } - // log_info ("dist %s -> %s = %d\n", ctx->getWireName(src).c_str(ctx), ctx->getWireName(dst).c_str(ctx), + // log_info ("dist %s -> %s = %d\n", ctx->nameOfWire(src), ctx->nameOfWire(dst), // length); return length < thresh; } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 8d21c5b3..ed2dfc29 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -1853,7 +1853,7 @@ class Ecp5Packer next = upstream.front(); upstream.pop(); if (ctx->debug) - log_info(" visited %s\n", ctx->getWireName(next).c_str(ctx)); + log_info(" visited %s\n", ctx->nameOfWire(next)); IdString basename = ctx->getWireBasename(next); if (basename == bnke_name || basename == global_name) { break; diff --git a/gui/designwidget.cc b/gui/designwidget.cc index f856b5f6..ff79c3a1 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -631,7 +631,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt addProperty(portInfoItem, QVariant::String, "Name", item.c_str(ctx)); addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item))); WireId wire = ctx->getBelPinWire(bel, item); - addProperty(portInfoItem, QVariant::String, "Wire", ctx->getWireName(wire).c_str(ctx), ElementType::WIRE); + addProperty(portInfoItem, QVariant::String, "Wire", ctx->nameOfWire(wire), ElementType::WIRE); } } else if (type == ElementType::WIRE) { std::lock_guard lock_ui(ctx->ui_mutex); @@ -644,8 +644,8 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET); - addProperty(topItem, QVariant::String, "Conflicting Wire", - ctx->getWireName(ctx->getConflictingWireWire(wire)).c_str(ctx), ElementType::WIRE); + addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingWireWire(wire)), + ElementType::WIRE); addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)), ElementType::NET); @@ -666,7 +666,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt for (const auto &item : ctx->getWireBelPins(wire)) { QString belname = ""; if (item.bel != BelId()) - belname = ctx->getBelName(item.bel).c_str(ctx); + belname = ctx->nameOfBel(item.bel); QString pinname = item.pin.c_str(ctx); QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname); @@ -707,16 +707,15 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET); if (ctx->getConflictingPipWire(pip) != WireId()) { - addProperty(topItem, QVariant::String, "Conflicting Wire", - ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx), ElementType::WIRE); + addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingPipWire(pip)), + ElementType::WIRE); } else { addProperty(topItem, QVariant::String, "Conflicting Wire", "", ElementType::NONE); } addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)), ElementType::NET); - addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), - ElementType::WIRE); - addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx), + addProperty(topItem, QVariant::String, "Src Wire", ctx->nameOfWire(ctx->getPipSrcWire(pip)), ElementType::WIRE); + addProperty(topItem, QVariant::String, "Dest Wire", ctx->nameOfWire(ctx->getPipDstWire(pip)), ElementType::WIRE); QtProperty *attrsItem = addSubGroup(topItem, "Attributes"); @@ -769,14 +768,13 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt QtProperty *wiresItem = addSubGroup(topItem, "Wires"); for (auto &item : net->wires) { - auto name = ctx->getWireName(item.first).c_str(ctx); + auto name = ctx->nameOfWire(item.first); QtProperty *wireItem = addSubGroup(wiresItem, name); addProperty(wireItem, QVariant::String, "Wire", name, ElementType::WIRE); if (item.second.pip != PipId()) - addProperty(wireItem, QVariant::String, "Pip", ctx->getPipName(item.second.pip).c_str(ctx), - ElementType::PIP); + addProperty(wireItem, QVariant::String, "Pip", ctx->nameOfPip(item.second.pip), ElementType::PIP); else addProperty(wireItem, QVariant::String, "Pip", "", ElementType::PIP); diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 67ab80fd..9c90e2c5 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -779,22 +779,22 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event) rendererArgs_->x = event->x(); rendererArgs_->y = event->y(); if (closest.type == ElementType::BEL) { - rendererArgs_->hintText = std::string("BEL\n") + ctx_->getBelName(closest.bel).c_str(ctx_); + rendererArgs_->hintText = std::string("BEL\n") + ctx_->getBelName(closest.bel).str(ctx_); CellInfo *cell = ctx_->getBoundBelCell(closest.bel); if (cell != nullptr) rendererArgs_->hintText += std::string("\nCELL\n") + ctx_->nameOf(cell); } else if (closest.type == ElementType::WIRE) { - rendererArgs_->hintText = std::string("WIRE\n") + ctx_->getWireName(closest.wire).c_str(ctx_); + rendererArgs_->hintText = std::string("WIRE\n") + ctx_->getWireName(closest.wire).str(ctx_); NetInfo *net = ctx_->getBoundWireNet(closest.wire); if (net != nullptr) rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net); } else if (closest.type == ElementType::PIP) { - rendererArgs_->hintText = std::string("PIP\n") + ctx_->getPipName(closest.pip).c_str(ctx_); + rendererArgs_->hintText = std::string("PIP\n") + ctx_->getPipName(closest.pip).str(ctx_); NetInfo *net = ctx_->getBoundPipNet(closest.pip); if (net != nullptr) rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net); } else if (closest.type == ElementType::GROUP) { - rendererArgs_->hintText = std::string("GROUP\n") + ctx_->getGroupName(closest.group).c_str(ctx_); + rendererArgs_->hintText = std::string("GROUP\n") + ctx_->getGroupName(closest.group).str(ctx_); } else rendererArgs_->hintText = ""; diff --git a/ice40/delay.cc b/ice40/delay.cc index 40dcff16..a3469876 100644 --- a/ice40/delay.cc +++ b/ice40/delay.cc @@ -80,7 +80,7 @@ void ice40DelayFuzzerMain(Context *ctx) printf("%s %d %d %s %s %d %d\n", cursor == dst ? "dst" : "src", int(ctx->chip_info->wire_data[cursor.index].x), int(ctx->chip_info->wire_data[cursor.index].y), - ctx->getWireType(cursor).c_str(ctx), ctx->getWireName(cursor).c_str(ctx), int(delay), + ctx->getWireType(cursor).c_str(ctx), ctx->nameOfWire(cursor), int(delay), int(ctx->estimateDelay(cursor, dst))); if (cursor == src) diff --git a/ice40/pack.cc b/ice40/pack.cc index bac8e170..9add84cd 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -417,7 +417,7 @@ static BelId find_padin_gbuf(Context *ctx, BelId bel, IdString port_name) auto wire = ctx->getBelPinWire(bel, port_name); if (wire == WireId()) - log_error("BEL '%s' has no global buffer connection available\n", ctx->getBelName(bel).c_str(ctx)); + log_error("BEL '%s' has no global buffer connection available\n", ctx->nameOfBel(bel)); for (auto src_bel : ctx->getWireBelPins(wire)) { if (ctx->getBelType(src_bel.bel) == id_SB_GB && src_bel.pin == id_GLOBAL_BUFFER_OUTPUT) { @@ -839,7 +839,7 @@ static void place_plls(Context *ctx) if (conflict_cell == ci) continue; log_error("PLL '%s' PACKAGEPIN forces it to BEL %s but BEL is already assigned to PLL '%s'\n", - ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx), conflict_cell->name.c_str(ctx)); + ci->name.c_str(ctx), ctx->nameOfBel(found_bel), conflict_cell->name.c_str(ctx)); } // Is it user constrained ? @@ -849,8 +849,7 @@ static void place_plls(Context *ctx) if (bel_constrain != found_bel) log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN " "connection\n", - ci->name.c_str(ctx), ctx->getBelName(bel_constrain).c_str(ctx), - ctx->getBelName(found_bel).c_str(ctx)); + ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel)); } else { // No, we can constrain it ourselves ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx); @@ -999,7 +998,7 @@ static void place_plls(Context *ctx) log_error("PLL '%s' couldn't be placed anywhere, no suitable BEL found.%s\n", ci->name.c_str(ctx), could_be_pad ? " Did you mean to use a PAD PLL ?" : ""); - log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx)); + log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->nameOfBel(found_bel)); if (could_be_pad) log_info(" (given its connections, this PLL could have been a PAD PLL)\n"); -- cgit v1.2.3 From 9614d3722929f99520c6b83600641c14ef37188b Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 13:03:11 +0000 Subject: docs: Update archapi.md with IdStringList Signed-off-by: D. Shah --- docs/archapi.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/archapi.md b/docs/archapi.md index 6b9b0913..e3c06efd 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -106,11 +106,11 @@ Get list of cell types that this architecture accepts. Bel Methods ----------- -### BelId getBelByName(IdString name) const +### BelId getBelByName(IdStringList name) const -Lookup a bel by its name. +Lookup a bel by its name, which is a list of IdStrings joined by `getNameDelimiter()`. -### IdString getBelName(BelId bel) const +### IdStringList getBelName(BelId bel) const Get the name for a bel. (Bel names must be unique.) @@ -186,11 +186,11 @@ Return a list of all pins on that bel. Wire Methods ------------ -### WireId getWireByName(IdString name) const +### WireId getWireByName(IdStringList name) const -Lookup a wire by its name. +Lookup a wire by its name, which is a list of IdStrings joined by `getNameDelimiter()`. -### IdString getWireName(WireId wire) const +### IdStringList getWireName(WireId wire) const Get the name for a wire. (Wire names must be unique.) @@ -262,11 +262,11 @@ of the bounds is almost always better than an under-estimate. Pip Methods ----------- -### PipId getPipByName(IdString name) const +### PipId getPipByName(IdStringList name) const -Lookup a pip by its name. +Lookup a pip by its name, which is a list of IdStrings joined by `getNameDelimiter()`. -### IdString getPipName(PipId pip) const +### IdStringList getPipName(PipId pip) const Get the name for a pip. (Pip names must be unique.) @@ -353,11 +353,11 @@ Get all pips uphill of a wire, i.e. pips that use this wire as destination wire. Group Methods ------------- -### GroupId getGroupByName(IdString name) const +### GroupId getGroupByName(IdStringList name) const -Lookup a group by its name. +Lookup a group by its name, which is a list of IdStrings joined by `getNameDelimiter()`. -### IdString getGroupName(GroupId group) const +### IdStringList getGroupName(GroupId group) const Get the name for a group. (Group names must be unique.) -- cgit v1.2.3 From d792bce0fb03529ee57b6f6ed5b0c234f503e452 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Fri, 29 Jan 2021 13:30:56 +0000 Subject: ecp5: Implement IdStringList for all arch object names This is a complete implementation of IdStringList for ECP5; excluding the GUI (which you will have to disable for it to build). Signed-off-by: D. Shah --- common/archcheck.cc | 4 +- common/nextpnr.cc | 34 +++++++++++++--- common/nextpnr.h | 25 +++++++++++- ecp5/arch.cc | 104 ++++++++++++++++++++++--------------------------- ecp5/arch.h | 26 ++++++------- ecp5/arch_pybindings.h | 6 +-- ecp5/bitstream.cc | 15 +++---- 7 files changed, 121 insertions(+), 93 deletions(-) diff --git a/common/archcheck.cc b/common/archcheck.cc index 6efa3a1e..28b0c147 100644 --- a/common/archcheck.cc +++ b/common/archcheck.cc @@ -45,7 +45,7 @@ void archcheck_names(const Context *ctx) log_info("Checking wire names..\n"); for (WireId wire : ctx->getWires()) { - IdString name = ctx->getWireName(wire); + IdStringList name = ctx->getWireName(wire); WireId wire2 = ctx->getWireByName(name); if (wire != wire2) { log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire)); @@ -64,7 +64,7 @@ void archcheck_names(const Context *ctx) #ifndef ARCH_ECP5 log_info("Checking pip names..\n"); for (PipId pip : ctx->getPips()) { - IdString name = ctx->getPipName(pip); + IdStringList name = ctx->getPipName(pip); PipId pip2 = ctx->getPipByName(name); if (pip != pip2) { log_error("pip != pip2, name = %s\n", ctx->nameOfPip(pip)); diff --git a/common/nextpnr.cc b/common/nextpnr.cc index c9084a75..f7f368f1 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -299,19 +299,25 @@ const char *BaseCtx::nameOfBel(BelId bel) const const char *BaseCtx::nameOfWire(WireId wire) const { const Context *ctx = getCtx(); - return ctx->getWireName(wire).c_str(ctx); + std::string &s = ctx->log_strs.next(); + ctx->getWireName(wire).build_str(ctx, s); + return s.c_str(); } const char *BaseCtx::nameOfPip(PipId pip) const { const Context *ctx = getCtx(); - return ctx->getPipName(pip).c_str(ctx); + std::string &s = ctx->log_strs.next(); + ctx->getPipName(pip).build_str(ctx, s); + return s.c_str(); } const char *BaseCtx::nameOfGroup(GroupId group) const { const Context *ctx = getCtx(); - return ctx->getGroupName(group).c_str(ctx); + std::string &s = ctx->log_strs.next(); + ctx->getGroupName(group).build_str(ctx, s); + return s.c_str(); } BelId BaseCtx::getBelByNameStr(const std::string &str) @@ -320,6 +326,24 @@ BelId BaseCtx::getBelByNameStr(const std::string &str) return ctx->getBelByName(IdStringList::parse(ctx, str)); } +WireId BaseCtx::getWireByNameStr(const std::string &str) +{ + Context *ctx = getCtx(); + return ctx->getWireByName(IdStringList::parse(ctx, str)); +} + +PipId BaseCtx::getPipByNameStr(const std::string &str) +{ + Context *ctx = getCtx(); + return ctx->getPipByName(IdStringList::parse(ctx, str)); +} + +GroupId BaseCtx::getGroupByNameStr(const std::string &str) +{ + Context *ctx = getCtx(); + return ctx->getGroupByName(IdStringList::parse(ctx, str)); +} + WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const { if (net_info->driver.cell == nullptr) @@ -701,10 +725,10 @@ void BaseCtx::archInfoToAttributes() for (auto &item : ni->wires) { if (!first) routing += ";"; - routing += getCtx()->getWireName(item.first).c_str(this); + routing += getCtx()->getWireName(item.first).str(getCtx()); routing += ";"; if (item.second.pip != PipId()) - routing += getCtx()->getPipName(item.second.pip).c_str(this); + routing += getCtx()->getPipName(item.second.pip).str(getCtx()); routing += ";" + std::to_string(item.second.strength); first = false; } diff --git a/common/nextpnr.h b/common/nextpnr.h index 9523e418..19d919e1 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -235,8 +235,28 @@ struct IdStringList const IdString *begin() const { return ids.begin(); } const IdString *end() const { return ids.end(); } const IdString &operator[](size_t idx) const { return ids[idx]; } + bool operator==(const IdStringList &other) const { return ids == other.ids; } + bool operator!=(const IdStringList &other) const { return ids != other.ids; } }; +NEXTPNR_NAMESPACE_END + +namespace std { +template <> struct hash +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX IdStringList &obj) const noexcept + { + std::size_t seed = 0; + boost::hash_combine(seed, hash()(obj.size())); + for (auto &id : obj) + boost::hash_combine(seed, hash()(id)); + return seed; + } +}; +} // namespace std + +NEXTPNR_NAMESPACE_BEGIN + // 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 @@ -890,8 +910,11 @@ 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 + // Wrappers of arch functions that take a string and handle IdStringList parsing BelId getBelByNameStr(const std::string &str); + WireId getWireByNameStr(const std::string &str); + PipId getPipByNameStr(const std::string &str); + GroupId getGroupByNameStr(const std::string &str); // -------------------------------------------------------------- diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 928a9c5f..d86bad5d 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -37,17 +37,6 @@ NEXTPNR_NAMESPACE_BEGIN -static std::tuple split_identifier_name(const std::string &name) -{ - size_t first_slash = name.find('/'); - NPNR_ASSERT(first_slash != std::string::npos); - size_t second_slash = name.find('/', first_slash + 1); - NPNR_ASSERT(second_slash != std::string::npos); - return std::make_tuple(std::stoi(name.substr(1, first_slash)), - std::stoi(name.substr(first_slash + 2, second_slash - first_slash)), - name.substr(second_slash + 1)); -}; - // ----------------------------------------------------------------------- void IdString::initialize_arch(const BaseCtx *ctx) @@ -133,6 +122,17 @@ Arch::Arch(ArchArgs args) : args(args) 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))); + + for (int i = 0; i < chip_info->width; i++) { + IdString x_id = id(stringf("X%d", i)); + x_ids.push_back(x_id); + id_to_x[x_id] = i; + } + for (int i = 0; i < chip_info->height; i++) { + IdString y_id = id(stringf("Y%d", i)); + y_ids.push_back(y_id); + id_to_y[y_id] = i; + } } // ----------------------------------------------------------------------- @@ -215,29 +215,21 @@ IdString Arch::archArgsToId(ArchArgs args) const BelId Arch::getBelByName(IdStringList name) const { - // TODO: take advantage of IdStringList for fast parsing + if (name.size() != 3) + return BelId(); 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(getCtx())); + loc.x = id_to_x.at(name[0]); + loc.y = id_to_y.at(name[1]); ret.location = loc; const LocationTypePOD *loci = locInfo(ret); for (int i = 0; i < int(loci->bel_data.size()); i++) { - if (std::strcmp(loci->bel_data[i].name.get(), basename.c_str()) == 0) { + if (std::strcmp(loci->bel_data[i].name.get(), name[2].c_str(this)) == 0) { ret.index = i; - break; + return ret; } } -#if 0 - if (ret.index >= 0) - bel_by_name[name] = ret; -#endif - return ret; + return BelId(); } BelRange Arch::getBelsByTile(int x, int y) const @@ -286,36 +278,31 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const // ----------------------------------------------------------------------- -WireId Arch::getWireByName(IdString name) const +WireId Arch::getWireByName(IdStringList name) const { + if (name.size() != 3) + return WireId(); WireId ret; - auto it = wire_by_name.find(name); - if (it != wire_by_name.end()) - return it->second; - Location loc; - std::string basename; - std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); + loc.x = id_to_x.at(name[0]); + loc.y = id_to_y.at(name[1]); ret.location = loc; const LocationTypePOD *loci = locInfo(ret); for (int i = 0; i < int(loci->wire_data.size()); i++) { - if (std::strcmp(loci->wire_data[i].name.get(), basename.c_str()) == 0) { + if (std::strcmp(loci->wire_data[i].name.get(), name[2].c_str(this)) == 0) { ret.index = i; - ret.location = loc; - break; + return ret; } } - if (ret.index >= 0) - wire_by_name[name] = ret; - else - ret.location = Location(); - return ret; + return WireId(); } // ----------------------------------------------------------------------- -PipId Arch::getPipByName(IdString name) const +PipId Arch::getPipByName(IdStringList name) const { + if (name.size() != 3) + return PipId(); auto it = pip_by_name.find(name); if (it != pip_by_name.end()) return it->second; @@ -323,7 +310,8 @@ PipId Arch::getPipByName(IdString name) const PipId ret; Location loc; std::string basename; - std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); + loc.x = id_to_x.at(name[0]); + loc.y = id_to_y.at(name[1]); ret.location = loc; const LocationTypePOD *loci = locInfo(ret); for (int i = 0; i < int(loci->pip_data.size()); i++) { @@ -333,24 +321,23 @@ PipId Arch::getPipByName(IdString name) const pip_by_name[getPipName(curr)] = curr; } if (pip_by_name.find(name) == pip_by_name.end()) - NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this)); + NPNR_ASSERT_FALSE_STR("no pip named " + name.str(getCtx())); return pip_by_name[name]; } -IdString Arch::getPipName(PipId pip) const +IdStringList Arch::getPipName(PipId pip) const { NPNR_ASSERT(pip != PipId()); - int x = pip.location.x; - int y = pip.location.y; - - std::string src_name = getWireName(getPipSrcWire(pip)).str(this); - std::replace(src_name.begin(), src_name.end(), '/', '.'); - - std::string dst_name = getWireName(getPipDstWire(pip)).str(this); - std::replace(dst_name.begin(), dst_name.end(), '/', '.'); + // TODO: can we improve how pip names are stored/built? + auto &pip_data = locInfo(pip)->pip_data[pip.index]; + WireId src = getPipSrcWire(pip), dst = getPipDstWire(pip); + std::string pip_name = stringf("%d_%d_%s->%d_%d_%s", pip_data.rel_src_loc.x, pip_data.rel_src_loc.y, + getWireBasename(src).c_str(this), pip_data.rel_dst_loc.x, pip_data.rel_dst_loc.y, + getWireBasename(dst).c_str(this)); - return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name); + std::array ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)}; + return IdStringList(ids); } // ----------------------------------------------------------------------- @@ -1215,7 +1202,7 @@ const std::vector Arch::availableRouters = {"router1", "router2"}; // ----------------------------------------------------------------------- -GroupId Arch::getGroupByName(IdString name) const +GroupId Arch::getGroupByName(IdStringList name) const { for (auto g : getGroups()) if (getGroupName(g) == name) @@ -1223,7 +1210,7 @@ GroupId Arch::getGroupByName(IdString name) const return GroupId(); } -IdString Arch::getGroupName(GroupId group) const +IdStringList Arch::getGroupName(GroupId group) const { std::string suffix; @@ -1232,10 +1219,11 @@ IdString Arch::getGroupName(GroupId group) const suffix = "switchbox"; break; default: - return IdString(); + return IdStringList(); } - return id("X" + std::to_string(group.location.x) + "/Y" + std::to_string(group.location.y) + "/" + suffix); + std::array ids{x_ids.at(group.location.x), y_ids.at(group.location.y), id(suffix)}; + return IdStringList(ids); } std::vector Arch::getGroups() const diff --git a/ecp5/arch.h b/ecp5/arch.h index 303d9afe..9997cd5c 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -441,9 +441,7 @@ struct Arch : BaseCtx const PackageInfoPOD *package_info; const SpeedGradePOD *speed_grade; - mutable std::unordered_map bel_by_name; - mutable std::unordered_map wire_by_name; - mutable std::unordered_map pip_by_name; + mutable std::unordered_map pip_by_name; std::vector bel_to_cell; std::unordered_map wire_to_net; @@ -452,6 +450,8 @@ struct Arch : BaseCtx // fast access to X and Y IdStrings for building object names std::vector x_ids, y_ids; + // inverse of the above for name->object mapping + std::unordered_map id_to_x, id_to_y; ArchArgs args; Arch(ArchArgs args); @@ -598,16 +598,14 @@ struct Arch : BaseCtx // ------------------------------------------------- - WireId getWireByName(IdString name) const; + WireId getWireByName(IdStringList name) const; - IdString getWireName(WireId wire) const + IdStringList getWireName(WireId wire) const { NPNR_ASSERT(wire != WireId()); - - std::stringstream name; - name << "X" << wire.location.x << "/Y" << wire.location.y << "/" - << locInfo(wire)->wire_data[wire.index].name.get(); - return id(name.str()); + std::array ids{x_ids.at(wire.location.x), y_ids.at(wire.location.y), + id(locInfo(wire)->wire_data[wire.index].name.get())}; + return IdStringList(ids); } IdString getWireType(WireId wire) const @@ -716,8 +714,8 @@ struct Arch : BaseCtx // ------------------------------------------------- - PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const; + PipId getPipByName(IdStringList name) const; + IdStringList getPipName(PipId pip) const; IdString getPipType(PipId pip) const { return IdString(); } @@ -895,8 +893,8 @@ struct Arch : BaseCtx // ------------------------------------------------- - GroupId getGroupByName(IdString name) const; - IdString getGroupName(GroupId group) const; + GroupId getGroupByName(IdStringList name) const; + IdStringList getGroupName(GroupId group) const; std::vector getGroups() const; std::vector getGroupBels(GroupId group) const; std::vector getGroupWires(GroupId group) const; diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h index 90c7c757..4228f12b 100644 --- a/ecp5/arch_pybindings.h +++ b/ecp5/arch_pybindings.h @@ -42,7 +42,7 @@ template <> struct string_converter template <> struct string_converter { - WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); } + WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); } std::string to_str(Context *ctx, WireId id) { @@ -54,7 +54,7 @@ template <> struct string_converter template <> struct string_converter { - WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); } + WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); } std::string to_str(Context *ctx, WireId id) { @@ -66,7 +66,7 @@ template <> struct string_converter template <> struct string_converter { - PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); } + PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); } std::string to_str(Context *ctx, PipId id) { diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 0841fa32..4a43bfca 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -811,14 +811,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex NetInfo *lsrnet = nullptr; if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr) lsrnet = ci->ports.at(ctx->id("LSR")).net; - if (ctx->getBoundWireNet(ctx->getWireByName( - ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) { + if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR0")) == lsrnet) { cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR")); } - if (ctx->getBoundWireNet(ctx->getWireByName( - ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) { + if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR1")) == lsrnet) { cc.tiles[tname].add_enum("LSR1.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR")); @@ -827,12 +825,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex NetInfo *clknet = nullptr; if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr) clknet = ci->ports.at(ctx->id("CLK")).net; - if (ctx->getBoundWireNet(ctx->getWireByName( - ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK0")))) == clknet) { + if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK0")) == clknet) { cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK")); } - if (ctx->getBoundWireNet(ctx->getWireByName( - ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK1")))) == clknet) { + if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK1")) == clknet) { cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK")); } } @@ -907,8 +903,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex (ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() || ci->ports.at(ctx->id("IOLTO")).net == nullptr)) { // Tie tristate low if unconnected for outputs or bidir - std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back()); - WireId jpt_wire = ctx->getWireByName(ctx->id(jpt)); + WireId jpt_wire = ctx->getWireByLocAndBasename(bel.location, fmt_str("JPADDT" << pio.back())); PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin(); WireId cib_wire = ctx->getPipSrcWire(jpt_pip); std::string cib_tile = -- cgit v1.2.3 From 3ae96bff886911d5629bdee9d48478ee69518551 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Mon, 1 Feb 2021 10:49:59 +0000 Subject: Refactor GUI to use IdStringLists The GUI internally had an 'IdStringList' type that I hadn't spotted, to avoid a conflict this is renamed to IdList which also reflects its new purpose better. Signed-off-by: D. Shah --- gui/designwidget.cc | 42 ++++++++++++++++++++---------------------- gui/designwidget.h | 2 +- gui/treemodel.cc | 10 +++++----- gui/treemodel.h | 47 ++++++++++++++++++++++++----------------------- 4 files changed, 50 insertions(+), 51 deletions(-) diff --git a/gui/designwidget.cc b/gui/designwidget.cc index ff79c3a1..a5dc7e3e 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -340,11 +340,9 @@ void DesignWidget::newContext(Context *ctx) } getTreeByElementType(ElementType::CELL) - ->loadData(ctx, - std::unique_ptr(new TreeModel::IdStringList(ElementType::CELL))); + ->loadData(ctx, std::unique_ptr(new TreeModel::IdList(ElementType::CELL))); getTreeByElementType(ElementType::NET) - ->loadData(ctx, - std::unique_ptr(new TreeModel::IdStringList(ElementType::NET))); + ->loadData(ctx, std::unique_ptr(new TreeModel::IdList(ElementType::NET))); } updateTree(); } @@ -357,10 +355,10 @@ void DesignWidget::updateTree() while (i != highlightSelected.end()) { QMap::iterator prev = i; ++i; - if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()) == ctx->nets.end()) { + if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()[0]) == ctx->nets.end()) { highlightSelected.erase(prev); } - if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()) == ctx->cells.end()) { + if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()[0]) == ctx->cells.end()) { highlightSelected.erase(prev); } } @@ -369,13 +367,13 @@ void DesignWidget::updateTree() std::lock_guard lock_ui(ctx->ui_mutex); std::lock_guard lock(ctx->mutex); - std::vector cells; + std::vector cells; for (auto &pair : ctx->cells) { - cells.push_back(pair.first); + cells.push_back(IdStringList(pair.first)); } - std::vector nets; + std::vector nets; for (auto &pair : ctx->nets) { - nets.push_back(pair.first); + nets.push_back(IdStringList(pair.first)); } getTreeByElementType(ElementType::CELL)->updateElements(cells); @@ -603,7 +601,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt clearProperties(); - IdString c = clickItem->id(); + IdStringList c = clickItem->id(); Q_EMIT selected(getDecals(type, c), false); if (type == ElementType::BEL) { @@ -613,7 +611,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt BelId bel = ctx->getBelByName(c); QtProperty *topItem = addTopLevelProperty("Bel"); - addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); + addProperty(topItem, QVariant::String, "Name", ctx->nameOfBel(bel)); addProperty(topItem, QVariant::String, "Type", ctx->getBelType(bel).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL); @@ -640,7 +638,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt WireId wire = ctx->getWireByName(c); QtProperty *topItem = addTopLevelProperty("Wire"); - addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); + addProperty(topItem, QVariant::String, "Name", ctx->nameOfWire(wire)); addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET); @@ -677,7 +675,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt int counter = 0; QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill"); for (const auto &item : ctx->getPipsDownhill(wire)) { - addProperty(pipsDownItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP); + addProperty(pipsDownItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP); counter++; if (counter == 50) { addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); @@ -688,7 +686,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt counter = 0; QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill"); for (const auto &item : ctx->getPipsUphill(wire)) { - addProperty(pipsUpItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP); + addProperty(pipsUpItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP); counter++; if (counter == 50) { addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); @@ -702,7 +700,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt PipId pip = ctx->getPipByName(c); QtProperty *topItem = addTopLevelProperty("Pip"); - addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); + addProperty(topItem, QVariant::String, "Name", ctx->nameOfPip(pip)); addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET); @@ -734,7 +732,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt std::lock_guard lock_ui(ctx->ui_mutex); std::lock_guard lock(ctx->mutex); - NetInfo *net = ctx->nets.at(c).get(); + NetInfo *net = ctx->nets.at(c[0]).get(); QtProperty *topItem = addTopLevelProperty("Net"); @@ -785,14 +783,14 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt std::lock_guard lock_ui(ctx->ui_mutex); std::lock_guard lock(ctx->mutex); - CellInfo *cell = ctx->cells.at(c).get(); + CellInfo *cell = ctx->cells.at(c[0]).get(); QtProperty *topItem = addTopLevelProperty("Cell"); addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx)); if (cell->bel != BelId()) - addProperty(topItem, QVariant::String, "Bel", ctx->getBelName(cell->bel).c_str(ctx), ElementType::BEL); + addProperty(topItem, QVariant::String, "Bel", ctx->nameOfBel(cell->bel), ElementType::BEL); else addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL); addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength)); @@ -836,7 +834,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt } } -std::vector DesignWidget::getDecals(ElementType type, IdString value) +std::vector DesignWidget::getDecals(ElementType type, IdStringList value) { std::vector decals; switch (type) { @@ -859,7 +857,7 @@ std::vector DesignWidget::getDecals(ElementType type, IdString value) } } break; case ElementType::NET: { - NetInfo *net = ctx->nets.at(value).get(); + NetInfo *net = ctx->nets.at(value[0]).get(); for (auto &item : net->wires) { decals.push_back(ctx->getWireDecal(item.first)); if (item.second.pip != PipId()) { @@ -868,7 +866,7 @@ std::vector DesignWidget::getDecals(ElementType type, IdString value) } } break; case ElementType::CELL: { - CellInfo *cell = ctx->cells.at(value).get(); + CellInfo *cell = ctx->cells.at(value[0]).get(); if (cell->bel != BelId()) { decals.push_back(ctx->getBelDecal(cell->bel)); } diff --git a/gui/designwidget.h b/gui/designwidget.h index 89c6e702..cde69099 100644 --- a/gui/designwidget.h +++ b/gui/designwidget.h @@ -71,7 +71,7 @@ class DesignWidget : public QWidget int getElementIndex(ElementType type); void updateButtons(); void addToHistory(int tab, QModelIndex item); - std::vector getDecals(ElementType type, IdString value); + std::vector getDecals(ElementType type, IdStringList value); void updateHighlightGroup(QList item, int group); void clearAllSelectionModels(); Q_SIGNALS: diff --git a/gui/treemodel.cc b/gui/treemodel.cc index 448c9794..cc563202 100644 --- a/gui/treemodel.cc +++ b/gui/treemodel.cc @@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN namespace TreeModel { // converts 'aa123bb432' -> ['aa', '123', 'bb', '432'] -std::vector IdStringList::alphaNumSplit(const QString &str) +std::vector IdList::alphaNumSplit(const QString &str) { std::vector res; QString current_part; @@ -53,12 +53,12 @@ std::vector IdStringList::alphaNumSplit(const QString &str) return res; } -void IdStringList::updateElements(Context *ctx, std::vector elements) +void IdList::updateElements(Context *ctx, std::vector elements) { bool changed = false; // For any elements that are not yet in managed_, created them. - std::unordered_set element_set; + std::unordered_set element_set; for (auto elem : elements) { element_set.insert(elem); auto existing = managed_.find(elem); @@ -134,7 +134,7 @@ void IdStringList::updateElements(Context *ctx, std::vector elements) }); } -void IdStringList::search(QList &results, QString text, int limit) +void IdList::search(QList &results, QString text, int limit) { for (const auto &child : children_) { if (limit != -1 && results.size() > limit) @@ -157,7 +157,7 @@ void Model::loadData(Context *ctx, std::unique_ptr data) endResetModel(); } -void Model::updateElements(std::vector elements) +void Model::updateElements(std::vector elements) { if (!ctx_) return; diff --git a/gui/treemodel.h b/gui/treemodel.h index 49168a91..7b599e65 100644 --- a/gui/treemodel.h +++ b/gui/treemodel.h @@ -95,16 +95,16 @@ class Item int indexOf(Item *child) { return children_.indexOf(child, 0); } // Arch id and type that correspond to this element. - virtual IdString id() const { return IdString(); } + virtual IdStringList id() const { return IdStringList(); } virtual ElementType type() const { return ElementType::NONE; } // Lazy loading methods. virtual bool canFetchMore() const { return false; } virtual void fetchMore() {} - virtual boost::optional getById(IdString id) { return boost::none; } + virtual boost::optional getById(IdStringList id) { return boost::none; } virtual void search(QList &results, QString text, int limit) {} - virtual void updateElements(Context *ctx, std::vector elements) {} + virtual void updateElements(Context *ctx, std::vector elements) {} virtual ~Item() { @@ -118,46 +118,46 @@ class Item class IdStringItem : public Item { private: - IdString id_; + IdStringList id_; ElementType type_; public: - IdStringItem(Context *ctx, IdString str, Item *parent, ElementType type) - : Item(QString(str.c_str(ctx)), parent), id_(str), type_(type) + IdStringItem(Context *ctx, IdStringList str, Item *parent, ElementType type) + : Item(QString(str.str(ctx).c_str()), parent), id_(str), type_(type) { } - virtual IdString id() const override { return id_; } + virtual IdStringList id() const override { return id_; } virtual ElementType type() const override { return type_; } }; -// IdString list is a static list of IdStrings which can be set/updates from +// IdList is a static list of IdStringLists which can be set/updates from // a vector of IdStrings. It will render each IdStrings as a child, with the // list sorted in a smart way. -class IdStringList : public Item +class IdList : public Item { private: // Children that we manage the memory for, stored for quick lookup from // IdString to child. - std::unordered_map> managed_; + std::unordered_map> managed_; // Type of children that the list creates. ElementType child_type_; public: - // Create an IdStringList at given parent that will contain elements of + // Create an IdList at given parent that will contain elements of // the given type. - IdStringList(ElementType type) : Item("root", nullptr), child_type_(type) {} + IdList(ElementType type) : Item("root", nullptr), child_type_(type) {} // Split a name into alpha/non-alpha parts, which is then used for sorting // of children. static std::vector alphaNumSplit(const QString &str); // getById finds a child for the given IdString. - virtual boost::optional getById(IdString id) override { return managed_.at(id).get(); } + virtual boost::optional getById(IdStringList id) override { return managed_.at(id).get(); } // (Re-)create children from a list of IdStrings. - virtual void updateElements(Context *ctx, std::vector elements) override; + virtual void updateElements(Context *ctx, std::vector elements) override; // Find children that contain the given text. virtual void search(QList &results, QString text, int limit) override; @@ -173,7 +173,7 @@ template class ElementList : public Item // A map from tile (X,Y) to list of ElementTs in that tile. using ElementMap = std::map, std::vector>; // A method that converts an ElementT to an IdString. - using ElementGetter = std::function; + using ElementGetter = std::function; private: Context *ctx_; @@ -184,7 +184,7 @@ template class ElementList : public Item ElementGetter getter_; // Children that we manage the memory for, stored for quick lookup from // IdString to child. - std::unordered_map> managed_; + std::unordered_map> managed_; // Type of children that he list creates. ElementType child_type_; @@ -209,9 +209,10 @@ template class ElementList : public Item size_t end = std::min(start + count, elements()->size()); for (size_t i = start; i < end; i++) { auto idstring = getter_(ctx_, elements()->at(i)); - QString name(idstring.c_str(ctx_)); + std::string name_str = idstring.str(ctx_); + QString name(name_str.c_str()); - // Remove X.../Y.../ prefix + // Remove X.../Y.../ prefix - TODO: find a way to use IdStringList splitting here QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_); if (name.startsWith(prefix)) name.remove(0, prefix.size()); @@ -224,7 +225,7 @@ template class ElementList : public Item virtual void fetchMore() override { fetchMore(100); } // getById finds a child for the given IdString. - virtual boost::optional getById(IdString id) override + virtual boost::optional getById(IdStringList id) override { // Search requires us to load all our elements... while (canFetchMore()) @@ -267,7 +268,7 @@ template class ElementXYRoot : public Item // A map from tile (X,Y) to list of ElementTs in that tile. using ElementMap = std::map, std::vector>; // A method that converts an ElementT to an IdString. - using ElementGetter = std::function; + using ElementGetter = std::function; private: Context *ctx_; @@ -319,7 +320,7 @@ template class ElementXYRoot : public Item } // getById finds a child for the given IdString. - virtual boost::optional getById(IdString id) override + virtual boost::optional getById(IdStringList id) override { // For now, scan linearly all ElementLists. // TODO(q3k) fix this once we have tree API from arch @@ -353,7 +354,7 @@ class Model : public QAbstractItemModel ~Model(); void loadData(Context *ctx, std::unique_ptr data); - void updateElements(std::vector elements); + void updateElements(std::vector elements); Item *nodeFromIndex(const QModelIndex &idx) const; QModelIndex indexFromNode(Item *node) { @@ -366,7 +367,7 @@ class Model : public QAbstractItemModel QList search(QString text); - boost::optional nodeForId(IdString id) const { return root_->getById(id); } + boost::optional nodeForId(IdStringList id) const { return root_->getById(id); } // Override QAbstractItemModel methods int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; -- cgit v1.2.3 From b31b21fd5151ab783fbe665e23a0848b2c172339 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Mon, 1 Feb 2021 11:23:17 +0000 Subject: ice40: Implement IdStringList for all arch object names Signed-off-by: D. Shah --- ice40/arch.cc | 55 ++++++++++++++++++++++++++++++++++------------------- ice40/arch.h | 39 +++++++++++++++++++++++-------------- ice40/arch_place.cc | 2 +- ice40/chipdb.py | 21 ++++++++++++-------- ice40/pack.cc | 28 +++++++++++++-------------- 5 files changed, 88 insertions(+), 57 deletions(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index 6fe77e4b..43308a52 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -110,6 +110,17 @@ Arch::Arch(ArchArgs args) : args(args) if (package_info == nullptr) log_error("Unsupported package '%s'.\n", args.package.c_str()); + for (int i = 0; i < chip_info->width; i++) { + IdString x_id = id(stringf("X%d", i)); + x_ids.push_back(x_id); + id_to_x[x_id] = i; + } + for (int i = 0; i < chip_info->height; i++) { + IdString y_id = id(stringf("Y%d", i)); + y_ids.push_back(y_id); + id_to_y[y_id] = i; + } + bel_carry.resize(chip_info->bel_data.size()); bel_to_cell.resize(chip_info->bel_data.size()); wire_to_net.resize(chip_info->wire_data.size()); @@ -196,13 +207,16 @@ IdString Arch::archArgsToId(ArchArgs args) const // ----------------------------------------------------------------------- -BelId Arch::getBelByName(IdString name) const +BelId Arch::getBelByName(IdStringList name) const { BelId ret; if (bel_by_name.empty()) { - for (size_t i = 0; i < chip_info->bel_data.size(); i++) - bel_by_name[id(chip_info->bel_data[i].name.get())] = i; + for (size_t i = 0; i < chip_info->bel_data.size(); i++) { + BelId b; + b.index = i; + bel_by_name[getBelName(b)] = i; + } } auto it = bel_by_name.find(name); @@ -357,13 +371,16 @@ bool Arch::isBelLocked(BelId bel) const // ----------------------------------------------------------------------- -WireId Arch::getWireByName(IdString name) const +WireId Arch::getWireByName(IdStringList name) const { WireId ret; if (wire_by_name.empty()) { - for (int i = 0; i < int(chip_info->wire_data.size()); i++) - wire_by_name[id(chip_info->wire_data[i].name.get())] = i; + for (int i = 0; i < int(chip_info->wire_data.size()); i++) { + WireId w; + w.index = i; + wire_by_name[getWireName(w)] = i; + } } auto it = wire_by_name.find(name); @@ -427,7 +444,7 @@ std::vector> Arch::getWireAttrs(WireId wire) co // ----------------------------------------------------------------------- -PipId Arch::getPipByName(IdString name) const +PipId Arch::getPipByName(IdStringList name) const { PipId ret; @@ -446,24 +463,21 @@ PipId Arch::getPipByName(IdString name) const return ret; } -IdString Arch::getPipName(PipId pip) const +IdStringList Arch::getPipName(PipId pip) const { NPNR_ASSERT(pip != PipId()); -#if 1 int x = chip_info->pip_data[pip.index].x; int y = chip_info->pip_data[pip.index].y; - std::string src_name = chip_info->wire_data[chip_info->pip_data[pip.index].src].name.get(); - std::replace(src_name.begin(), src_name.end(), '/', '.'); + auto &src_wire = chip_info->wire_data[chip_info->pip_data[pip.index].src]; + auto &dst_wire = chip_info->wire_data[chip_info->pip_data[pip.index].dst]; - std::string dst_name = chip_info->wire_data[chip_info->pip_data[pip.index].dst].name.get(); - std::replace(dst_name.begin(), dst_name.end(), '/', '.'); + std::string src_name = stringf("%d.%d.%s", int(src_wire.name_x), int(src_wire.name_y), src_wire.name.get()); + std::string dst_name = stringf("%d.%d.%s", int(dst_wire.name_x), int(dst_wire.name_y), dst_wire.name.get()); - return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name); -#else - return id(chip_info->pip_data[pip.index].name.get()); -#endif + std::array ids{x_ids.at(x), y_ids.at(y), id(src_name + ".->." + dst_name)}; + return IdStringList(ids); } IdString Arch::getPipType(PipId pip) const { return IdString(); } @@ -503,7 +517,7 @@ std::string Arch::getBelPackagePin(BelId bel) const // ----------------------------------------------------------------------- -GroupId Arch::getGroupByName(IdString name) const +GroupId Arch::getGroupByName(IdStringList name) const { for (auto g : getGroups()) if (getGroupName(g) == name) @@ -511,7 +525,7 @@ GroupId Arch::getGroupByName(IdString name) const return GroupId(); } -IdString Arch::getGroupName(GroupId group) const +IdStringList Arch::getGroupName(GroupId group) const { std::string suffix; @@ -553,7 +567,8 @@ IdString Arch::getGroupName(GroupId group) const return IdString(); } - return id("X" + std::to_string(group.x) + "/Y" + std::to_string(group.y) + "/" + suffix); + std::array ids{x_ids.at(group.x), y_ids.at(group.y), id(suffix)}; + return IdStringList(ids); } std::vector Arch::getGroups() const diff --git a/ice40/arch.h b/ice40/arch.h index b9934dad..1987f17a 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -91,6 +91,8 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD { }; RelPtr name; + int8_t name_x, name_y; + int16_t padding; RelSlice pips_uphill, pips_downhill; RelSlice bel_pins; @@ -378,9 +380,9 @@ struct Arch : BaseCtx const ChipInfoPOD *chip_info; const PackageInfoPOD *package_info; - mutable std::unordered_map bel_by_name; - mutable std::unordered_map wire_by_name; - mutable std::unordered_map pip_by_name; + mutable std::unordered_map bel_by_name; + mutable std::unordered_map wire_by_name; + mutable std::unordered_map pip_by_name; mutable std::unordered_map bel_by_loc; std::vector bel_carry; @@ -389,6 +391,11 @@ struct Arch : BaseCtx std::vector pip_to_net; std::vector switches_locked; + // fast access to X and Y IdStrings for building object names + std::vector x_ids, y_ids; + // inverse of the above for name->object mapping + std::unordered_map id_to_x, id_to_y; + ArchArgs args; Arch(ArchArgs args); @@ -411,12 +418,14 @@ struct Arch : BaseCtx // ------------------------------------------------- - BelId getBelByName(IdString name) const; + BelId getBelByName(IdStringList name) const; - IdString getBelName(BelId bel) const + IdStringList getBelName(BelId bel) const { NPNR_ASSERT(bel != BelId()); - return id(chip_info->bel_data[bel.index].name.get()); + auto &data = chip_info->bel_data[bel.index]; + std::array ids{x_ids.at(data.x), y_ids.at(data.y), id(data.name.get())}; + return IdStringList(ids); } uint32_t getBelChecksum(BelId bel) const { return bel.index; } @@ -501,12 +510,14 @@ struct Arch : BaseCtx // ------------------------------------------------- - WireId getWireByName(IdString name) const; + WireId getWireByName(IdStringList name) const; - IdString getWireName(WireId wire) const + IdStringList getWireName(WireId wire) const { NPNR_ASSERT(wire != WireId()); - return id(chip_info->wire_data[wire.index].name.get()); + auto &data = chip_info->wire_data[wire.index]; + std::array ids{x_ids.at(data.name_x), y_ids.at(data.name_y), id(data.name.get())}; + return IdStringList(ids); } IdString getWireType(WireId wire) const; @@ -594,7 +605,7 @@ struct Arch : BaseCtx // ------------------------------------------------- - PipId getPipByName(IdString name) const; + PipId getPipByName(IdStringList name) const; void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { @@ -704,7 +715,7 @@ struct Arch : BaseCtx return loc; } - IdString getPipName(PipId pip) const; + IdStringList getPipName(PipId pip) const; IdString getPipType(PipId pip) const; std::vector> getPipAttrs(PipId pip) const; @@ -761,8 +772,8 @@ struct Arch : BaseCtx // ------------------------------------------------- - GroupId getGroupByName(IdString name) const; - IdString getGroupName(GroupId group) const; + GroupId getGroupByName(IdStringList name) const; + IdStringList getGroupName(GroupId group) const; std::vector getGroups() const; std::vector getGroupBels(GroupId group) const; std::vector getGroupWires(GroupId group) const; @@ -896,7 +907,7 @@ struct Arch : BaseCtx int getDrivenGlobalNetwork(BelId bel) const { NPNR_ASSERT(getBelType(bel) == id_SB_GB); - IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT)); + IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT))[2]; return std::stoi(std::string("") + glb_net.str(this).back()); } diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index ede8d47f..e4f302fd 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -142,7 +142,7 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const break; // Are we perhaps a PAD INPUT Bel that can be placed here? - if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) + if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(getCtx())) return true; // Conflict diff --git a/ice40/chipdb.py b/ice40/chipdb.py index b7c28ae3..cc3397eb 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -778,7 +778,7 @@ def add_bel_output(bel, wire, port): def add_bel_lc(x, y, z): bel = len(bel_name) - bel_name.append("X%d/Y%d/lc%d" % (x, y, z)) + bel_name.append((x, y, "lc%d" % z)) bel_type.append("ICESTORM_LC") bel_pos.append((x, y, z)) bel_wires.append(list()) @@ -837,7 +837,7 @@ def add_bel_lc(x, y, z): def add_bel_io(x, y, z): bel = len(bel_name) - bel_name.append("X%d/Y%d/io%d" % (x, y, z)) + bel_name.append((x, y, "io%d" % z)) bel_type.append("SB_IO") bel_pos.append((x, y, z)) bel_wires.append(list()) @@ -871,7 +871,7 @@ def add_bel_io(x, y, z): def add_bel_ram(x, y): bel = len(bel_name) - bel_name.append("X%d/Y%d/ram" % (x, y)) + bel_name.append((x, y, "ram")) bel_type.append("ICESTORM_RAM") bel_pos.append((x, y, 0)) bel_wires.append(list()) @@ -905,7 +905,7 @@ def add_bel_gb(xy, x, y, g): return bel = len(bel_name) - bel_name.append("X%d/Y%d/gb" % (x, y)) + bel_name.append((x, y, "gb")) bel_type.append("SB_GB") bel_pos.append((x, y, 2)) bel_wires.append(list()) @@ -942,7 +942,7 @@ def add_bel_ec(ec): ectype, x, y, z = ec bel = len(bel_name) extra_cell_config[bel] = [] - bel_name.append("X%d/Y%d/%s_%d" % (x, y, ectype.lower(), z)) + bel_name.append((x, y, "%s_%d" % (ectype.lower(), z))) bel_type.append(ectype) bel_pos.append((x, y, z)) bel_wires.append(list()) @@ -1140,7 +1140,7 @@ for bel in range(len(bel_name)): bba.l("bel_data_%s" % dev_name, "BelInfoPOD") for bel in range(len(bel_name)): - bba.s(bel_name[bel], "name") + bba.s(bel_name[bel][-1], "name") bba.u32(constids[bel_type[bel]], "type") bba.r_slice("bel_wires_%d" % bel, len(bel_wires[bel]), "bel_wires") bba.u8(bel_pos[bel][0], "x") @@ -1215,7 +1215,9 @@ for wire in range(num_wires): num_bel_pins = 0 info = dict() - info["name"] = "X%d/Y%d/%s" % wire_names_r[wire] + info["name"] = wire_names_r[wire][2] + info["name_x"] = wire_names_r[wire][0] + info["name_y"] = wire_names_r[wire][1] info["num_uphill"] = num_uphill info["list_uphill"] = list_uphill @@ -1263,7 +1265,7 @@ for package in packages: pins_info = [] for pin in pins: pinname, x, y, z = pin - pin_bel = "X%d/Y%d/io%d" % (x, y, z) + pin_bel = (x, y, "io%d" % z) bel_idx = bel_name.index(pin_bel) pins_info.append((pinname, bel_idx)) bba.l("package_%s_pins" % safename, "PackagePinPOD") @@ -1311,6 +1313,9 @@ for t in range(num_tile_types): bba.l("wire_data_%s" % dev_name, "WireInfoPOD") for wire, info in enumerate(wireinfo): bba.s(info["name"], "name") + bba.u8(info["name_x"], "name_x") + bba.u8(info["name_y"], "name_y") + bba.u16(0, "padding") bba.r_slice(info["list_uphill"], info["num_uphill"], "pips_uphill") bba.r_slice(info["list_downhill"], info["num_downhill"], "pips_downhill") bba.r_slice(info["list_bel_pins"], info["num_bel_pins"], "bel_pins") diff --git a/ice40/pack.cc b/ice40/pack.cc index 9add84cd..a909b08b 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -435,7 +435,7 @@ static std::unique_ptr create_padin_gbuf(Context *ctx, CellInfo *cell, // Find the matching SB_GB BEL connected to the same global network if (!cell->attrs.count(ctx->id("BEL"))) log_error("Unconstrained SB_GB_IO %s is not supported.\n", ctx->nameOf(cell)); - BelId bel = ctx->getBelByName(ctx->id(cell->attrs[ctx->id("BEL")].as_string())); + BelId bel = ctx->getBelByNameStr(cell->attrs[ctx->id("BEL")].as_string()); BelId gb_bel = find_padin_gbuf(ctx, bel, port_name); NPNR_ASSERT(gb_bel != BelId()); @@ -666,7 +666,7 @@ static void promote_globals(Context *ctx) /* And possibly limits what we can promote */ if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) { /* If the SB_GB is locked, doesn't matter what it drives */ - BelId bel = ctx->getBelByName(ctx->id(cell.second->attrs[ctx->id("BEL")].as_string())); + BelId bel = ctx->getBelByNameStr(cell.second->attrs[ctx->id("BEL")].as_string()); int glb_id = ctx->getDrivenGlobalNetwork(bel); if ((glb_id % 2) == 0) resets_available--; @@ -785,7 +785,7 @@ static void place_plls(Context *ctx) // If it's constrained already, add to already used list if (ci->attrs.count(ctx->id("BEL"))) { - BelId bel_constrain = ctx->getBelByName(ctx->id(ci->attrs[ctx->id("BEL")].as_string())); + BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string()); if (pll_all_bels.count(bel_constrain) == 0) log_error("PLL '%s' is constrained to invalid BEL '%s'\n", ci->name.c_str(ctx), ci->attrs[ctx->id("BEL")].as_string().c_str()); @@ -820,7 +820,7 @@ static void place_plls(Context *ctx) log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx), io_cell->name.c_str(ctx)); - BelId io_bel = ctx->getBelByName(ctx->id(io_cell->attrs.at(ctx->id("BEL")).as_string())); + BelId io_bel = ctx->getBelByNameStr(io_cell->attrs.at(ctx->id("BEL")).as_string()); BelId found_bel; // Find the PLL BEL that would suit that connection @@ -845,7 +845,7 @@ static void place_plls(Context *ctx) // Is it user constrained ? if (ci->attrs.count(ctx->id("BEL"))) { // Yes. Check it actually matches ! - BelId bel_constrain = ctx->getBelByName(ctx->id(ci->attrs[ctx->id("BEL")].as_string())); + BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string()); if (bel_constrain != found_bel) log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN " "connection\n", @@ -857,7 +857,7 @@ static void place_plls(Context *ctx) } // Inform user - log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx)); + log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->nameOfBel(found_bel)); } // Scan all SB_IOs to check for conflict with PLL BELs @@ -875,7 +875,7 @@ static void place_plls(Context *ctx) continue; // Check all placed PLL (either forced by user, or forced by PACKAGEPIN) - BelId io_bel = ctx->getBelByName(ctx->id(io_ci->attrs[ctx->id("BEL")].as_string())); + BelId io_bel = ctx->getBelByNameStr(io_ci->attrs[ctx->id("BEL")].as_string()); for (auto placed_pll : pll_used_bels) { BelPin pll_io_a, pll_io_b; @@ -909,7 +909,7 @@ static void place_plls(Context *ctx) continue; // Check all placed PLL (either forced by user, or forced by PACKAGEPIN) - BelId gb_bel = ctx->getBelByName(ctx->id(gb_ci->attrs[ctx->id("BEL")].as_string())); + BelId gb_bel = ctx->getBelByNameStr(gb_ci->attrs[ctx->id("BEL")].as_string()); for (auto placed_pll : pll_used_bels) { CellInfo *ci = placed_pll.second; @@ -968,7 +968,7 @@ static void place_plls(Context *ctx) bool could_be_pad = false; BelId pad_bel; if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(ctx->id("BEL"))) - pad_bel = ctx->getBelByName(ctx->id(ni->driver.cell->attrs[ctx->id("BEL")].as_string())); + pad_bel = ctx->getBelByNameStr(ni->driver.cell->attrs[ctx->id("BEL")].as_string()); // Find a BEL for it BelId found_bel; @@ -1066,9 +1066,9 @@ static BelId cell_place_unique(Context *ctx, CellInfo *ci) continue; if (ctx->isBelLocked(bel)) continue; - IdString bel_name = ctx->getBelName(bel); + IdStringList bel_name = ctx->getBelName(bel); ci->attrs[ctx->id("BEL")] = bel_name.str(ctx); - log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), bel_name.c_str(ctx)); + log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel)); return bel; } log_error("Unable to place cell '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); @@ -1278,9 +1278,9 @@ static void pack_special(Context *ctx) if (bel == BelId() || ctx->getBelType(bel) != ci->type) log_error("Unable to find placement for cell '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); - IdString bel_name = ctx->getBelName(bel); + IdStringList bel_name = ctx->getBelName(bel); ci->attrs[ctx->id("BEL")] = bel_name.str(ctx); - log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), bel_name.c_str(ctx)); + log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel)); } } @@ -1497,7 +1497,7 @@ void pack_plls(Context *ctx) } constr_fail: // PLL must have been placed already in place_plls() - BelId pll_bel = ctx->getBelByName(ctx->id(packed->attrs[ctx->id("BEL")].as_string())); + BelId pll_bel = ctx->getBelByNameStr(packed->attrs[ctx->id("BEL")].as_string()); NPNR_ASSERT(pll_bel != BelId()); // Deal with PAD PLL peculiarities -- cgit v1.2.3 From 6566a011b43289b9b550f3b7f8801156275cb321 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Mon, 1 Feb 2021 11:46:10 +0000 Subject: nexus: Implement IdStringList for all arch object names Signed-off-by: D. Shah --- common/nextpnr.h | 6 +++++ nexus/arch.cc | 70 +++++++++++++++++++++++++++----------------------------- nexus/arch.h | 43 +++++++++++++++++----------------- nexus/pack.cc | 2 +- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 19d919e1..d4db9e9e 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -181,6 +181,12 @@ template class SSOArray std::fill(begin(), end(), init); } + SSOArray(const SSOArray &other) : m_size(other.size()) + { + alloc(); + std::copy(other.begin(), other.end(), begin()); + } + template SSOArray(const Tother &other) : m_size(other.size()) { alloc(); diff --git a/nexus/arch.cc b/nexus/arch.cc index 95b409bf..267795dd 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -32,20 +32,6 @@ NEXTPNR_NAMESPACE_BEGIN -namespace { -static std::tuple split_identifier_name(const std::string &name) -{ - size_t first_slash = name.find('/'); - NPNR_ASSERT(first_slash != std::string::npos); - size_t second_slash = name.find('/', first_slash + 1); - NPNR_ASSERT(second_slash != std::string::npos); - return std::make_tuple(std::stoi(name.substr(1, first_slash)), - std::stoi(name.substr(first_slash + 2, second_slash - first_slash)), - name.substr(second_slash + 1)); -}; - -} // namespace - // ----------------------------------------------------------------------- void IdString::initialize_arch(const BaseCtx *ctx) @@ -134,6 +120,17 @@ Arch::Arch(ArchArgs args) : args(args) ts.bels_by_z[bel.z].index = j; } } + + for (int i = 0; i < chip_info->width; i++) { + IdString x_id = id(stringf("X%d", i)); + x_ids.push_back(x_id); + id_to_x[x_id] = i; + } + for (int i = 0; i < chip_info->height; i++) { + IdString y_id = id(stringf("Y%d", i)); + y_ids.push_back(y_id); + id_to_y[y_id] = i; + } init_cell_pin_data(); // Validate and set up package package_idx = -1; @@ -193,17 +190,17 @@ IdString Arch::archArgsToId(ArchArgs args) const { return id(args.device); } // ----------------------------------------------------------------------- -BelId Arch::getBelByName(IdString name) const +BelId Arch::getBelByName(IdStringList name) const { - int x, y; - std::string belname; - std::tie(x, y, belname) = split_identifier_name(name.str(this)); + if (name.size() != 3) + return BelId(); + int x = id_to_x.at(name[0]); + int y = id_to_y.at(name[1]); NPNR_ASSERT(x >= 0 && x < chip_info->width); NPNR_ASSERT(y >= 0 && y < chip_info->height); auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; - IdString bn = id(belname); for (size_t i = 0; i < tile.bels.size(); i++) { - if (tile.bels[i].name == bn.index) { + if (tile.bels[i].name == name[2].index) { BelId ret; ret.tile = y * chip_info->width + x; ret.index = i; @@ -305,17 +302,17 @@ std::vector> Arch::getBelAttrs(BelId bel) const // ----------------------------------------------------------------------- -WireId Arch::getWireByName(IdString name) const +WireId Arch::getWireByName(IdStringList name) const { - int x, y; - std::string wirename; - std::tie(x, y, wirename) = split_identifier_name(name.str(this)); + if (name.size() != 3) + return WireId(); + int x = id_to_x.at(name[0]); + int y = id_to_y.at(name[1]); NPNR_ASSERT(x >= 0 && x < chip_info->width); NPNR_ASSERT(y >= 0 && y < chip_info->height); auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; - IdString wn = id(wirename); for (size_t i = 0; i < tile.wires.size(); i++) { - if (tile.wires[i].name == wn.index) { + if (tile.wires[i].name == name[2].index) { WireId ret; ret.tile = y * chip_info->width + x; ret.index = i; @@ -342,26 +339,27 @@ std::vector> Arch::getWireAttrs(WireId wire) co // ----------------------------------------------------------------------- -PipId Arch::getPipByName(IdString name) const +PipId Arch::getPipByName(IdStringList name) const { - int x, y; - std::string pipname; - std::tie(x, y, pipname) = split_identifier_name(name.str(this)); + if (name.size() != 5) + return PipId(); + int x = id_to_x.at(name[0]); + int y = id_to_y.at(name[1]); NPNR_ASSERT(x >= 0 && x < chip_info->width); NPNR_ASSERT(y >= 0 && y < chip_info->height); PipId ret; ret.tile = y * chip_info->width + x; - auto sep_pos = pipname.find(':'); - ret.index = std::stoi(pipname.substr(0, sep_pos)); + ret.index = std::stoi(name[2].str(this)); return ret; } -IdString Arch::getPipName(PipId pip) const +IdStringList Arch::getPipName(PipId pip) const { NPNR_ASSERT(pip != PipId()); - return id(stringf("X%d/Y%d/%d:%s->%s", pip.tile % chip_info->width, pip.tile / chip_info->width, pip.index, - nameOf(loc_data(pip).wires[pip_data(pip).from_wire].name), - nameOf(loc_data(pip).wires[pip_data(pip).to_wire].name))); + std::array ids{x_ids.at(pip.tile % chip_info->width), y_ids.at(pip.tile / chip_info->width), + id(stringf("%d", pip.index)), IdString(loc_data(pip).wires[pip_data(pip).to_wire].name), + IdString(loc_data(pip).wires[pip_data(pip).from_wire].name)}; + return IdStringList(ids); } IdString Arch::getPipType(PipId pip) const { return IdString(); } diff --git a/nexus/arch.h b/nexus/arch.h index 3063ce67..d37c5026 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -897,6 +897,11 @@ struct Arch : BaseCtx std::unordered_map wire_to_net; std::unordered_map pip_to_net; + // fast access to X and Y IdStrings for building object names + std::vector x_ids, y_ids; + // inverse of the above for name->object mapping + std::unordered_map id_to_x, id_to_y; + // ------------------------------------------------- std::string getChipName() const; @@ -913,17 +918,14 @@ struct Arch : BaseCtx // ------------------------------------------------- - BelId getBelByName(IdString name) const; + BelId getBelByName(IdStringList name) const; - IdString getBelName(BelId bel) const + IdStringList getBelName(BelId bel) const { - std::string name = "X"; - name += std::to_string(bel.tile % chip_info->width); - name += "/Y"; - name += std::to_string(bel.tile / chip_info->width); - name += "/"; - name += nameOf(IdString(bel_data(bel).name)); - return id(name); + NPNR_ASSERT(bel != BelId()); + std::array ids{x_ids.at(bel.tile % chip_info->width), y_ids.at(bel.tile / chip_info->width), + IdString(bel_data(bel).name)}; + return IdStringList(ids); } uint32_t getBelChecksum(BelId bel) const { return (bel.tile << 16) ^ bel.index; } @@ -1024,16 +1026,13 @@ struct Arch : BaseCtx // ------------------------------------------------- - WireId getWireByName(IdString name) const; - IdString getWireName(WireId wire) const + WireId getWireByName(IdStringList name) const; + IdStringList getWireName(WireId wire) const { - std::string name = "X"; - name += std::to_string(wire.tile % chip_info->width); - name += "/Y"; - name += std::to_string(wire.tile / chip_info->width); - name += "/"; - name += nameOf(IdString(wire_data(wire).name)); - return id(name); + NPNR_ASSERT(wire != WireId()); + std::array ids{x_ids.at(wire.tile % chip_info->width), y_ids.at(wire.tile / chip_info->width), + IdString(wire_data(wire).name)}; + return IdStringList(ids); } IdString getWireType(WireId wire) const; @@ -1137,8 +1136,8 @@ struct Arch : BaseCtx // ------------------------------------------------- - PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const; + PipId getPipByName(IdStringList name) const; + IdStringList getPipName(PipId pip) const; void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { @@ -1290,8 +1289,8 @@ struct Arch : BaseCtx // ------------------------------------------------- - GroupId getGroupByName(IdString name) const { return GroupId(); } - IdString getGroupName(GroupId group) const { return IdString(); } + GroupId getGroupByName(IdStringList name) const { return GroupId(); } + IdStringList getGroupName(GroupId group) const { return IdStringList(); } std::vector getGroups() const { return {}; } std::vector getGroupBels(GroupId group) const { return {}; } std::vector getGroupWires(GroupId group) const { return {}; } diff --git a/nexus/pack.cc b/nexus/pack.cc index df479ef5..32bdfdb9 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -544,7 +544,7 @@ struct NexusPacker { if (!ci->attrs.count(id_BEL)) return BelId(); - return ctx->getBelByName(ctx->id(ci->attrs.at(id_BEL).as_string())); + return ctx->getBelByNameStr(ci->attrs.at(id_BEL).as_string()); } void pack_io() -- cgit v1.2.3 From 2a9584ea31973d415f7fdf58fc06482af57d3a0d Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Mon, 1 Feb 2021 12:03:16 +0000 Subject: gowin: Stub implementation of IdStringList Signed-off-by: D. Shah --- gowin/arch.cc | 28 ++++++++++++++-------------- gowin/arch.h | 21 ++++++++++++--------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 5a1a56e3..201641cd 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -759,14 +759,14 @@ void IdString::initialize_arch(const BaseCtx *ctx) // --------------------------------------------------------------- -BelId Arch::getBelByName(IdString name) const +BelId Arch::getBelByName(IdStringList name) const { - if (bels.count(name)) - return name; + if (bels.count(name[0])) + return name[0]; return BelId(); } -IdString Arch::getBelName(BelId bel) const { return bel; } +IdStringList Arch::getBelName(BelId bel) const { return IdStringList(bel); } Loc Arch::getBelLocation(BelId bel) const { @@ -836,14 +836,14 @@ std::vector Arch::getBelPins(BelId bel) const // --------------------------------------------------------------- -WireId Arch::getWireByName(IdString name) const +WireId Arch::getWireByName(IdStringList name) const { - if (wires.count(name)) - return name; + if (wires.count(name[0])) + return name[0]; return WireId(); } -IdString Arch::getWireName(WireId wire) const { return wire; } +IdStringList Arch::getWireName(WireId wire) const { return IdStringList(wire); } IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; } @@ -890,14 +890,14 @@ const std::vector &Arch::getWires() const { return wire_ids; } // --------------------------------------------------------------- -PipId Arch::getPipByName(IdString name) const +PipId Arch::getPipByName(IdStringList name) const { - if (pips.count(name)) - return name; + if (pips.count(name[0])) + return name[0]; return PipId(); } -IdString Arch::getPipName(PipId pip) const { return pip; } +IdStringList Arch::getPipName(PipId pip) const { return IdStringList(pip); } IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; } @@ -950,9 +950,9 @@ const std::vector &Arch::getPipsUphill(WireId wire) const { return wires. // --------------------------------------------------------------- -GroupId Arch::getGroupByName(IdString name) const { return name; } +GroupId Arch::getGroupByName(IdStringList name) const { return name[0]; } -IdString Arch::getGroupName(GroupId group) const { return group; } +IdStringList Arch::getGroupName(GroupId group) const { return IdStringList(group); } std::vector Arch::getGroups() const { diff --git a/gowin/arch.h b/gowin/arch.h index 6337255a..4754772b 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -323,10 +323,13 @@ struct Arch : BaseCtx int getGridDimY() const { return gridDimY; } int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } - char getNameDelimiter() const { return '/'; } + char getNameDelimiter() const + { + return ' '; /* use a non-existent delimiter as we aren't using IdStringLists yet */ + } - BelId getBelByName(IdString name) const; - IdString getBelName(BelId bel) const; + BelId getBelByName(IdStringList name) const; + IdStringList getBelName(BelId bel) const; Loc getBelLocation(BelId bel) const; BelId getBelByLocation(Loc loc) const; const std::vector &getBelsByTile(int x, int y) const; @@ -344,8 +347,8 @@ struct Arch : BaseCtx PortType getBelPinType(BelId bel, IdString pin) const; std::vector getBelPins(BelId bel) const; - WireId getWireByName(IdString name) const; - IdString getWireName(WireId wire) const; + WireId getWireByName(IdStringList name) const; + IdStringList getWireName(WireId wire) const; IdString getWireType(WireId wire) const; const std::map &getWireAttrs(WireId wire) const; uint32_t getWireChecksum(WireId wire) const; @@ -359,8 +362,8 @@ struct Arch : BaseCtx const std::vector &getWires() const; const std::vector &getWireBelPins(WireId wire) const; - PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const; + PipId getPipByName(IdStringList name) const; + IdStringList getPipName(PipId pip) const; IdString getPipType(PipId pip) const; const std::map &getPipAttrs(PipId pip) const; uint32_t getPipChecksum(PipId pip) const; @@ -378,8 +381,8 @@ struct Arch : BaseCtx const std::vector &getPipsDownhill(WireId wire) const; const std::vector &getPipsUphill(WireId wire) const; - GroupId getGroupByName(IdString name) const; - IdString getGroupName(GroupId group) const; + GroupId getGroupByName(IdStringList name) const; + IdStringList getGroupName(GroupId group) const; std::vector getGroups() const; const std::vector &getGroupBels(GroupId group) const; const std::vector &getGroupWires(GroupId group) const; -- cgit v1.2.3 From 7cff69f9453e0c95f8eb9a12b004afa20b69501e Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Tue, 2 Feb 2021 14:48:29 +0000 Subject: generic: Use IdStringList for all arch object names Signed-off-by: D. Shah --- common/nextpnr.h | 15 +++++++++ common/pybindings.h | 12 +++++++ common/timing_opt.cc | 2 +- generic/arch.cc | 74 +++++++++++++++++++++++-------------------- generic/arch.h | 79 ++++++++++++++++++++++++---------------------- generic/arch_pybindings.cc | 62 ++++++++++++++++++------------------ generic/archdefs.h | 10 +++--- 7 files changed, 146 insertions(+), 108 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index d4db9e9e..78bbf66e 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -243,6 +243,21 @@ struct IdStringList const IdString &operator[](size_t idx) const { return ids[idx]; } bool operator==(const IdStringList &other) const { return ids == other.ids; } bool operator!=(const IdStringList &other) const { return ids != other.ids; } + bool operator<(const IdStringList &other) const + { + if (size() > other.size()) + return false; + if (size() < other.size()) + return true; + for (size_t i = 0; i < size(); i++) { + IdString a = ids[i], b = other[i]; + if (a.index < b.index) + return true; + if (a.index > b.index) + return false; + } + return false; + } }; NEXTPNR_NAMESPACE_END diff --git a/common/pybindings.h b/common/pybindings.h index e50ffd1b..3e33a374 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -74,6 +74,18 @@ template <> struct string_converter inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); } }; +template <> struct string_converter +{ + IdStringList from_str(Context *ctx, std::string name) { return IdStringList::parse(ctx, name); } + std::string to_str(Context *ctx, const IdStringList &id) { return id.str(ctx); } +}; + +template <> struct string_converter +{ + IdStringList from_str(Context *ctx, std::string name) { return IdStringList::parse(ctx, name); } + std::string to_str(Context *ctx, const IdStringList &id) { return id.str(ctx); } +}; + } // namespace PythonConversion NEXTPNR_NAMESPACE_END diff --git a/common/timing_opt.cc b/common/timing_opt.cc index 7ee7b805..9c601e48 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -59,7 +59,7 @@ template <> struct hash> return seed; } }; -#if !defined(ARCH_GENERIC) && !defined(ARCH_GOWIN) +#if !defined(ARCH_GOWIN) template <> struct hash> { std::size_t diff --git a/generic/arch.cc b/generic/arch.cc index 4bf337bd..9b131959 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -28,31 +28,31 @@ NEXTPNR_NAMESPACE_BEGIN -WireInfo &Arch::wire_info(IdString wire) +WireInfo &Arch::wire_info(IdStringList wire) { auto w = wires.find(wire); if (w == wires.end()) - NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(this)); + NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(getCtx())); return w->second; } -PipInfo &Arch::pip_info(IdString pip) +PipInfo &Arch::pip_info(IdStringList pip) { auto p = pips.find(pip); if (p == pips.end()) - NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(this)); + NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(getCtx())); return p->second; } -BelInfo &Arch::bel_info(IdString bel) +BelInfo &Arch::bel_info(IdStringList bel) { auto b = bels.find(bel); if (b == bels.end()) - NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(this)); + NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(getCtx())); return b->second; } -void Arch::addWire(IdString name, IdString type, int x, int y) +void Arch::addWire(IdStringList name, IdString type, int x, int y) { NPNR_ASSERT(wires.count(name) == 0); WireInfo &wi = wires[name]; @@ -64,7 +64,8 @@ void Arch::addWire(IdString name, IdString type, int x, int y) wire_ids.push_back(name); } -void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc) +void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay, + Loc loc) { NPNR_ASSERT(pips.count(name) == 0); PipInfo &pi = pips[name]; @@ -90,7 +91,7 @@ void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWi tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1); } -void Arch::addBel(IdString name, IdString type, Loc loc, bool gb) +void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb) { NPNR_ASSERT(bels.count(name) == 0); NPNR_ASSERT(bel_by_loc.count(loc) == 0); @@ -124,7 +125,7 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb) tileBelDimZ[loc.x][loc.y] = std::max(tileBelDimZ[loc.x][loc.y], loc.z + 1); } -void Arch::addBelInput(IdString bel, IdString name, IdString wire) +void Arch::addBelInput(IdStringList bel, IdString name, IdStringList wire) { NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); PinInfo &pi = bel_info(bel).pins[name]; @@ -136,7 +137,7 @@ void Arch::addBelInput(IdString bel, IdString name, IdString wire) wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addBelOutput(IdString bel, IdString name, IdString wire) +void Arch::addBelOutput(IdStringList bel, IdString name, IdStringList wire) { NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); PinInfo &pi = bel_info(bel).pins[name]; @@ -148,7 +149,7 @@ void Arch::addBelOutput(IdString bel, IdString name, IdString wire) wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addBelInout(IdString bel, IdString name, IdString wire) +void Arch::addBelInout(IdStringList bel, IdString name, IdStringList wire) { NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); PinInfo &pi = bel_info(bel).pins[name]; @@ -160,13 +161,13 @@ void Arch::addBelInout(IdString bel, IdString name, IdString wire) wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addGroupBel(IdString group, IdString bel) { groups[group].bels.push_back(bel); } +void Arch::addGroupBel(IdStringList group, IdStringList bel) { groups[group].bels.push_back(bel); } -void Arch::addGroupWire(IdString group, IdString wire) { groups[group].wires.push_back(wire); } +void Arch::addGroupWire(IdStringList group, IdStringList wire) { groups[group].wires.push_back(wire); } -void Arch::addGroupPip(IdString group, IdString pip) { groups[group].pips.push_back(pip); } +void Arch::addGroupPip(IdStringList group, IdStringList pip) { groups[group].pips.push_back(pip); } -void Arch::addGroupGroup(IdString group, IdString grp) { groups[group].groups.push_back(grp); } +void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); } void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic) { @@ -198,11 +199,14 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) refreshUiGroup(group); } -void Arch::setWireAttr(IdString wire, IdString key, const std::string &value) { wire_info(wire).attrs[key] = value; } +void Arch::setWireAttr(IdStringList wire, IdString key, const std::string &value) +{ + wire_info(wire).attrs[key] = value; +} -void Arch::setPipAttr(IdString pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; } +void Arch::setPipAttr(IdStringList pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; } -void Arch::setBelAttr(IdString bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; } +void Arch::setBelAttr(IdStringList bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; } void Arch::setLutK(int K) { args.K = K; } @@ -212,9 +216,12 @@ void Arch::setDelayScaling(double scale, double offset) args.delayOffset = offset; } -void Arch::addCellTimingClock(IdString cell, IdString port) { cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT; } +void Arch::addCellTimingClock(IdStringList cell, IdString port) +{ + cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT; +} -void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay) +void Arch::addCellTimingDelay(IdStringList cell, IdString fromPort, IdString toPort, DelayInfo delay) { if (get_or_default(cellTiming[cell].portClasses, fromPort, TMG_IGNORE) == TMG_IGNORE) cellTiming[cell].portClasses[fromPort] = TMG_COMB_INPUT; @@ -223,7 +230,7 @@ void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, cellTiming[cell].combDelays[CellDelayKey{fromPort, toPort}] = delay; } -void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold) +void Arch::addCellTimingSetupHold(IdStringList cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold) { TimingClockingInfo ci; ci.clock_port = clock; @@ -234,7 +241,7 @@ void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, cellTiming[cell].portClasses[port] = TMG_REGISTER_INPUT; } -void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq) +void Arch::addCellTimingClockToOut(IdStringList cell, IdString port, IdString clock, DelayInfo clktoq) { TimingClockingInfo ci; ci.clock_port = clock; @@ -256,14 +263,14 @@ void IdString::initialize_arch(const BaseCtx *ctx) {} // --------------------------------------------------------------- -BelId Arch::getBelByName(IdString name) const +BelId Arch::getBelByName(IdStringList name) const { if (bels.count(name)) return name; return BelId(); } -IdString Arch::getBelName(BelId bel) const { return bel; } +IdStringList Arch::getBelName(BelId bel) const { return bel; } Loc Arch::getBelLocation(BelId bel) const { @@ -321,7 +328,7 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const { const auto &bdata = bels.at(bel); if (!bdata.pins.count(pin)) - log_error("bel '%s' has no pin '%s'\n", bel.c_str(this), pin.c_str(this)); + log_error("bel '%s' has no pin '%s'\n", getCtx()->nameOfBel(bel), pin.c_str(this)); return bdata.pins.at(pin).wire; } @@ -337,14 +344,14 @@ std::vector Arch::getBelPins(BelId bel) const // --------------------------------------------------------------- -WireId Arch::getWireByName(IdString name) const +WireId Arch::getWireByName(IdStringList name) const { if (wires.count(name)) return name; return WireId(); } -IdString Arch::getWireName(WireId wire) const { return wire; } +IdStringList Arch::getWireName(WireId wire) const { return wire; } IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; } @@ -391,14 +398,14 @@ const std::vector &Arch::getWires() const { return wire_ids; } // --------------------------------------------------------------- -PipId Arch::getPipByName(IdString name) const +PipId Arch::getPipByName(IdStringList name) const { if (pips.count(name)) return name; return PipId(); } -IdString Arch::getPipName(PipId pip) const { return pip; } +IdStringList Arch::getPipName(PipId pip) const { return pip; } IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; } @@ -455,9 +462,9 @@ const std::vector &Arch::getPipsUphill(WireId wire) const { return wires. // --------------------------------------------------------------- -GroupId Arch::getGroupByName(IdString name) const { return name; } +GroupId Arch::getGroupByName(IdStringList name) const { return name; } -IdString Arch::getGroupName(GroupId group) const { return group; } +IdStringList Arch::getGroupName(GroupId group) const { return group; } std::vector Arch::getGroups() const { @@ -582,8 +589,7 @@ bool Arch::route() const std::vector &Arch::getDecalGraphics(DecalId decal) const { if (!decal_graphics.count(decal)) { - std::cerr << "No decal named " << decal.str(this) << std::endl; - log_error("No decal named %s!\n", decal.c_str(this)); + std::cerr << "No decal named " << decal.str(getCtx()) << std::endl; } return decal_graphics.at(decal); } diff --git a/generic/arch.h b/generic/arch.h index 3ec9dc5d..205f388a 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -36,7 +36,8 @@ struct WireInfo; struct PipInfo { - IdString name, type; + IdStringList name; + IdString type; std::map attrs; NetInfo *bound_net; WireId srcWire, dstWire; @@ -47,7 +48,8 @@ struct PipInfo struct WireInfo { - IdString name, type; + IdStringList name; + IdString type; std::map attrs; NetInfo *bound_net; std::vector downhill, uphill; @@ -60,14 +62,15 @@ struct WireInfo struct PinInfo { - IdString name; + IdStringList name; WireId wire; PortType type; }; struct BelInfo { - IdString name, type; + IdStringList name; + IdString type; std::map attrs; CellInfo *bound_cell; std::unordered_map pins; @@ -78,7 +81,7 @@ struct BelInfo struct GroupInfo { - IdString name; + IdStringList name; std::vector bels; std::vector wires; std::vector pips; @@ -117,17 +120,17 @@ struct Arch : BaseCtx { std::string chipName; - std::unordered_map wires; - std::unordered_map pips; - std::unordered_map bels; + std::unordered_map wires; + std::unordered_map pips; + std::unordered_map bels; std::unordered_map groups; // These functions include useful errors if not found - WireInfo &wire_info(IdString wire); - PipInfo &pip_info(IdString wire); - BelInfo &bel_info(IdString wire); + WireInfo &wire_info(IdStringList wire); + PipInfo &pip_info(IdStringList wire); + BelInfo &bel_info(IdStringList wire); - std::vector bel_ids, wire_ids, pip_ids; + std::vector bel_ids, wire_ids, pip_ids; std::unordered_map bel_by_loc; std::vector>> bels_by_tile; @@ -138,20 +141,20 @@ struct Arch : BaseCtx std::vector> tileBelDimZ; std::vector> tilePipDimZ; - std::unordered_map cellTiming; + std::unordered_map cellTiming; - void addWire(IdString name, IdString type, int x, int y); - void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc); + void addWire(IdStringList name, IdString type, int x, int y); + void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay, Loc loc); - void addBel(IdString name, IdString type, Loc loc, bool gb); - void addBelInput(IdString bel, IdString name, IdString wire); - void addBelOutput(IdString bel, IdString name, IdString wire); - void addBelInout(IdString bel, IdString name, IdString wire); + void addBel(IdStringList name, IdString type, Loc loc, bool gb); + void addBelInput(IdStringList bel, IdString name, IdStringList wire); + void addBelOutput(IdStringList bel, IdString name, IdStringList wire); + void addBelInout(IdStringList bel, IdString name, IdStringList wire); - void addGroupBel(IdString group, IdString bel); - void addGroupWire(IdString group, IdString wire); - void addGroupPip(IdString group, IdString pip); - void addGroupGroup(IdString group, IdString grp); + void addGroupBel(IdStringList group, IdStringList bel); + void addGroupWire(IdStringList group, IdStringList wire); + void addGroupPip(IdStringList group, IdStringList pip); + void addGroupGroup(IdStringList group, IdStringList grp); void addDecalGraphic(DecalId decal, const GraphicElement &graphic); void setWireDecal(WireId wire, DecalXY decalxy); @@ -159,17 +162,17 @@ struct Arch : BaseCtx void setBelDecal(BelId bel, DecalXY decalxy); void setGroupDecal(GroupId group, DecalXY decalxy); - void setWireAttr(IdString wire, IdString key, const std::string &value); - void setPipAttr(IdString pip, IdString key, const std::string &value); - void setBelAttr(IdString bel, IdString key, const std::string &value); + void setWireAttr(IdStringList wire, IdString key, const std::string &value); + void setPipAttr(IdStringList pip, IdString key, const std::string &value); + void setBelAttr(IdStringList bel, IdString key, const std::string &value); void setLutK(int K); void setDelayScaling(double scale, double offset); - void addCellTimingClock(IdString cell, IdString port); - void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); - void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); - void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); + void addCellTimingClock(IdStringList cell, IdString port); + void addCellTimingDelay(IdStringList cell, IdString fromPort, IdString toPort, DelayInfo delay); + void addCellTimingSetupHold(IdStringList cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); + void addCellTimingClockToOut(IdStringList cell, IdString port, IdString clock, DelayInfo clktoq); // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. @@ -189,8 +192,8 @@ struct Arch : BaseCtx int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } char getNameDelimiter() const { return '/'; } - BelId getBelByName(IdString name) const; - IdString getBelName(BelId bel) const; + BelId getBelByName(IdStringList name) const; + IdStringList getBelName(BelId bel) const; Loc getBelLocation(BelId bel) const; BelId getBelByLocation(Loc loc) const; const std::vector &getBelsByTile(int x, int y) const; @@ -208,8 +211,8 @@ struct Arch : BaseCtx PortType getBelPinType(BelId bel, IdString pin) const; std::vector getBelPins(BelId bel) const; - WireId getWireByName(IdString name) const; - IdString getWireName(WireId wire) const; + WireId getWireByName(IdStringList name) const; + IdStringList getWireName(WireId wire) const; IdString getWireType(WireId wire) const; const std::map &getWireAttrs(WireId wire) const; uint32_t getWireChecksum(WireId wire) const; @@ -223,8 +226,8 @@ struct Arch : BaseCtx const std::vector &getWires() const; const std::vector &getWireBelPins(WireId wire) const; - PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const; + PipId getPipByName(IdStringList name) const; + IdStringList getPipName(PipId pip) const; IdString getPipType(PipId pip) const; const std::map &getPipAttrs(PipId pip) const; uint32_t getPipChecksum(PipId pip) const; @@ -242,8 +245,8 @@ struct Arch : BaseCtx const std::vector &getPipsDownhill(WireId wire) const; const std::vector &getPipsUphill(WireId wire) const; - GroupId getGroupByName(IdString name) const; - IdString getGroupName(GroupId group) const; + GroupId getGroupByName(IdStringList name) const; + IdStringList getGroupName(GroupId group) const; std::vector getGroups() const; const std::vector &getGroupBels(GroupId group) const; const std::vector &getGroupWires(GroupId group) const; diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc index 23f2c05c..4fc76c96 100644 --- a/generic/arch_pybindings.cc +++ b/generic/arch_pybindings.cc @@ -35,6 +35,7 @@ template <> struct string_converter std::string to_str(Context *ctx, const IdString &id) { return id.str(ctx); } }; + } // namespace PythonConversion void arch_wrap_python(py::module &m) @@ -152,37 +153,37 @@ void arch_wrap_python(py::module &m) pass_through>::def_wrap(ctx_cls, "addClock"); // Generic arch construction API - fn_wrapper_4a_v, + fn_wrapper_4a_v, conv_from_str, pass_through, pass_through>::def_wrap(ctx_cls, "addWire", "name"_a, "type"_a, "x"_a, "y"_a); - fn_wrapper_6a_v, - conv_from_str, conv_from_str, conv_from_str, pass_through, - pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a, - "delay"_a, "loc"_a); + fn_wrapper_6a_v, + conv_from_str, conv_from_str, conv_from_str, + pass_through, pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, + "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a); - fn_wrapper_4a_v, + fn_wrapper_4a_v, conv_from_str, pass_through, pass_through>::def_wrap(ctx_cls, "addBel", "name"_a, "type"_a, "loc"_a, "gb"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInput", "bel"_a, - "name"_a, "wire"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, - "name"_a, "wire"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInout", "bel"_a, - "name"_a, "wire"_a); - - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInput", "bel"_a, + "name"_a, "wire"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, + "name"_a, "wire"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInout", "bel"_a, + "name"_a, "wire"_a); + + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a); fn_wrapper_2a_v, pass_through>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic")); @@ -211,16 +212,17 @@ void arch_wrap_python(py::module &m) pass_through>::def_wrap(ctx_cls, "setDelayScaling", "scale"_a, "offset"_a); fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "addCellTimingClock", "cell"_a, - "port"_a); + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addCellTimingClock", + "cell"_a, "port"_a); fn_wrapper_4a_v, conv_from_str, conv_from_str, + conv_from_str, conv_from_str, conv_from_str, pass_through>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a, "toPort"_a, "delay"_a); fn_wrapper_5a_v, conv_from_str, conv_from_str, pass_through, - pass_through>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a, - "setup"_a, "hold"_a); + conv_from_str, conv_from_str, conv_from_str, + pass_through, pass_through>::def_wrap(ctx_cls, "addCellTimingSetupHold", + "cell"_a, "port"_a, "clock"_a, + "setup"_a, "hold"_a); fn_wrapper_4a_v, conv_from_str, conv_from_str, pass_through>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, diff --git a/generic/archdefs.h b/generic/archdefs.h index 7623bf40..fad36894 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -46,11 +46,11 @@ struct DelayInfo } }; -typedef IdString BelId; -typedef IdString WireId; -typedef IdString PipId; -typedef IdString GroupId; -typedef IdString DecalId; +typedef IdStringList BelId; +typedef IdStringList WireId; +typedef IdStringList PipId; +typedef IdStringList GroupId; +typedef IdStringList DecalId; typedef IdString BelBucketId; struct ArchNetInfo -- cgit v1.2.3 From 15bf9e4f74cdd52e8e03abcac4c7fa1fc26b3367 Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Tue, 2 Feb 2021 17:07:44 +0000 Subject: Post-rebase fix Signed-off-by: D. Shah --- generic/arch.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/generic/arch.h b/generic/arch.h index 205f388a..ab554d53 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -277,13 +277,12 @@ struct Arch : BaseCtx std::vector getCellTypes() const { - std::vector cell_types; - cell_types.reserve(bels.size()); + std::unordered_set cell_types; for (auto bel : bels) { - cell_types.push_back(bel.first); + cell_types.insert(bel.second.type); } - return cell_types; + return std::vector{cell_types.begin(), cell_types.end()}; } std::vector getBelBuckets() const { return getCellTypes(); } -- cgit v1.2.3