aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2021-02-03 09:48:07 +0000
committerGitHub <noreply@github.com>2021-02-03 09:48:07 +0000
commit9a79163eab89e6351cd06c37d5916174acdfc754 (patch)
tree60bccc139d7ea739257322b4bd2d01a0913c503a
parent9c5d13a630581c08c7f828a8db192721314e32c3 (diff)
parent15bf9e4f74cdd52e8e03abcac4c7fa1fc26b3367 (diff)
downloadnextpnr-9a79163eab89e6351cd06c37d5916174acdfc754.tar.gz
nextpnr-9a79163eab89e6351cd06c37d5916174acdfc754.tar.bz2
nextpnr-9a79163eab89e6351cd06c37d5916174acdfc754.zip
Merge pull request #561 from YosysHQ/dave/idstringlist
Use IdStringList for bel/wire/pip/group names
-rw-r--r--common/arch_pybindings_shared.h3
-rw-r--r--common/archcheck.cc16
-rw-r--r--common/nextpnr.cc91
-rw-r--r--common/nextpnr.h155
-rw-r--r--common/place_common.cc7
-rw-r--r--common/placer1.cc14
-rw-r--r--common/placer_heap.cc4
-rw-r--r--common/pybindings.h12
-rw-r--r--common/timing.cc3
-rw-r--r--common/timing_opt.cc11
-rw-r--r--docs/archapi.md29
-rw-r--r--ecp5/arch.cc107
-rw-r--r--ecp5/arch.h40
-rw-r--r--ecp5/arch_pybindings.h8
-rw-r--r--ecp5/bitstream.cc15
-rw-r--r--ecp5/globals.cc19
-rw-r--r--ecp5/pack.cc48
-rw-r--r--generic/arch.cc74
-rw-r--r--generic/arch.h87
-rw-r--r--generic/arch_pybindings.cc62
-rw-r--r--generic/archdefs.h10
-rw-r--r--gowin/arch.cc28
-rw-r--r--gowin/arch.h20
-rw-r--r--gui/designwidget.cc64
-rw-r--r--gui/designwidget.h2
-rw-r--r--gui/fpgaviewwidget.cc8
-rw-r--r--gui/treemodel.cc10
-rw-r--r--gui/treemodel.h47
-rw-r--r--ice40/arch.cc55
-rw-r--r--ice40/arch.h40
-rw-r--r--ice40/arch_place.cc2
-rw-r--r--ice40/chipdb.py21
-rw-r--r--ice40/delay.cc2
-rw-r--r--ice40/pack.cc37
-rw-r--r--nexus/arch.cc70
-rw-r--r--nexus/arch.h44
-rw-r--r--nexus/pack.cc2
37 files changed, 771 insertions, 496 deletions
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<Context, decltype(&Context::hierarchy), &Context::hierarchy, wr
readwrite_wrapper<Context, decltype(&Context::top_module), &Context::top_module, conv_to_str<IdString>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "top_module");
+fn_wrapper_0a<Context, decltype(&Context::getNameDelimiter), &Context::getNameDelimiter, pass_through<char>>::def_wrap(
+ ctx_cls, "getNameDelimiter");
+
fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias");
fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>,
diff --git a/common/archcheck.cc b/common/archcheck.cc
index f5760c88..28b0c147 100644
--- a/common/archcheck.cc
+++ b/common/archcheck.cc
@@ -36,19 +36,19 @@ 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));
}
}
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", name.c_str(ctx));
+ log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire));
}
}
@@ -64,10 +64,10 @@ 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", 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/nextpnr.cc b/common/nextpnr.cc
index 9a856b99..f7f368f1 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;
@@ -76,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);
@@ -248,25 +291,57 @@ 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
{
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)
+{
+ Context *ctx = getCtx();
+ 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
@@ -620,7 +695,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)
@@ -650,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;
}
@@ -672,7 +747,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 b4f68f93..78bbf66e 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -145,6 +145,152 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdString>
NEXTPNR_NAMESPACE_BEGIN
+// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise
+template <typename T, size_t N> class SSOArray
+{
+ private:
+ union
+ {
+ T data_static[N];
+ T *data_heap;
+ };
+ size_t m_size;
+ inline bool is_heap() const { 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() : m_size(0){};
+
+ SSOArray(size_t size, const T &init = T()) : m_size(size)
+ {
+ alloc();
+ std::fill(begin(), end(), init);
+ }
+
+ SSOArray(const SSOArray &other) : m_size(other.size())
+ {
+ alloc();
+ std::copy(other.begin(), other.end(), begin());
+ }
+
+ template <typename Tother> 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());
+ }
+ 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<IdString, 4> ids;
+
+ IdStringList(){};
+ IdStringList(size_t n) : ids(n, IdString()){};
+ IdStringList(IdString id) : ids(1, id){};
+ template <typename Tlist> IdStringList(const Tlist &list) : ids(list){};
+
+ static IdStringList parse(Context *ctx, const std::string &str);
+ 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]; }
+ 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
+
+namespace std {
+template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdStringList>
+{
+ std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX IdStringList &obj) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, hash<size_t>()(obj.size()));
+ for (auto &id : obj)
+ boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(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
+{
+ private:
+ static const size_t N = 100;
+ std::array<std::string, N> buffer;
+ size_t index = 0;
+
+ public:
+ std::string &next();
+};
+
struct GraphicElement
{
enum type_t
@@ -667,6 +813,9 @@ struct BaseCtx
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str;
+ // Temporary string backing store for logging
+ mutable StrRingBuffer log_strs;
+
// Project settings and config switches
std::unordered_map<IdString, Property> settings;
@@ -782,6 +931,12 @@ struct BaseCtx
const char *nameOfPip(PipId pip) const;
const char *nameOfGroup(GroupId group) const;
+ // 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);
+
// --------------------------------------------------------------
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..280dd02e 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;
@@ -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/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/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<const IdString>
inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); }
};
+template <> struct string_converter<IdStringList>
+{
+ 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<const IdStringList>
+{
+ 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.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/common/timing_opt.cc b/common/timing_opt.cc
index 025084b7..9c601e48 100644
--- a/common/timing_opt.cc
+++ b/common/timing_opt.cc
@@ -59,7 +59,7 @@ template <> struct hash<std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId>>
return seed;
}
};
-#if !defined(ARCH_GENERIC) && !defined(ARCH_GOWIN)
+#if !defined(ARCH_GOWIN)
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
{
std::size_t
@@ -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/docs/archapi.md b/docs/archapi.md
index 49183c63..e3c06efd 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,15 +103,14 @@ Cell Methods
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.)
@@ -183,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.)
@@ -259,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.)
@@ -350,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.)
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 25f95c53..d86bad5d 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -37,17 +37,6 @@
NEXTPNR_NAMESPACE_BEGIN
-static std::tuple<int, int, std::string> 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)
@@ -128,6 +117,22 @@ 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)));
+
+ 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;
+ }
}
// -----------------------------------------------------------------------
@@ -208,27 +213,23 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
-BelId Arch::getBelByName(IdString name) const
+BelId Arch::getBelByName(IdStringList name) const
{
+ if (name.size() != 3)
+ return BelId();
BelId ret;
- auto it = bel_by_name.find(name);
- if (it != bel_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->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 (ret.index >= 0)
- bel_by_name[name] = ret;
- return ret;
+ return BelId();
}
BelRange Arch::getBelsByTile(int x, int y) const
@@ -277,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;
@@ -314,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++) {
@@ -324,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<IdString, 3> ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)};
+ return IdStringList(ids);
}
// -----------------------------------------------------------------------
@@ -1206,7 +1202,7 @@ const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
// -----------------------------------------------------------------------
-GroupId Arch::getGroupByName(IdString name) const
+GroupId Arch::getGroupByName(IdStringList name) const
{
for (auto g : getGroups())
if (getGroupName(g) == name)
@@ -1214,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;
@@ -1223,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<IdString, 3> ids{x_ids.at(group.location.x), y_ids.at(group.location.y), id(suffix)};
+ return IdStringList(ids);
}
std::vector<GroupId> Arch::getGroups() const
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 18a70fe8..9997cd5c 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -441,15 +441,18 @@ struct Arch : BaseCtx
const PackageInfoPOD *package_info;
const SpeedGradePOD *speed_grade;
- mutable std::unordered_map<IdString, BelId> bel_by_name;
- mutable std::unordered_map<IdString, WireId> wire_by_name;
- mutable std::unordered_map<IdString, PipId> pip_by_name;
+ mutable std::unordered_map<IdStringList, PipId> pip_by_name;
std::vector<CellInfo *> bel_to_cell;
std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<WireId, int> wire_fanout;
+ // fast access to X and Y IdStrings for building object names
+ std::vector<IdString> x_ids, y_ids;
+ // inverse of the above for name->object mapping
+ std::unordered_map<IdString, int> id_to_x, id_to_y;
+
ArchArgs args;
Arch(ArchArgs args);
@@ -471,22 +474,23 @@ 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 '/'; }
// -------------------------------------------------
- BelId getBelByName(IdString name) const;
+ BelId getBelByName(IdStringList name) const;
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
}
- IdString getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
- std::stringstream name;
- name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get();
- return id(name.str());
+ std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
+ id(locInfo(bel)->bel_data[bel.index].name.get())};
+ return IdStringList(ids);
}
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
@@ -594,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<IdString, 3> 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
@@ -712,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(); }
@@ -891,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<GroupId> getGroups() const;
std::vector<BelId> getGroupBels(GroupId group) const;
std::vector<WireId> getGroupWires(GroupId group) const;
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index dd3161ae..4228f12b 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -30,7 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); }
std::string to_str(Context *ctx, BelId id)
{
@@ -42,7 +42,7 @@ template <> struct string_converter<BelId>
template <> struct string_converter<WireId>
{
- 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<WireId>
template <> struct string_converter<const WireId>
{
- 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<const WireId>
template <> struct string_converter<PipId>
{
- 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 =
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 218090e1..478e5fac 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
@@ -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();
@@ -300,7 +299,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;
@@ -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 b60d6c7d..ed2dfc29 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -522,7 +522,7 @@ class Ecp5Packer
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
} else {
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx),
- ctx->getBelName(pinBel).c_str(ctx));
+ ctx->nameOfBel(pinBel));
}
trio->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
}
@@ -1657,7 +1657,7 @@ class Ecp5Packer
CellInfo *dcu = clki->driver.cell;
if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
- BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(dcu->attrs.at(ctx->id("BEL")).as_string());
if (bel == BelId())
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
Loc loc = ctx->getBelLocation(bel);
@@ -1704,7 +1704,7 @@ class Ecp5Packer
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
- available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL")).as_string())));
+ available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
}
// Place PLL connected to fixed drivers such as IO close to their source
for (auto cell : sorted(ctx->cells)) {
@@ -1716,7 +1716,7 @@ class Ecp5Packer
const CellInfo *drivercell = drivernet->driver.cell;
if (!drivercell->attrs.count(ctx->id("BEL")))
continue;
- BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId drvbel = ctx->getBelByNameStr(drivercell->attrs.at(ctx->id("BEL")).as_string());
Loc drvloc = ctx->getBelLocation(drvbel);
BelId closest_pll;
int closest_distance = std::numeric_limits<int>::max();
@@ -1848,12 +1848,12 @@ 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)
- 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;
@@ -1913,17 +1913,17 @@ class Ecp5Packer
log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input"
"(while processing '%s').\n",
ci->name.c_str(ctx));
- BelId pio_bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId pio_bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(pio_bel != BelId());
Loc pio_loc = ctx->getBelLocation(pio_bel);
if (pio_loc.z != 0)
log_error("PIO '%s' does not appear to be a DQS site (expecting an 'A' pin).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
pio_loc.z = 8;
BelId dqsbuf = ctx->getBelByLocation(pio_loc);
if (dqsbuf == BelId() || ctx->getBelType(dqsbuf) != id_DQSBUFM)
log_error("PIO '%s' does not appear to be a DQS site (didn't find a DQSBUFM).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
ci->attrs[ctx->id("BEL")] = ctx->getBelName(dqsbuf).str(ctx);
bool got_dqsg = ctx->getPIODQSGroup(pio_bel, dqsbuf_dqsg[ci->name].first, dqsbuf_dqsg[ci->name].second);
NPNR_ASSERT(got_dqsg);
@@ -2078,15 +2078,14 @@ class Ecp5Packer
log_error("IOLOGIC functionality (DDR, DELAY, DQS, etc) can only be used with pin-constrained PIO "
"(while processing '%s').\n",
curr->name.c_str(ctx));
- BelId bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(bel != BelId());
return bel;
};
auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) {
BelId bel = get_pio_bel(pio, curr);
- log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx),
- ctx->getBelName(bel).c_str(ctx));
+ log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
Loc loc = ctx->getBelLocation(bel);
bool s = false;
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1))
@@ -2292,8 +2291,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("D2"), iol, id_TXDATA2);
replace_port(ci, ctx->id("D3"), iol, id_TXDATA3);
if (ci->type == ctx->id("ODDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("D4"), iol, id_TXDATA4);
@@ -2326,8 +2324,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("Q2"), iol, id_RXDATA2);
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
if (ci->type == ctx->id("IDDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
@@ -2579,7 +2576,7 @@ class Ecp5Packer
if (!user.cell->attrs.count(ctx->id("BEL")))
continue;
Loc user_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
continue;
@@ -2594,8 +2591,8 @@ class Ecp5Packer
CellInfo *drv = input->driver.cell;
if (!drv->attrs.count(ctx->id("BEL")))
continue;
- Loc drv_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string())));
+ Loc drv_loc =
+ ctx->getBelLocation(ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string()));
BelId closest;
int closest_x = -1; // aim for same side of chip
for (auto bel : ctx->getBels()) {
@@ -2639,7 +2636,7 @@ class Ecp5Packer
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
continue;
- BelId bel = ctx->getBelByName(ctx->id(str_or_default(ci->attrs, ctx->id("BEL"))));
+ BelId bel = ctx->getBelByNameStr(str_or_default(ci->attrs, ctx->id("BEL")));
NPNR_ASSERT(bel != BelId());
Loc pioLoc = ctx->getBelLocation(bel);
if (ci->type == id_DQSBUFM)
@@ -2683,8 +2680,7 @@ class Ecp5Packer
const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO);
if (eclki != nullptr && eclki->driver.cell != nullptr) {
if (eclki->driver.cell->type == id_ECLKBRIDGECS) {
- BelId bel =
- ctx->getBelByName(ctx->id(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string());
Loc loc = ctx->getBelLocation(bel);
ci->attrs[ctx->id("BEL")] =
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
@@ -2697,7 +2693,7 @@ class Ecp5Packer
for (auto user : eclko->users) {
if (user.cell->type == id_TRELLIS_ECLKBUF) {
Loc eckbuf_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKSYNCB)
continue;
@@ -2726,7 +2722,7 @@ class Ecp5Packer
const CellInfo *uc = usr.cell;
if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL")))
continue;
- BelId dqsb_bel = ctx->getBelByName(ctx->id(uc->attrs.at(ctx->id("BEL")).as_string()));
+ BelId dqsb_bel = ctx->getBelByNameStr(uc->attrs.at(ctx->id("BEL")).as_string());
Loc dqsb_loc = ctx->getBelLocation(dqsb_bel);
if (dqsb_loc.x > 15)
right_bank_users = true;
@@ -2809,7 +2805,7 @@ class Ecp5Packer
CellInfo *drv = clki->driver.cell;
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
continue;
- BelId bel = ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string());
// Find a CLKDIVF that is routeable from the ECLKSYNC
std::queue<WireId> visit;
visit.push(ctx->getBelPinWire(bel, id_ECLKO));
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<IdString> 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<WireId> &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<PipId> &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<GroupId> Arch::getGroups() const
{
@@ -582,8 +589,7 @@ bool Arch::route()
const std::vector<GraphicElement> &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 f3e26bb5..ab554d53 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<IdString, std::string> attrs;
NetInfo *bound_net;
WireId srcWire, dstWire;
@@ -47,7 +48,8 @@ struct PipInfo
struct WireInfo
{
- IdString name, type;
+ IdStringList name;
+ IdString type;
std::map<IdString, std::string> attrs;
NetInfo *bound_net;
std::vector<PipId> 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<IdString, std::string> attrs;
CellInfo *bound_cell;
std::unordered_map<IdString, PinInfo> pins;
@@ -78,7 +81,7 @@ struct BelInfo
struct GroupInfo
{
- IdString name;
+ IdStringList name;
std::vector<BelId> bels;
std::vector<WireId> wires;
std::vector<PipId> pips;
@@ -117,17 +120,17 @@ struct Arch : BaseCtx
{
std::string chipName;
- std::unordered_map<IdString, WireInfo> wires;
- std::unordered_map<IdString, PipInfo> pips;
- std::unordered_map<IdString, BelInfo> bels;
+ std::unordered_map<IdStringList, WireInfo> wires;
+ std::unordered_map<IdStringList, PipInfo> pips;
+ std::unordered_map<IdStringList, BelInfo> bels;
std::unordered_map<GroupId, GroupInfo> 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<IdString> bel_ids, wire_ids, pip_ids;
+ std::vector<IdStringList> bel_ids, wire_ids, pip_ids;
std::unordered_map<Loc, BelId> bel_by_loc;
std::vector<std::vector<std::vector<BelId>>> bels_by_tile;
@@ -138,20 +141,20 @@ struct Arch : BaseCtx
std::vector<std::vector<int>> tileBelDimZ;
std::vector<std::vector<int>> tilePipDimZ;
- std::unordered_map<IdString, CellTiming> cellTiming;
+ std::unordered_map<IdStringList, CellTiming> 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.
@@ -187,9 +190,10 @@ 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;
+ BelId getBelByName(IdStringList name) const;
+ IdStringList getBelName(BelId bel) const;
Loc getBelLocation(BelId bel) const;
BelId getBelByLocation(Loc loc) const;
const std::vector<BelId> &getBelsByTile(int x, int y) const;
@@ -207,8 +211,8 @@ struct Arch : BaseCtx
PortType getBelPinType(BelId bel, IdString pin) const;
std::vector<IdString> 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<IdString, std::string> &getWireAttrs(WireId wire) const;
uint32_t getWireChecksum(WireId wire) const;
@@ -222,8 +226,8 @@ struct Arch : BaseCtx
const std::vector<WireId> &getWires() const;
const std::vector<BelPin> &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<IdString, std::string> &getPipAttrs(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const;
@@ -241,8 +245,8 @@ struct Arch : BaseCtx
const std::vector<PipId> &getPipsDownhill(WireId wire) const;
const std::vector<PipId> &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<GroupId> getGroups() const;
const std::vector<BelId> &getGroupBels(GroupId group) const;
const std::vector<WireId> &getGroupWires(GroupId group) const;
@@ -273,13 +277,12 @@ struct Arch : BaseCtx
std::vector<IdString> getCellTypes() const
{
- std::vector<IdString> cell_types;
- cell_types.reserve(bels.size());
+ std::unordered_set<IdString> cell_types;
for (auto bel : bels) {
- cell_types.push_back(bel.first);
+ cell_types.insert(bel.second.type);
}
- return cell_types;
+ return std::vector<IdString>{cell_types.begin(), cell_types.end()};
}
std::vector<BelBucketId> getBelBuckets() const { return getCellTypes(); }
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<const IdString &>
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<float>>::def_wrap(ctx_cls, "addClock");
// Generic arch construction API
- fn_wrapper_4a_v<Context, decltype(&Context::addWire), &Context::addWire, conv_from_str<IdString>,
+ fn_wrapper_4a_v<Context, decltype(&Context::addWire), &Context::addWire, conv_from_str<IdStringList>,
conv_from_str<IdString>, pass_through<int>, pass_through<int>>::def_wrap(ctx_cls, "addWire",
"name"_a, "type"_a, "x"_a,
"y"_a);
- fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdString>,
- conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>,
- pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a,
- "delay"_a, "loc"_a);
+ fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
+ conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>,
+ pass_through<DelayInfo>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
+ "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a);
- fn_wrapper_4a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdString>,
+ fn_wrapper_4a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>,
conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>>::def_wrap(ctx_cls, "addBel",
"name"_a, "type"_a,
"loc"_a, "gb"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdString>,
- conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
- "name"_a, "wire"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdString>,
- conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
- "name"_a, "wire"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdString>,
- conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
- "name"_a, "wire"_a);
-
- fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdString>,
- conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdString>,
- conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdString>,
- conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdString>,
- conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdStringList>,
+ conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
+ "name"_a, "wire"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdStringList>,
+ conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
+ "name"_a, "wire"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdStringList>,
+ conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
+ "name"_a, "wire"_a);
+
+ fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>,
+ conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
+ fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>,
+ conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
+ fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>,
+ conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
+ fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdStringList>,
+ conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>,
pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic"));
@@ -211,16 +212,17 @@ void arch_wrap_python(py::module &m)
pass_through<double>>::def_wrap(ctx_cls, "setDelayScaling", "scale"_a, "offset"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addCellTimingClock), &Context::addCellTimingClock,
- conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addCellTimingClock", "cell"_a,
- "port"_a);
+ conv_from_str<IdStringList>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addCellTimingClock",
+ "cell"_a, "port"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingDelay), &Context::addCellTimingDelay,
- conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
+ conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<IdString>,
pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a,
"toPort"_a, "delay"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addCellTimingSetupHold), &Context::addCellTimingSetupHold,
- conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>,
- pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a,
- "setup"_a, "hold"_a);
+ conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<IdString>,
+ pass_through<DelayInfo>, pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold",
+ "cell"_a, "port"_a, "clock"_a,
+ "setup"_a, "hold"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingClockToOut), &Context::addCellTimingClockToOut,
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
pass_through<DelayInfo>>::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
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<IdString> 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<WireId> &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<PipId> &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<GroupId> Arch::getGroups() const
{
diff --git a/gowin/arch.h b/gowin/arch.h
index f12c604e..4754772b 100644
--- a/gowin/arch.h
+++ b/gowin/arch.h
@@ -323,9 +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 ' '; /* 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<BelId> &getBelsByTile(int x, int y) const;
@@ -343,8 +347,8 @@ struct Arch : BaseCtx
PortType getBelPinType(BelId bel, IdString pin) const;
std::vector<IdString> 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<IdString, std::string> &getWireAttrs(WireId wire) const;
uint32_t getWireChecksum(WireId wire) const;
@@ -358,8 +362,8 @@ struct Arch : BaseCtx
const std::vector<WireId> &getWires() const;
const std::vector<BelPin> &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<IdString, std::string> &getPipAttrs(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const;
@@ -377,8 +381,8 @@ struct Arch : BaseCtx
const std::vector<PipId> &getPipsDownhill(WireId wire) const;
const std::vector<PipId> &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<GroupId> getGroups() const;
const std::vector<BelId> &getGroupBels(GroupId group) const;
const std::vector<WireId> &getGroupWires(GroupId group) const;
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index f856b5f6..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<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::CELL)));
+ ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::CELL)));
getTreeByElementType(ElementType::NET)
- ->loadData(ctx,
- std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::NET)));
+ ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::NET)));
}
updateTree();
}
@@ -357,10 +355,10 @@ void DesignWidget::updateTree()
while (i != highlightSelected.end()) {
QMap<TreeModel::Item *, int>::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<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex);
- std::vector<IdString> cells;
+ std::vector<IdStringList> cells;
for (auto &pair : ctx->cells) {
- cells.push_back(pair.first);
+ cells.push_back(IdStringList(pair.first));
}
- std::vector<IdString> nets;
+ std::vector<IdStringList> 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);
@@ -631,7 +629,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<std::mutex> lock_ui(ctx->ui_mutex);
@@ -640,12 +638,12 @@ 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);
- 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 +664,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);
@@ -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,21 +700,20 @@ 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);
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");
@@ -735,7 +732,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex);
- NetInfo *net = ctx->nets.at(c).get();
+ NetInfo *net = ctx->nets.at(c[0]).get();
QtProperty *topItem = addTopLevelProperty("Net");
@@ -769,14 +766,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);
@@ -787,14 +783,14 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> 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));
@@ -838,7 +834,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
}
}
-std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
+std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdStringList value)
{
std::vector<DecalXY> decals;
switch (type) {
@@ -861,7 +857,7 @@ std::vector<DecalXY> 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()) {
@@ -870,7 +866,7 @@ std::vector<DecalXY> 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<DecalXY> getDecals(ElementType type, IdString value);
+ std::vector<DecalXY> getDecals(ElementType type, IdStringList value);
void updateHighlightGroup(QList<TreeModel::Item *> item, int group);
void clearAllSelectionModels();
Q_SIGNALS:
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/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<QString> IdStringList::alphaNumSplit(const QString &str)
+std::vector<QString> IdList::alphaNumSplit(const QString &str)
{
std::vector<QString> res;
QString current_part;
@@ -53,12 +53,12 @@ std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
return res;
}
-void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
+void IdList::updateElements(Context *ctx, std::vector<IdStringList> elements)
{
bool changed = false;
// For any elements that are not yet in managed_, created them.
- std::unordered_set<IdString> element_set;
+ std::unordered_set<IdStringList> 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<IdString> elements)
});
}
-void IdStringList::search(QList<Item *> &results, QString text, int limit)
+void IdList::search(QList<Item *> &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<Item> data)
endResetModel();
}
-void Model::updateElements(std::vector<IdString> elements)
+void Model::updateElements(std::vector<IdStringList> 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<Item *> getById(IdString id) { return boost::none; }
+ virtual boost::optional<Item *> getById(IdStringList id) { return boost::none; }
virtual void search(QList<Item *> &results, QString text, int limit) {}
- virtual void updateElements(Context *ctx, std::vector<IdString> elements) {}
+ virtual void updateElements(Context *ctx, std::vector<IdStringList> 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<IdString, std::unique_ptr<IdStringItem>> managed_;
+ std::unordered_map<IdStringList, std::unique_ptr<IdStringItem>> 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<QString> alphaNumSplit(const QString &str);
// getById finds a child for the given IdString.
- virtual boost::optional<Item *> getById(IdString id) override { return managed_.at(id).get(); }
+ virtual boost::optional<Item *> getById(IdStringList id) override { return managed_.at(id).get(); }
// (Re-)create children from a list of IdStrings.
- virtual void updateElements(Context *ctx, std::vector<IdString> elements) override;
+ virtual void updateElements(Context *ctx, std::vector<IdStringList> elements) override;
// Find children that contain the given text.
virtual void search(QList<Item *> &results, QString text, int limit) override;
@@ -173,7 +173,7 @@ template <typename ElementT> class ElementList : public Item
// A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString.
- using ElementGetter = std::function<IdString(Context *, ElementT)>;
+ using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private:
Context *ctx_;
@@ -184,7 +184,7 @@ template <typename ElementT> class ElementList : public Item
ElementGetter getter_;
// Children that we manage the memory for, stored for quick lookup from
// IdString to child.
- std::unordered_map<IdString, std::unique_ptr<Item>> managed_;
+ std::unordered_map<IdStringList, std::unique_ptr<Item>> managed_;
// Type of children that he list creates.
ElementType child_type_;
@@ -209,9 +209,10 @@ template <typename ElementT> 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 <typename ElementT> class ElementList : public Item
virtual void fetchMore() override { fetchMore(100); }
// getById finds a child for the given IdString.
- virtual boost::optional<Item *> getById(IdString id) override
+ virtual boost::optional<Item *> getById(IdStringList id) override
{
// Search requires us to load all our elements...
while (canFetchMore())
@@ -267,7 +268,7 @@ template <typename ElementT> class ElementXYRoot : public Item
// A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString.
- using ElementGetter = std::function<IdString(Context *, ElementT)>;
+ using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private:
Context *ctx_;
@@ -319,7 +320,7 @@ template <typename ElementT> class ElementXYRoot : public Item
}
// getById finds a child for the given IdString.
- virtual boost::optional<Item *> getById(IdString id) override
+ virtual boost::optional<Item *> 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<Item> data);
- void updateElements(std::vector<IdString> elements);
+ void updateElements(std::vector<IdStringList> elements);
Item *nodeFromIndex(const QModelIndex &idx) const;
QModelIndex indexFromNode(Item *node)
{
@@ -366,7 +367,7 @@ class Model : public QAbstractItemModel
QList<QModelIndex> search(QString text);
- boost::optional<Item *> nodeForId(IdString id) const { return root_->getById(id); }
+ boost::optional<Item *> nodeForId(IdStringList id) const { return root_->getById(id); }
// Override QAbstractItemModel methods
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
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<std::pair<IdString, std::string>> 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<IdString, 3> 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<IdString, 3> ids{x_ids.at(group.x), y_ids.at(group.y), id(suffix)};
+ return IdStringList(ids);
}
std::vector<GroupId> Arch::getGroups() const
diff --git a/ice40/arch.h b/ice40/arch.h
index fd92d988..1987f17a 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -91,6 +91,8 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {
};
RelPtr<char> name;
+ int8_t name_x, name_y;
+ int16_t padding;
RelSlice<int32_t> pips_uphill, pips_downhill;
RelSlice<BelPortPOD> bel_pins;
@@ -378,9 +380,9 @@ struct Arch : BaseCtx
const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info;
- mutable std::unordered_map<IdString, int> bel_by_name;
- mutable std::unordered_map<IdString, int> wire_by_name;
- mutable std::unordered_map<IdString, int> pip_by_name;
+ mutable std::unordered_map<IdStringList, int> bel_by_name;
+ mutable std::unordered_map<IdStringList, int> wire_by_name;
+ mutable std::unordered_map<IdStringList, int> pip_by_name;
mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry;
@@ -389,6 +391,11 @@ struct Arch : BaseCtx
std::vector<NetInfo *> pip_to_net;
std::vector<WireId> switches_locked;
+ // fast access to X and Y IdStrings for building object names
+ std::vector<IdString> x_ids, y_ids;
+ // inverse of the above for name->object mapping
+ std::unordered_map<IdString, int> id_to_x, id_to_y;
+
ArchArgs args;
Arch(ArchArgs args);
@@ -407,15 +414,18 @@ 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 '/'; }
// -------------------------------------------------
- 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<IdString, 3> 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; }
@@ -500,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<IdString, 3> 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;
@@ -593,7 +605,7 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdString name) const;
+ PipId getPipByName(IdStringList name) const;
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{
@@ -703,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<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
@@ -760,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<GroupId> getGroups() const;
std::vector<BelId> getGroupBels(GroupId group) const;
std::vector<WireId> getGroupWires(GroupId group) const;
@@ -895,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/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..a909b08b 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) {
@@ -435,7 +435,7 @@ static std::unique_ptr<CellInfo> 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
@@ -839,18 +839,17 @@ 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 ?
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",
- 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);
@@ -858,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
@@ -876,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;
@@ -910,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;
@@ -969,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;
@@ -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");
@@ -1067,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));
@@ -1279,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));
}
}
@@ -1498,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
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<int, int, std::string> 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<std::pair<IdString, std::string>> 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<std::pair<IdString, std::string>> 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<IdString, 5> 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 ee66599a..d37c5026 100644
--- a/nexus/arch.h
+++ b/nexus/arch.h
@@ -897,6 +897,11 @@ struct Arch : BaseCtx
std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net;
+ // fast access to X and Y IdStrings for building object names
+ std::vector<IdString> x_ids, y_ids;
+ // inverse of the above for name->object mapping
+ std::unordered_map<IdString, int> id_to_x, id_to_y;
+
// -------------------------------------------------
std::string getChipName() const;
@@ -909,20 +914,18 @@ 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 '/'; }
// -------------------------------------------------
- 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<IdString, 3> 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; }
@@ -1023,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<IdString, 3> 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;
@@ -1136,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)
{
@@ -1289,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<GroupId> getGroups() const { return {}; }
std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
std::vector<WireId> 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()