aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorD. Shah <dave@ds0.me>2021-01-29 12:12:12 +0000
committerD. Shah <dave@ds0.me>2021-02-02 17:00:12 +0000
commit6d23461bcd83d27c6b365948a5e85db80389832e (patch)
tree0898b73747b67bd6c2286ed6bc849b56a985269b /common
parent0dbe7f96a39640c42dbb2ebb41324d0edf2a5f4b (diff)
downloadnextpnr-6d23461bcd83d27c6b365948a5e85db80389832e.tar.gz
nextpnr-6d23461bcd83d27c6b365948a5e85db80389832e.tar.bz2
nextpnr-6d23461bcd83d27c6b365948a5e85db80389832e.zip
ecp5: Proof-of-concept using IdStringList for bel names
This uses the new IdStringList API to store bel names for the ECP5. Note that other arches and the GUI do not yet build with this proof-of-concept patch. getBelByName still uses the old implementation and could be more efficiently implemented with further development. Signed-off-by: D. Shah <dave@ds0.me>
Diffstat (limited to 'common')
-rw-r--r--common/archcheck.cc4
-rw-r--r--common/nextpnr.cc22
-rw-r--r--common/nextpnr.h26
-rw-r--r--common/place_common.cc7
-rw-r--r--common/placer1.cc8
-rw-r--r--common/placer_heap.cc4
-rw-r--r--common/timing_opt.cc9
7 files changed, 56 insertions, 24 deletions
diff --git a/common/archcheck.cc b/common/archcheck.cc
index f5760c88..412feca9 100644
--- a/common/archcheck.cc
+++ b/common/archcheck.cc
@@ -36,10 +36,10 @@ void archcheck_names(const Context *ctx)
log_info("Checking bel names..\n");
for (BelId bel : ctx->getBels()) {
- IdString name = ctx->getBelName(bel);
+ IdStringList name = ctx->getBelName(bel);
BelId bel2 = ctx->getBelByName(name);
if (bel != bel2) {
- log_error("bel != bel2, name = %s\n", name.c_str(ctx));
+ log_error("bel != bel2, name = %s\n", ctx->nameOfBel(bel));
}
}
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 57baedf9..c9084a75 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -111,6 +111,14 @@ TimingConstrObjectId BaseCtx::timingWildcardObject()
return id;
}
+std::string &StrRingBuffer::next()
+{
+ std::string &s = buffer.at(index++);
+ if (index >= N)
+ index = 0;
+ return s;
+}
+
TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain)
{
NPNR_ASSERT(clockDomain->clkconstr != nullptr);
@@ -283,7 +291,9 @@ void BaseCtx::removeConstraint(IdString constrName)
const char *BaseCtx::nameOfBel(BelId bel) const
{
const Context *ctx = getCtx();
- return ctx->getBelName(bel).c_str(ctx);
+ std::string &s = ctx->log_strs.next();
+ ctx->getBelName(bel).build_str(ctx, s);
+ return s.c_str();
}
const char *BaseCtx::nameOfWire(WireId wire) const
@@ -304,6 +314,12 @@ const char *BaseCtx::nameOfGroup(GroupId group) const
return ctx->getGroupName(group).c_str(ctx);
}
+BelId BaseCtx::getBelByNameStr(const std::string &str)
+{
+ Context *ctx = getCtx();
+ return ctx->getBelByName(IdStringList::parse(ctx, str));
+}
+
WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
{
if (net_info->driver.cell == nullptr)
@@ -655,7 +671,7 @@ void BaseCtx::archInfoToAttributes()
if (ci->attrs.find(id("BEL")) != ci->attrs.end()) {
ci->attrs.erase(ci->attrs.find(id("BEL")));
}
- ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(this);
+ ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(getCtx());
ci->attrs[id("BEL_STRENGTH")] = (int)ci->belStrength;
}
if (ci->constr_x != ci->UNCONSTR)
@@ -707,7 +723,7 @@ void BaseCtx::attributesToArchInfo()
if (str != ci->attrs.end())
strength = (PlaceStrength)str->second.as_int64();
- BelId b = getCtx()->getBelByName(id(val->second.as_string()));
+ BelId b = getCtx()->getBelByNameStr(val->second.as_string());
getCtx()->bindBel(b, ci, strength);
}
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 66f31867..9523e418 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -148,14 +148,13 @@ NEXTPNR_NAMESPACE_BEGIN
// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise
template <typename T, size_t N> class SSOArray
{
+ private:
union
{
T data_static[N];
T *data_heap;
};
size_t m_size;
-
- private:
inline bool is_heap() const { return (m_size > N); }
void alloc()
{
@@ -224,8 +223,8 @@ struct IdStringList
SSOArray<IdString, 4> ids;
IdStringList(){};
- explicit IdStringList(size_t n) : ids(n, IdString()){};
- explicit IdStringList(IdString id) : ids(1, id){};
+ IdStringList(size_t n) : ids(n, IdString()){};
+ IdStringList(IdString id) : ids(1, id){};
template <typename Tlist> IdStringList(const Tlist &list) : ids(list){};
static IdStringList parse(Context *ctx, const std::string &str);
@@ -238,6 +237,19 @@ struct IdStringList
const IdString &operator[](size_t idx) const { return ids[idx]; }
};
+// A ring buffer of strings, so we can return a simple const char * pointer for %s formatting - inspired by how logging
+// in Yosys works Let's just hope noone tries to log more than 100 things in one call....
+class StrRingBuffer
+{
+ private:
+ static const size_t N = 100;
+ std::array<std::string, N> buffer;
+ size_t index = 0;
+
+ public:
+ std::string &next();
+};
+
struct GraphicElement
{
enum type_t
@@ -760,6 +772,9 @@ struct BaseCtx
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str;
+ // Temporary string backing store for logging
+ mutable StrRingBuffer log_strs;
+
// Project settings and config switches
std::unordered_map<IdString, Property> settings;
@@ -875,6 +890,9 @@ struct BaseCtx
const char *nameOfPip(PipId pip) const;
const char *nameOfGroup(GroupId group) const;
+ // Overrides of arch functions that take a string and handle IdStringList parsing
+ BelId getBelByNameStr(const std::string &str);
+
// --------------------------------------------------------------
bool allUiReload = true;
diff --git a/common/place_common.cc b/common/place_common.cc
index 3f89169a..6526c38e 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -158,8 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
all_placed = true;
}
if (ctx->verbose)
- log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
- ctx->getBelName(best_bel).c_str(ctx));
+ log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->nameOfBel(best_bel));
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
cell = ripup_target;
@@ -375,7 +374,7 @@ class ConstraintLegaliseWorker
if (confl_cell != nullptr) {
if (ctx->verbose)
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
- ctx->getBelName(confl_cell->bel).c_str(ctx));
+ ctx->nameOfBel(confl_cell->bel));
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target);
rippedCells.insert(confl_cell->name);
@@ -489,7 +488,7 @@ class ConstraintLegaliseWorker
for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0)
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
- ctx->getBelName(cell.second->bel).c_str(ctx));
+ ctx->nameOfBel(cell.second->bel));
return score;
}
};
diff --git a/common/placer1.cc b/common/placer1.cc
index 1c039090..c54c3cf2 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -154,7 +154,7 @@ class SAPlacer
auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string();
- BelId bel = ctx->getBelByName(ctx->id(loc_name));
+ BelId bel = ctx->getBelByNameStr(loc_name);
if (bel == BelId()) {
log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n",
@@ -409,18 +409,18 @@ class SAPlacer
if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
+ ctx->nameOfBel(bel), cell_text.c_str());
} else {
log_error("post-placement validity check failed for Bel '%s' "
"(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
+ ctx->nameOfBel(bel), cell_text.c_str());
}
}
}
for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0)
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
- ctx->getBelName(cell.second->bel).c_str(ctx));
+ ctx->nameOfBel(cell.second->bel));
timing_analysis(ctx);
ctx->unlock();
return true;
diff --git a/common/placer_heap.cc b/common/placer_heap.cc
index d149a5b0..7882c8da 100644
--- a/common/placer_heap.cc
+++ b/common/placer_heap.cc
@@ -305,7 +305,7 @@ class HeAPPlacer
if (ctx->getBoundBelCell(cell.second->bel) != cell.second)
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
if (ctx->debug)
- log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->getBelName(cell.second->bel).c_str(ctx));
+ log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel));
}
ctx->unlock();
@@ -379,7 +379,7 @@ class HeAPPlacer
auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string();
- BelId bel = ctx->getBelByName(ctx->id(loc_name));
+ BelId bel = ctx->getBelByNameStr(loc_name);
if (bel == BelId()) {
log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n",
diff --git a/common/timing_opt.cc b/common/timing_opt.cc
index 025084b7..7ee7b805 100644
--- a/common/timing_opt.cc
+++ b/common/timing_opt.cc
@@ -427,7 +427,7 @@ class TimingOptimiser
if (pn->users.at(i).cell == port->cell && pn->users.at(i).port == port->port)
crit = net_crit.at(pn->name).criticality.at(i);
log_info(" %s.%s at %s crit %0.02f\n", port->cell->name.c_str(ctx), port->port.c_str(ctx),
- ctx->getBelName(port->cell->bel).c_str(ctx), crit);
+ ctx->nameOfBel(port->cell->bel), crit);
}
if (std::find(path_cells.begin(), path_cells.end(), port->cell->name) != path_cells.end())
continue;
@@ -472,10 +472,9 @@ class TimingOptimiser
if (ctx->debug) {
for (auto cell : path_cells) {
- log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx),
- ctx->getBelName(ctx->cells[cell]->bel).c_str(ctx));
+ log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx), ctx->nameOfBel(ctx->cells[cell]->bel));
for (auto neigh : cell_neighbour_bels.at(cell)) {
- log_info(" %s\n", ctx->getBelName(neigh).c_str(ctx));
+ log_info(" %s\n", ctx->nameOfBel(neigh));
}
}
}
@@ -597,7 +596,7 @@ class TimingOptimiser
CellInfo *cell = ctx->cells.at(rt_entry.first).get();
cell_swap_bel(cell, rt_entry.second);
if (ctx->debug)
- log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->getBelName(rt_entry.second).c_str(ctx));
+ log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->nameOfBel(rt_entry.second));
}
} else {